Merge "Add folder shapes for corresponding icon shapes" into main
diff --git a/Android.bp b/Android.bp
index 5b986ab..1e1e0ad 100644
--- a/Android.bp
+++ b/Android.bp
@@ -452,6 +452,7 @@
         "AndroidManifest-common.xml",
     ],
     lint: {
+        extra_check_modules: ["Launcher3LintChecker"],
         baseline_filename: "lint-baseline.xml",
     },
 }
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 9051ca8..6948133 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -10,4 +10,3 @@
 [Hook Scripts]
 checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --config_xml tools/checkstyle.xml --sha ${PREUPLOAD_COMMIT}
 
-flag_hook = ${REPO_ROOT}/frameworks/base/packages/SystemUI/flag_check.py --msg=${PREUPLOAD_COMMIT_MESSAGE} --files=${PREUPLOAD_FILES} --project=${REPO_PATH}
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 1726eca..5186740 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -584,3 +584,10 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "enable_mouse_interaction_changes"
+  namespace: "launcher"
+  description: "Changes mouse interaction behavior"
+  bug: "388897603"
+}
diff --git a/aconfig/launcher_overview.aconfig b/aconfig/launcher_overview.aconfig
index 30b0d40..f379e22 100644
--- a/aconfig/launcher_overview.aconfig
+++ b/aconfig/launcher_overview.aconfig
@@ -89,3 +89,10 @@
       purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "enable_overview_on_connected_displays"
+    namespace: "launcher_overview"
+    description: "Enable overview on connected displays."
+    bug: "363251602"
+}
diff --git a/checks/Android.bp b/checks/Android.bp
new file mode 100644
index 0000000..dfd701e
--- /dev/null
+++ b/checks/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2025 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 {
+    default_team: "trendy_team_system_ui_please_use_a_more_specific_subteam_if_possible_",
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library_host {
+    name: "Launcher3LintChecker",
+    srcs: ["src/**/*.kt"],
+    plugins: ["auto_service_plugin"],
+    libs: [
+        "auto_service_annotations",
+        "lint_api",
+    ],
+    kotlincflags: ["-Xjvm-default=all"],
+}
+
+java_test_host {
+    name: "Launcher3LintCheckerTest",
+    defaults: ["AndroidLintCheckerTestDefaults"],
+    srcs: ["tests/**/*.kt"],
+    data: [
+        ":androidx.annotation_annotation",
+        ":dagger2",
+        ":kotlinx-coroutines-core",
+    ],
+    device_common_data: [
+        ":framework",
+    ],
+    static_libs: [
+        "Launcher3LintChecker",
+    ],
+}
diff --git a/checks/src/com/android/internal/launcher3/lint/CustomDialogDetector.kt b/checks/src/com/android/internal/launcher3/lint/CustomDialogDetector.kt
new file mode 100644
index 0000000..37358bb
--- /dev/null
+++ b/checks/src/com/android/internal/launcher3/lint/CustomDialogDetector.kt
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2025 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.
+ */
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import org.jetbrains.uast.UClass
+
+/** Detector to identify custom usage of Android's Dialog within the Launcher3 codebase. */
+class CustomDialogDetector : Detector(), SourceCodeScanner {
+
+    override fun applicableSuperClasses(): List<String> {
+        return listOf(DIALOG_CLASS_NAME)
+    }
+
+    override fun visitClass(context: JavaContext, declaration: UClass) {
+        val superTypeClassNames = declaration.superTypes.mapNotNull { it.resolve()?.qualifiedName }
+        if (superTypeClassNames.contains(DIALOG_CLASS_NAME)) {
+            context.report(
+                ISSUE,
+                declaration,
+                context.getNameLocation(declaration),
+                "Class implements Dialog",
+            )
+        }
+    }
+
+    companion object {
+        private const val DIALOG_CLASS_NAME = "android.app.Dialog"
+
+        @JvmField
+        val ISSUE =
+            Issue.create(
+                id = "IllegalUseOfCustomDialog",
+                briefDescription = "dialogs should not be used in Launcher",
+                explanation =
+                    """
+                Don't use custom Dialogs within the launcher code base, instead consider utilizing
+                AbstractFloatingView to display content that should float above the launcher where
+                it can be correctly managed for dismissal.
+            """
+                        .trimIndent(),
+                category = Category.CORRECTNESS,
+                priority = 10,
+                severity = Severity.ERROR,
+                implementation =
+                    Implementation(CustomDialogDetector::class.java, Scope.JAVA_FILE_SCOPE),
+            )
+    }
+}
diff --git a/checks/src/com/android/internal/launcher3/lint/Launcher3IssueRegistry.kt b/checks/src/com/android/internal/launcher3/lint/Launcher3IssueRegistry.kt
new file mode 100644
index 0000000..c77c42b
--- /dev/null
+++ b/checks/src/com/android/internal/launcher3/lint/Launcher3IssueRegistry.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2025 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.internal.launcher3.lint
+
+import CustomDialogDetector
+import com.android.tools.lint.client.api.IssueRegistry
+import com.android.tools.lint.client.api.Vendor
+import com.android.tools.lint.detector.api.CURRENT_API
+import com.android.tools.lint.detector.api.Issue
+import com.google.auto.service.AutoService
+
+@AutoService(IssueRegistry::class)
+@Suppress("UnstableApiUsage")
+class Launcher3IssueRegistry : IssueRegistry() {
+    override val issues: List<Issue>
+        get() = listOf(CustomDialogDetector.ISSUE)
+
+    override val api: Int
+        get() = CURRENT_API
+
+    override val minApi: Int
+        get() = 8
+
+    override val vendor: Vendor =
+        Vendor(
+            vendorName = "Android",
+            feedbackUrl = "http://b/issues/new?component=78010",
+            contact = "abegovic@google.com",
+        )
+}
diff --git a/checks/tests/com/android/internal/launcher3/lint/CustomDialogDetectorTest.kt b/checks/tests/com/android/internal/launcher3/lint/CustomDialogDetectorTest.kt
new file mode 100644
index 0000000..2a37953
--- /dev/null
+++ b/checks/tests/com/android/internal/launcher3/lint/CustomDialogDetectorTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2025 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.internal.launcher3.lint
+
+import CustomDialogDetector
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+/** Test for [CustomDialogDetector]. */
+class CustomDialogDetectorTest : Launcher3LintDetectorTest() {
+    override fun getDetector(): Detector = CustomDialogDetector()
+
+    override fun getIssues(): List<Issue> = listOf(CustomDialogDetector.ISSUE)
+
+    @Test
+    fun classDoesNotExtendDialog_noViolation() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                    package test.pkg
+
+                    class SomeClass
+                """
+                        .trimIndent()
+                ),
+                *androidStubs,
+            )
+            .issues(CustomDialogDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classDoesExtendDialog_violation() {
+        lint()
+            .files(
+                TestFiles.kotlin(
+                    """
+                    package test.pkg
+
+                    import android.app.Dialog
+
+                    class SomeClass(context: Context) : Dialog(context)
+                """
+                        .trimIndent()
+                ),
+                *androidStubs,
+            )
+            .issues(CustomDialogDetector.ISSUE)
+            .run()
+            .expect(
+                ("""
+                src/test/pkg/SomeClass.kt:5: Error: Class implements Dialog [IllegalUseOfCustomDialog]
+                class SomeClass(context: Context) : Dialog(context)
+                      ~~~~~~~~~
+                1 errors, 0 warnings
+                """)
+                    .trimIndent()
+            )
+    }
+}
diff --git a/checks/tests/com/android/internal/launcher3/lint/Launcher3LintDetectorTest.kt b/checks/tests/com/android/internal/launcher3/lint/Launcher3LintDetectorTest.kt
new file mode 100644
index 0000000..09085c7
--- /dev/null
+++ b/checks/tests/com/android/internal/launcher3/lint/Launcher3LintDetectorTest.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2025 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.internal.launcher3.lint
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.checks.infrastructure.TestLintTask
+import java.io.File
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/**
+ * Abstract class that should be used by any test for launcher 3 lint detectors.
+ *
+ * When you write your test, ensure that you pass [androidStubs] as part of your [TestFiles]
+ * definition.
+ */
+@RunWith(JUnit4::class)
+abstract class Launcher3LintDetectorTest : LintDetectorTest() {
+
+    /**
+     * Customize the lint task to disable SDK usage completely. This ensures that running the tests
+     * in Android Studio has the same result as running the tests in atest
+     */
+    override fun lint(): TestLintTask =
+        super.lint().allowMissingSdk(true).sdkHome(File("/dev/null"))
+
+    companion object {
+        private val libraryNames =
+            arrayOf(
+                "androidx.annotation_annotation.jar",
+                "dagger2.jar",
+                "framework.jar",
+                "kotlinx-coroutines-core.jar",
+            )
+
+        /**
+         * This file contains stubs of framework APIs and System UI classes for testing purposes
+         * only. The stubs are not used in the lint detectors themselves.
+         */
+        val androidStubs =
+            libraryNames
+                .map { TestFiles.LibraryReferenceTestFile(File(it).canonicalFile) }
+                .toTypedArray()
+    }
+}
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index eba4ae6..4c4a403 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Programvoorstelle is geaktiveer"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Programvoorstelle is gedeaktiveer"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Voorspelde app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Gebaarnavigasietutoriaal"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Draai jou toestel"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Draai asseblief jou toestel om die tutoriaal oor gebaarnavigasie te voltooi"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Maak seker dat jy van die rand heel regs of heel links af swiep"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk word gewys"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taakbalk en borrels wys links"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taakbalk en borrels wys regs"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is versteek"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Taakbalk en borrels is versteek"</string>
     <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>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 019850d..2716fd5 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"የመተግበሪያ አስተያየት ጥቆማዎች ነቅቷል"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"የመተግበሪያ አስተያየቶች ቦዝነዋል"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"የተገመተው መተግበሪያ፦ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"የእጅ ምልክት ዳሰሳ አጋዥ ሥልጠና"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"መሣሪያዎን ያሽከርክሩ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"የእጅ ምልክት ዳሰሳ አጋዥ ሥልጠናን ለማጠናቀቅ እባክዎ መሣሪያዎን ያሽከርክሩ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ከቀኝ ጥግ ወይም ከግራ ጥግ ጠርዝ ጀምሮ ማንሸራተትዎን ያረጋግጡ"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index a77335f..a866bb9 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -132,8 +132,6 @@
     <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>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index a7a66e9..4292a76 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"এপৰ পৰামৰ্শসমূহ সক্ষম কৰা আছে"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"এপৰ পৰামৰ্শসমূহ অক্ষম কৰা আছে"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"পূৰ্বানুমান কৰা এপ্: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"আঙুলিৰ স্পৰ্শৰ নিৰ্দেশেৰে কৰা নেভিগেশ্বন সম্পৰ্কীয় টিউট’ৰিয়েল"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"আপোনাৰ ডিভাইচটো ঘূৰাওক"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"আঙুলিৰ স্পৰ্শৰ নিৰ্দেশেৰে কৰা নেভিগেশ্বনৰ টিউট’ৰিয়েল শেষ কৰিবলৈ অনুগ্ৰহ কৰি আপোনাৰ ডিভাইচটো ঘূৰাওক"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"আপুনি সোঁ অথবা বাওঁ কাষৰ একেবাৰে সীমাৰ পৰা ছোৱাইপ কৰাটো নিশ্চিত কৰক"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 0e0181a..a7bd553 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Tətbiq təklifləri aktivdir"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Tətbiq təklifləri deaktivdir"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Proqnozlaşdırılan tətbiq: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Jest naviqasiyası üçün öyrədici"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Cihazı fırladın"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Jest naviqasiyası təlimatını tamamlamaq üçün cihazı fırladın"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Ən sağ və ya sol kənardan sürüşdürün"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"İşləmə paneli göstərilir"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"İşləmə paneli, yumrucuqlar solda göstərilir"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"İşləmə paneli, yumrucuqlar sağda göstərilir"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"İşləmə paneli gizlədilib"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"İşləmə paneli, yumrucuqlar gizlədilib"</string>
     <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>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 95767e2..ef46503 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Predlozi aplikacija su omogućeni"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Predlozi aplikacija su onemogućeni"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predviđamo aplikaciju: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Vodič za navigaciju pomoću pokreta"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotirajte uređaj"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotirajte uređaj da biste dovršili vodič za navigaciju pomoću pokreta"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Obavezno prevucite od same desne ili leve ivice"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Prikaz zadataka/oblačića levo"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Prikaz zadataka/oblačića desno"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je skrivena"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Skriveni zadaci/oblačići"</string>
     <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>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 0261c0f..205fe9d 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Прапановы праграм уключаны"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Прапановы праграм выключаны"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Праграма з падказкі: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Дапаможнік па навігацыі жэстамі"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Павярніце прыладу"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Каб пачаць азнаямленне з дапаможнікам па навігацыі жэстамі, павярніце прыладу"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Правядзіце пальцам справа налева ці злева направа ад самага краю экрана"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index 660d816..048806f 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Предложенията за приложения са активирани"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Функцията „Предложения за приложения“ е деактивирана"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Предвидено приложение: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Урок за навигирането с жестове"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Завъртете устройството си"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Моля, завъртете устройството си, за да завършите урока за навигиране с жестове"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Трябва да плъзнете пръст от най-дясната или най-лявата част на екрана"</string>
@@ -88,7 +87,7 @@
     <string name="gesture_tutorial_nice" msgid="2936275692616928280">"Чудесно!"</string>
     <string name="gesture_tutorial_step" msgid="1279786122817620968">"Урок <xliff:g id="CURRENT">%1$d</xliff:g>/<xliff:g id="TOTAL">%2$d</xliff:g>"</string>
     <string name="allset_title" msgid="5021126669778966707">"Готово!"</string>
-    <string name="allset_hint" msgid="459504134589971527">"Плъзнете пръст нагоре, за да отворите началния екран"</string>
+    <string name="allset_hint" msgid="459504134589971527">"Плъзнете с пръст нагоре, за да отворите началния екран"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Докоснете бутона „Начало“, за да преминете към началния екран"</string>
     <string name="allset_description_generic" msgid="5385500062202019855">"Можете да започнете да използвате <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
     <string name="default_device_name" msgid="6660656727127422487">"устройството"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index b5b0a5e..dec7443 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"অ্যাপ সাজেশন চালু করা আছে"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"অ্যাপ সাজেশন বন্ধ করা আছে"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"আপনার প্রয়োজন হতে পারে এমন অ্যাপ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"জেসচার নেভিগেশন সম্পর্কিত টিউটোরিয়াল"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"আপনার ডিভাইস ঘোরান"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"জেসচার নেভিগেশন টিউটোরিয়াল সম্পূর্ণ করতে আপনার ডিভাইসটি ঘোরান"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"স্ক্রিনের একেবারে ডান বা বাঁদিকের প্রান্ত থেকে সোয়াইপ করেছেন কিনা তা দেখে নিন"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index 69a5cdb..626279f 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Prijedlozi aplikacija su omogućeni"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Prijedlozi aplikacija su onemogućeni"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predviđena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Vodič za navigaciju pokretima"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotirajte uređaj"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotirajte uređaj da završite vodič za navigaciju pokretima"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Prevucite s krajnjeg desnog ili lijevog ruba"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka zadataka je prikazana"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Traka zadataka/oblačići prik. lijevo"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Traka zadataka/oblačići prik. desno"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka zadataka je sakrivena"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Traka zadataka/oblačići sakriveni"</string>
     <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>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index cc643a6..810e8f8 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Els suggeriments d\'aplicacions estan activats"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Els suggeriments d\'aplicacions estan desactivats"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicció d\'aplicació: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial de navegació amb gestos"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gira el dispositiu"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Gira el dispositiu per completar el tutorial de navegació amb gestos"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Assegura\'t de lliscar des de l\'extrem dret o esquerre de la pantalla."</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Es mostra la Barra de tasques"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barra i bombolles a l\'esquerra"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barra i bombolles a la dreta"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"S\'ha amagat la Barra de tasques"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barra i bombolles amagades"</string>
     <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>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index eb0e8c8..9fd2fa5 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Návrhy aplikací jsou povoleny"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Návrhy aplikací jsou zakázány"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Předpokládaná aplikace: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Výukový program navigace gesty"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Otočte zařízení"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Pokud chcete dokončit výukový program navigace gesty, otočte zařízení"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Přejeďte prstem z úplného pravého nebo levého okraje obrazovky"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikací je zobrazen"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Panel a bubliny vlevo zobr."</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Panel a bubliny vpravo zobr."</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikací je skrytý"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Panel a bubliny jsou skryty"</string>
     <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 navigační režim"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index a7b7d04..b2a5f33 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Appforslag er aktiveret"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Appforslag er deaktiveret"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App, du forventes at skulle bruge: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Vejledning i navigation med bevægelser"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotér din enhed"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotér enheden for at gennemgå vejledningen i navigation med bevægelser"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Stryg fra kanten yderst til højre eller venstre"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Proceslinjen vises"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Proceslinje og bobler til venstre"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Proceslinje og bobler til højre"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Proceslinjen er skjult"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Proceslinje og bobler skjult"</string>
     <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>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index dd7b467..93fba3b 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Funktion „App-Vorschläge“ aktiviert"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Funktion \"App-Vorschläge\" deaktiviert"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Vorgeschlagene App: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Anleitung zur Bedienung über Gesten"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gerät drehen"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Bitte drehe dein Gerät, um die Anleitung für die Bedienung über Gesten abzuschließen"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Wische vom äußersten rechten oder linken Displayrand"</string>
@@ -92,7 +91,7 @@
     <string name="allset_button_hint" msgid="2395219947744706291">"Startbildschirmtaste drücken, um zum Startbildschirm zu gehen"</string>
     <string name="allset_description_generic" msgid="5385500062202019855">"Du kannst dein <xliff:g id="DEVICE">%1$s</xliff:g> jetzt verwenden"</string>
     <string name="default_device_name" msgid="6660656727127422487">"Gerät"</string>
-    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
+    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen für die Systemnavigation"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Teilen"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Splitscreen"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskleiste eingeblendet"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskleiste &amp; Bubbles links eingeblendet"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskleiste &amp; Bubbles rechts eingeblendet"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskleiste ausgeblendet"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Taskleiste &amp; Bubbles ausgeblendet"</string>
     <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>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 058d7ba..960831e 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Οι προτεινόμενες εφαρμογές ενεργοποιήθηκαν"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Οι προτεινόμενες εφαρμογές είναι απενεργοποιημένες"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Εφαρμογή από πρόβλεψη: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Οδηγός για την πλοήγηση με κινήσεις"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Περιστρέψτε τη συσκευή σας"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Περιστρέψτε τη συσκευή σας για να ολοκληρώσετε τον οδηγό πλοήγησης με κινήσεις"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Φροντίστε να σύρετε από το άκρο της δεξιάς ή της αριστερής πλευράς."</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index 506e36d..bf115f2 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App suggestions enabled"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App suggestions are disabled"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicted app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Gesture navigation tutorial"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskbar and bubbles left shown"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskbar and 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 and 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>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index f91f4ee..cd6abc3 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App suggestions enabled"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App suggestions are disabled"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicted app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Gesture Navigation Tutorial"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index 506e36d..bf115f2 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App suggestions enabled"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App suggestions are disabled"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicted app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Gesture navigation tutorial"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskbar and bubbles left shown"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskbar and 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 and 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>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index 506e36d..bf115f2 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App suggestions enabled"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App suggestions are disabled"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicted app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Gesture navigation tutorial"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotate your device"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Please rotate your device to complete the gesture navigation tutorial"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Make sure you swipe from the far-right or far-left edge"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar shown"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskbar and bubbles left shown"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskbar and 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 and 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>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index dd969d7..0955f28 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugerencias de apps habilitadas"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Las sugerencias de aplicaciones están inhabilitadas"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predicción de app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Instructivo de navegación por gestos"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rota el dispositivo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rota el dispositivo para completar el instructivo de la navegación por gestos"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Asegúrate de deslizar desde el extremo derecho o izquierdo"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barra tareas y burb. a la izq."</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barra tareas y burb. a la der."</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barra tareas y burb. ocultas"</string>
     <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>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 1da35e6..a5ac1d2 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugerencias de aplicaciones habilitadas"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Las sugerencias de aplicaciones están inhabilitadas"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplicación sugerida: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial de navegación por gestos"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gira el dispositivo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Gira el dispositivo para completar el tutorial de navegación por gestos"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Asegúrate de deslizar desde el borde derecho o izquierdo de la pantalla"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tareas visible"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Tareas y burbujas a izquierda"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Tareas y burbujas a derecha"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tareas oculta"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Tareas y burbujas ocultas"</string>
     <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>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 70acc52..bb56954 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Rakenduste soovitused on lubatud"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Rakenduste soovitused on keelatud"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ennustatud rakendus: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Liigutustega navigeerimise juhend"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Pöörake seadet"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Pöörake seadet, et liigutustega navigeerimise õpetused lõpetada"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pühkige kindlasti parem- või vasakpoolsest servast"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tegumiriba on kuvatud"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Tegumiriba ja mullid kuvatakse"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Tegumiriba ja mullid kuvatakse paremal"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tegumiriba on peidetud"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Tegumiriba ja mullid on peidetud"</string>
     <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>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index af5962a..9ee1255 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Gaituta daude aplikazioen iradokizunak"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Desgaituta daude aplikazioen iradokizunak"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Iragarritako aplikazioa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Keinu bidezko nabigazioaren tutoriala"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Biratu gailua"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Keinu bidezko nabigazioaren tutoriala osatzeko, biratu gailua"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Ziurtatu hatza pantailaren eskuineko edo ezkerreko ertzetik hasten zarela pasatzen"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Zereginen barra ikusgai dago"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Zereginen barra eta burbuilak ezkerrean ikusgai"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Zereginen barra eta burbuilak eskuinean ikusgai"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Zereginen barra itxita dago"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Zereginen barra eta burbuilak ezkutatuta"</string>
     <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>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index 40469f5..d1ca8ed 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"«پیشنهاد برنامه» فعال است"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"«پیشنهاد برنامه» غیرفعال است"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"برنامه پیش‌بینی‌شده: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"آموزش گام‌به‌گام پیمایش اشاره‌ای"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"دستگاهتان را بچرخانید"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"لطفاً برای تکمیل آموزش گام‌به‌گام پیمایش اشاره‌ای، دستگاهتان را بچرخانید"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"دقت کنید که از انتهای لبه سمت راست یا سمت چپ تند بکشید"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 6907e49..13750dc 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sovellusehdotukset käytössä"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sovellusehdotukset on poistettu käytöstä"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ennakoitu sovellus: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Eleillä navigoinnin ohje"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Käännä laite"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Käännä laite, niin voit katsoa esittelyn eleillä navigoinnista"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pyyhkäise aivan oikeasta tai vasemmasta reunasta"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Tehtäväpalkki näkyvissä"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Vas. palkki ja kuplat näkyvissä"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Oik. palkki ja kuplat näkyvissä"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Tehtäväpalkki piilotettu"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Palkki ja kuplat piilotettu"</string>
     <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>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index d57479d..b83e33c 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Les suggestions d\'applis sont activées"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Les suggestions d\'applis sont désactivées"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Appli prédite : <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutoriel de navigation par gestes"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Faites pivoter votre appareil"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Veuillez faire pivoter votre appareil pour terminer le tutoriel de navigation par gestes"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Assurez-vous de balayer l\'écran à partir de l\'extrémité droite ou gauche"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barre des tâches/bulles à gauche"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barre des tâches/bulles à droite"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barre des tâches/bulles masquées"</string>
     <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>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index b185e0c..66102d5 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Suggestions d\'applications activées"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Les suggestions d\'applications sont désactivées"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Application prédite : <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutoriel sur la navigation par gestes"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Faire pivoter l\'appareil"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Veuillez faire pivoter votre appareil pour effectuer le tutoriel de navigation par gestes"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Veillez à bien balayer l\'écran depuis le bord gauche ou droit"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barre des tâches affichée"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barre des tâches et bulles affichées à gauche"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barre des tâches et bulles affichées à droite"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barre des tâches masquée"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barre des tâches et bulles masquées"</string>
     <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>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 8990a5f..16c448c 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"As suxestións de aplicacións están activadas"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"As suxestións de aplicacións están desactivadas"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplicación predita: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Titorial de navegación con xestos"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Xira o dispositivo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Xira o dispositivo para completar o titorial de navegación con xestos"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Asegúrate de pasar o dedo desde o bordo dereito ou esquerdo"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Estase mostrando a barra de tarefas"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barra e burbullas á esquerda"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barra e burbullas á dereita"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Non se está mostrando a barra de tarefas"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barra e burbullas ocultas"</string>
     <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>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index cb8a35a..0cc6091 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ઍપના સુઝાવો ચાલુ છે"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ઍપના સુઝાવો બંધ છે"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"પૂર્વાનુમાનિત ઍપ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"સંકેતથી નૅવિગેશનનું ટ્યૂટૉરિઅલ"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"તમારા ડિવાઇસને ફેરવો"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"સંકેતથી નૅવિગેશન ટ્યૂટૉરિઅલ પૂર્ણ કરવા માટે કૃપા કરીને તમારા ડિવાઇસને ફેરવો"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ખાતરી કરો કે તમે એકદમ દૂરની જમણી કે ડાબી કિનારીએથી સ્વાઇપ કરો છો"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index b7ca582..2135dac 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"सुझाए गए ऐप्लिकेशन की सुविधा चालू है"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"सुझाए गए ऐप्लिकेशन की सुविधा बंद है"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"सुझाया गया ऐप्लिकेशन: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"जेस्चर वाले नेविगेशन के लिए ट्यूटोरियल"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"अपना डिवाइस घुमाएं"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"जेस्चर वाले नेविगेशन से जुड़े ट्यूटोरियल को पूरा करने के लिए अपने डिवाइस को घुमाएं"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"स्क्रीन पर बिलकुल दाएं या बाएं किनारे से स्वाइप करें"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index cb7d9b9..0fd3123 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Predlaganje apl. omogućeno"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Predlaganje apl. onemogućeno"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predviđena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Vodič za navigaciju pokretima"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zakrenite uređaj"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Zakrenite uređaj da biste dovršili vodič o navigaciji pokretima"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Prijeđite prstom od krajnjeg desnog ili krajnjeg lijevog ruba"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Traka sa zadacima prikazana"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Traka sa zadacima/oblačići prikazani lijevo"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Traka sa zadacima/oblačići prikazani desno"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Traka sa zadacima skrivena"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Traka sa zadacima/oblačići skriveni"</string>
     <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>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 184fef0..92ada47 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Alkalmazásjavaslatok engedélyezve"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Alkalmazásjavaslatok letiltva"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Várható alkalmazás: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Kézmozdulatokkal való navigáció útmutatója"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Forgassa el eszközét"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Forgassa el eszközét a kézmozdulatokkal való navigáció útmutatójának befejezéséhez"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Csúsztasson a képernyő jobb vagy bal széléről."</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Feladatsáv megjelenítve"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Feladatsáv és buborék balra"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Feladatsáv és buborék jobbra"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Feladatsáv elrejtve"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Rejtett feladatsáv és buborék"</string>
     <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>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 8da1a6d..7751ea1 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"«Առաջարկվող հավելվածներ» գործառույթը միացված է"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"«Առաջարկվող հավելվածներ» գործառույթն անջատված է"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Առաջարկվող հավելված՝ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Ժեստերով նավիգացիայի ուղեցույց"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Պտտեք սարքը"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Պտտեք սարքը՝ ժեստերով նավիգացիայի ուղեցույցն ավարտելու համար"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Համոզվեք, որ մատը սահեցնում եք էկրանի աջ կամ ձախ եզրից"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index eb592db..1909376 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Saran aplikasi diaktifkan"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Saran aplikasi dinonaktifkan"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplikasi yang diprediksi: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial Navigasi Gestur"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Putar perangkat Anda"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Putar perangkat Anda untuk menyelesaikan tutorial navigasi gestur"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pastikan Anda menggeser dari tepi ujung kanan atau ujung kiri"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ditampilkan"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskbar &amp; balon kiri ditampilkan"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskbar &amp; bubbles kanan ditampilkan"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar disembunyikan"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Taskbar &amp; balon disembunyikan"</string>
     <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>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 3500001..30d6dad 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Kveikt á tillögum að forritum"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Slökkt er á tillögðum forritum"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Tillaga að forriti: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Leiðsögn fyrir bendingastjórnun"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Snúðu tækinu"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Snúðu tækinu til að ljúka leiðsögn um bendingastjórnun"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Passaðu að strjúka frá jaðri hægri eða vinstri brúnar"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Forritastika sýnd"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Verkstika og blöðrur sýndar til vinstri"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Verkstika og blöðrur sýndar til hægri"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Forritastika falin"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Verkstika og blöðrur eru faldar"</string>
     <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>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index b8fa813..7f80107 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"La funzionalità app suggerite è attiva"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"La funzionalità app suggerite è disattivata"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App prevista: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial sulla navigazione tramite gesti"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Ruota il dispositivo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ruota il dispositivo per completare il tutorial relativo alla navigazione tramite gesti"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Assicurati di scorrere dal bordo all\'estrema destra o all\'estrema sinistra"</string>
@@ -92,7 +91,7 @@
     <string name="allset_button_hint" msgid="2395219947744706291">"Tocca il pulsante Home per andare alla schermata Home"</string>
     <string name="allset_description_generic" msgid="5385500062202019855">"Puoi iniziare a usare il tuo <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
     <string name="default_device_name" msgid="6660656727127422487">"dispositivo"</string>
-    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Impostazioni Navigazione del sistema"</annotation></string>
+    <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Impostazioni di navigazione del sistema"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Condividi"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
     <string name="action_split" msgid="2098009717623550676">"Dividi"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index c6fc845..f93f741 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"התכונה \'הצעות לאפליקציות\' מופעלת"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ההצעות לאפליקציות מושבתות"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"האפליקציות החזויות: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"מדריך לניווט באמצעות תנועות"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"צריך לסובב את המכשיר"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"צריך לסובב את המכשיר כדי להשלים את המדריך לניווט באמצעות תנועות"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"חשוב להחליק מהקצה השמאלי או הימני"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 5fdcf4a..e3625cb 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"アプリの候補表示が有効です"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"アプリの候補は無効です"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"予測されたアプリ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ジェスチャー ナビゲーションのチュートリアル"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"デバイスを回転してください"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ジェスチャー ナビゲーションのチュートリアルを終了するには、デバイスを回転してください"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"右端または左端からスワイプしてください"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index 01becd7..623319d 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"აპის შეთავაზებები ჩართულია"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"აპის შეთავაზებები გათიშულია"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ნაწინასწარმეტყველები აპი: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ჟესტებით ნავიგაციის სახელმძღვანელო"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"შეატრიალეთ მოწყობილობა"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ჟესტებით ნავიგაციის სახელმძღვანელოს დასასრულებლად შეატრიალეთ თქვენი მოწყობილობა"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"გადაფურცლეთ უკიდურესი მარჯვენა ან მარცხენა ბოლოდან"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 3280908..f707689 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"\"Қолданба ұсыныстары\" функциясы қосылды."</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"\"Қолданба ұсыныстары\" функциясы өшірулі."</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Болжалды қолданба: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Қимылмен басқару оқулығы"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Құрылғыны бұрыңыз"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Қимылмен басқару нұсқаулығын аяқтау үшін құрылғыны бұрыңыз."</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Экранның оң немесе сол жиегінен сырғытыңыз."</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index d05ef16..25e1ef2 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"បានបើក​ការណែនាំ​កម្មវិធី"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"បានបិទ​ការណែនាំ​កម្មវិធី"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"កម្មវិធី​ដែលបាន​ព្យាករ៖ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"មេរៀនអំពីការរុករក​ដោយប្រើចលនា"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"បង្វិលឧបករណ៍របស់អ្នក"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"សូមបង្វិលឧបករណ៍របស់អ្នក ដើម្បីបញ្ចប់មេរៀនអំពីការរុករកដោយប្រើចលនា"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ត្រូវប្រាកដថា​អ្នកអូសពី​គែមខាងស្ដាំ ឬ​ខាងឆ្វេង"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 3240b2a..ed4b806 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ಶಿಫಾರಸು ಮಾಡಿದ ಆ್ಯಪ್: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ಗೆಸ್ಚರ್ ನ್ಯಾವಿಗೇಶನ್ ಟುಟೋರಿಯಲ್"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಿರುಗಿಸಿ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ಗೆಸ್ಚರ್ ನ್ಯಾವಿಗೇಶನ್ ಟುಟೋರಿಯಲ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು, ನಿಮ್ಮ ಸಾಧನವನ್ನು ತಿರುಗಿಸಿ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ನೀವು ಬಲಕೊನೆಯ ಅಂಚಿನಿಂದ ಅಥವಾ ಎಡಕೊನೆಯ ಅಂಚಿನಿಂದ ಸ್ವೈಪ್ ಮಾಡುತ್ತಿದ್ದೀರಿ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"ಟಾಸ್ಕ್‌ಬಾರ್ ತೋರಿಸಲಾಗಿದೆ"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"ಟಾಸ್ಕ್‌ಬಾರ್ &amp; ಬಬಲ್ಸ್ ತೋರಿಸಲಾಗಿದೆ"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"ಟಾಸ್ಕ್‌ಬಾರ್ &amp; ಬಬಲ್ಸ್ ಬಲಭಾಗದಲ್ಲಿ ತೋರಿಸಲಾಗಿದೆ"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"ಟಾಸ್ಕ್‌ಬಾರ್ ಮರೆಮಾಡಲಾಗಿದೆ"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"ಟಾಸ್ಕ್‌ಬಾರ್ &amp; ಬಬಲ್ಸ್ ಮರೆಮಾಡಲಾಗಿದೆ"</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>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index c8b8674..d11e0b2 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"앱 제안이 사용 설정됨"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"앱 제안이 사용 중지됨"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"예상 앱: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"동작 탐색 튜토리얼"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"기기를 회전시키세요"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"동작 탐색 튜토리얼을 완료하려면 기기를 회전시키세요."</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"오른쪽 또는 왼쪽 가장자리 끝에서 스와이프하세요."</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 6dafcd0..3d59332 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Сунушталган колдонмолор функциясы иштетилди"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Сунушталган колдонмолор функциясы өчүрүлгөн"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Божомолдонгон колдонмо: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Жаңсап чабыттоо боюнча үйрөткүч"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Түзмөгүңүздү буруңуз"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Жаңсап чабыттоо үйрөткүчүнүн аягына чыгуу үчүн түзмөктү буруңуз"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Экранды эң четинен оңдон солго же солдон оңго карай сүрүңүз"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index a13da69..e480766 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ເປີດການນຳໃຊ້ການແນະນຳແອັບແລ້ວ"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ປິດການນຳໃຊ້ການແນະນຳແອັບແລ້ວ"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ແອັບທີ່ຄາດເດົາໄວ້: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ສອນການນຳໃຊ້ການນຳທາງແບບທ່າທາງ"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ໝຸນອຸປະກອນຂອງທ່ານ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ກະລຸນາໝຸນອຸປະກອນຂອງທ່ານເພື່ອເຮັດຕາມການສອນການນຳໃຊ້ກ່ຽວກັບການນຳທາງແບບທ່າທາງໃຫ້ສຳເລັດ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ກະລຸນາກວດສອບວ່າທ່ານປັດຈາກຂອບຂວາສຸດ ຫຼື ຊ້າຍສຸດ"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 7334b0a..2bcbb6d 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Siūlomų programų funkcija įgalinta"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Siūlomų programų funkcija išjungta"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Numatoma programa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Naršymo gestais mokomoji medžiaga"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Pasukite įrenginį"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Pasukite įrenginį, kad pereitumėte į naršymo gestais mokomąją medžiagą"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Turite perbraukti nuo dešiniojo ar kairiojo krašto"</string>
@@ -90,7 +89,7 @@
     <string name="allset_title" msgid="5021126669778966707">"Paruošta!"</string>
     <string name="allset_hint" msgid="459504134589971527">"Perbraukite aukštyn, kad grįžtumėte į pagrindinį ekraną"</string>
     <string name="allset_button_hint" msgid="2395219947744706291">"Norėdami eiti į pagrindinį ekraną, palieskite pagrindinio ekrano mygtuką"</string>
-    <string name="allset_description_generic" msgid="5385500062202019855">"Esate pasirengę pradėti naudoti <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
+    <string name="allset_description_generic" msgid="5385500062202019855">"Jau parengta naudoti: <xliff:g id="DEVICE">%1$s</xliff:g>"</string>
     <string name="default_device_name" msgid="6660656727127422487">"įrenginys"</string>
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Sistemos naršymo nustatymai"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Bendrinti"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Užduočių juosta rodoma"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Užduočių juosta ir burbulai rodomi kairėje"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Užduočių juosta ir burbulai rodomi dešinėje"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Užduočių juosta paslėpta"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Užduočių juosta ir burbulai paslėpti"</string>
     <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>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index bbf45c3..7d88140 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Ieteicamās lietotnes ir iespējotas"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Ieteicamās lietotnes ir atspējotas"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Prognozētā lietotne: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Žestu navigācijas pamācība"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Pagrieziet ierīci"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Lūdzu, pagrieziet savu ierīci, lai pabeigtu žestu navigācijas apmācību."</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Jāvelk no pašas labās vai kreisās malas."</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Uzdevumu josla tiek rādīta"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Uzdevumu josla/burbuļi pa kreisi"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Uzdevumu josla/burbuļi pa labi"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Uzdevumu josla paslēpta"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Uzdevumu josla/burbuļi paslēpti"</string>
     <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>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index 5340854..632196b 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Предлозите за апликации се овозможени"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Предлозите за апликации се оневозможени"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Предвидена апликација: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Упатство за навигација со движења"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Ротирајте го уредот"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ротирајте го уредот за да го завршите упатството за навигација со движење"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Повлечете од крајниот десен или крајниот лев раб"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index d92ddbc..2246889 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ആപ്പ് നിർദ്ദേശങ്ങൾ പ്രവർത്തനക്ഷമമാക്കി"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ആപ്പ് നിർദ്ദേശങ്ങൾ പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"പ്രവചിച്ച ആപ്പ്: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ജെസ്ച്ചർ നാവിഗേഷൻ ട്യൂട്ടോറിയൽ"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"നിങ്ങളുടെ ഉപകരണം റൊട്ടേറ്റ് ചെയ്യുക"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ജെസ്ച്ചർ നാവിഗേഷൻ ട്യൂട്ടോറിയൽ പൂർത്തിയാക്കാൻ നിങ്ങളുടെ ഉപകരണം റൊട്ടേറ്റ് ചെയ്യുക"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"വലത്തേയറ്റത്തെയോ ഇടത്തേയറ്റത്തെയോ അരികിൽ നിന്നാണ് സ്വെെപ്പ് ചെയ്യുന്നതെന്ന് ഉറപ്പാക്കുക"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 2b335a9..94adf88 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Санал болгож буй аппуудыг идэвхжүүлсэн"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Санал болгож буй аппуудыг идэвхгүй болгосон"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Таамаглаж буй апп: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Зангааны навигацын заавар"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Төхөөрөмжөө эргүүлэх"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Зангааны навигацын практик хичээлийг дуусгахын тулд төхөөрөмжөө эргүүлнэ үү"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Та баруун зах эсвэл зүүн захын ирмэгээс шударна уу"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index 647e88d..d2fdb42 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"अ‍ॅप सूचना सुरू केल्या आहेत"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"अ‍ॅप सूचना बंद केल्या आहेत"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"पूर्वानुमान केलेले अ‍ॅप: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"जेश्चर नेव्हिगेशन ट्यूटोरियल"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"तुमचे डिव्हाइस फिरवा"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"कृपया जेश्चर नेव्हिगेशन ट्यूटोरियल पूर्ण करण्यासाठी तुमचे डिव्हाइस फिरवा"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"तुम्ही स्क्रीनच्या अगदी उजव्या किंवा अगदी डाव्या कडेपासून स्‍वाइप करत आहात खात्री करा"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index baffcbb..66c5bdb 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Cadangan apl didayakan"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Cadangan apl dilumpuhkan"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Apl yang diramalkan: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial Navigasi Gerak Isyarat"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Putarkan peranti anda"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Sila putarkan peranti anda untuk melengkapkan tutorial navigasi gerak isyarat"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pastikan anda meleret dari hujung sebelah kanan atau hujung sebelah kiri"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index f89920b..c9ac441 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"အက်ပ်အကြံပြုချက်များ ဖွင့်ထားသည်"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"အက်ပ်အကြံပြုချက်များကို ပိတ်ထားသည်"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ကြိုတင်မှန်းဆထားသော အက်ပ်− <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"လက်ဟန်ဖြင့် လမ်းညွှန်ခြင်း အသုံးပြုနည်း"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"သင့်စက်ကို လှည့်ပါ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"လက်ဟန်ဖြင့် လမ်းညွှန်ခြင်း ရှင်းလင်းပို့ချချက်အား အပြီးသတ်ရန် သင့်စက်ကို လှည့်ပါ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ညာ (သို့) ဘယ်ဘက်အစွန်ဆုံးမှ ပွတ်ဆွဲကြောင်း သေချာပါစေ"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taskbar ပြထားသည်"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"ဘယ်ဘက်၌ Taskbar နှင့် ပူဖောင်းကွက် ပြထားသည်"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"ညာဘက်၌ Taskbar နှင့် ပူဖောင်းကွက် ပြထားသည်"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taskbar ဖျောက်ထားသည်"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Taskbar နှင့် ပူဖောင်းကွက် ဖျောက်ထားသည်"</string>
     <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>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 3be8d68..aa19606 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Appforslag er på"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Appforslag er slått av"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Foreslått app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Veiledning for navigasjon med bevegelser"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Roter enheten"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Roter enheten for å fullføre veiledningen for navigasjon med bevegelser"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Sørg for at du sveiper fra kanten helt til høyre eller venstre"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Oppgavelinjen vises"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Venstre oppgavelinje/boble vises"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Høyre oppgavelinje/bobler vises"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Oppgavelinjen er skjult"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Oppgavelinje og bobler skjult"</string>
     <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>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 4ed8bb9..4793ad3 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"सिफारिस गरिएका एप देखाउने सुविधा अन गरिएको छ"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"सिफारिस गरिएका एपहरू देखाउने सुविधा असक्षम पारिएको छ"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"पूर्वानुमान गरिएको एप: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"जेस्चर नेभिगेसनसम्बन्धी ट्युटोरियल"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"आफ्नो डिभाइस रोटेट गर्नुहोस्"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"जेस्चर नेभिगेसनको ट्युटोरियल पूरा गर्न कृपया आफ्नो डिभाइस रोटेट गर्नुहोस्"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"स्क्रिनको सबैभन्दा दायाँ किनारा वा सबैभन्दा बायाँ किनाराबाट स्वाइप गर्नुहोस्"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index c1c1a22..3cd9457 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"App-suggesties staan aan"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"App-suggesties staan uit"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Voorspelde app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial voor navigatie met gebaren"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Het apparaat draaien"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Draai het apparaat om de tutorial voor navigatie met gebaren af te ronden"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Swipe vanaf de rechter- of linkerrand"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Taakbalk wordt getoond"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taakbalk en bubbels links getoond"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taakbalk en bubbels rechts getoond"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Taakbalk is verborgen"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Taakbalk en bubbels verborgen"</string>
     <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>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 789ba0a..20420d9 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ଆପ୍ ପରାମର୍ଶଗୁଡ଼ିକୁ ସକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ଆପ୍ ପରାମର୍ଶଗୁଡ଼ିକୁ ଅକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ପୂର୍ବାନୁମାନ କରାଯାଇଥିବା ଆପ୍: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ଜେଶ୍ଚର ନାଭିଗେସନ ଟ୍ୟୁଟୋରିଆଲ"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ଆପଣଙ୍କ ଡିଭାଇସକୁ ରୋଟେଟ କରନ୍ତୁ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ଜେଶ୍ଚର ନାଭିଗେସନ ଟ୍ୟୁଟୋରିଆଲ ସମ୍ପୂର୍ଣ୍ଣ କରିବାକୁ ଦୟାକରି ଆପଣଙ୍କ ଡିଭାଇସ ରୋଟେଟ କରନ୍ତୁ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ଆପଣ ସ୍କ୍ରିନର ଏକଦମ-ଡାହାଣ ବା ବାମ ଧାରରୁ ସ୍ୱାଇପ କରୁଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 2392890..5cab154 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ਐਪ ਸੁਝਾਵਾਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ਐਪ ਸੁਝਾਵਾਂ ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"ਪੂਰਵ ਅਨੁਮਾਨਿਤ ਐਪ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"ਇਸ਼ਾਰਾ ਨੈਵੀਗੇਸ਼ਨ ਸੰਬੰਧੀ ਟਿਊਟੋਰੀਅਲ"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਘੁੰਮਾਓ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"ਕਿਰਪਾ ਕਰਕੇ ਇਸ਼ਾਰਾ ਨੈਵੀਗੇਸ਼ਨ ਟਿਊਟੋਰੀਅਲ ਨੂੰ ਪੂਰਾ ਕਰਨ ਲਈ ਆਪਣੇ ਡੀਵਾਈਸ ਨੂੰ ਘੁੰਮਾਓ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ਇਹ ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ ਸੱਜੇ ਜਾਂ ਖੱਬੇ ਪਾਸੇ ਦੇ ਬਿਲਕੁਲ ਕਿਨਾਰੇ ਤੋਂ ਸਵਾਈਪ ਕਰਦੇ ਹੋ"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 74aec66..94e39d0 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Włączono sugestie aplikacji"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sugestie aplikacji są wyłączone"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Przewidywana aplikacja: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Samouczek dotyczący nawigacji przy użyciu gestów"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Obróć urządzenie"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Obróć urządzenie, aby ukończyć samouczek nawigacji przy użyciu gestów"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pamiętaj, aby przesuwać palcem od samej krawędzi (prawej lub lewej)"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Pasek aplikacji widoczny"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Pasek i dymki po lewej"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Pasek i dymki po prawej"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Pasek aplikacji ukryty"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Pasek i dymki są ukryte"</string>
     <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>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index 56d5514..cace987 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugestões de apps ativadas"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"As sugestões de apps estão desativadas"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App prevista: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial da navegação por gestos"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rode o dispositivo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rode o seu dispositivo para concluir o tutorial de navegação por gestos"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Deslize a partir da extremidade mais à direita ou mais à esquerda"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas apresentada"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barra de tarefas/balões à esq."</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barra de tarefas/balões à dir."</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas ocultada"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barra tarefas/balões ocultos"</string>
     <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>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index bdcad13..434cf6b 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"O recurso \"sugestões de apps\" está ativado"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"O recurso \"sugestões de apps\" está desativado"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"App previsto: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial da navegação por gestos"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Gire o dispositivo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Gire o dispositivo para concluir o tutorial da navegação por gestos"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Deslize da borda direita ou esquerda"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Barra de tarefas visível"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Barra de tar. e balões à esq."</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Barra de tar. e balões à dir."</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Barra de tarefas oculta"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Barra de tar. e balões ocultos"</string>
     <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>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 6a05909..ac25e6d 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Sugestiile de aplicații au fost activate"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sugestiile de aplicații au fost dezactivate"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplicația estimată: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial de navigare prin gesturi"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotește dispozitivul"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotește dispozitivul pentru a încheia tutorialul de navigare prin gesturi"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Glisează dinspre marginea dreaptă îndepărtată sau dinspre marginea stângă îndepărtată"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Bara de activități este afișată"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Bară și baloane stânga afișate"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Bară &amp; baloane dreapta afișate"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Bara de activități este ascunsă"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Bară și baloane ascunse"</string>
     <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>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 69f560d..9700f16 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Функция \"Рекомендуемые приложения\" включена."</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Функция \"Рекомендуемые приложения\" отключена."</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Рекомендуемое приложение: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Руководство: навигация с помощью жестов"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Поверните устройство"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Чтобы перейти к руководству по жестам, нужно повернуть устройство."</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Проведите справа налево или слева направо от самого края экрана."</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 2b1f147..cd33d09 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"යෙදුම් යෝජනා සබලිතයි"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"යෙදුම් යෝජනා අබල කර ඇත"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"පුරෝකථනය කළ යෙදුම: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"අභින සංචාලන නිබන්ධනය"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"ඔබේ උපාංගය කරකවන්න"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"අභින සංචාලන නිබන්ධනය සම්පූර්ණ කිරීම සඳහා ඔබේ උපාංගය කරකවන්න"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ඔබ ඈත දකුණු හෝ ඈත වම් දාරයේ සිට ස්වයිප් කරන බව සහතික කර ගන්න"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index c2e6b85..7f44a23 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Návrhy aplikácií zapnuté"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Návrhy aplikácií vypnuté"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predpovedaná aplikácia: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Návod na navigáciu gestami"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Otočte zariadenie"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Otočte zariadenie a dokončite tak návod, ako navigovať gestami"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Musíte potiahnuť úplne z pravého alebo ľavého okraja."</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Panel aplikácií je zobrazený"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Panel aplik. a bubl. sú vľavo"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Panel aplik. a bubl. sú vpravo"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Panel aplikácií je skrytý"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Panel aplik. a bubl. sú skryté"</string>
     <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>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 0922f24..f504abc 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Predlogi aplikacij so omogočeni."</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Predlogi aplikacij so onemogočeni."</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Predvidena aplikacija: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Vadnica za krmarjenje s potezami"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zasukajte napravo"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Zasukajte napravo, če si želite ogledati vadnico za krmarjenje s potezami"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Pazite, da povlečete s skrajno desnega ali skrajno levega roba."</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Opravilna vrstica je prikazana"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Prikazani so opravilna vrstica in oblački na levi"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Prikazani so opravilna vrstica in oblački na desni"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Opravilna vrstica je skrita"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Opravilna vrstica in oblački so skriti"</string>
     <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>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 50b9fa1..36769cb 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Aplikacionet e sugjeruara janë aktivizuar"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Sugjerimet e aplikacioneve janë çaktivizuar"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Aplikacioni i parashikuar: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Udhëzuesi për navigimin me gjeste"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rrotullo pajisjen"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rrotullo pajisjen për të përfunduar udhëzuesin e navigimit me gjeste"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Sigurohu që të rrëshqasësh shpejt nga skaji më i djathtë ose më i majtë"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Shiriti i detyrave i shfaqur"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Shiriti i detyrave dhe flluskat majtas janë shfaqur"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Shiriti i detyrave dhe flluskat djathtas janë shfaqur"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Shiriti i detyrave i fshehur"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Shiriti i detyrave dhe flluskat janë fshehur"</string>
     <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>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index a20e927..0d89f74 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Предлози апликација су омогућени"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Предлози апликација су онемогућени"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Предвиђамо апликацију: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Водич за навигацију помоћу покрета"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Ротирајте уређај"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ротирајте уређај да бисте довршили водич за навигацију помоћу покрета"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Обавезно превуците од саме десне или леве ивице"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 7c826cd..9941818 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Appförslag har aktiverats"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Appförslag har inaktiverats"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Appförslag: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Guide för navigering med rörelser"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Rotera enheten"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Rotera enheten för att slutföra guiden för navigering med rörelser"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Se till att du sveper ända från högerkanten eller vänsterkanten"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Aktivitetsfältet visas"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Vänster fält och bubblor visas"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Höger fält och bubblor visas"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Aktivitetsfältet är dolt"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Fält och bubblor dolda"</string>
     <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>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 9181599..c7e5c30 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Mapendekezo ya programu yamewashwa"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Umezima mapendekezo ya programu"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Programu iliyotabiriwa: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Mafunzo ya Usogezaji kwa Kutumia Ishara"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zungusha kifaa chako"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Tafadhali zungusha kifaa chako ili ukamilishe mafunzo ya usogezaji kwa kutumia ishara"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Hakikisha unatelezesha kidole kutoka ukingo wa kulia au kushoto kabisa"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Upauzana umeonyeshwa"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Upauzana na viputo vinaonyeshwa kushoto"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Upauzana na viputo vinaonyeshwa kulia"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Upauzana umefichwa"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Upauzana na viputo vimefichwa"</string>
     <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>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 4e3a075..042679c 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ஆப்ஸ் பரிந்துரைகள் இயக்கப்பட்டுள்ளன"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ஆப்ஸ் பரிந்துரைகள் முடக்கப்பட்டுள்ளன"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"கணித்த ஆப்ஸ்: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"சைகை வழிசெலுத்தலுக்கான பயிற்சி"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"உங்கள் சாதனத்தைச் சுழற்றுங்கள்"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"சைகை வழிசெலுத்தல் பயிற்சியை நிறைவுசெய்ய உங்கள் சாதனத்தைச் சுழற்றுங்கள்"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"வலது அல்லது இடது ஓரத்தின் விளிம்பிலிருந்து ஸ்வைப் செய்வதை உறுதிசெய்துகொள்ளுங்கள்"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"செயல் பட்டி காட்டப்படுகிறது"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"செயல் பட்டி &amp; குமிழை இடதுபுறம் காட்டும்"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"செயல் பட்டி &amp; குமிழை வலதுபுறம் காட்டும்"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"செயல் பட்டி மறைக்கப்பட்டுள்ளது"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"செயல் பட்டி &amp; குமிழை மறைக்கும்"</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>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 94fac1b..081708c 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"యాప్ సలహాలు ఎనేబుల్ చేయబడ్డాయి"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"యాప్ సూచ‌న‌లు డిజేబుల్‌ చేయబడ్డాయి"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"సూచించబడిన యాప్: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"సంజ్ఞ నావిగేషన్ ట్యుటోరియల్"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"మీ పరికరాన్ని రొటేట్ చేయండి"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"సంజ్ఞ నావిగేషన్ ట్యుటోరియల్‌ను పూర్తి చేయడానికి దయచేసి మీ పరికరాన్ని రొటేట్ చేయండి"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"కుడి వైపు చిట్ట చివరి లేదా ఎడమ వైపు చిట్ట చివరి అంచు నుండి స్వైప్ చేస్తున్నారని నిర్ధారించుకోండి"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index ee515b9..61dfaa6 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"เปิดใช้แอปแนะนำแล้ว"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ปิดใช้คำแนะนำเกี่ยวกับแอปอยู่"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"แอปที่คาดว่าจะใช้: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"บทแนะนำการไปยังส่วนต่างๆ ด้วยท่าทางสัมผัส"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"หมุนอุปกรณ์ของคุณ"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"โปรดหมุนอุปกรณ์เพื่อทำตามบทแนะนำการนำทางด้วยท่าทางสัมผัสให้เสร็จสมบูรณ์"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"ปัดจากขอบด้านขวาสุดหรือซ้ายสุด"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index 1bc4a3d..8374628 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Naka-enable ang mga iminumungkahing app"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Naka-disable ang mga iminumungkahing app"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Hinulaang app: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Tutorial sa Navigation gamit ang Galaw"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"I-rotate ang iyong device"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Paki-rotate ang iyong device para tapusin ang tutorial sa navigation gamit ang galaw"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Tiyaking magsa-swipe ka mula sa dulong kanan o dulong kaliwang gilid"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ipinapakita ang taskbar"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Taskbar at bubble sa kaliwa"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Taskbar at bubble sa kanan"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Nakatago ang taskbar"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Nakatago ang taskbar at bubble"</string>
     <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>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 691e6c0..9a1bf54 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Uygulama önerileri etkinleştirildi"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Uygulama önerileri devre dışı bırakıldı"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Tahmin edilen uygulama: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Hareketle Gezinme Eğitimi"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Cihazınızı döndürün"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Hareketle gezinme eğitimini tamamlamak için lütfen cihazınızı döndürün"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"En sağ veya en sol kenardan kaydırdığınızdan emin olun"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Görev çubuğu gösteriliyor"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Görev çubuğu ve baloncuklar solda gösteriliyor"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Görev çubuğu ve baloncuklar sağda gösteriliyor"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Görev çubuğu gizlendi"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Görev çubuğu ve baloncuklar gizli"</string>
     <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>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 1668b4f..1036700 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Рекомендовані додатки ввімкнено"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Рекомендовані додатки вимкнено"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Передбачений додаток: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Посібник із навігації за допомогою жестів"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Оберніть пристрій"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Обертайте пристрій, щоб ознайомитися з посібником із навігації за допомогою жестів"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Проведіть пальцем від самого краю екрана (правого або лівого)"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 5b780c3..fde634f 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"ایپ کی تجاویز فعال ہیں"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"ایپ کی تجاویز غیر فعال ہیں"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"پیشن گوئی کردہ ایپ: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"اشاروں والی نیویگیشن ٹیوٹوریل"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"اپنا آلہ گھمائیں"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"براہ کرم اشاروں والی نیویگیشن کا ٹیوٹوریل مکمل کرنے کے لیے اپنا آلہ گھمائیں"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"یقینی بنائیں کہ آپ دائیں یا بائیں کنارے سے دور سے سوائپ کریں"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 7de3648..ab514b3 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Ilova tavsiyalari yoqildi"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Endi ilova takliflari chiqmaydi"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Taklif etilgan ilova: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Ishorali navigatsiya darsligi"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Qurilmangizni buring"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Ishorali navigatsiya darsligini tugatish uchun qurilmani buring"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Ekran chetidan boshlab oʻngdan yoki chapdan suring"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Vazifalar paneli ochiq"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Panel va bulutchalar chapda"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Panel va bulutchalar oʻngda"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Vazifalar paneli yopiq"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Panel va bulutchalar berk"</string>
     <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>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index dffcd6c..f35138b 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Đã bật tính năng Ứng dụng đề xuất"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Tính năng Ứng dụng đề xuất bị tắt"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Ứng dụng dự đoán: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Hướng dẫn thực hiện thao tác bằng cử chỉ"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Xoay thiết bị của bạn"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Vui lòng xoay thiết bị của bạn để hoàn tất hướng dẫn thao tác bằng cử chỉ"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Hãy vuốt từ mép ngoài cùng bên phải hoặc ngoài cùng bên trái"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Đã hiện thanh thao tác"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"Hiện thanh tác vụ, b.bóng trái"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"Hiện thanh tác vụ, b.bóng phải"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Đã ẩn thanh thao tác"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"Đã ẩn thanh tác vụ &amp; bong bóng"</string>
     <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>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 4d35d39..9665800 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"已启用应用建议"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"已停用应用建议"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"预测的应用:<xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"手势导航教程"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"请旋转设备"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"请旋转设备,完成手势导航教程"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"确保从最右侧或最左侧边缘开始滑动"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index fd11ba1..d65aba1 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"已啟用應用程式建議"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"已停用應用程式建議"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"預測應用程式:<xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"手勢導覽教學課程"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"旋轉裝置方向"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"請旋轉裝置方向以完成手勢導覽教學課程"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"請確保從螢幕最右側或最左側邊緣滑動"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 729f7fd..0b94911 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"應用程式建議功能已啟用"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"應用程式建議功能已停用"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"預測的應用程式:<xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"手勢操作教學課程"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"旋轉裝置螢幕方向"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"如要完成手勢操作教學課程,請旋轉裝置螢幕方向"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"請務必從螢幕最右側或最左側滑動"</string>
@@ -132,8 +131,6 @@
     <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>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 5209ac1..8ad0b94 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -46,8 +46,7 @@
     <string name="hotsaet_tip_prediction_enabled" msgid="2233554377501347650">"Iziphakamiso zohlelo lokusebenza zinikwe amandla"</string>
     <string name="hotsaet_tip_prediction_disabled" msgid="1506426298884658491">"Iziphakamiso zohlelo lokusebenza zikhutshaziwe"</string>
     <string name="hotseat_prediction_content_description" msgid="4582028296938078419">"Uhlelo lokusebenza olubikezelwe: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
-    <!-- no translation found for gesture_tutorial_title (2750751261768388354) -->
-    <skip />
+    <string name="gesture_tutorial_title" msgid="2750751261768388354">"Okokufundisa Kokuzulazula Kokuthinta"</string>
     <string name="gesture_tutorial_rotation_prompt_title" msgid="7537946781362766964">"Zungezisa idivayisi yakho"</string>
     <string name="gesture_tutorial_rotation_prompt" msgid="1664493449851960691">"Sicela uzungezise idivayisi yakho ukuze uqedele okokufundisa kokufuna ngokuthinta"</string>
     <string name="back_gesture_feedback_swipe_too_far_from_edge" msgid="4175100312909721217">"Qinisekisa ukuthi uswayipha ukusuka onqenqemeni olukude ngakwesokudla noma olukude ngakwesokunxele"</string>
@@ -132,8 +131,6 @@
     <string name="taskbar_a11y_shown_title" msgid="6842833581088937713">"Ibha yomsebenzi ibonisiwe"</string>
     <string name="taskbar_a11y_shown_with_bubbles_left_title" msgid="4242431789851790046">"ITaskbar namabhamuza aboniswe kwesokunxele"</string>
     <string name="taskbar_a11y_shown_with_bubbles_right_title" msgid="8219065376188180113">"ITaskbar namabhamuza aboniswe kwesokudla"</string>
-    <string name="taskbar_a11y_hidden_title" msgid="9154903639589659284">"Ibha yomsebenzi ifihliwe"</string>
-    <string name="taskbar_a11y_hidden_with_bubbles_title" msgid="7397395993149508087">"ITaskbar namabhamuza afihliwe"</string>
     <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>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index f38693d..4ba4e2b 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1567,8 +1567,7 @@
 
     private boolean isFreeformAnimation(RemoteAnimationTarget[] appTargets) {
         return DesktopModeStatus.canEnterDesktopMode(mLauncher.getApplicationContext())
-                && (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS.isTrue()
-                    || DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue())
+                && DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_EXIT_TRANSITIONS_BUGFIX.isTrue()
                 && Arrays.stream(appTargets)
                         .anyMatch(app -> app.taskInfo != null && app.taskInfo.isFreeform());
     }
@@ -1746,6 +1745,10 @@
             if (rectFSpringAnim != null && anim.getChildAnimations().isEmpty()) {
                 addCujInstrumentation(rectFSpringAnim, Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME);
             } else {
+                if (isFreeformAnimation(appTargets)) {
+                    addCujInstrumentation(anim,
+                            Cuj.CUJ_DESKTOP_MODE_EXIT_MODE_ON_LAST_WINDOW_CLOSE);
+                }
                 addCujInstrumentation(anim, playFallBackAnimation
                         ? Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME_FALLBACK
                         : Cuj.CUJ_LAUNCHER_APP_CLOSE_TO_HOME);
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
index 6cf9b9e..36c5fba 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopAppLaunchTransitionManager.kt
@@ -74,8 +74,7 @@
 
     private fun shouldRegisterTransitions(): Boolean =
         DesktopModeStatus.canEnterDesktopMode(context) &&
-            (DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS.isTrue ||
-                DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue)
+            DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue
 
     companion object {
         private fun buildAppLaunchFilter(): TransitionFilter {
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
index 010a5c8..40cfe92 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
@@ -60,7 +60,7 @@
                 callback,
             )
         val transition = RemoteTransition(animRunner, appThread, "RecentsToDesktop")
-        systemUiProxy.showDesktopApps(desktopTaskView.display.displayId, transition)
+        systemUiProxy.showDesktopApps(desktopTaskView.displayId, transition)
     }
 
     /** Launch desktop tasks from recents view */
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 289e720..2e48910 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -40,9 +40,10 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BACK_DISMISS_IME;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -133,7 +134,14 @@
     private static final int FLAG_IME_SWITCHER_BUTTON_VISIBLE = 1 << 0;
     /** Whether the IME is visible. */
     private static final int FLAG_IME_VISIBLE = 1 << 1;
-    private static final int FLAG_ROTATION_BUTTON_VISIBLE = 1 << 2;
+    /**
+     * The back button is visually adjusted to indicate that it will dismiss the IME when pressed.
+     * This only takes effect while the IME is visible. By default, it is set while the IME is
+     * visible, but may be overridden by the
+     * {@link android.inputmethodservice.InputMethodService.BackDispositionMode backDispositionMode}
+     * set by the IME.
+     */
+    private static final int FLAG_BACK_DISMISS_IME = 1 << 2;
     private static final int FLAG_A11Y_VISIBLE = 1 << 3;
     private static final int FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE = 1 << 4;
     private static final int FLAG_KEYGUARD_VISIBLE = 1 << 5;
@@ -275,13 +283,14 @@
     }
 
     protected void setupController() {
-        boolean isThreeButtonNav = mContext.isThreeButtonNav();
+        final boolean isThreeButtonNav = mContext.isThreeButtonNav();
+        final boolean isPhoneMode = mContext.isPhoneMode();
         DeviceProfile deviceProfile = mContext.getDeviceProfile();
         Resources resources = mContext.getResources();
 
         int setupSize = mControllers.taskbarActivityContext.getSetupWindowSize();
-        Point p = DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, resources,
-                mContext.isPhoneMode(), mContext.isGestureNav());
+        Point p = DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, resources, isPhoneMode,
+                mContext.isGestureNav());
         ViewGroup.LayoutParams navButtonsViewLayoutParams = mNavButtonsView.getLayoutParams();
         navButtonsViewLayoutParams.width = p.x;
         if (!mContext.isUserSetupComplete()) {
@@ -302,9 +311,10 @@
             mImeSwitcherButton = addButton(switcherResId, BUTTON_IME_SWITCH,
                     isThreeButtonNav ? mStartContextualContainer : mEndContextualContainer,
                     mControllers.navButtonController, R.id.ime_switcher);
+            // A11y and IME Switcher buttons overlap on phone mode, show only a11y if both visible.
             mPropertyHolders.add(new StatePropertyHolder(mImeSwitcherButton,
-                    flags -> ((flags & FLAG_IME_SWITCHER_BUTTON_VISIBLE) != 0)
-                            && ((flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)));
+                    flags -> (flags & FLAG_IME_SWITCHER_BUTTON_VISIBLE) != 0
+                            && !(isPhoneMode && (flags & FLAG_A11Y_VISIBLE) != 0)));
         }
 
         mPropertyHolders.add(new StatePropertyHolder(
@@ -318,7 +328,7 @@
                         .get(ALPHA_INDEX_SMALL_SCREEN),
                 flags -> (flags & FLAG_SMALL_SCREEN) == 0));
 
-        if (!mContext.isPhoneMode()) {
+        if (!isPhoneMode) {
             mPropertyHolders.add(new StatePropertyHolder(mControllers.taskbarDragLayerController
                     .getKeyguardBgTaskbar(), flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0));
         }
@@ -333,10 +343,10 @@
 
         // Make sure to remove nav bar buttons translation when any of the following occur:
         // - Notification shade is expanded
-        // - IME is showing (add separate translation for IME)
+        // - IME is visible (add separate translation for IME)
         // - VoiceInteractionWindow (assistant) is showing
         // - Keyboard shortcuts helper is showing
-        if (!mContext.isPhoneMode()) {
+        if (!isPhoneMode) {
             int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE
                     | FLAG_VOICE_INTERACTION_WINDOW_SHOWING | FLAG_KEYBOARD_SHORTCUT_HELPER_SHOWING;
             mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
@@ -364,9 +374,9 @@
             initButtons(mNavButtonContainer, mEndContextualContainer,
                     mControllers.navButtonController);
             updateButtonLayoutSpacing();
-            updateStateForFlag(FLAG_SMALL_SCREEN, mContext.isPhoneMode());
+            updateStateForFlag(FLAG_SMALL_SCREEN, isPhoneMode);
 
-            if (!mContext.isPhoneMode()) {
+            if (!isPhoneMode) {
                 mPropertyHolders.add(new StatePropertyHolder(
                         mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
                         flags -> (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
@@ -393,7 +403,7 @@
                 R.bool.floating_rotation_button_position_left);
         mControllers.rotationButtonController.setRotationButton(mFloatingRotationButton,
                 mRotationButtonListener);
-        if (mContext.isPhoneMode()) {
+        if (isPhoneMode) {
             mTaskbarTransitions.init();
         }
 
@@ -449,7 +459,7 @@
                     flags -> (flags & FLAG_IME_VISIBLE) == 0));
         }
         mPropertyHolders.add(new StatePropertyHolder(mBackButton,
-                flags -> (flags & FLAG_IME_VISIBLE) != 0,
+                flags -> (flags & FLAG_BACK_DISMISS_IME) != 0,
                 ROTATION_DRAWABLE_PERCENT, 1f, 0f));
         // Translate back button to be at end/start of other buttons for keyguard (only after SUW
         // since it is laid to align with SUW actions while in that state)
@@ -498,8 +508,7 @@
                 endContainer, navButtonController, R.id.accessibility_button,
                 R.layout.taskbar_contextual_button);
         mPropertyHolders.add(new StatePropertyHolder(mA11yButton,
-                flags -> (flags & FLAG_A11Y_VISIBLE) != 0
-                        && (flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0));
+                flags -> (flags & FLAG_A11Y_VISIBLE) != 0));
 
         mSpace = new Space(mNavButtonsView.getContext());
         mSpace.setOnClickListener(view -> navButtonController.onButtonClick(BUTTON_SPACE, view));
@@ -510,8 +519,9 @@
     private void parseSystemUiFlags(@SystemUiStateFlags long sysUiStateFlags) {
         mSysuiStateFlags = sysUiStateFlags;
         boolean isImeSwitcherButtonVisible =
-                (sysUiStateFlags & SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING) != 0;
-        boolean isImeVisible = (sysUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0;
+                (sysUiStateFlags & SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE) != 0;
+        boolean isImeVisible = (sysUiStateFlags & SYSUI_STATE_IME_VISIBLE) != 0;
+        boolean isBackDismissIme = (sysUiStateFlags & SYSUI_STATE_BACK_DISMISS_IME) != 0;
         boolean a11yVisible = (sysUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
         boolean isHomeDisabled = (sysUiStateFlags & SYSUI_STATE_HOME_DISABLED) != 0;
         boolean isRecentsDisabled = (sysUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0;
@@ -527,6 +537,7 @@
 
         updateStateForFlag(FLAG_IME_SWITCHER_BUTTON_VISIBLE, isImeSwitcherButtonVisible);
         updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible);
+        updateStateForFlag(FLAG_BACK_DISMISS_IME, isBackDismissIme);
         updateStateForFlag(FLAG_A11Y_VISIBLE, a11yVisible);
         updateStateForFlag(FLAG_DISABLE_HOME, isHomeDisabled);
         updateStateForFlag(FLAG_DISABLE_RECENTS, isRecentsDisabled);
@@ -1231,7 +1242,7 @@
         appendFlag(str, flags, FLAG_IME_SWITCHER_BUTTON_VISIBLE,
                 "FLAG_IME_SWITCHER_BUTTON_VISIBLE");
         appendFlag(str, flags, FLAG_IME_VISIBLE, "FLAG_IME_VISIBLE");
-        appendFlag(str, flags, FLAG_ROTATION_BUTTON_VISIBLE, "FLAG_ROTATION_BUTTON_VISIBLE");
+        appendFlag(str, flags, FLAG_BACK_DISMISS_IME, "FLAG_BACK_DISMISS_IME");
         appendFlag(str, flags, FLAG_A11Y_VISIBLE, "FLAG_A11Y_VISIBLE");
         appendFlag(str, flags, FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE,
                 "FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE");
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index e8a0c45..8a06b11 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -43,6 +43,7 @@
 import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING;
+import static com.android.window.flags.Flags.enableStartLaunchTransitionFromTaskbarBugfix;
 import static com.android.wm.shell.Flags.enableTinyTaskbar;
 
 import static java.lang.invoke.MethodHandles.Lookup.PROTECTED;
@@ -1513,9 +1514,7 @@
         BubbleTextView.RunningAppState runningAppState =
                 mControllers.taskbarRecentAppsController.getRunningAppState(taskId);
         return runningAppState == RunningAppState.MINIMIZED
-                && (DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS.isTrue()
-                    || DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS_BUGFIX.isTrue()
-                    );
+                && DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_ALTTAB_TRANSITIONS_BUGFIX.isTrue();
     }
 
     private RemoteTransition createDesktopAppLaunchRemoteTransition(
@@ -1689,7 +1688,11 @@
         }
         // There is no task associated with this launch - launch a new task through an intent
         ActivityOptionsWrapper opts = getActivityLaunchDesktopOptions();
-        mSysUiProxy.startLaunchIntentTransition(intent, opts.options.toBundle(), displayId);
+        if (enableStartLaunchTransitionFromTaskbarBugfix()) {
+            mSysUiProxy.startLaunchIntentTransition(intent, opts.options.toBundle(), displayId);
+        } else {
+            startActivity(intent, opts.options.toBundle());
+        }
     }
 
     /** Expands a folder icon when it is clicked */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index b46b0dc..17fb959 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -91,6 +91,7 @@
     private static final boolean DEBUG = false;
     // TODO(b/382378283) remove all logs with this tag
     public static final String NULL_TASKBAR_ROOT_LAYOUT_TAG = "b/382378283";
+    public static final String ILLEGAL_ARGUMENT_WM_ADD_VIEW = "b/391653300";
 
     /**
      * All the configurations which do not initiate taskbar recreation.
@@ -306,6 +307,7 @@
                 int configDiff = mOldConfig.diff(newConfig) & ~SKIP_RECREATE_CONFIG_CHANGES;
 
                 if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0) {
+                    Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW, "onConfigurationChanged: theme changed");
                     // Only recreate for theme changes, not other UI mode changes such as docking.
                     int oldUiNightMode = (mOldConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
                     int newUiNightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
@@ -360,6 +362,7 @@
     }
 
     private void destroyTaskbarForDisplay(int displayId) {
+        Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW, "destroyTaskbarForDisplay: " + displayId);
         TaskbarActivityContext taskbar = getTaskbarForDisplay(displayId);
         debugWhyTaskbarNotDestroyed("destroyTaskbarForDisplay: " + taskbar, displayId);
         if (taskbar != null) {
@@ -522,6 +525,7 @@
     private void recreateTaskbarForDisplay(int displayId) {
         Trace.beginSection("recreateTaskbar");
         try {
+            Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW, "recreateTaskbarForDisplay: " + displayId);
             // TODO: make this code display specific
             DeviceProfile dp = mUserUnlocked ?
                     LauncherAppState.getIDP(mWindowContext).getDeviceProfile(mWindowContext) : null;
@@ -711,9 +715,9 @@
 
     /**
      * Signal from SysUI indicating that a non-mirroring display was just connected to the
-     * primary device.
+     * primary device or a previously mirroring display is switched to extended mode.
      */
-    public void onDisplayReady(int displayId) {
+    public void onDisplayAddSystemDecorations(int displayId) {
     }
 
     /**
@@ -723,6 +727,11 @@
     public void onDisplayRemoved(int displayId) {
     }
 
+    /**
+     * Signal from SysUI indicating that system decorations should be removed from the display.
+     */
+    public void onDisplayRemoveSystemDecorations(int displayId) {}
+
     private void removeActivityCallbacksAndListeners() {
         if (mActivity != null) {
             mActivity.removeOnDeviceProfileChangeListener(mDebugActivityDeviceProfileChanged);
@@ -789,9 +798,15 @@
         }
 
         if (!isTaskbarRootLayoutAddedForDisplay(displayId)) {
-            mWindowManager.addView(getTaskbarRootLayoutForDisplay(displayId),
-                    taskbar.getWindowLayoutParams());
-            mAddedRootLayouts.put(displayId, true);
+            FrameLayout rootLayout = getTaskbarRootLayoutForDisplay(displayId);
+            if (rootLayout != null) {
+                mWindowManager.addView(getTaskbarRootLayoutForDisplay(displayId),
+                        taskbar.getWindowLayoutParams());
+                mAddedRootLayouts.put(displayId, true);
+            } else {
+                Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW,
+                        "addTaskbarRootViewToWindow - root layout null | displayId=" + displayId);
+            }
         } else {
             Log.d(NULL_TASKBAR_ROOT_LAYOUT_TAG,
                     "addTaskbarRootViewToWindow - root layout already added | displayId="
@@ -800,6 +815,7 @@
     }
 
     private void removeTaskbarRootViewFromWindow(int displayId) {
+        Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW, "removeTaskbarRootViewFromWindow: " + displayId);
         FrameLayout rootLayout = getTaskbarRootLayoutForDisplay(displayId);
         if (!enableTaskbarNoRecreate() || rootLayout == null) {
             return;
@@ -875,6 +891,7 @@
      * @param displayId The ID of the display for which to create the taskbar root layout.
      */
     private void createTaskbarRootLayout(int displayId) {
+        Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW, "createTaskbarRootLayout: " + displayId);
         FrameLayout newTaskbarRootLayout = new FrameLayout(mWindowContext) {
             @Override
             public boolean dispatchTouchEvent(MotionEvent ev) {
@@ -902,6 +919,7 @@
      * @return The taskbar root layout {@link FrameLayout} for a given display or {@code null}.
      */
     private FrameLayout getTaskbarRootLayoutForDisplay(int displayId) {
+        Log.d(ILLEGAL_ARGUMENT_WM_ADD_VIEW, "getTaskbarRootLayoutForDisplay: " + displayId);
         FrameLayout frameLayout = mRootLayouts.get(displayId);
         if (frameLayout != null) {
             return frameLayout;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index f905c5f..6815f97 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -25,7 +25,6 @@
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.IntSet;
@@ -39,9 +38,9 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Predicate;
 
 /**
@@ -114,15 +113,9 @@
         return modified;
     }
 
-
     @Override
-    public void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) {
-        updateWorkspaceItems(updated, mContext);
-    }
-
-    @Override
-    public void bindRestoreItemsChange(HashSet<ItemInfo> updates) {
-        updateRestoreItems(updates, mContext);
+    public void bindItemsUpdated(Set<ItemInfo> updates) {
+        updateContainerItems(updates, mContext);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 68114f1..1ca3dfb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -34,8 +34,7 @@
 import static com.android.quickstep.util.SystemUiFlagUtils.isTaskbarHidden;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DIALOG_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
 
@@ -260,9 +259,7 @@
     private @Nullable AnimatorSet mAnimator;
     private boolean mIsSystemGestureInProgress;
     /** Whether the IME is visible. */
-    private boolean mIsImeShowing;
-    /** Whether the IME Switcher button is visible. */
-    private boolean mIsImeSwitcherButtonShowing;
+    private boolean mIsImeVisible;
 
     private final Alarm mTimeoutAlarm = new Alarm();
     private boolean mEnableBlockingTimeoutDuringTests = false;
@@ -1122,7 +1119,7 @@
      */
     @VisibleForTesting
     long getTaskbarStashStartDelayForIme() {
-        if (mIsImeShowing) {
+        if (mIsImeVisible) {
             // Only delay when IME is exiting, not entering.
             return 0;
         }
@@ -1148,9 +1145,7 @@
         updateStateForFlag(FLAG_STASHED_DEVICE_LOCKED,
                 SystemUiFlagUtils.isLocked(systemUiStateFlags));
 
-        mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING);
-        mIsImeSwitcherButtonShowing =
-                hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING);
+        mIsImeVisible = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_VISIBLE);
         if (updateStateForFlag(FLAG_STASHED_IME, shouldStashForIme())) {
             animDuration = TASKBAR_STASH_DURATION_FOR_IME;
             startDelay = getTaskbarStashStartDelayForIme();
@@ -1166,7 +1161,7 @@
     }
 
     /**
-     * We stash when IME or IME switcher is showing.
+     * We stash when the IME is visible.
      *
      * <p>Do not stash if in small screen, with 3 button nav, and in landscape (or seascape).
      * <p>Do not stash if taskbar is transient.
@@ -1202,7 +1197,7 @@
             return false;
         }
 
-        return mIsImeShowing || mIsImeSwitcherButtonShowing;
+        return mIsImeVisible;
     }
 
     /**
@@ -1377,8 +1372,7 @@
         pw.println(prefix + "\tappliedState=" + getStateString(mStatePropertyHolder.mPrevFlags));
         pw.println(prefix + "\tmState=" + getStateString(mState));
         pw.println(prefix + "\tmIsSystemGestureInProgress=" + mIsSystemGestureInProgress);
-        pw.println(prefix + "\tmIsImeShowing=" + mIsImeShowing);
-        pw.println(prefix + "\tmIsImeSwitcherButtonShowing=" + mIsImeSwitcherButtonShowing);
+        pw.println(prefix + "\tmIsImeVisible=" + mIsImeVisible);
     }
 
     private static String getStateString(long flags) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index aff879e..4e029e3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -19,8 +19,7 @@
 
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
@@ -92,10 +91,9 @@
     private static final long MASK_HIDE_BUBBLE_BAR = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
-            | SYSUI_STATE_IME_SHOWING
+            | SYSUI_STATE_IME_VISIBLE
             | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
-            | SYSUI_STATE_QUICK_SETTINGS_EXPANDED
-            | SYSUI_STATE_IME_SWITCHER_BUTTON_SHOWING;
+            | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
 
     private static final long MASK_HIDE_HANDLE_VIEW = SYSUI_STATE_BOUNCER_SHOWING
             | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING
@@ -239,7 +237,7 @@
 
         boolean sysuiLocked = (flags & MASK_SYSUI_LOCKED) != 0;
         mBubbleStashController.setSysuiLocked(sysuiLocked);
-        mIsImeVisible = (flags & SYSUI_STATE_IME_SHOWING) != 0;
+        mIsImeVisible = (flags & SYSUI_STATE_IME_VISIBLE) != 0;
         if (mIsImeVisible) {
             mBubbleBarViewController.onImeVisible();
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index a44fde7..36a4865 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -214,7 +214,7 @@
         boolean animate = shouldAnimateIconChange(info);
         Drawable oldIcon = getIcon();
         int oldPlateColor = mPlateColor.currentColor;
-        applyFromWorkspaceItem(info, null);
+        applyFromWorkspaceItem(info);
 
         setContentDescription(
                 mIsPinned ? info.contentDescription :
diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
index 2e2d7cc..d097dba 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
+++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
@@ -192,4 +192,6 @@
 
     override fun getApplicationInfoHash(appInfo: ApplicationInfo): String =
         (appInfo.sourceDir?.hashCode() ?: 0).toString() + " " + appInfo.longVersionCode
+
+    override fun getRoundIconRes(appInfo: ApplicationInfo) = appInfo.roundIconRes
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 49a5ac5..cbfcda7 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -86,6 +86,8 @@
 import com.android.quickstep.util.WorkspaceRevealAnim;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
+import com.android.window.flags.Flags;
+import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 
 /**
  * Handles quick switching to a recent task from the home screen. To give as much flexibility to
@@ -184,6 +186,12 @@
             mIsTrackpadSwipe = isTrackpadFourFingerSwipe(ev);
             return mIsTrackpadSwipe;
         }
+        if (DesktopModeStatus.canEnterDesktopMode(mLauncher.getContext())
+                //TODO(b/345296916): replace with dev option once in teamfood
+                && Flags.enableQuickswitchDesktopSplitBugfix()
+                && mRecentsView.getNonDesktopTaskViewCount() < 1) {
+            return false;
+        }
         return true;
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index d673720..f582324 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -149,9 +149,9 @@
         mOverviewPanel.setFullscreenProgress(progress);
         if (progress > UPDATE_SYSUI_FLAGS_THRESHOLD) {
             int sysuiFlags = 0;
-            TaskView tv = mOverviewPanel.getFirstTaskView();
-            if (tv != null) {
-                sysuiFlags = tv.getTaskContainers().getFirst().getSysUiStatusNavFlags();
+            TaskView firstTaskView = mOverviewPanel.getFirstTaskView();
+            if (firstTaskView != null) {
+                sysuiFlags = firstTaskView.getSysUiStatusNavFlags();
             }
             mLauncher.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, sysuiFlags);
         } else {
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 8b76ce9..5f8b89a 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -120,6 +120,7 @@
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
+import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.statemanager.StatefulContainer;
 import com.android.launcher3.taskbar.TaskbarThresholdUtils;
@@ -932,7 +933,7 @@
             TaskView runningTask = mRecentsView.getRunningTaskView();
             TaskView centermostTask = mRecentsView.getTaskViewNearestToCenterOfScreen();
             int centermostTaskFlags = centermostTask == null ? 0
-                    : centermostTask.getTaskContainers().getFirst().getSysUiStatusNavFlags();
+                    : centermostTask.getSysUiStatusNavFlags();
             boolean swipeUpThresholdPassed = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
             boolean quickswitchThresholdPassed = centermostTask != runningTask;
 
@@ -955,7 +956,7 @@
 
     @Override
     public void onRecentsAnimationStart(RecentsAnimationController controller,
-            RecentsAnimationTargets targets, TransitionInfo transitionInfo) {
+            RecentsAnimationTargets targets, @Nullable TransitionInfo transitionInfo) {
         super.onRecentsAnimationStart(controller, targets, transitionInfo);
         if (targets.hasDesktopTasks(mContext)) {
             mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets, transitionInfo);
@@ -1527,8 +1528,9 @@
                 .withInputType(mGestureState.isTrackpadGesture()
                         ? SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TRACKPAD
                         : SysUiStatsLog.LAUNCHER_UICHANGED__INPUT_TYPE__TOUCH);
-        if (targetTask != null) {
-            logger.withItemInfo(targetTask.getFirstItemInfo());
+        ItemInfo itemInfo;
+        if (targetTask != null && (itemInfo = targetTask.getFirstItemInfo()) != null) {
+            logger.withItemInfo(itemInfo);
         }
 
         int pageIndex = endTarget == LAST_TASK || mRecentsView == null
@@ -2369,9 +2371,6 @@
                 ActiveGestureLog.CompoundString nextTaskLog =
                         ActiveGestureLog.CompoundString.newEmptyString();
                 for (TaskContainer container : nextTask.getTaskContainers()) {
-                    if (container == null) {
-                        continue;
-                    }
                     nextTaskLog.append("[id: %d, pkg: %s] | ",
                             container.getTask().key.id,
                             container.getTask().key.getPackageName());
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index c60d3e8..e1e9c99 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -56,6 +56,7 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.animation.TransitionAnimator;
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.InputConsumerController;
 
 import java.util.Collections;
@@ -300,7 +301,9 @@
             // Disable if swiping to PIP
             return null;
         }
-        if (sourceTaskView == null || sourceTaskView.getFirstTask().key.getComponent() == null) {
+        Task firstTask;
+        if (sourceTaskView == null || ((firstTask = sourceTaskView.getFirstTask()) == null)
+                || firstTask.key.getComponent() == null) {
             // Disable if it's an invalid task
             return null;
         }
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
index 6ad9a2c..94d115b 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt
@@ -375,7 +375,7 @@
                 override fun onRecentsAnimationStart(
                     controller: RecentsAnimationController,
                     targets: RecentsAnimationTargets,
-                    transitionInfo: TransitionInfo,
+                    transitionInfo: TransitionInfo?,
                 ) {
                     Log.d(TAG, "recents animation started: $command")
                     if (recentsInWindowFlagSet) {
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 01ced75..bb72408 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -18,6 +18,7 @@
 
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 
+import static com.android.launcher3.Flags.enableSeparateExternalDisplayTasks;
 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.GroupedTaskInfo.TYPE_FREEFORM;
@@ -47,12 +48,18 @@
 import com.android.wm.shell.shared.GroupedTaskInfo;
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
 
+import kotlin.collections.ArraysKt;
+import kotlin.collections.CollectionsKt;
+import kotlin.collections.MapsKt;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -350,10 +357,9 @@
                 // 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 (DesktopModeStatus.canEnterDesktopMode(mContext)) {
-                    GroupTask desktopTask = createDesktopTask(rawTask.getBaseGroupedTask());
-                    if (desktopTask != null) {
-                        allTasks.add(desktopTask);
-                    }
+                    List<DesktopTask> desktopTasks = createDesktopTasks(
+                            rawTask.getBaseGroupedTask());
+                    allTasks.addAll(desktopTasks);
                 }
                 continue;
             }
@@ -421,20 +427,35 @@
         return allTasks;
     }
 
-    private @Nullable DesktopTask createDesktopTask(GroupedTaskInfo recentTaskInfo) {
-        ArrayList<Task> tasks = new ArrayList<>(recentTaskInfo.getTaskInfoList().size());
-        int[] minimizedTaskIds = recentTaskInfo.getMinimizedTaskIds();
-        for (TaskInfo taskInfo : recentTaskInfo.getTaskInfoList()) {
-            Task.TaskKey key = new Task.TaskKey(taskInfo);
-            Task task = Task.from(key, taskInfo, false);
-            task.positionInParent = taskInfo.positionInParent;
-            task.appBounds = taskInfo.configuration.windowConfiguration.getAppBounds();
-            task.isVisible = taskInfo.isVisible;
-            task.isMinimized =
-                    Arrays.stream(minimizedTaskIds).anyMatch(taskId -> taskId == taskInfo.taskId);
-            tasks.add(task);
+    private Task createTask(TaskInfo taskInfo, Set<Integer> minimizedTaskIds) {
+        Task.TaskKey key = new Task.TaskKey(taskInfo);
+        Task task = Task.from(key, taskInfo, false);
+        task.positionInParent = taskInfo.positionInParent;
+        task.appBounds = taskInfo.configuration.windowConfiguration.getAppBounds();
+        task.isVisible = taskInfo.isVisible;
+        task.isMinimized = minimizedTaskIds.contains(taskInfo.taskId);
+        return task;
+    }
+
+    private List<DesktopTask> createDesktopTasks(GroupedTaskInfo recentTaskInfo) {
+        int[] minimizedTaskIdArray = recentTaskInfo.getMinimizedTaskIds();
+        Set<Integer> minimizedTaskIds = minimizedTaskIdArray != null
+                ? CollectionsKt.toSet(ArraysKt.asIterable(minimizedTaskIdArray))
+                : Collections.emptySet();
+        if (enableSeparateExternalDisplayTasks()) {
+            Map<Integer, List<Task>> perDisplayTasks = new HashMap<>();
+            for (TaskInfo taskInfo : recentTaskInfo.getTaskInfoList()) {
+                Task task = createTask(taskInfo, minimizedTaskIds);
+                List<Task> tasks = perDisplayTasks.computeIfAbsent(taskInfo.displayId,
+                        k -> new ArrayList<>());
+                tasks.add(task);
+            }
+            return MapsKt.map(perDisplayTasks, it -> new DesktopTask(it.getValue()));
+        } else {
+            List<Task> tasks = CollectionsKt.map(recentTaskInfo.getTaskInfoList(),
+                    it -> createTask(it, minimizedTaskIds));
+            return List.of(new DesktopTask(tasks));
         }
-        return new DesktopTask(tasks);
     }
 
     public void dump(String prefix, PrintWriter writer) {
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 87bf81c..c6b858b 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -22,6 +22,7 @@
 
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
+import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.util.ArraySet;
@@ -103,7 +104,7 @@
             RemoteAnimationTarget[] appTargets,
             RemoteAnimationTarget[] wallpaperTargets,
             Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras,
-            TransitionInfo transitionInfo) {
+            @Nullable TransitionInfo transitionInfo) {
         long appCount = Arrays.stream(appTargets)
                 .filter(app -> app.mode == MODE_CLOSING)
                 .count();
@@ -207,7 +208,7 @@
      */
     public interface RecentsAnimationListener {
         default void onRecentsAnimationStart(RecentsAnimationController controller,
-                RecentsAnimationTargets targets, TransitionInfo transitionInfo) {}
+                RecentsAnimationTargets targets, @Nullable TransitionInfo transitionInfo) {}
 
         /**
          * Callback from the system when the recents animation is canceled. {@param thumbnailData}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 0c89a80..e1e962a 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -37,7 +37,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_MAGNIFICATION_OVERLAP;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
@@ -586,7 +586,7 @@
     /** Returns whether IME is rendering nav buttons, and IME is currently showing. */
     public boolean isImeRenderingNavButtons() {
         return mCanImeRenderGesturalNavButtons && mMode == NO_BUTTON
-                && ((mSystemUiStateFlags & SYSUI_STATE_IME_SHOWING) != 0);
+                && ((mSystemUiStateFlags & SYSUI_STATE_IME_VISIBLE) != 0);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index ef63b9b..f96bbcb 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -217,7 +217,7 @@
      * transform params per app in {@code targets.apps} list.
      */
     public RemoteTargetHandle[] assignTargetsForDesktop(
-            RemoteAnimationTargets targets, TransitionInfo transitionInfo) {
+            RemoteAnimationTargets targets, @Nullable TransitionInfo transitionInfo) {
         resizeRemoteTargetHandles(targets);
 
         for (int i = 0; i < mRemoteTargetHandles.length; i++) {
diff --git a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
index 5264643..d2a491d 100644
--- a/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/SimpleOrientationTouchTransformer.java
@@ -22,35 +22,35 @@
 import android.content.Context;
 import android.view.MotionEvent;
 
+import com.android.launcher3.dagger.ApplicationContext;
+import com.android.launcher3.dagger.LauncherAppSingleton;
+import com.android.launcher3.util.DaggerSingletonObject;
+import com.android.launcher3.util.DaggerSingletonTracker;
 import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.MainThreadInitializedObject;
-import com.android.launcher3.util.SafeCloseable;
+import com.android.quickstep.dagger.QuickstepBaseAppComponent;
 
+import javax.inject.Inject;
+
+@LauncherAppSingleton
 public class SimpleOrientationTouchTransformer implements
-        DisplayController.DisplayInfoChangeListener, SafeCloseable {
+        DisplayController.DisplayInfoChangeListener {
 
-    public static final MainThreadInitializedObject<SimpleOrientationTouchTransformer> INSTANCE =
-            new MainThreadInitializedObject<>(SimpleOrientationTouchTransformer::new);
+    public static final DaggerSingletonObject<SimpleOrientationTouchTransformer> INSTANCE =
+            new DaggerSingletonObject<>(
+                    QuickstepBaseAppComponent::getSimpleOrientationTouchTransformer);
 
-    private final Context mContext;
     private OrientationRectF mOrientationRectF;
     private OrientationRectF mTouchingOrientationRectF;
     private int mViewRotation;
 
-    public SimpleOrientationTouchTransformer(Context context) {
-        this(context, DisplayController.INSTANCE.get(context));
-    }
-
-    @androidx.annotation.VisibleForTesting
-    public SimpleOrientationTouchTransformer(Context context, DisplayController displayController) {
-        mContext = context;
+    @Inject
+    public SimpleOrientationTouchTransformer(@ApplicationContext Context context,
+            DisplayController displayController,
+            DaggerSingletonTracker tracker) {
         displayController.addChangeListener(this);
-        onDisplayInfoChanged(context, displayController.getInfo(), CHANGE_ALL);
-    }
+        tracker.addCloseable(() -> displayController.removeChangeListener(this));
 
-    @Override
-    public void close() {
-        DisplayController.INSTANCE.get(mContext).removeChangeListener(this);
+        onDisplayInfoChanged(context, displayController.getInfo(), CHANGE_ALL);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.kt b/quickstep/src/com/android/quickstep/SystemUiProxy.kt
index 87953c7..d5382ad 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.kt
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.kt
@@ -126,7 +126,7 @@
     private val systemUiProxyDeathRecipient =
         IBinder.DeathRecipient { Executors.MAIN_EXECUTOR.execute { clearProxy() } }
 
-    // Save the listeners passed into the proxy since OverviewProxyService may not have been bound
+    // Save the listeners passed into the proxy since LauncherProxyService may not have been bound
     // yet, and we'll need to set/register these listeners with SysUI when they do.  Note that it is
     // up to the caller to clear the listeners to prevent leaks as these can be held indefinitely
     // in case SysUI needs to rebind.
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 1fd7211..63b8aaf 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -156,7 +156,7 @@
         mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() {
             @Override
             public void onRecentsAnimationStart(RecentsAnimationController controller,
-                    RecentsAnimationTargets targets, TransitionInfo transitionInfo) {
+                    RecentsAnimationTargets targets, @Nullable TransitionInfo transitionInfo) {
                 if (enableHandleDelayedGestureCallbacks() && mRecentsAnimationStartPending) {
                     ActiveGestureProtoLogProxy.logStartRecentsAnimationCallback(
                             "onRecentsAnimationStart");
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index ff9c9f6..0772159 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -233,7 +233,7 @@
             RecentsView overviewPanel = mTaskContainer.getTaskView().getRecentsView();
             // Task has already been dismissed
             if (overviewPanel == null) return;
-            overviewPanel.initiateSplitSelect(mTaskContainer.getTaskView());
+            overviewPanel.initiateSplitSelect(mTaskContainer);
         }
 
         protected void saveAppPair() {
@@ -369,7 +369,7 @@
 
             @Override
             public void onClick(View view) {
-                saveScreenshot(mTaskContainer.getTaskView().getFirstTask());
+                saveScreenshot(mTaskContainer.getTask());
                 dismissTaskMenuView();
             }
         }
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index ab5e830..ee1d8a6 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -48,6 +48,7 @@
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.popup.SystemShortcut.AppInfo;
 import com.android.launcher3.util.InstantAppResolver;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
@@ -128,20 +129,28 @@
     };
 
     class SplitSelectSystemShortcut extends SystemShortcut {
-        private final TaskView mTaskView;
+        private final TaskContainer mTaskContainer;
         private final SplitPositionOption mSplitPositionOption;
 
-        public SplitSelectSystemShortcut(RecentsViewContainer container, TaskView taskView,
+        public SplitSelectSystemShortcut(RecentsViewContainer container,
+                TaskContainer taskContainer, TaskView taskView,
                 SplitPositionOption option) {
             super(option.iconResId, option.textResId, container, taskView.getFirstItemInfo(),
                     taskView);
-            mTaskView = taskView;
+            mTaskContainer = taskContainer;
             mSplitPositionOption = option;
         }
 
         @Override
         public void onClick(View view) {
-            mTaskView.initiateSplitSelect(mSplitPositionOption);
+            RecentsView recentsView = mTaskContainer.getTaskView().getRecentsView();
+            if (recentsView != null) {
+                recentsView.initiateSplitSelect(
+                        mTaskContainer,
+                        mSplitPositionOption.stagePosition,
+                        SplitConfigurationOptions.getLogEventForPosition(
+                                mSplitPositionOption.stagePosition));
+            }
         }
     }
 
@@ -152,7 +161,6 @@
     class SaveAppPairSystemShortcut extends SystemShortcut<RecentsViewContainer> {
         private final GroupedTaskView mTaskView;
 
-
         public SaveAppPairSystemShortcut(RecentsViewContainer container, GroupedTaskView taskView,
             int iconResId) {
             super(iconResId, R.string.save_app_pair, container, taskView.getFirstItemInfo(),
@@ -202,14 +210,14 @@
         }
 
         private void startActivity() {
-            final Task.TaskKey taskKey = mTaskView.getFirstTask().key;
-            final int taskId = taskKey.id;
             final ActivityOptions options = makeLaunchOptions(mTarget);
-            if (options != null) {
-                options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+            if (options == null) {
+                return;
             }
-            if (options != null
-                    && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
+            final Task.TaskKey taskKey = mTaskContainer.getTask().key;
+            final int taskId = taskKey.id;
+            options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+            if (ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId,
                     options)) {
                 final Runnable animStartedListener = () -> {
                     // Hide the task view and wait for the window to be resized
@@ -252,8 +260,8 @@
                 overridePendingAppTransitionMultiThumbFuture(
                         future, animStartedListener, mHandler, true /* scaleUp */,
                         taskKey.displayId);
-                mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getFirstItemInfo())
-                        .log(mLauncherEvent);
+                mTarget.getStatsLogManager().logger().withItemInfo(mTaskContainer.getItemInfo())
+                            .log(mLauncherEvent);
             }
         }
 
@@ -327,7 +335,8 @@
             return orientationHandler.getSplitPositionOptions(deviceProfile)
                     .stream()
                     .map((Function<SplitPositionOption, SystemShortcut>) option ->
-                            new SplitSelectSystemShortcut(container, taskView, option))
+                            new SplitSelectSystemShortcut(container, taskContainer, taskView,
+                                    option))
                     .collect(Collectors.toList());
         }
     };
@@ -420,24 +429,24 @@
 
         private static final String TAG = "PinSystemShortcut";
 
-        private final TaskView mTaskView;
+        private final TaskContainer mTaskContainer;
 
         public PinSystemShortcut(RecentsViewContainer target,
                 TaskContainer taskContainer) {
             super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
                     taskContainer.getItemInfo(), taskContainer.getTaskView());
-            mTaskView = taskContainer.getTaskView();
+            mTaskContainer = taskContainer;
         }
 
         @Override
         public void onClick(View view) {
-            if (mTaskView.launchAsStaticTile() != null) {
+            if (mTaskContainer.getTaskView().launchAsStaticTile() != null) {
                 SystemUiProxy.INSTANCE.get(mTarget.asContext()).startScreenPinning(
-                        mTaskView.getFirstTask().key.id);
+                        mTaskContainer.getTask().key.id);
             }
             dismissTaskMenuView();
-            mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getFirstItemInfo())
-                    .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
+            mTarget.getStatsLogManager().logger().withItemInfo(mTaskContainer.getItemInfo())
+                        .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 3133907..e47223b 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -123,8 +123,9 @@
             int userId = itemInfo.user.getIdentifier();
             if (componentName != null) {
                 for (TaskView taskView : recentsView.getTaskViews()) {
-                    if (recentsView.isTaskViewVisible(taskView)) {
-                        Task.TaskKey key = taskView.getFirstTask().key;
+                    Task firstTask = taskView.getFirstTask();
+                    if (firstTask != null && recentsView.isTaskViewVisible(taskView)) {
+                        Task.TaskKey key = firstTask.key;
                         if (componentName.equals(key.getComponent()) && userId == key.userId) {
                             return taskView;
                         }
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 15f320d..51e59ff 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -100,7 +100,7 @@
 import com.android.quickstep.util.ContextualSearchInvoker;
 import com.android.quickstep.util.ContextualSearchStateManager;
 import com.android.quickstep.views.RecentsViewContainer;
-import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.recents.ILauncherProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.statusbar.phone.BarTransitions;
 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
@@ -141,9 +141,9 @@
     private final TISBinder mTISBinder = new TISBinder(this);
 
     /**
-     * Local IOverviewProxy implementation with some methods for local components
+     * Local ILauncherProxy implementation with some methods for local components
      */
-    public static class TISBinder extends IOverviewProxy.Stub {
+    public static class TISBinder extends ILauncherProxy.Stub {
 
         private final WeakReference<TouchInteractionService> mTis;
 
@@ -301,10 +301,10 @@
 
         @BinderThread
         @Override
-        public void onDisplayReady(int displayId) {
+        public void onDisplayAddSystemDecorations(int displayId) {
             MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(
-                    tis -> executeForTaskbarManager(
-                            taskbarManager -> taskbarManager.onDisplayReady(displayId))));
+                    tis -> executeForTaskbarManager(taskbarManager ->
+                            taskbarManager.onDisplayAddSystemDecorations(displayId))));
         }
 
         @BinderThread
@@ -317,6 +317,17 @@
 
         @BinderThread
         @Override
+        public void onDisplayRemoveSystemDecorations(int displayId) {
+            // TODO(b/391786915): Replace all
+            // `executeForTouchInteractionService(executeForTaskbarManager())` with just
+            // `executeForTaskbarManager` directly (since `tis` is unused).
+            MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(
+                    tis -> executeForTaskbarManager(taskbarManager -> taskbarManager
+                            .onDisplayRemoveSystemDecorations(displayId))));
+        }
+
+        @BinderThread
+        @Override
         public void updateWallpaperVisibility(int displayId, boolean visible) {
             MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(
                     tis -> executeForTaskbarManager(
@@ -412,7 +423,7 @@
                 try {
                     reply.sendResult(null);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "onUnbind: Failed to reply to OverviewProxyService", e);
+                    Log.w(TAG, "onUnbind: Failed to reply to LauncherProxyService", e);
                 }
             });
         }
diff --git a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
index fe25f32..adc45ae 100644
--- a/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
+++ b/quickstep/src/com/android/quickstep/dagger/QuickstepBaseAppComponent.java
@@ -23,9 +23,11 @@
 import com.android.quickstep.OverviewComponentObserver;
 import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.RotationTouchHelper;
+import com.android.quickstep.SimpleOrientationTouchTransformer;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TopTaskTracker;
 import com.android.quickstep.fallback.window.RecentsDisplayModel;
+import com.android.quickstep.logging.SettingsChangeLogger;
 import com.android.quickstep.util.AsyncClockEventDelegate;
 import com.android.quickstep.util.ContextualSearchStateManager;
 
@@ -58,4 +60,9 @@
     ContextualSearchStateManager getContextualSearchStateManager();
 
     RecentsAnimationDeviceState getRecentsAnimationDeviceState();
+
+    SettingsChangeLogger getSettingsChangeLogger();
+
+    SimpleOrientationTouchTransformer getSimpleOrientationTouchTransformer();
+
 }
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index fff7e9b..8d010e2 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -52,6 +52,7 @@
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.RecentsViewContainer;
+import com.android.quickstep.views.TaskContainer;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 
@@ -239,10 +240,10 @@
     }
 
     @Override
-    public void initiateSplitSelect(TaskView taskView,
+    public void initiateSplitSelect(TaskContainer taskContainer,
             @SplitConfigurationOptions.StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
-        super.initiateSplitSelect(taskView, stagePosition, splitEvent);
+        super.initiateSplitSelect(taskContainer, stagePosition, splitEvent);
         mContainer.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
     }
 
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
index cda6c1b..3082dc6 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowManager.kt
@@ -41,9 +41,11 @@
 import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory
 import com.android.launcher3.statemanager.StatefulContainer
 import com.android.launcher3.taskbar.TaskbarUIController
+import com.android.launcher3.testing.TestLogging
 import com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORDINAL
 import com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_SPLIT_SELECT_ORDINAL
 import com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL
+import com.android.launcher3.testing.shared.TestProtocol.SEQUENCE_MAIN
 import com.android.launcher3.util.ContextTracker
 import com.android.launcher3.util.DisplayController
 import com.android.launcher3.util.RunnableList
@@ -237,6 +239,7 @@
     private val onBackInvokedCallback: () -> Unit = {
         // If we are in live tile mode, launch the live task, otherwise return home
         recentsView?.runningTaskView?.launchWithAnimation() ?: startHome()
+        TestLogging.recordEvent(SEQUENCE_MAIN, "onBackInvoked")
     }
 
     private fun cleanupRecentsWindow() {
diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
index 973fb2f..5adc960 100644
--- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java
@@ -125,7 +125,7 @@
 
     @Override
     public void onRecentsAnimationStart(RecentsAnimationController controller,
-            RecentsAnimationTargets targets, TransitionInfo transitionInfo) {
+            RecentsAnimationTargets targets, @Nullable TransitionInfo transitionInfo) {
         super.onRecentsAnimationStart(controller, targets, transitionInfo);
         initTransformParams();
     }
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 946ca2a..0cc349d 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -44,16 +44,18 @@
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.dagger.ApplicationContext;
+import com.android.launcher3.dagger.LauncherAppSingleton;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.model.DeviceGridState;
+import com.android.launcher3.util.DaggerSingletonObject;
+import com.android.launcher3.util.DaggerSingletonTracker;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.Info;
-import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.NavigationMode;
-import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.SettingsCache;
+import com.android.quickstep.dagger.QuickstepBaseAppComponent;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -61,18 +63,20 @@
 import java.io.IOException;
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 /**
  * Utility class to log launcher settings changes
  */
+@LauncherAppSingleton
 public class SettingsChangeLogger implements
-        DisplayController.DisplayInfoChangeListener, OnSharedPreferenceChangeListener,
-        SafeCloseable {
+        DisplayController.DisplayInfoChangeListener, OnSharedPreferenceChangeListener {
 
     /**
      * Singleton instance
      */
-    public static MainThreadInitializedObject<SettingsChangeLogger> INSTANCE =
-            new MainThreadInitializedObject<>(SettingsChangeLogger::new);
+    public static DaggerSingletonObject<SettingsChangeLogger> INSTANCE =
+            new DaggerSingletonObject<>(QuickstepBaseAppComponent::getSettingsChangeLogger);
 
     private static final String TAG = "SettingsChangeLogger";
     private static final String BOOLEAN_PREF = "SwitchPreference";
@@ -85,26 +89,43 @@
     private StatsLogManager.LauncherEvent mNotificationDotsEvent;
     private StatsLogManager.LauncherEvent mHomeScreenSuggestionEvent;
 
-    SettingsChangeLogger(@ApplicationContext Context context) {
-        this(context, StatsLogManager.newInstance(context));
+    private final SettingsCache.OnChangeListener mListener = this::onNotificationDotsChanged;
+
+    @Inject
+    SettingsChangeLogger(@ApplicationContext Context context,
+            DaggerSingletonTracker tracker,
+            DisplayController displayController,
+            SettingsCache settingsCache) {
+        this(context, StatsLogManager.newInstance(context), tracker, displayController,
+                settingsCache);
     }
 
     @VisibleForTesting
-    SettingsChangeLogger(Context context, StatsLogManager statsLogManager) {
+    SettingsChangeLogger(@ApplicationContext Context context,
+            StatsLogManager statsLogManager,
+            DaggerSingletonTracker tracker,
+            DisplayController displayController,
+            SettingsCache settingsCache) {
         mContext = context;
         mStatsLogManager = statsLogManager;
         mLoggablePrefs = loadPrefKeys(context);
 
-        DisplayController.INSTANCE.get(context).addChangeListener(this);
-        mNavMode = DisplayController.getNavigationMode(context);
+        displayController.addChangeListener(this);
+        mNavMode = displayController.getInfo().getNavigationMode();
+        tracker.addCloseable(() -> displayController.removeChangeListener(this));
 
         getPrefs(context).registerOnSharedPreferenceChangeListener(this);
         getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this);
+        tracker.addCloseable(() -> {
+            getPrefs(mContext).unregisterOnSharedPreferenceChangeListener(this);
+            getDevicePrefs(mContext).unregisterOnSharedPreferenceChangeListener(this);
+        });
 
-        SettingsCache settingsCache = SettingsCache.INSTANCE.get(context);
-        settingsCache.register(NOTIFICATION_BADGING_URI,
-                this::onNotificationDotsChanged);
+        settingsCache.register(NOTIFICATION_BADGING_URI, mListener);
         onNotificationDotsChanged(settingsCache.getValue(NOTIFICATION_BADGING_URI));
+        tracker.addCloseable(() -> {
+            settingsCache.unregister(NOTIFICATION_BADGING_URI, mListener);
+        });
     }
 
     private static ArrayMap<String, LoggablePref> loadPrefKeys(Context context) {
@@ -207,12 +228,6 @@
         return mLoggablePrefs;
     }
 
-    @Override
-    public void close() {
-        getPrefs(mContext).unregisterOnSharedPreferenceChangeListener(this);
-        getDevicePrefs(mContext).unregisterOnSharedPreferenceChangeListener(this);
-    }
-
     @VisibleForTesting
     static class LoggablePref {
         public boolean defaultValue;
diff --git a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
index 2f95413..002a4e8 100644
--- a/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
+++ b/quickstep/src/com/android/quickstep/recents/data/TasksRepository.kt
@@ -17,7 +17,6 @@
 package com.android.quickstep.recents.data
 
 import android.graphics.drawable.Drawable
-import android.graphics.drawable.ShapeDrawable
 import android.util.Log
 import com.android.launcher3.util.coroutines.DispatcherProvider
 import com.android.quickstep.recents.data.TaskVisualsChangedDelegate.TaskIconChangedCallback
@@ -52,37 +51,29 @@
     override fun getAllTaskData(forceRefresh: Boolean): Flow<List<Task>> {
         if (forceRefresh) {
             recentsModel.getTasks { newTaskList ->
-                val oldTaskMap = tasks.value
                 val recentTasks =
                     newTaskList
                         .flatMap { groupTask -> groupTask.tasks }
                         .associateBy { it.key.id }
                         .also { newTaskMap ->
                             // Clean tasks that are not in the latest group tasks list.
-                            val tasksNoLongerVisible = oldTaskMap.keys.subtract(newTaskMap.keys)
+                            val tasksNoLongerVisible = tasks.value.keys.subtract(newTaskMap.keys)
                             removeTasks(tasksNoLongerVisible)
-
-                            // Use pre-loaded thumbnail data and icon from the previous list.
-                            // This reduces the Thumbnail loading time in the Overview and prevent
-                            // empty thumbnail and icon.
-                            val cache =
-                                taskRequests.keys
-                                    .mapNotNull { key ->
-                                        val task = oldTaskMap[key] ?: return@mapNotNull null
-                                        key to Pair(task.thumbnail, task.icon)
-                                    }
-                                    .toMap()
-
-                            newTaskMap.values.forEach { task ->
-                                task.thumbnail = task.thumbnail ?: cache[task.key.id]?.first
-                                task.icon = task.icon ?: cache[task.key.id]?.second
-                            }
                         }
-                tasks.value = MapForStateFlow(recentTasks)
                 Log.d(
                     TAG,
-                    "getAllTaskData: oldTasks ${oldTaskMap.keys}, newTasks: ${recentTasks.keys}",
+                    "getAllTaskData: oldTasks ${tasks.value.keys}, newTasks: ${recentTasks.keys}",
                 )
+                tasks.value = MapForStateFlow(recentTasks)
+
+                // Request data for completed tasks to prevent stale data.
+                // This will prevent thumbnail and icon from being replaced and
+                // null due to race condition.
+                taskRequests.values.forEach { (taskKey, job) ->
+                    if (job.isCompleted) {
+                        requestTaskData(taskKey.id)
+                    }
+                }
             }
         }
         return tasks.map { it.values.toList() }
@@ -202,13 +193,11 @@
     private suspend fun getIconFromDataSource(task: Task) =
         withContext(dispatcherProvider.background) {
             val iconCacheEntry = taskIconDataSource.getIcon(task)
-            val icon = iconCacheEntry.icon.constantState?.newDrawable()?.mutate() ?: EMPTY_DRAWABLE
-            IconData(icon, iconCacheEntry.contentDescription, iconCacheEntry.title)
+            IconData(iconCacheEntry.icon, iconCacheEntry.contentDescription, iconCacheEntry.title)
         }
 
     companion object {
         private const val TAG = "TasksRepository"
-        private val EMPTY_DRAWABLE = ShapeDrawable()
     }
 
     /** Helper class to support StateFlow emissions when using a Map with a MutableStateFlow. */
diff --git a/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt b/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
index 358537c..02f48e6 100644
--- a/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
+++ b/quickstep/src/com/android/quickstep/recents/di/RecentsDependencies.kt
@@ -26,9 +26,10 @@
 import com.android.quickstep.recents.data.TaskVisualsChangedDelegate
 import com.android.quickstep.recents.data.TaskVisualsChangedDelegateImpl
 import com.android.quickstep.recents.data.TasksRepository
+import com.android.quickstep.recents.domain.usecase.GetSysUiStatusNavFlagsUseCase
+import com.android.quickstep.recents.domain.usecase.GetTaskUseCase
 import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
 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.SplashAlphaUseCase
 import com.android.quickstep.task.thumbnail.TaskThumbnailViewData
@@ -177,12 +178,8 @@
                 TaskThumbnailViewData::class.java -> TaskThumbnailViewData()
                 TaskThumbnailViewModel::class.java ->
                     TaskThumbnailViewModelImpl(
-                        recentsViewData = inject(),
-                        taskContainerData = inject(scopeId),
                         dispatcherProvider = inject(),
                         getThumbnailPositionUseCase = inject(),
-                        tasksRepository = inject(),
-                        deviceProfileRepository = inject(),
                         splashAlphaUseCase = inject(scopeId),
                     )
                 TaskOverlayViewModel::class.java -> {
@@ -195,9 +192,9 @@
                         dispatcherProvider = inject(),
                     )
                 }
+                GetTaskUseCase::class.java -> GetTaskUseCase(repository = inject())
                 GetThumbnailUseCase::class.java -> GetThumbnailUseCase(taskRepository = inject())
-                SysUiStatusNavFlagsUseCase::class.java ->
-                    SysUiStatusNavFlagsUseCase(taskRepository = inject())
+                GetSysUiStatusNavFlagsUseCase::class.java -> GetSysUiStatusNavFlagsUseCase()
                 GetThumbnailPositionUseCase::class.java ->
                     GetThumbnailPositionUseCase(
                         deviceProfileRepository = inject(),
diff --git a/quickstep/src/com/android/quickstep/recents/domain/model/TaskModel.kt b/quickstep/src/com/android/quickstep/recents/domain/model/TaskModel.kt
index 3823100..bf29b1d 100644
--- a/quickstep/src/com/android/quickstep/recents/domain/model/TaskModel.kt
+++ b/quickstep/src/com/android/quickstep/recents/domain/model/TaskModel.kt
@@ -38,7 +38,7 @@
  */
 data class TaskModel(
     val id: TaskId,
-    val title: String,
+    val title: String?,
     val titleDescription: String?,
     val icon: Drawable?,
     val thumbnail: ThumbnailData?,
diff --git a/quickstep/src/com/android/quickstep/recents/domain/usecase/GetSysUiStatusNavFlagsUseCase.kt b/quickstep/src/com/android/quickstep/recents/domain/usecase/GetSysUiStatusNavFlagsUseCase.kt
new file mode 100644
index 0000000..da0e2d1
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/domain/usecase/GetSysUiStatusNavFlagsUseCase.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2025 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.domain.usecase
+
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
+import com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV
+import com.android.launcher3.util.SystemUiController.FLAG_DARK_STATUS
+import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_NAV
+import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_STATUS
+import com.android.systemui.shared.recents.model.ThumbnailData
+
+/** UseCase to calculate flags for status bar and navigation bar */
+class GetSysUiStatusNavFlagsUseCase {
+    operator fun invoke(thumbnailData: ThumbnailData?): Int {
+        if (thumbnailData == null) return 0
+        val thumbnailAppearance = thumbnailData.appearance
+        var flags = 0
+        flags =
+            flags or
+                if (thumbnailAppearance and APPEARANCE_LIGHT_STATUS_BARS != 0) FLAG_LIGHT_STATUS
+                else FLAG_DARK_STATUS
+        flags =
+            flags or
+                if (thumbnailAppearance and APPEARANCE_LIGHT_NAVIGATION_BARS != 0) FLAG_LIGHT_NAV
+                else FLAG_DARK_NAV
+        return flags
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/recents/ui/mapper/TaskUiStateMapper.kt b/quickstep/src/com/android/quickstep/recents/ui/mapper/TaskUiStateMapper.kt
new file mode 100644
index 0000000..fb62268
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/recents/ui/mapper/TaskUiStateMapper.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2025 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.ui.mapper
+
+import com.android.quickstep.recents.ui.viewmodel.TaskData
+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.ThumbnailHeader
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
+
+object TaskUiStateMapper {
+
+    /**
+     * Converts a [TaskData] object into a [TaskThumbnailUiState] for display in the UI.
+     *
+     * This function handles different types of [TaskData] and determines the appropriate UI state
+     * based on the data and provided flags.
+     *
+     * @param taskData The [TaskData] to convert. Can be null or a specific subclass.
+     * @param isLiveTile A flag indicating whether the task data represents live tile.
+     * @param hasHeader A flag indicating whether the UI should display a header.
+     * @return A [TaskThumbnailUiState] representing the UI state for the given task data.
+     */
+    fun toTaskThumbnailUiState(
+        taskData: TaskData?,
+        isLiveTile: Boolean,
+        hasHeader: Boolean,
+    ): TaskThumbnailUiState =
+        when {
+            taskData !is TaskData.Data -> Uninitialized
+            isLiveTile -> createLiveTileState(taskData, hasHeader)
+            isBackgroundOnly(taskData) -> BackgroundOnly(taskData.backgroundColor)
+            isSnapshotSplash(taskData) ->
+                SnapshotSplash(createSnapshotState(taskData, hasHeader), taskData.icon)
+            else -> Uninitialized
+        }
+
+    private fun createSnapshotState(taskData: TaskData.Data, hasHeader: Boolean): Snapshot =
+        if (canHeaderBeCreated(taskData, hasHeader)) {
+            Snapshot.WithHeader(
+                taskData.thumbnailData?.thumbnail!!,
+                taskData.thumbnailData.rotation,
+                taskData.backgroundColor,
+                ThumbnailHeader(taskData.icon!!, taskData.titleDescription!!),
+            )
+        } else {
+            Snapshot.WithoutHeader(
+                taskData.thumbnailData?.thumbnail!!,
+                taskData.thumbnailData.rotation,
+                taskData.backgroundColor,
+            )
+        }
+
+    private fun isBackgroundOnly(taskData: TaskData.Data) =
+        taskData.isLocked || taskData.thumbnailData == null
+
+    private fun isSnapshotSplash(taskData: TaskData.Data) =
+        taskData.thumbnailData?.thumbnail != null && !taskData.isLocked
+
+    private fun canHeaderBeCreated(taskData: TaskData.Data, hasHeader: Boolean) =
+        hasHeader && taskData.icon != null && taskData.titleDescription != null
+
+    private fun createLiveTileState(taskData: TaskData.Data, hasHeader: Boolean) =
+        if (canHeaderBeCreated(taskData, hasHeader)) {
+            // TODO(http://b/353965691): figure out what to do when `icon` or `titleDescription` is
+            //  null.
+            LiveTile.WithHeader(ThumbnailHeader(taskData.icon!!, taskData.titleDescription!!))
+        } else LiveTile.WithoutHeader
+}
diff --git a/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskTileUiState.kt b/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskTileUiState.kt
index 5f98479..118a931 100644
--- a/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskTileUiState.kt
+++ b/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskTileUiState.kt
@@ -29,29 +29,39 @@
  * @property tasks The list of [TaskTileUiState] objects representing the individual tasks.
  * @property isLiveTile Indicates whether this data is intended for a live tile. If `true`, the
  *   running app will be displayed instead of the thumbnail.
+ * @property sysUiStatusNavFlags Flags for status bar and navigation bar
  */
-data class TaskTileUiState(val tasks: List<TaskData>, val isLiveTile: Boolean)
+data class TaskTileUiState(
+    val tasks: List<TaskData>,
+    val isLiveTile: Boolean,
+    val hasHeader: Boolean,
+    val sysUiStatusNavFlags: Int,
+)
 
-sealed interface TaskData {
+sealed class TaskData {
+    abstract val taskId: Int
+
     /** When no data was found for the TaskId provided */
-    data class NoData(val taskId: Int) : TaskData
+    data class NoData(override val taskId: Int) : TaskData()
 
     /**
      * This class provides UI information related to a Task (App) to be displayed within a TaskView.
      *
      * @property taskId Identifier of the task
      * @property title App title
+     * @property titleDescription App content description
      * @property icon App icon
      * @property thumbnailData Information related to the last snapshot retrieved from the app
      * @property backgroundColor The background color of the task.
      * @property isLocked Indicates whether the task is locked or not.
      */
     data class Data(
-        val taskId: Int,
-        val title: String,
+        override val taskId: Int,
+        val title: String?,
+        val titleDescription: String?,
         val icon: Drawable?,
         val thumbnailData: ThumbnailData?,
         val backgroundColor: Int,
         val isLocked: Boolean,
-    ) : TaskData
+    ) : TaskData()
 }
diff --git a/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt b/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt
index 2e51a8a..4936e30 100644
--- a/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt
+++ b/quickstep/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModel.kt
@@ -16,12 +16,16 @@
 
 package com.android.quickstep.recents.ui.viewmodel
 
+import android.annotation.ColorInt
 import android.util.Log
+import androidx.core.graphics.ColorUtils
 import com.android.launcher3.util.coroutines.DispatcherProvider
 import com.android.quickstep.recents.domain.model.TaskId
 import com.android.quickstep.recents.domain.model.TaskModel
+import com.android.quickstep.recents.domain.usecase.GetSysUiStatusNavFlagsUseCase
 import com.android.quickstep.recents.domain.usecase.GetTaskUseCase
 import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.views.TaskViewType
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -37,8 +41,10 @@
  */
 @OptIn(ExperimentalCoroutinesApi::class)
 class TaskViewModel(
+    private val taskViewType: TaskViewType,
     recentsViewData: RecentsViewData,
     private val getTaskUseCase: GetTaskUseCase,
+    private val getSysUiStatusNavFlagsUseCase: GetSysUiStatusNavFlagsUseCase,
     dispatcherProvider: DispatcherProvider,
 ) {
     private var taskIds = MutableStateFlow(emptySet<Int>())
@@ -53,16 +59,20 @@
             }
             .distinctUntilChanged()
 
+    private val taskData =
+        taskIds.flatMapLatest { ids ->
+            // Combine Tasks requests
+            combine(
+                ids.map { id -> getTaskUseCase(id).map { taskModel -> id to taskModel } },
+                ::mapToTaskData,
+            )
+        }
+
+    val tintAmount: Flow<Float> = recentsViewData.tintAmount
+
     val state: Flow<TaskTileUiState> =
-        taskIds
-            .flatMapLatest { ids ->
-                // Combine Tasks requests
-                combine(
-                    ids.map { id -> getTaskUseCase(id).map { taskModel -> id to taskModel } },
-                    ::mapToUiState,
-                )
-            }
-            .combine(isLiveTile) { tasks, isLiveTile -> TaskTileUiState(tasks, isLiveTile) }
+        combine(taskData, isLiveTile) { tasks, isLiveTile -> mapToTaskTile(tasks, isLiveTile) }
+            .distinctUntilChanged()
             .flowOn(dispatcherProvider.background)
 
     fun bind(vararg taskId: TaskId) {
@@ -70,21 +80,34 @@
         taskIds.value = taskId.toSet()
     }
 
-    private fun mapToUiState(result: Array<Pair<TaskId, TaskModel?>>): List<TaskData> =
-        result.map { mapToUiState(it.first, it.second) }
+    private fun mapToTaskTile(tasks: List<TaskData>, isLiveTile: Boolean): TaskTileUiState {
+        val firstThumbnailData = (tasks.firstOrNull() as? TaskData.Data)?.thumbnailData
+        return TaskTileUiState(
+            tasks = tasks,
+            isLiveTile = isLiveTile,
+            hasHeader = taskViewType == TaskViewType.DESKTOP,
+            sysUiStatusNavFlags = getSysUiStatusNavFlagsUseCase(firstThumbnailData),
+        )
+    }
 
-    private fun mapToUiState(taskId: TaskId, result: TaskModel?): TaskData =
+    private fun mapToTaskData(result: Array<Pair<TaskId, TaskModel?>>): List<TaskData> =
+        result.map { mapToTaskData(it.first, it.second) }
+
+    private fun mapToTaskData(taskId: TaskId, result: TaskModel?): TaskData =
         result?.let {
             TaskData.Data(
                 taskId = taskId,
                 title = result.title,
+                titleDescription = result.titleDescription,
                 icon = result.icon,
                 thumbnailData = result.thumbnail,
-                backgroundColor = result.backgroundColor,
+                backgroundColor = result.backgroundColor.removeAlpha(),
                 isLocked = result.isLocked,
             )
         } ?: TaskData.NoData(taskId)
 
+    @ColorInt private fun Int.removeAlpha(): Int = ColorUtils.setAlphaComponent(this, 0xff)
+
     private companion object {
         const val TAG = "TaskViewModel"
     }
diff --git a/quickstep/src/com/android/quickstep/recents/usecase/SysUiStatusNavFlagsUseCase.kt b/quickstep/src/com/android/quickstep/recents/usecase/SysUiStatusNavFlagsUseCase.kt
deleted file mode 100644
index 5be5f4a..0000000
--- a/quickstep/src/com/android/quickstep/recents/usecase/SysUiStatusNavFlagsUseCase.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.usecase
-
-import android.view.WindowInsetsController
-import com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV
-import com.android.launcher3.util.SystemUiController.FLAG_DARK_STATUS
-import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_NAV
-import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_STATUS
-import com.android.quickstep.recents.data.RecentTasksRepository
-
-/** UseCase to calculate flags for status bar and navigation bar */
-class SysUiStatusNavFlagsUseCase(private val taskRepository: RecentTasksRepository) {
-    fun getSysUiStatusNavFlags(taskId: Int): Int {
-        val thumbnailData = taskRepository.getCurrentThumbnailById(taskId) ?: return 0
-
-        val thumbnailAppearance = thumbnailData.appearance
-        var flags = 0
-        flags =
-            flags or
-                if (
-                    thumbnailAppearance and WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS != 0
-                )
-                    FLAG_LIGHT_STATUS
-                else FLAG_DARK_STATUS
-        flags =
-            flags or
-                if (
-                    thumbnailAppearance and
-                        WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS != 0
-                )
-                    FLAG_LIGHT_NAV
-                else FLAG_DARK_NAV
-        return flags
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt b/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt
index 168c1e0..723df55 100644
--- a/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt
+++ b/quickstep/src/com/android/quickstep/recents/viewmodel/TaskContainerViewModel.kt
@@ -16,23 +16,11 @@
 
 package com.android.quickstep.recents.viewmodel
 
-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 splashAlphaUseCase: SplashAlphaUseCase,
-) {
-    fun getThumbnail(taskId: Int): Bitmap? = getThumbnailUseCase.run(taskId)
-
-    fun getSysUiStatusNavFlags(taskId: Int) =
-        sysUiStatusNavFlagsUseCase.getSysUiStatusNavFlags(taskId)
-
+class TaskContainerViewModel(private val splashAlphaUseCase: SplashAlphaUseCase) {
     fun shouldShowThumbnailSplash(taskId: Int): Boolean =
         (runBlocking { splashAlphaUseCase.execute(taskId).firstOrNull() } ?: 0f) > 0f
 }
diff --git a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
index 02baa39..34b0206 100644
--- a/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
+++ b/quickstep/src/com/android/quickstep/task/thumbnail/TaskThumbnailView.kt
@@ -20,6 +20,7 @@
 import android.graphics.Color
 import android.graphics.Outline
 import android.graphics.Rect
+import android.graphics.drawable.ShapeDrawable
 import android.util.AttributeSet
 import android.util.Log
 import android.view.LayoutInflater
@@ -29,7 +30,9 @@
 import androidx.annotation.ColorInt
 import androidx.core.view.isInvisible
 import com.android.launcher3.Flags.enableDesktopExplodedView
+import com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA
 import com.android.launcher3.R
+import com.android.launcher3.util.MultiPropertyFactory
 import com.android.launcher3.util.ViewPool
 import com.android.launcher3.util.coroutines.DispatcherProvider
 import com.android.quickstep.recents.di.RecentsDependencies
@@ -70,11 +73,13 @@
     private val thumbnailView: FixedSizeImageView by lazy { findViewById(R.id.task_thumbnail) }
     private val splashBackground: View by lazy { findViewById(R.id.splash_background) }
     private val splashIcon: FixedSizeImageView by lazy { findViewById(R.id.splash_icon) }
+    private val dimAlpha: MultiPropertyFactory<View> by lazy {
+        MultiPropertyFactory(scrimView, VIEW_ALPHA, ScrimViewAlpha.entries.size, ::maxOf)
+    }
 
     private var taskThumbnailViewHeader: TaskThumbnailViewHeader? = null
 
     private var uiState: TaskThumbnailUiState = Uninitialized
-
     private val bounds = Rect()
 
     var cornerRadius: Float = 0f
@@ -108,26 +113,6 @@
         viewData = RecentsDependencies.get(this)
         updateViewDataValues()
         viewModel = RecentsDependencies.get(this)
-        viewModel.uiState
-            .dropWhile { it == Uninitialized }
-            .flowOn(dispatcherProvider.background)
-            .onEach { viewModelUiState ->
-                Log.d(TAG, "viewModelUiState changed from: $uiState to: $viewModelUiState")
-                uiState = viewModelUiState
-                resetViews()
-                when (viewModelUiState) {
-                    is Uninitialized -> {}
-                    is LiveTile -> drawLiveWindow(viewModelUiState)
-                    is SnapshotSplash -> drawSnapshotSplash(viewModelUiState)
-                    is BackgroundOnly -> drawBackground(viewModelUiState.backgroundColor)
-                }
-            }
-            .launchIn(viewAttachedScope)
-        viewModel.dimProgress
-            .dropWhile { it == 0f }
-            .flowOn(dispatcherProvider.background)
-            .onEach { dimProgress -> scrimView.alpha = dimProgress }
-            .launchIn(viewAttachedScope)
         viewModel.splashAlpha
             .dropWhile { it == 0f }
             .flowOn(dispatcherProvider.background)
@@ -166,6 +151,27 @@
         }
     }
 
+    fun setState(state: TaskThumbnailUiState) {
+        Log.d(TAG, "viewModelUiState changed from: $uiState to: $state")
+        if (uiState == state) return
+        uiState = state
+        resetViews()
+        when (state) {
+            is Uninitialized -> {}
+            is LiveTile -> drawLiveWindow(state)
+            is SnapshotSplash -> drawSnapshotSplash(state)
+            is BackgroundOnly -> drawBackground(state.backgroundColor)
+        }
+    }
+
+    fun updateTintAmount(tintAmount: Float) {
+        dimAlpha[ScrimViewAlpha.TintAmount.ordinal].value = tintAmount
+    }
+
+    fun updateMenuOpenProgress(progress: Float) {
+        dimAlpha[ScrimViewAlpha.MenuProgress.ordinal].value = progress * MAX_SCRIM_ALPHA
+    }
+
     private fun updateViewDataValues() {
         viewData.width.value = width
         viewData.height.value = height
@@ -219,7 +225,8 @@
         drawSnapshot(snapshotSplash.snapshot)
 
         splashBackground.setBackgroundColor(snapshotSplash.snapshot.backgroundColor)
-        splashIcon.setImageDrawable(snapshotSplash.splash)
+        val icon = snapshotSplash.splash?.constantState?.newDrawable()?.mutate() ?: ShapeDrawable()
+        splashIcon.setImageDrawable(icon)
     }
 
     private fun drawSnapshot(snapshot: Snapshot) {
@@ -238,10 +245,6 @@
         thumbnailView.imageMatrix = viewModel.getThumbnailPositionState(width, height, isLayoutRtl)
     }
 
-    private companion object {
-        const val TAG = "TaskThumbnailView"
-    }
-
     private fun maybeCreateHeader() {
         if (enableDesktopExplodedView() && taskThumbnailViewHeader == null) {
             taskThumbnailViewHeader =
@@ -251,4 +254,14 @@
             addView(taskThumbnailViewHeader)
         }
     }
+
+    private companion object {
+        const val TAG = "TaskThumbnailView"
+        private const val MAX_SCRIM_ALPHA = 0.4f
+
+        enum class ScrimViewAlpha {
+            MenuProgress,
+            TintAmount,
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt
index 5f2de94..279ce39 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskContainerData.kt
@@ -19,7 +19,5 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 
 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 a048a1d..c89bf01 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModel.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModel.kt
@@ -17,20 +17,13 @@
 package com.android.quickstep.task.viewmodel
 
 import android.graphics.Matrix
-import com.android.quickstep.task.thumbnail.TaskThumbnailUiState
 import kotlinx.coroutines.flow.Flow
 
 /** ViewModel for representing TaskThumbnails */
 interface TaskThumbnailViewModel {
-    /** Provides the level of dimming that the View should have */
-    val dimProgress: Flow<Float>
-
     /** Provides the alpha of the splash icon */
     val splashAlpha: Flow<Float>
 
-    /** Provides the UiState by which the task thumbnail can be represented */
-    val uiState: Flow<TaskThumbnailUiState>
-
     /** Attaches this ViewModel to a specific task id for it to provide data from. */
     fun bind(taskId: Int)
 
diff --git a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt
index a154c3c..635d08b 100644
--- a/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt
+++ b/quickstep/src/com/android/quickstep/task/viewmodel/TaskThumbnailViewModelImpl.kt
@@ -16,100 +16,34 @@
 
 package com.android.quickstep.task.viewmodel
 
-import android.annotation.ColorInt
 import android.app.ActivityTaskManager.INVALID_TASK_ID
-import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
 import android.graphics.Matrix
 import android.util.Log
-import androidx.core.graphics.ColorUtils
-import com.android.launcher3.Flags.enableDesktopExplodedView
 import com.android.launcher3.util.coroutines.DispatcherProvider
-import com.android.quickstep.recents.data.RecentTasksRepository
-import com.android.quickstep.recents.data.RecentsDeviceProfileRepository
 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.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.ThumbnailHeader
-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
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.flow.map
 
 @OptIn(ExperimentalCoroutinesApi::class)
 class TaskThumbnailViewModelImpl(
-    recentsViewData: RecentsViewData,
-    taskContainerData: TaskContainerData,
     dispatcherProvider: DispatcherProvider,
-    private val tasksRepository: RecentTasksRepository,
-    private val deviceProfileRepository: RecentsDeviceProfileRepository,
     private val getThumbnailPositionUseCase: GetThumbnailPositionUseCase,
     private val splashAlphaUseCase: SplashAlphaUseCase,
 ) : TaskThumbnailViewModel {
-    private val task = MutableStateFlow<Flow<Task?>>(flowOf(null))
     private val splashProgress = MutableStateFlow(flowOf(0f))
     private var taskId: Int = INVALID_TASK_ID
 
-    override val dimProgress: Flow<Float> =
-        combine(taskContainerData.taskMenuOpenProgress, recentsViewData.tintAmount) {
-                taskMenuOpenProgress,
-                tintAmount ->
-                max(taskMenuOpenProgress * MAX_SCRIM_ALPHA, tintAmount)
-            }
-            .flowOn(dispatcherProvider.background)
-
     override val splashAlpha =
         splashProgress.flatMapLatest { it }.flowOn(dispatcherProvider.background)
 
-    private val isLiveTile =
-        combine(
-                task.flatMapLatest { it }.map { it?.key?.id }.distinctUntilChanged(),
-                recentsViewData.runningTaskIds,
-                recentsViewData.runningTaskShowScreenshot,
-            ) { taskId, runningTaskIds, runningTaskShowScreenshot ->
-                runningTaskIds.contains(taskId) && !runningTaskShowScreenshot
-            }
-            .distinctUntilChanged()
-
-    override val uiState: Flow<TaskThumbnailUiState> =
-        combine(task.flatMapLatest { it }, isLiveTile) { taskVal, isRunning ->
-                // TODO(b/369339561) This log is firing a lot. Reduce emissions from TasksRepository
-                //  then re-enable this log.
-                //                Log.d(
-                //                    TAG,
-                //                    "Received task and / or live tile update. taskVal: $taskVal"
-                //                    + " isRunning: $isRunning.",
-                //                )
-                when {
-                    taskVal == null -> Uninitialized
-                    isRunning -> createLiveTileState(taskVal)
-                    isBackgroundOnly(taskVal) ->
-                        BackgroundOnly(taskVal.colorBackground.removeAlpha())
-                    isSnapshotSplashState(taskVal) ->
-                        SnapshotSplash(createSnapshotState(taskVal), taskVal.icon)
-                    else -> Uninitialized
-                }
-            }
-            .distinctUntilChanged()
-            .flowOn(dispatcherProvider.background)
-
     override fun bind(taskId: Int) {
         Log.d(TAG, "bind taskId: $taskId")
         this.taskId = taskId
-        task.value = tasksRepository.getTaskDataById(taskId)
         splashProgress.value = splashAlphaUseCase.execute(taskId)
     }
 
@@ -122,64 +56,7 @@
             is ThumbnailPositionState.MissingThumbnail -> Matrix.IDENTITY_MATRIX
         }
 
-    private fun isBackgroundOnly(task: Task): Boolean = task.isLocked || task.thumbnail == null
-
-    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!!
-        var thumbnailHeader = maybeCreateHeader(task)
-        return if (thumbnailHeader != null)
-            Snapshot.WithHeader(
-                bitmap,
-                thumbnailData.rotation,
-                task.colorBackground.removeAlpha(),
-                thumbnailHeader,
-            )
-        else
-            Snapshot.WithoutHeader(
-                bitmap,
-                thumbnailData.rotation,
-                task.colorBackground.removeAlpha(),
-            )
-    }
-
-    private fun shouldHaveThumbnailHeader(task: Task): Boolean {
-        return deviceProfileRepository.getRecentsDeviceProfile().canEnterDesktopMode &&
-            enableDesktopExplodedView() &&
-            task.key.windowingMode == WINDOWING_MODE_FREEFORM
-    }
-
-    private fun maybeCreateHeader(task: Task): ThumbnailHeader? {
-        // Header is only needed when this task is a desktop task and Overivew exploded view is
-        // enabled.
-        if (!shouldHaveThumbnailHeader(task)) {
-            return null
-        }
-
-        // TODO(http://b/353965691): figure out what to do when `icon` or `titleDescription` is
-        // null.
-        val icon = task.icon ?: return null
-        val titleDescription = task.titleDescription ?: return null
-        return ThumbnailHeader(icon, titleDescription)
-    }
-
-    private fun createLiveTileState(task: Task): LiveTile {
-        val thumbnailHeader = maybeCreateHeader(task)
-        return if (thumbnailHeader != null) LiveTile.WithHeader(thumbnailHeader)
-        else LiveTile.WithoutHeader
-    }
-
-    @ColorInt private fun Int.removeAlpha(): Int = ColorUtils.setAlphaComponent(this, 0xff)
-
     private companion object {
-        const val MAX_SCRIM_ALPHA = 0.4f
         const val TAG = "TaskThumbnailViewModel"
     }
 }
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index 6b8650f..f20d7a5 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -128,26 +128,25 @@
                             & ItemInfoWithIcon.FLAG_NOT_PINNABLE) != 0));
         if (!taskView.containsMultipleTasks()
                 || hasUnpinnableApp
-                || !(taskView instanceof GroupedTaskView)) {
+                || !(taskView instanceof GroupedTaskView groupedTaskView)) {
             return false;
         }
 
-        GroupedTaskView gtv = (GroupedTaskView) taskView;
-        List<TaskContainer> containers = gtv.getTaskContainers();
-        ComponentKey taskKey1 = TaskUtils.getLaunchComponentKeyForTask(
-                containers.get(0).getTask().key);
-        ComponentKey taskKey2 = TaskUtils.getLaunchComponentKeyForTask(
-                containers.get(1).getTask().key);
-        AppInfo app1 = resolveAppInfoByComponent(taskKey1);
-        AppInfo app2 = resolveAppInfoByComponent(taskKey2);
+        ComponentKey leftTopComponentKey = TaskUtils.getLaunchComponentKeyForTask(
+                groupedTaskView.getLeftTopTaskContainer().getTask().key);
+        ComponentKey rightBottomComponentKey = TaskUtils.getLaunchComponentKeyForTask(
+                groupedTaskView.getRightBottomTaskContainer().getTask().key);
+        AppInfo leftTopAppInfo = resolveAppInfoByComponent(leftTopComponentKey);
+        AppInfo rightBottomAppInfo = resolveAppInfoByComponent(rightBottomComponentKey);
 
-        if (app1 == null || app2 == null) {
+        if (leftTopAppInfo == null || rightBottomAppInfo == null) {
             // Disallow saving app pairs for apps that don't have a front-door in Launcher
             return false;
         }
 
-        if (PackageManagerHelper.isSameAppForMultiInstance(app1, app2)) {
-            if (!app1.supportsMultiInstance() || !app2.supportsMultiInstance()) {
+        if (PackageManagerHelper.isSameAppForMultiInstance(leftTopAppInfo, rightBottomAppInfo)) {
+            if (!leftTopAppInfo.supportsMultiInstance()
+                    || !rightBottomAppInfo.supportsMultiInstance()) {
                 return false;
             }
         }
@@ -183,9 +182,8 @@
             return;
         }
 
-        List<TaskContainer> containers = gtv.getTaskContainers();
         List<TaskViewItemInfo> recentsInfos =
-                containers.stream().map(TaskContainer::getItemInfo).toList();
+                gtv.getTaskContainers().stream().map(TaskContainer::getItemInfo).toList();
         List<WorkspaceItemInfo> apps =
                 recentsInfos.stream().map(this::resolveAppPairWorkspaceInfo).toList();
 
diff --git a/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt b/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt
new file mode 100644
index 0000000..e1a8578
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/ExternalDisplays.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util
+
+import android.view.Display.DEFAULT_DISPLAY
+import com.android.systemui.shared.recents.model.Task
+
+/** Whether this displayId belongs to an external display */
+val Int.isExternalDisplay
+    get() = this != DEFAULT_DISPLAY
+
+/** Returns displayId of this [Task], default to [DEFAULT_DISPLAY] */
+val Task?.displayId
+    get() = this?.key?.displayId ?: DEFAULT_DISPLAY
+
+/** Returns if this task belongs tto [DEFAULT_DISPLAY] */
+val Task?.isExternalDisplay
+    get() = displayId.isExternalDisplay
diff --git a/quickstep/src/com/android/quickstep/views/AddDesktopButton.kt b/quickstep/src/com/android/quickstep/views/AddDesktopButton.kt
index 1dab18a..e353160 100644
--- a/quickstep/src/com/android/quickstep/views/AddDesktopButton.kt
+++ b/quickstep/src/com/android/quickstep/views/AddDesktopButton.kt
@@ -21,7 +21,9 @@
 import android.graphics.drawable.shapes.RoundRectShape
 import android.util.AttributeSet
 import android.widget.ImageButton
+import com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X
 import com.android.launcher3.R
+import com.android.launcher3.util.MultiPropertyFactory
 
 /**
  * Button for supporting multiple desktop sessions. The button will be next to the first TaskView
@@ -30,6 +32,29 @@
 class AddDesktopButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
     ImageButton(context, attrs) {
 
+    private enum class TranslationX {
+        GRID,
+        OFFSET,
+    }
+
+    private val multiTranslationX =
+        MultiPropertyFactory(this, VIEW_TRANSLATE_X, TranslationX.entries.size) { a: Float, b: Float
+            ->
+            a + b
+        }
+
+    var gridTranslationX
+        get() = multiTranslationX[TranslationX.GRID.ordinal].value
+        set(value) {
+            multiTranslationX[TranslationX.GRID.ordinal].value = value
+        }
+
+    var offsetTranslationX
+        get() = multiTranslationX[TranslationX.OFFSET.ordinal].value
+        set(value) {
+            multiTranslationX[TranslationX.OFFSET.ordinal].value = value
+        }
+
     override fun onFinishInflate() {
         super.onFinishInflate()
 
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
index 38ffe50..229c8f5 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.kt
@@ -55,6 +55,12 @@
 
     private val MINIMUM_RATIO_TO_SHOW_ICON = 0.2f
 
+    val leftTopTaskContainer: TaskContainer
+        get() = taskContainers[0]
+
+    val rightBottomTaskContainer: TaskContainer
+        get() = taskContainers[1]
+
     // TODO(b/336612373): Support new TTV for GroupedTaskView
     var splitBoundsConfig: SplitConfigurationOptions.SplitBounds? = null
         private set
@@ -72,8 +78,8 @@
         val splitBoundsConfig = splitBoundsConfig ?: return
         val inSplitSelection = getThisTaskCurrentlyInSplitSelection() != INVALID_TASK_ID
         pagedOrientationHandler.measureGroupedTaskViewThumbnailBounds(
-            taskContainers[0].snapshotView,
-            taskContainers[1].snapshotView,
+            leftTopTaskContainer.snapshotView,
+            rightBottomTaskContainer.snapshotView,
             widthSize,
             heightSize,
             splitBoundsConfig,
@@ -165,10 +171,10 @@
                 val iconMargins = (iconViewMarginStart + iconViewBackgroundMarginStart) * 2
                 // setMaxWidth() needs to be called before mIconView.setIconOrientation which is
                 // called in the super below.
-                (taskContainers[0].iconView as IconAppChipView).setMaxWidth(
+                (leftTopTaskContainer.iconView as IconAppChipView).setMaxWidth(
                     groupedTaskViewSizes.first.x - iconMargins
                 )
-                (taskContainers[1].iconView as IconAppChipView).setMaxWidth(
+                (rightBottomTaskContainer.iconView as IconAppChipView).setMaxWidth(
                     groupedTaskViewSizes.second.x - iconMargins
                 )
             }
@@ -189,16 +195,12 @@
                 if (deviceProfile.isLeftRightSplit) splitBoundsConfig.leftTaskPercent
                 else splitBoundsConfig.topTaskPercent
             val bottomRightTaskPercent = 1 - topLeftTaskPercent
-            taskContainers[0]
-                .iconView
-                .setFlexSplitAlpha(
-                    if (topLeftTaskPercent < MINIMUM_RATIO_TO_SHOW_ICON) 0f else 1f
-                )
-            taskContainers[1]
-                .iconView
-                .setFlexSplitAlpha(
-                    if (bottomRightTaskPercent < MINIMUM_RATIO_TO_SHOW_ICON) 0f else 1f
-                )
+            leftTopTaskContainer.iconView.setFlexSplitAlpha(
+                if (topLeftTaskPercent < MINIMUM_RATIO_TO_SHOW_ICON) 0f else 1f
+            )
+            rightBottomTaskContainer.iconView.setFlexSplitAlpha(
+                if (bottomRightTaskPercent < MINIMUM_RATIO_TO_SHOW_ICON) 0f else 1f
+            )
         }
 
         if (enableOverviewIconMenu()) {
@@ -210,8 +212,8 @@
                     layoutParams.height,
                 )
             pagedOrientationHandler.setSplitIconParams(
-                taskContainers[0].iconView.asView(),
-                taskContainers[1].iconView.asView(),
+                leftTopTaskContainer.iconView.asView(),
+                rightBottomTaskContainer.iconView.asView(),
                 taskIconHeight,
                 groupedTaskViewSizes.first.x,
                 groupedTaskViewSizes.first.y,
@@ -224,11 +226,11 @@
             )
         } else {
             pagedOrientationHandler.setSplitIconParams(
-                taskContainers[0].iconView.asView(),
-                taskContainers[1].iconView.asView(),
+                leftTopTaskContainer.iconView.asView(),
+                rightBottomTaskContainer.iconView.asView(),
                 taskIconHeight,
-                taskContainers[0].snapshotView.measuredWidth,
-                taskContainers[0].snapshotView.measuredHeight,
+                leftTopTaskContainer.snapshotView.measuredWidth,
+                leftTopTaskContainer.snapshotView.measuredHeight,
                 measuredHeight,
                 measuredWidth,
                 isRtl,
@@ -288,8 +290,8 @@
         recentsView?.let {
             it.splitSelectController.launchExistingSplitPair(
                 if (launchingExistingTaskView) this else null,
-                taskContainers[0].task.key.id,
-                taskContainers[1].task.key.id,
+                leftTopTaskContainer.task.key.id,
+                rightBottomTaskContainer.task.key.id,
                 STAGE_POSITION_TOP_OR_LEFT,
                 callback,
                 isQuickSwitch,
@@ -319,14 +321,14 @@
             // checks below aren't reliable since both of those views may be gone/transformed
             val initSplitTaskId = getThisTaskCurrentlyInSplitSelection()
             if (initSplitTaskId != INVALID_TASK_ID) {
-                return if (initSplitTaskId == taskContainers[0].task.key.id) 1 else 0
+                return if (initSplitTaskId == leftTopTaskContainer.task.key.id) 1 else 0
             }
         }
 
         // Check which of the two apps was selected
         if (
-            taskContainers[1].iconView.asView().containsPoint(lastTouchDownPosition) ||
-                taskContainers[1].snapshotView.containsPoint(lastTouchDownPosition)
+            rightBottomTaskContainer.iconView.asView().containsPoint(lastTouchDownPosition) ||
+                rightBottomTaskContainer.snapshotView.containsPoint(lastTouchDownPosition)
         ) {
             return 1
         }
diff --git a/quickstep/src/com/android/quickstep/views/IconView.kt b/quickstep/src/com/android/quickstep/views/IconView.kt
index 2e6c4bf..6da52d6 100644
--- a/quickstep/src/com/android/quickstep/views/IconView.kt
+++ b/quickstep/src/com/android/quickstep/views/IconView.kt
@@ -45,11 +45,11 @@
     private var msdlPlayerWrapper: MSDLPlayerWrapper? = null
 
     constructor(context: Context) : super(context) {
-        msdlPlayerWrapper = MSDLPlayerWrapper.INSTANCE.get(context)
+        setUpHaptics()
     }
 
     constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
-        msdlPlayerWrapper = MSDLPlayerWrapper.INSTANCE.get(context)
+        setUpHaptics()
     }
 
     constructor(
@@ -57,11 +57,15 @@
         attrs: AttributeSet?,
         defStyleAttr: Int,
     ) : super(context, attrs, defStyleAttr) {
-        msdlPlayerWrapper = MSDLPlayerWrapper.INSTANCE.get(context)
+        setUpHaptics()
     }
 
     init {
         multiValueAlpha.setUpdateVisibility(true)
+    }
+
+    private fun setUpHaptics() {
+        msdlPlayerWrapper = MSDLPlayerWrapper.INSTANCE.get(context)
         // Haptics are handled by the MSDLPlayerWrapper
         isHapticFeedbackEnabled = !Flags.msdlFeedback() || msdlPlayerWrapper == null
     }
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 9be462c..c6bd677 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -36,7 +36,6 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.desktop.DesktopRecentsTransitionController;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.statehandlers.DepthController;
@@ -127,9 +126,11 @@
         // If Launcher needs to return to split select state, do it now, after the icon has updated.
         if (mContainer.hasPendingSplitSelectInfo()) {
             PendingSplitSelectInfo recoveryData = mContainer.getPendingSplitSelectInfo();
-            if (recoveryData.getStagedTaskId() == taskId) {
+            TaskContainer taskContainer;
+            if (recoveryData != null && recoveryData.getStagedTaskId() == taskId && (taskContainer =
+                    mUtils.getTaskContainerById(taskId)) != null) {
                 initiateSplitSelect(
-                        getTaskViewByTaskId(recoveryData.getStagedTaskId()),
+                        taskContainer,
                         recoveryData.getStagePosition(), recoveryData.getSource()
                 );
                 mContainer.finishSplitSelectRecovery();
@@ -240,10 +241,10 @@
     }
 
     @Override
-    public void initiateSplitSelect(TaskView taskView,
+    public void initiateSplitSelect(TaskContainer taskContainer,
             @SplitConfigurationOptions.StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
-        super.initiateSplitSelect(taskView, stagePosition, splitEvent);
+        super.initiateSplitSelect(taskContainer, stagePosition, splitEvent);
         getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
     }
 
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c0b026b..1b59f5b 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -40,6 +40,7 @@
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
 import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile;
 import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
+import static com.android.launcher3.Flags.enableSeparateExternalDisplayTasks;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
@@ -651,13 +652,13 @@
                 return;
             }
 
-            TaskView taskView = getTaskViewByTaskId(taskId);
-            if (taskView == null) {
-                Log.d(TAG, "onTaskRemoved: " + taskId + ", no associated TaskView");
+            TaskContainer taskContainer = mUtils.getTaskContainerById(taskId);
+            if (taskContainer == null) {
+                Log.d(TAG, "onTaskRemoved: " + taskId + ", no associated Task");
                 return;
             }
             Log.d(TAG, "onTaskRemoved: " + taskId);
-            Task.TaskKey taskKey = taskView.getFirstTask().key;
+            Task.TaskKey taskKey = taskContainer.getTask().key;
             UI_HELPER_EXECUTOR.execute(new CancellableTask<>(
                     () -> PackageManagerWrapper.getInstance()
                             .getActivityInfo(taskKey.getComponent(), taskKey.userId) == null,
@@ -846,7 +847,7 @@
 
     private final RecentsViewModel mRecentsViewModel;
     private final RecentsViewModelHelper mHelper;
-    private final RecentsViewUtils mUtils = new RecentsViewUtils(this);
+    protected final RecentsViewUtils mUtils = new RecentsViewUtils(this);
 
     private final Matrix mTmpMatrix = new Matrix();
 
@@ -907,6 +908,7 @@
         if (DesktopModeStatus.enableMultipleDesktops(mContext)) {
             mAddDesktopButton = (AddDesktopButton) LayoutInflater.from(context).inflate(
                     R.layout.overview_add_desktop_button, this, false);
+            mAddDesktopButton.setOnClickListener(this::createDesk);
         }
 
         mTaskViewPool = new ViewPool<>(context, this, R.layout.task, 20 /* max size */,
@@ -1115,7 +1117,7 @@
                 TaskView taskView = getTaskViewByTaskId(taskId);
                 if (taskView != null) {
                     for (TaskContainer container : taskView.getTaskContainers()) {
-                        if (container == null || taskId != container.getTask().key.id) {
+                        if (taskId != container.getTask().key.id) {
                             continue;
                         }
                         container.getThumbnailViewDeprecated().setThumbnail(container.getTask(),
@@ -1130,9 +1132,10 @@
     @Override
     public void onTaskIconChanged(@NonNull String pkg, @NonNull UserHandle user) {
         for (TaskView taskView : getTaskViews()) {
-            Task task = taskView.getFirstTask();
-            if (pkg.equals(task.key.getPackageName()) && task.key.userId == user.getIdentifier()) {
-                task.icon = null;
+            Task firstTask = taskView.getFirstTask();
+            if (firstTask != null && pkg.equals(firstTask.key.getPackageName())
+                    && firstTask.key.userId == user.getIdentifier()) {
+                firstTask.icon = null;
                 if (taskView.getTaskContainers().stream().anyMatch(
                         container -> container.getIconView().getDrawable() != null)) {
                     taskView.onTaskListVisibilityChanged(true /* visible */);
@@ -1827,7 +1830,7 @@
             return;
         }
 
-        int runningTaskExpectedIndex = getRunningTaskExpectedIndex(runningTaskView);
+        int runningTaskExpectedIndex = mUtils.getRunningTaskExpectedIndex(runningTaskView);
         if (mCurrentPage == runningTaskExpectedIndex) {
             return;
         }
@@ -1847,28 +1850,6 @@
         updateTaskSize();
     }
 
-    private int getRunningTaskExpectedIndex(TaskView runningTaskView) {
-        int firstTaskViewIndex = indexOfChild(getFirstTaskView());
-        if (mContainer.getDeviceProfile().isTablet) {
-            if (runningTaskView instanceof DesktopTaskView) {
-                return firstTaskViewIndex; // Desktop running task is always in front.
-            } else if (enableLargeDesktopWindowingTile()) {
-                // Other running task is behind desktop tasks.
-                return getDesktopTaskViewCount() + firstTaskViewIndex;
-            } else {
-                return firstTaskViewIndex;
-            }
-        } else {
-            int currentIndex = indexOfChild(runningTaskView);
-            if (currentIndex != -1) {
-                return currentIndex; // Keep the position if running task already in layout.
-            } else {
-                // New running task are added to the front to begin with.
-                return firstTaskViewIndex;
-            }
-        }
-    }
-
     @Override
     protected void onScrollerAnimationAborted() {
         ActiveGestureProtoLogProxy.logOnScrollerAnimationAborted();
@@ -1956,6 +1937,9 @@
         if (enableLargeDesktopWindowingTile()) {
             taskGroups = mUtils.sortDesktopTasksToFront(taskGroups);
         }
+        if (enableSeparateExternalDisplayTasks()) {
+            taskGroups = mUtils.sortExternalDisplayTasksToFront(taskGroups);
+        }
 
         if (mAddDesktopButton != null) {
             // Add `mAddDesktopButton` as the first child.
@@ -2137,6 +2121,11 @@
         return mUtils.getDesktopTaskViewCount();
     }
 
+    /** Counts {@link TaskView}s that are not {@link DesktopTaskView} instances. */
+    public int getNonDesktopTaskViewCount() {
+        return mUtils.getNonDesktopTaskViewCount();
+    }
+
     /**
      * Returns the number of tasks in the top row of the overview grid.
      */
@@ -3033,7 +3022,7 @@
             if (mAddDesktopButton != null && wasEmpty) {
                 addView(mAddDesktopButton);
             }
-            addView(taskView, getRunningTaskExpectedIndex(taskView));
+            addView(taskView, mUtils.getRunningTaskExpectedIndex(taskView));
             runningTaskViewId = taskView.getTaskViewId();
             if (wasEmpty) {
                 addView(mClearAllButton);
@@ -3467,7 +3456,7 @@
                 // `mAddDesktopButton`, shift `mAddDesktopButton` to accommodate.
                 translationX += largeTaskWidthAndSpacing;
             }
-            mAddDesktopButton.setTranslationX(translationX);
+            mAddDesktopButton.setGridTranslationX(translationX);
         }
 
         final TaskView runningTask = getRunningTaskView();
@@ -4096,6 +4085,7 @@
                         } else {
                             removeTaskInternal(dismissedTaskView);
                         }
+                        // TODO(b/391918297): Logging when the TaskView does not have tasks as well.
                         mContainer.getStatsLogManager().logger()
                                 .withItemInfo(dismissedTaskView.getFirstItemInfo())
                                 .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
@@ -4605,6 +4595,12 @@
         }
     }
 
+    private void createDesk(View view) {
+        SystemUiProxy.INSTANCE
+                .get(getContext())
+                .createDesktop(mContainer.getDisplay().getDisplayId());
+    }
+
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
         if (isHandlingTouch() || event.getAction() != KeyEvent.ACTION_DOWN) {
@@ -4973,8 +4969,8 @@
             } else if (child instanceof ClearAllButton) {
                 getPagedOrientationHandler().getPrimaryViewTranslate().set(child,
                         totalTranslationX);
-            } else {
-                // TODO(b/389209581): Handle the page offsets update of the 'mAddDesktopButton'.
+            } else if (child instanceof AddDesktopButton addDesktopButton) {
+                addDesktopButton.setOffsetTranslationX(totalTranslationX);
             }
             if (mEnableDrawingLiveTile && i == getRunningTaskIndex()) {
                 runActionOnRemoteHandles(
@@ -5177,18 +5173,20 @@
      * Primarily used by overview actions to initiate split from focused task, logs the source
      * of split invocation as such.
      */
-    public void initiateSplitSelect(TaskView taskView) {
+    public void initiateSplitSelect(TaskContainer taskContainer) {
         int defaultSplitPosition = getPagedOrientationHandler()
                 .getDefaultSplitPosition(mContainer.getDeviceProfile());
-        initiateSplitSelect(taskView, defaultSplitPosition, LAUNCHER_OVERVIEW_ACTIONS_SPLIT);
+        initiateSplitSelect(taskContainer, defaultSplitPosition, LAUNCHER_OVERVIEW_ACTIONS_SPLIT);
     }
 
     /** TODO(b/266477929): Consolidate this call w/ the one below */
-    public void initiateSplitSelect(TaskView taskView, @StagePosition int stagePosition,
+    public void initiateSplitSelect(TaskContainer taskContainer,
+            @StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
+        TaskView taskView = taskContainer.getTaskView();
         mSplitHiddenTaskView = taskView;
         mSplitSelectStateController.setInitialTaskSelect(null /*intent*/, stagePosition,
-                taskView.getFirstItemInfo(), splitEvent, taskView.getFirstTask().key.id);
+                taskContainer.getItemInfo(), splitEvent, taskContainer.getTask().key.id);
         mSplitSelectStateController.setAnimateCurrentTaskDismissal(
                 true /*animateCurrentTaskDismissal*/);
         mSplitHiddenTaskViewIndex = indexOfChild(taskView);
@@ -5279,15 +5277,16 @@
         boolean isInitiatingTaskViewSplitPair =
                 mSplitSelectStateController.isDismissingFromSplitPair();
         if (isInitiatingSplitFromTaskView && isInitiatingTaskViewSplitPair
-                && mSplitHiddenTaskView instanceof GroupedTaskView) {
+                && mSplitHiddenTaskView instanceof GroupedTaskView groupedTaskView) {
             // Splitting from Overview for split pair task
             createInitialSplitSelectAnimation(builder);
 
             // Animate pair thumbnail into full thumbnail
-            boolean primaryTaskSelected = mSplitHiddenTaskView.getTaskIds()[0]
+            boolean primaryTaskSelected = groupedTaskView.getLeftTopTaskContainer().getTask().key.id
                     == mSplitSelectStateController.getInitialTaskId();
-            TaskContainer taskContainer = mSplitHiddenTaskView
-                    .getTaskContainers().get(primaryTaskSelected ? 1 : 0);
+            TaskContainer taskContainer =
+                    primaryTaskSelected ? groupedTaskView.getRightBottomTaskContainer()
+                            : groupedTaskView.getLeftTopTaskContainer();
             mSplitSelectStateController.getSplitAnimationController()
                     .addInitialSplitFromPair(taskContainer, builder,
                             mContainer.getDeviceProfile(),
@@ -5715,7 +5714,7 @@
         updateGridProperties();
         updateScrollSynchronously();
 
-        int targetSysUiFlags = taskView.getTaskContainers().getFirst().getSysUiStatusNavFlags();
+        int targetSysUiFlags = taskView.getSysUiStatusNavFlags();
         final boolean[] passedOverviewThreshold = new boolean[]{false};
         AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(taskView);
         anim.play(new AnimatedFloat(v -> {
@@ -5773,8 +5772,12 @@
                 } else {
                     taskView.launchWithoutAnimation(this::onTaskLaunchAnimationEnd);
                 }
-                mContainer.getStatsLogManager().logger().withItemInfo(taskView.getFirstItemInfo())
-                        .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
+                // TODO(b/391918297): Logging when there is no associated task.
+                ItemInfo firstItemInfo = taskView.getFirstItemInfo();
+                if (firstItemInfo != null) {
+                    mContainer.getStatsLogManager().logger().withItemInfo(firstItemInfo)
+                            .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
+                }
             } else {
                 onTaskLaunchAnimationEnd(false);
             }
@@ -6157,7 +6160,7 @@
         if (addDesktopButtonIndex != -1 && addDesktopButtonIndex < outPageScrolls.length) {
             outPageScrolls[addDesktopButtonIndex] =
                     newPageScrolls[addDesktopButtonIndex] + Math.round(
-                            mAddDesktopButton.getTranslationX());
+                            mAddDesktopButton.getGridTranslationX());
         }
 
         int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
index dcb954a..94e8c03 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
+++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt
@@ -20,8 +20,10 @@
 import android.view.View
 import androidx.core.view.children
 import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
+import com.android.launcher3.Flags.enableSeparateExternalDisplayTasks
 import com.android.launcher3.util.IntArray
 import com.android.quickstep.util.GroupTask
+import com.android.quickstep.util.isExternalDisplay
 import com.android.quickstep.views.RecentsView.RUNNING_TASK_ATTACH_ALPHA
 import com.android.systemui.shared.recents.model.ThumbnailData
 import java.util.function.BiConsumer
@@ -52,6 +54,12 @@
         return otherTasks + desktopTasks
     }
 
+    fun sortExternalDisplayTasksToFront(tasks: List<GroupTask>): List<GroupTask> {
+        val (externalDisplayTasks, otherTasks) =
+            tasks.partition { it.tasks.firstOrNull().isExternalDisplay }
+        return otherTasks + externalDisplayTasks
+    }
+
     class TaskViewsIterable(val recentsView: RecentsView<*, *>) : Iterable<TaskView> {
         /** Iterates TaskViews when its index inside the RecentsView is needed. */
         fun forEachWithIndexInParent(consumer: BiConsumer<Int, TaskView>) {
@@ -67,6 +75,9 @@
     /** Counts [TaskView]s that are [DesktopTaskView] instances. */
     fun getDesktopTaskViewCount(): Int = taskViews.count { it is DesktopTaskView }
 
+    /** Counts [TaskView]s that are not [DesktopTaskView] instances. */
+    fun getNonDesktopTaskViewCount(): Int = taskViews.count { it !is DesktopTaskView }
+
     /** Returns a list of all large TaskView Ids from [TaskView]s */
     fun getLargeTaskViewIds(): List<Int> = taskViews.filter { it.isLargeTile }.map { it.taskViewId }
 
@@ -96,9 +107,47 @@
     fun getExpectedCurrentTask(runningTaskView: TaskView?, focusedTaskView: TaskView?): TaskView? =
         runningTaskView
             ?: focusedTaskView
-            ?: taskViews.firstOrNull { it !is DesktopTaskView }
+            ?: taskViews.firstOrNull {
+                it !is DesktopTaskView &&
+                    !(enableSeparateExternalDisplayTasks() && it.isExternalDisplay)
+            }
             ?: taskViews.lastOrNull()
 
+    private fun getDeviceProfile() = (recentsView.mContainer as RecentsViewContainer).deviceProfile
+
+    fun getRunningTaskExpectedIndex(runningTaskView: TaskView): Int {
+        val firstTaskViewIndex = recentsView.indexOfChild(getFirstTaskView())
+        return if (getDeviceProfile().isTablet) {
+            var index = firstTaskViewIndex
+            if (enableLargeDesktopWindowingTile() && runningTaskView !is DesktopTaskView) {
+                // For fullsreen tasks, skip over Desktop tasks in its section
+                index +=
+                    if (enableSeparateExternalDisplayTasks()) {
+                        if (runningTaskView.isExternalDisplay) {
+                            taskViews.count { it is DesktopTaskView && it.isExternalDisplay }
+                        } else {
+                            taskViews.count { it is DesktopTaskView && !it.isExternalDisplay }
+                        }
+                    } else {
+                        getDesktopTaskViewCount()
+                    }
+            }
+            if (enableSeparateExternalDisplayTasks() && !runningTaskView.isExternalDisplay) {
+                // For main display section, skip over external display tasks
+                index += taskViews.count { it.isExternalDisplay }
+            }
+            index
+        } else {
+            val currentIndex: Int = recentsView.indexOfChild(runningTaskView)
+            return if (currentIndex != -1) {
+                currentIndex // Keep the position if running task already in layout.
+            } else {
+                // New running task are added to the front to begin with.
+                firstTaskViewIndex
+            }
+        }
+    }
+
     /** Returns the first TaskView if it exists, or null otherwise. */
     fun getFirstTaskView(): TaskView? = taskViews.firstOrNull()
 
@@ -175,6 +224,9 @@
     /** Returns true if there are at least one TaskView has been added to the RecentsView. */
     fun hasTaskViews() = taskViews.any()
 
+    fun getTaskContainerById(taskId: Int) =
+        taskViews.firstNotNullOfOrNull { it.getTaskContainerById(taskId) }
+
     private fun getRowRect(firstView: View?, lastView: View?, outRowRect: Rect) {
         outRowRect.setEmpty()
         firstView?.let {
@@ -204,7 +256,7 @@
         outTopRowRect: Rect,
         outBottomRowRect: Rect,
     ) {
-        if (!(recentsView.mContainer as RecentsViewContainer).deviceProfile.isTablet) {
+        if (!getDeviceProfile().isTablet) {
             getRowRect(getFirstTaskView(), getLastTaskView(), outTaskViewRowRect)
             return
         }
diff --git a/quickstep/src/com/android/quickstep/views/TaskContainer.kt b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
index 7ac0946..a9e84ef 100644
--- a/quickstep/src/com/android/quickstep/views/TaskContainer.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskContainer.kt
@@ -28,6 +28,8 @@
 import com.android.quickstep.recents.di.get
 import com.android.quickstep.recents.di.getScope
 import com.android.quickstep.recents.di.inject
+import com.android.quickstep.recents.ui.mapper.TaskUiStateMapper
+import com.android.quickstep.recents.ui.viewmodel.TaskData
 import com.android.quickstep.recents.viewmodel.TaskContainerViewModel
 import com.android.quickstep.task.thumbnail.TaskThumbnailView
 import com.android.quickstep.task.viewmodel.TaskContainerData
@@ -61,11 +63,7 @@
 
     // TODO(b/335649589): Ideally create and obtain this from DI.
     private val taskContainerViewModel: TaskContainerViewModel by lazy {
-        TaskContainerViewModel(
-            sysUiStatusNavFlagsUseCase = RecentsDependencies.get(),
-            getThumbnailUseCase = RecentsDependencies.get(),
-            splashAlphaUseCase = RecentsDependencies.get(),
-        )
+        TaskContainerViewModel(splashAlphaUseCase = RecentsDependencies.get())
     }
 
     init {
@@ -84,13 +82,9 @@
         }
     }
 
-    val splitAnimationThumbnail: Bitmap?
-        get() =
-            if (enableRefactorTaskThumbnail()) {
-                taskContainerViewModel.getThumbnail(task.key.id)
-            } else {
-                thumbnailViewDeprecated.thumbnail
-            }
+    var splitAnimationThumbnail: Bitmap? = null
+        get() = if (enableRefactorTaskThumbnail()) field else thumbnailViewDeprecated.thumbnail
+        private set
 
     val thumbnailView: TaskThumbnailView
         get() {
@@ -110,12 +104,6 @@
                 taskContainerViewModel.shouldShowThumbnailSplash(task.key.id)
             else thumbnailViewDeprecated.shouldShowSplashView()
 
-    val sysUiStatusNavFlags: Int
-        get() =
-            if (enableRefactorTaskThumbnail())
-                taskContainerViewModel.getSysUiStatusNavFlags(task.key.id)
-            else thumbnailViewDeprecated.sysUiStatusNavFlags
-
     /** Builds proto for logging */
     val itemInfo: TaskViewItemInfo
         get() = TaskViewItemInfo(this)
@@ -146,7 +134,7 @@
         thumbnailView.destroyScopes()
     }
 
-    fun bindThumbnailView() {
+    private fun bindThumbnailView() {
         taskThumbnailViewModel.bind(task.key.id)
     }
 
@@ -163,4 +151,18 @@
         digitalWellBeingToast?.let { addAccessibleChildToList(it, outChildren) }
         overlay.addChildForAccessibility(outChildren)
     }
+
+    fun setState(state: TaskData?, liveTile: Boolean, hasHeader: Boolean) {
+        thumbnailView.setState(TaskUiStateMapper.toTaskThumbnailUiState(state, liveTile, hasHeader))
+        splitAnimationThumbnail =
+            if (state is TaskData.Data) state.thumbnailData?.thumbnail else null
+    }
+
+    fun updateTintAmount(tintAmount: Float) {
+        thumbnailView.updateTintAmount(tintAmount)
+    }
+
+    fun updateMenuOpenProgress(progress: Float) {
+        thumbnailView.updateMenuOpenProgress(progress)
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 63bc509..0b3eb75 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -368,8 +368,7 @@
             mRevealAnimator.addUpdateListener(animation -> {
                 float animatedFraction = animation.getAnimatedFraction();
                 float openProgress = closing ? (1 - animatedFraction) : animatedFraction;
-                mTaskContainer.getTaskContainerData()
-                        .getTaskMenuOpenProgress().setValue(openProgress);
+                mTaskContainer.updateMenuOpenProgress(openProgress);
             });
         } else {
             openCloseAnimatorBuilder.with(ObjectAnimator.ofFloat(
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt
index e7a395f..9807b0d 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskView.kt
@@ -33,7 +33,6 @@
 import android.view.Display
 import android.view.MotionEvent
 import android.view.View
-import android.view.View.OnClickListener
 import android.view.ViewGroup
 import android.view.ViewStub
 import android.view.accessibility.AccessibilityNodeInfo
@@ -50,6 +49,7 @@
 import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
 import com.android.launcher3.Flags.enableOverviewIconMenu
 import com.android.launcher3.Flags.enableRefactorTaskThumbnail
+import com.android.launcher3.Flags.enableSeparateExternalDisplayTasks
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.launcher3.anim.AnimatedFloat
@@ -63,13 +63,12 @@
 import com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE
 import com.android.launcher3.util.MultiValueAlpha
 import com.android.launcher3.util.RunnableList
-import com.android.launcher3.util.SplitConfigurationOptions
 import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
-import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
 import com.android.launcher3.util.TraceHelper
 import com.android.launcher3.util.TransformingTouchDelegate
 import com.android.launcher3.util.ViewPool
+import com.android.launcher3.util.coroutines.DispatcherProvider
 import com.android.launcher3.util.rects.set
 import com.android.quickstep.FullscreenDrawParams
 import com.android.quickstep.RecentsModel
@@ -77,6 +76,11 @@
 import com.android.quickstep.TaskOverlayFactory
 import com.android.quickstep.TaskViewUtils
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler
+import com.android.quickstep.recents.di.RecentsDependencies
+import com.android.quickstep.recents.di.get
+import com.android.quickstep.recents.di.inject
+import com.android.quickstep.recents.ui.viewmodel.TaskTileUiState
+import com.android.quickstep.recents.ui.viewmodel.TaskViewModel
 import com.android.quickstep.util.ActiveGestureErrorDetector
 import com.android.quickstep.util.ActiveGestureLog
 import com.android.quickstep.util.BorderAnimator
@@ -84,10 +88,20 @@
 import com.android.quickstep.util.RecentsOrientedState
 import com.android.quickstep.util.TaskCornerRadius
 import com.android.quickstep.util.TaskRemovedDuringLaunchListener
+import com.android.quickstep.util.displayId
+import com.android.quickstep.util.isExternalDisplay
 import com.android.quickstep.views.RecentsView.UNBOUND_TASK_VIEW_ID
 import com.android.systemui.shared.recents.model.Task
 import com.android.systemui.shared.recents.model.ThumbnailData
 import com.android.systemui.shared.system.ActivityManagerWrapper
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.collectLatest
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.launch
 
 /** A task in the Recents view. */
 open class TaskView
@@ -128,10 +142,17 @@
     val isRunningTask: Boolean
         get() = this === recentsView?.runningTaskView
 
+    val displayId: Int
+        get() = taskContainers.firstOrNull()?.task.displayId
+
+    val isExternalDisplay: Boolean
+        get() = displayId.isExternalDisplay
+
     val isLargeTile: Boolean
         get() =
             this == recentsView?.focusedTaskView ||
-                (enableLargeDesktopWindowingTile() && type == TaskViewType.DESKTOP)
+                (enableLargeDesktopWindowingTile() && type == TaskViewType.DESKTOP) ||
+                (enableSeparateExternalDisplayTasks() && isExternalDisplay)
 
     val recentsView: RecentsView<*, *>?
         get() = parent as? RecentsView<*, *>
@@ -139,14 +160,15 @@
     val pagedOrientationHandler: RecentsPagedOrientationHandler
         get() = orientedState.orientationHandler
 
-    @get:Deprecated("Use [taskContainers] instead.")
-    val firstTask: Task
-        /** Returns the first task bound to this TaskView. */
-        get() = taskContainers[0].task
+    val firstTaskContainer: TaskContainer?
+        get() = taskContainers.firstOrNull()
 
-    @get:Deprecated("Use [taskContainers] instead.")
-    val firstItemInfo: ItemInfo
-        get() = taskContainers[0].itemInfo
+    val firstTask: Task?
+        /** Returns the first task bound to this TaskView. */
+        get() = firstTaskContainer?.task
+
+    val firstItemInfo: ItemInfo?
+        get() = firstTaskContainer?.itemInfo
 
     protected val container: RecentsViewContainer =
         RecentsViewContainer.containerFromContext(context)
@@ -231,6 +253,11 @@
 
     var taskViewId = UNBOUND_TASK_VIEW_ID
     var isEndQuickSwitchCuj = false
+    var sysUiStatusNavFlags: Int = 0
+        get() =
+            if (enableRefactorTaskThumbnail()) field
+            else taskContainers.first().thumbnailViewDeprecated.sysUiStatusNavFlags
+        private set
 
     // Various animation progress variables.
     // progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
@@ -448,6 +475,11 @@
     private val settledProgressDismiss =
         settledProgressPropertyFactory.get(SETTLED_PROGRESS_INDEX_DISMISS)
 
+    private var viewModel: TaskViewModel? = null
+    private val dispatcherProvider: DispatcherProvider by RecentsDependencies.inject()
+    private val coroutineScope by lazy { CoroutineScope(SupervisorJob() + dispatcherProvider.main) }
+    private val coroutineJobs = mutableListOf<Job>()
+
     /**
      * Returns an animator of [settledProgressDismiss] that transition in with a built-in
      * interpolator.
@@ -601,6 +633,8 @@
 
     override fun onRecycle() {
         resetPersistentViewTransforms()
+
+        viewModel = null
         attachAlpha = 1f
         splitAlpha = 1f
         // Clear any references to the thumbnail (it will be re-read either from the cache or the
@@ -715,6 +749,52 @@
             ?.inflate()
     }
 
+    override fun onAttachedToWindow() {
+        super.onAttachedToWindow()
+        if (enableRefactorTaskThumbnail()) {
+            // The TaskView lifecycle is starts the ViewModel during onBind, and cleans it in
+            // onRecycle. So it should be initialized at this point. TaskView Lifecycle:
+            // `bind` -> `onBind` ->  onAttachedToWindow() -> onDetachFromWindow -> onRecycle
+            coroutineJobs +=
+                viewModel!!.tintAmount.onEach(::updateTintAmount).launchIn(coroutineScope)
+
+            coroutineJobs +=
+                coroutineScope.launch { viewModel!!.state.collectLatest(::updateTaskViewState) }
+        }
+    }
+
+    private fun updateTintAmount(amount: Float) {
+        taskContainers.forEach { it.updateTintAmount(amount) }
+    }
+
+    private fun updateTaskViewState(state: TaskTileUiState) {
+        sysUiStatusNavFlags = state.sysUiStatusNavFlags
+
+        // Updating containers
+        val mapOfTasks = state.tasks.associateBy { it.taskId }
+        taskContainers.forEach { container ->
+            container.setState(
+                state = mapOfTasks[container.task.key.id],
+                liveTile = state.isLiveTile,
+                hasHeader = type == TaskViewType.DESKTOP,
+            )
+        }
+    }
+
+    override fun onDetachedFromWindow() {
+        super.onDetachedFromWindow()
+        if (enableRefactorTaskThumbnail()) {
+            // The jobs are being cancelled in the background thread. So we make a copy of the list
+            // to prevent cleaning a new job that might be added to this list during onAttach
+            // or another moment in the lifecycle.
+            val coroutineJobsToCancel = coroutineJobs.toList()
+            coroutineJobs.clear()
+            coroutineScope.launch(dispatcherProvider.background) {
+                coroutineJobsToCancel.forEach { it.cancel("TaskView detaching from window") }
+            }
+        }
+    }
+
     /** Updates this task view to the given {@param task}. */
     open fun bind(
         task: Task,
@@ -738,6 +818,18 @@
     }
 
     open fun onBind(orientedState: RecentsOrientedState) {
+        if (enableRefactorTaskThumbnail()) {
+            viewModel =
+                TaskViewModel(
+                        taskViewType = type,
+                        recentsViewData = RecentsDependencies.get(),
+                        getTaskUseCase = RecentsDependencies.get(),
+                        getSysUiStatusNavFlagsUseCase = RecentsDependencies.get(),
+                        dispatcherProvider = RecentsDependencies.get(),
+                    )
+                    .apply { bind(*taskIds) }
+        }
+
         taskContainers.forEach {
             it.bind()
             if (enableRefactorTaskThumbnail()) {
@@ -848,7 +940,7 @@
     protected open fun updateThumbnailSize() {
         // TODO(b/271468547), we should default to setting translations only on the snapshot instead
         //  of a hybrid of both margins and translations
-        taskContainers[0].snapshotView.updateLayoutParams<LayoutParams> {
+        firstTaskContainer?.snapshotView?.updateLayoutParams<LayoutParams> {
             topMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
         }
         taskContainers.forEach { it.digitalWellBeingToast?.setupLayout() }
@@ -1012,10 +1104,13 @@
                 }
             }
         Log.d("b/310064698", "${taskIds.contentToString()} - onClick - callbackList: $callbackList")
-        container.statsLogManager
-            .logger()
-            .withItemInfo(firstItemInfo)
-            .log(LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP)
+        // TODO(b/391918297): Logging when there is no associated task.
+        firstItemInfo?.let {
+            container.statsLogManager
+                .logger()
+                .withItemInfo(it)
+                .log(LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP)
+        }
     }
 
     /** Launch of the current task (both live and inactive tasks) with an animation. */
@@ -1118,6 +1213,7 @@
      * @return CompletionStage to indicate the animation completion or null if the launch failed.
      */
     open fun launchAsStaticTile(): RunnableList? {
+        val firstTaskContainer = firstTaskContainer ?: return null
         TestLogging.recordEvent(
             TestProtocol.SEQUENCE_MAIN,
             "startActivityFromRecentsAsync",
@@ -1125,11 +1221,11 @@
         )
         val opts =
             container.getActivityLaunchOptions(this, null).apply {
-                options.launchDisplayId = display?.displayId ?: Display.DEFAULT_DISPLAY
+                options.launchDisplayId = displayId
             }
         if (
             ActivityManagerWrapper.getInstance()
-                .startActivityFromRecents(taskContainers[0].task.key, opts.options)
+                .startActivityFromRecents(firstTaskContainer.task.key, opts.options)
         ) {
             Log.d(
                 TAG,
@@ -1168,18 +1264,18 @@
         isQuickSwitch: Boolean = false,
         callback: (launched: Boolean) -> Unit,
     ) {
+        val firstTaskContainer = firstTaskContainer ?: return
         TestLogging.recordEvent(
             TestProtocol.SEQUENCE_MAIN,
             "startActivityFromRecentsAsync",
             taskIds.contentToString(),
         )
-        val firstContainer = taskContainers[0]
         val failureListener = TaskRemovedDuringLaunchListener(context.applicationContext)
         if (isQuickSwitch) {
             // We only listen for failures to launch in quickswitch because the during this
             // gesture launcher is in the background state, vs other launches which are in
             // the actual overview state
-            failureListener.register(container, firstContainer.task.key.id) {
+            failureListener.register(container, firstTaskContainer.task.key.id) {
                 notifyTaskLaunchFailed("launchWithoutAnimation")
                 recentsView?.let {
                     // Disable animations for now, as it is an edge case and the app usually
@@ -1211,12 +1307,12 @@
                     if (isQuickSwitch) {
                         setFreezeRecentTasksReordering()
                     }
-                    disableStartingWindow = firstContainer.shouldShowSplashView
+                    disableStartingWindow = firstTaskContainer.shouldShowSplashView
                 }
         Executors.UI_HELPER_EXECUTOR.execute {
             if (
                 !ActivityManagerWrapper.getInstance()
-                    .startActivityFromRecents(firstContainer.task.key, opts)
+                    .startActivityFromRecents(firstTaskContainer.task.key, opts)
             ) {
                 // If the call to start activity failed, then post the result immediately,
                 // otherwise, wait for the animation start callback from the activity options
@@ -1243,14 +1339,6 @@
         Toast.makeText(context, R.string.activity_not_available, Toast.LENGTH_SHORT).show()
     }
 
-    fun initiateSplitSelect(splitPositionOption: SplitPositionOption) {
-        recentsView?.initiateSplitSelect(
-            this,
-            splitPositionOption.stagePosition,
-            SplitConfigurationOptions.getLogEventForPosition(splitPositionOption.stagePosition),
-        )
-    }
-
     /**
      * Returns `true` if user is already in split select mode and this tap was to choose the second
      * app. `false` otherwise
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/FakeTaskThumbnailViewModel.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/FakeTaskThumbnailViewModel.kt
index 47d2bfc..3e0c186 100644
--- a/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/FakeTaskThumbnailViewModel.kt
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/FakeTaskThumbnailViewModel.kt
@@ -17,14 +17,11 @@
 package com.android.quickstep.task.thumbnail
 
 import android.graphics.Matrix
-import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
 import com.android.quickstep.task.viewmodel.TaskThumbnailViewModel
 import kotlinx.coroutines.flow.MutableStateFlow
 
 class FakeTaskThumbnailViewModel : TaskThumbnailViewModel {
-    override val dimProgress = MutableStateFlow(0f)
     override val splashAlpha = MutableStateFlow(0f)
-    override val uiState = MutableStateFlow<TaskThumbnailUiState>(Uninitialized)
 
     override fun bind(taskId: Int) {
         // no-op
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewScreenshotTest.kt
index a76f83c..356080a 100644
--- a/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewScreenshotTest.kt
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewScreenshotTest.kt
@@ -60,36 +60,61 @@
         screenshotRule.screenshotTest("taskThumbnailView_uninitialized") { activity ->
             activity.actionBar?.hide()
             val taskThumbnailView = createTaskThumbnailView(activity)
-            taskThumbnailViewModel.uiState.value = BackgroundOnly(Color.YELLOW)
-            taskThumbnailViewModel.uiState.value = Uninitialized
+            taskThumbnailView.setState(Uninitialized)
             taskThumbnailView
         }
     }
 
     @Test
     fun taskThumbnailView_recyclesToUninitialized() {
-        screenshotRule.screenshotTest(
-            "taskThumbnailView_uninitialized",
-            viewProvider = { activity ->
-                activity.actionBar?.hide()
-                val taskThumbnailView = createTaskThumbnailView(activity)
-                taskThumbnailViewModel.uiState.value = BackgroundOnly(Color.YELLOW)
-                taskThumbnailView
-            },
-            checkView = { _, taskThumbnailView ->
-                // Call onRecycle() after View is attached (end of block above)
-                (taskThumbnailView as TaskThumbnailView).onRecycle()
-                false
-            },
-        )
+        screenshotRule.screenshotTest("taskThumbnailView_uninitialized") { activity ->
+            activity.actionBar?.hide()
+            val taskThumbnailView = createTaskThumbnailView(activity)
+            taskThumbnailView.setState(BackgroundOnly(Color.YELLOW))
+            taskThumbnailView.onRecycle()
+            taskThumbnailView
+        }
     }
 
     @Test
     fun taskThumbnailView_backgroundOnly() {
         screenshotRule.screenshotTest("taskThumbnailView_backgroundOnly") { activity ->
             activity.actionBar?.hide()
-            taskThumbnailViewModel.uiState.value = BackgroundOnly(Color.YELLOW)
-            createTaskThumbnailView(activity)
+            createTaskThumbnailView(activity).apply { setState(BackgroundOnly(Color.YELLOW)) }
+        }
+    }
+
+    @Test
+    fun taskThumbnailView_dimmed_tintAmount() {
+        screenshotRule.screenshotTest("taskThumbnailView_dimmed_40") { activity ->
+            activity.actionBar?.hide()
+            createTaskThumbnailView(activity).apply {
+                setState(BackgroundOnly(Color.YELLOW))
+                updateTintAmount(.4f)
+            }
+        }
+    }
+
+    @Test
+    fun taskThumbnailView_dimmed_menuOpen() {
+        screenshotRule.screenshotTest("taskThumbnailView_dimmed_40") { activity ->
+            activity.actionBar?.hide()
+            createTaskThumbnailView(activity).apply {
+                setState(BackgroundOnly(Color.YELLOW))
+                updateMenuOpenProgress(1f)
+            }
+        }
+    }
+
+    @Test
+    fun taskThumbnailView_dimmed_tintAmountAndMenuOpen() {
+        screenshotRule.screenshotTest("taskThumbnailView_dimmed_80") { activity ->
+            activity.actionBar?.hide()
+            createTaskThumbnailView(activity).apply {
+                setState(BackgroundOnly(Color.YELLOW))
+                updateTintAmount(.8f)
+                updateMenuOpenProgress(1f)
+            }
         }
     }
 
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/AppEventProducerTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/AppEventProducerTest.java
index d4dd580..06a939a 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/AppEventProducerTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/AppEventProducerTest.java
@@ -35,9 +35,12 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.launcher3.dagger.LauncherAppComponent;
+import com.android.launcher3.dagger.LauncherAppSingleton;
 import com.android.launcher3.logger.LauncherAtom;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.AllModulesForTest;
 import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
 import com.android.launcher3.util.UserIconInfo;
 import com.android.systemui.shared.system.SysUiStatsLog;
@@ -51,6 +54,9 @@
 
 import java.util.Arrays;
 
+import dagger.BindsInstance;
+import dagger.Component;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class AppEventProducerTest {
@@ -72,7 +78,9 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mContext = new SandboxContext(getApplicationContext());
-        mContext.putObject(UserCache.INSTANCE, mUserCache);
+        mContext.initDaggerComponent(
+                DaggerAppEventProducerTest_TestComponent.builder().bindUserCache(mUserCache)
+        );
         mAppEventProducer = new AppEventProducer(mContext, null);
     }
 
@@ -129,4 +137,15 @@
                 .build());
         return itemBuilder.build();
     }
+
+    @LauncherAppSingleton
+    @Component(modules = { AllModulesForTest.class })
+    interface TestComponent extends LauncherAppComponent {
+        @Component.Builder
+        interface Builder extends LauncherAppComponent.Builder {
+            @BindsInstance
+            AppEventProducerTest.TestComponent.Builder bindUserCache(UserCache userCache);
+            @Override LauncherAppComponent build();
+        }
+    }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt
index 5cee434..be71640 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/data/TaskViewItemInfoTest.kt
@@ -21,15 +21,19 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.launcher3.Flags.enableRefactorTaskThumbnail
+import com.android.launcher3.dagger.LauncherAppComponent
+import com.android.launcher3.dagger.LauncherAppSingleton
 import com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE
 import com.android.launcher3.model.data.TaskViewItemInfo.Companion.createTaskViewAtom
 import com.android.launcher3.pm.UserCache
+import com.android.launcher3.util.AllModulesForTest
 import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext
 import com.android.launcher3.util.SplitConfigurationOptions
 import com.android.launcher3.util.TransformingTouchDelegate
 import com.android.launcher3.util.UserIconInfo
 import com.android.quickstep.TaskOverlayFactory
 import com.android.quickstep.TaskOverlayFactory.TaskOverlay
+import com.android.quickstep.TestComponent
 import com.android.quickstep.recents.di.RecentsDependencies
 import com.android.quickstep.task.thumbnail.TaskThumbnailView
 import com.android.quickstep.views.RecentsView
@@ -41,6 +45,8 @@
 import com.android.systemui.shared.recents.model.Task
 import com.android.systemui.shared.recents.model.Task.TaskKey
 import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -66,7 +72,9 @@
         whenever(recentsView.indexOfChild(taskView)).thenReturn(TASK_VIEW_INDEX)
         whenever(userInfo.isPrivate).thenReturn(false)
         whenever(userCache.getUserInfo(any())).thenReturn(userInfo)
-        context.putObject(UserCache.INSTANCE, userCache)
+        context.initDaggerComponent(
+            DaggerTaskViewItemInfoTest_TestComponent.builder().bindUserCache(userCache)
+        )
         RecentsDependencies.initialize(context)
     }
 
@@ -176,6 +184,17 @@
         )
     }
 
+    @LauncherAppSingleton
+    @Component(modules = [AllModulesForTest::class])
+    interface TestComponent : LauncherAppComponent {
+        @Component.Builder
+        interface Builder : LauncherAppComponent.Builder {
+            @BindsInstance fun bindUserCache(userCache: UserCache): Builder
+
+            override fun build(): TestComponent
+        }
+    }
+
     companion object {
         const val PACKAGE = "package"
         const val CLASS = "class"
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt
index 588c22c..021e1e4 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarStashControllerTest.kt
@@ -53,7 +53,7 @@
 import com.android.launcher3.util.LauncherMultivalentJUnit
 import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices
 import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED
-import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING
+import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_VISIBLE
 import com.android.wm.shell.Flags.FLAG_ENABLE_BUBBLE_BAR
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.TruthJUnit.assume
@@ -542,7 +542,7 @@
         assume().that(activityContext.isHardwareKeyboard).isFalse()
 
         getInstrumentation().runOnMainSync {
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, false)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, false)
             animatorTestRule.advanceTimeBy(TASKBAR_STASH_DURATION_FOR_IME)
         }
         assertThat(viewController.areIconsVisible()).isFalse()
@@ -555,7 +555,7 @@
         assume().that(activityContext.isHardwareKeyboard).isFalse()
 
         getInstrumentation().runOnMainSync {
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, true)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, true)
             animatorTestRule.advanceTimeBy(0)
         }
 
@@ -574,7 +574,7 @@
 
         // Start with IME shown.
         getInstrumentation().runOnMainSync {
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, true)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, true)
             animatorTestRule.advanceTimeBy(0)
         }
 
@@ -600,7 +600,7 @@
         assume().that(activityContext.isHardwareKeyboard).isFalse()
 
         getInstrumentation().runOnMainSync {
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, false)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, false)
             animatorTestRule.advanceTimeBy(TASKBAR_STASH_DURATION_FOR_IME)
         }
         assertThat(viewController.areIconsVisible()).isFalse()
@@ -613,7 +613,7 @@
         assume().that(activityContext.isHardwareKeyboard).isFalse()
 
         getInstrumentation().runOnMainSync {
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, false)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, false)
             animatorTestRule.advanceTimeBy(TASKBAR_STASH_DURATION_FOR_IME)
         }
 
@@ -633,7 +633,7 @@
         assume().that(activityContext.isHardwareKeyboard).isFalse()
 
         getInstrumentation().runOnMainSync {
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, true)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, true)
             animatorTestRule.advanceTimeBy(0)
         }
 
@@ -653,7 +653,7 @@
 
         getInstrumentation().runOnMainSync {
             stashController.updateStateForFlag(FLAG_IN_APP, true)
-            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_SHOWING, true)
+            stashController.updateStateForSysuiFlags(SYSUI_STATE_IME_VISIBLE, true)
         }
 
         assertThat(stashController.isStashed).isFalse()
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentTasksListTest.java
index cad3b99..c399bdb 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentTasksListTest.java
@@ -16,6 +16,10 @@
 
 package com.android.quickstep;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.launcher3.Flags.FLAG_ENABLE_SEPARATE_EXTERNAL_DISPLAY_TASKS;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static junit.framework.TestCase.assertNull;
@@ -36,6 +40,9 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -50,6 +57,7 @@
 import com.android.wm.shell.shared.split.SplitScreenConstants;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -65,6 +73,8 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class RecentTasksListTest {
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
 
     @Mock
     private Context mContext;
@@ -158,11 +168,13 @@
     }
 
     @Test
+    @DisableFlags(FLAG_ENABLE_SEPARATE_EXTERNAL_DISPLAY_TASKS)
     public void loadTasksInBackground_freeformTask_createsDesktopTask() throws Exception  {
         List<TaskInfo> tasks = Arrays.asList(
-                createRecentTaskInfo(1 /* taskId */),
-                createRecentTaskInfo(4 /* taskId */),
-                createRecentTaskInfo(5 /* taskId */));
+                createRecentTaskInfo(1 /* taskId */, DEFAULT_DISPLAY),
+                createRecentTaskInfo(4 /* taskId */, DEFAULT_DISPLAY),
+                createRecentTaskInfo(5 /* taskId */, 1 /* displayId */),
+                createRecentTaskInfo(6 /* taskId */, 1 /* displayId */));
         GroupedTaskInfo recentTaskInfos = GroupedTaskInfo.forFreeformTasks(
                 tasks, Collections.emptySet() /* minimizedTaskIds */);
         when(mSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
@@ -174,22 +186,57 @@
         assertEquals(1, taskList.size());
         assertEquals(TaskViewType.DESKTOP, taskList.get(0).taskViewType);
         List<Task> actualFreeformTasks = taskList.get(0).getTasks();
-        assertEquals(3, actualFreeformTasks.size());
+        assertEquals(4, actualFreeformTasks.size());
         assertEquals(1, actualFreeformTasks.get(0).key.id);
         assertFalse(actualFreeformTasks.get(0).isMinimized);
         assertEquals(4, actualFreeformTasks.get(1).key.id);
         assertFalse(actualFreeformTasks.get(1).isMinimized);
         assertEquals(5, actualFreeformTasks.get(2).key.id);
         assertFalse(actualFreeformTasks.get(2).isMinimized);
+        assertEquals(6, actualFreeformTasks.get(3).key.id);
+        assertFalse(actualFreeformTasks.get(3).isMinimized);
+    }
+
+    @Test
+    @EnableFlags(FLAG_ENABLE_SEPARATE_EXTERNAL_DISPLAY_TASKS)
+    public void loadTasksInBackground_freeformTask_createsDesktopTaskPerDisplay() throws Exception {
+        List<TaskInfo> tasks = Arrays.asList(
+                createRecentTaskInfo(1 /* taskId */, DEFAULT_DISPLAY),
+                createRecentTaskInfo(4 /* taskId */, DEFAULT_DISPLAY),
+                createRecentTaskInfo(5 /* taskId */, 1 /* displayId */),
+                createRecentTaskInfo(6 /* taskId */, 1 /* displayId */));
+        GroupedTaskInfo recentTaskInfos = GroupedTaskInfo.forFreeformTasks(
+                tasks, Collections.emptySet() /* minimizedTaskIds */);
+        when(mSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
+                .thenReturn(new ArrayList<>(Collections.singletonList(recentTaskInfos)));
+
+        List<GroupTask> taskList = mRecentTasksList.loadTasksInBackground(
+                Integer.MAX_VALUE /* numTasks */, -1 /* requestId */, false /* loadKeysOnly */);
+
+        assertEquals(2, taskList.size());
+        assertEquals(TaskViewType.DESKTOP, taskList.get(0).taskViewType);
+        List<Task> actualFreeformTasksDefaultDisplay = taskList.get(0).getTasks();
+        assertEquals(2, actualFreeformTasksDefaultDisplay.size());
+        assertEquals(1, actualFreeformTasksDefaultDisplay.get(0).key.id);
+        assertFalse(actualFreeformTasksDefaultDisplay.get(0).isMinimized);
+        assertEquals(4, actualFreeformTasksDefaultDisplay.get(1).key.id);
+        assertFalse(actualFreeformTasksDefaultDisplay.get(1).isMinimized);
+
+        List<Task> actualFreeformTasksExternalDisplay = taskList.get(1).getTasks();
+        assertEquals(2, actualFreeformTasksExternalDisplay.size());
+        assertEquals(5, actualFreeformTasksExternalDisplay.get(0).key.id);
+        assertFalse(actualFreeformTasksExternalDisplay.get(0).isMinimized);
+        assertEquals(6, actualFreeformTasksExternalDisplay.get(1).key.id);
+        assertFalse(actualFreeformTasksExternalDisplay.get(1).isMinimized);
     }
 
     @Test
     public void loadTasksInBackground_freeformTask_onlyMinimizedTasks_createDesktopTask()
             throws Exception {
         List<TaskInfo> tasks = Arrays.asList(
-                createRecentTaskInfo(1 /* taskId */),
-                createRecentTaskInfo(4 /* taskId */),
-                createRecentTaskInfo(5 /* taskId */));
+                createRecentTaskInfo(1 /* taskId */, DEFAULT_DISPLAY),
+                createRecentTaskInfo(4 /* taskId */, DEFAULT_DISPLAY),
+                createRecentTaskInfo(5 /* taskId */, DEFAULT_DISPLAY));
         Set<Integer> minimizedTaskIds =
                 Arrays.stream(new Integer[]{1, 4, 5}).collect(Collectors.toSet());
         GroupedTaskInfo recentTaskInfos = GroupedTaskInfo.forFreeformTasks(tasks, minimizedTaskIds);
@@ -211,9 +258,10 @@
         assertTrue(actualFreeformTasks.get(2).isMinimized);
     }
 
-    private TaskInfo createRecentTaskInfo(int taskId) {
+    private TaskInfo createRecentTaskInfo(int taskId, int displayId) {
         RecentTaskInfo recentTaskInfo = new RecentTaskInfo();
         recentTaskInfo.taskId = taskId;
+        recentTaskInfo.displayId = displayId;
         return recentTaskInfo;
     }
 }
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt
index cf59f44..14570b5 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/logging/SettingsChangeLoggerTest.kt
@@ -34,6 +34,9 @@
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_ENABLED
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_THEMED_ICON_DISABLED
 import com.android.launcher3.states.RotationHelper.ALLOW_ROTATION_PREFERENCE_KEY
+import com.android.launcher3.util.DaggerSingletonTracker
+import com.android.launcher3.util.DisplayController
+import com.android.launcher3.util.SettingsCache
 import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
@@ -60,6 +63,9 @@
     @Mock private lateinit var mStatsLogManager: StatsLogManager
 
     @Mock private lateinit var mMockLogger: StatsLogManager.StatsLogger
+    @Mock private lateinit var mTracker: DaggerSingletonTracker
+    private var displayController: DisplayController = DisplayController.INSTANCE.get(mContext)
+    private var settingsCache: SettingsCache = SettingsCache.INSTANCE.get(mContext)
 
     @Captor private lateinit var mEventCaptor: ArgumentCaptor<StatsLogManager.EventEnum>
 
@@ -82,7 +88,14 @@
         // To match the default value of ALLOW_ROTATION
         LauncherPrefs.get(mContext).put(item = ALLOW_ROTATION, value = false)
 
-        mSystemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager)
+        mSystemUnderTest =
+            SettingsChangeLogger(
+                mContext,
+                mStatsLogManager,
+                mTracker,
+                displayController,
+                settingsCache,
+            )
     }
 
     @After
@@ -93,7 +106,14 @@
 
     @Test
     fun loggingPrefs_correctDefaultValue() {
-        val systemUnderTest = SettingsChangeLogger(mContext, mStatsLogManager)
+        val systemUnderTest =
+            SettingsChangeLogger(
+                mContext,
+                mStatsLogManager,
+                mTracker,
+                displayController,
+                settingsCache,
+            )
 
         assertThat(systemUnderTest.loggingPrefs[ALLOW_ROTATION_PREFERENCE_KEY]!!.defaultValue)
             .isFalse()
@@ -120,7 +140,8 @@
         LauncherPrefs.get(mContext).put(item = ALLOW_ROTATION, value = true)
 
         // This a new object so the values of mLoggablePrefs will be different
-        SettingsChangeLogger(mContext, mStatsLogManager).logSnapshot(mInstanceId)
+        SettingsChangeLogger(mContext, mStatsLogManager, mTracker, displayController, settingsCache)
+            .logSnapshot(mInstanceId)
 
         verify(mMockLogger, atLeastOnce()).log(mEventCaptor.capture())
         val capturedEvents = mEventCaptor.allValues
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/domain/usecase/GetSysUiStatusNavFlagsUseCaseTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/domain/usecase/GetSysUiStatusNavFlagsUseCaseTest.kt
new file mode 100644
index 0000000..d384256
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/domain/usecase/GetSysUiStatusNavFlagsUseCaseTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2025 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.domain.usecase
+
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_CAPTION_BARS
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
+import com.android.launcher3.util.SystemUiController.FLAG_DARK_NAV
+import com.android.launcher3.util.SystemUiController.FLAG_DARK_STATUS
+import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_NAV
+import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_STATUS
+import com.android.systemui.shared.recents.model.ThumbnailData
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+
+class GetSysUiStatusNavFlagsUseCaseTest {
+    private val sut: GetSysUiStatusNavFlagsUseCase = GetSysUiStatusNavFlagsUseCase()
+
+    @Test
+    fun onLightStatusBarAppearance_returns_LightTheme() {
+        val thumbnailData = ThumbnailData(appearance = APPEARANCE_LIGHT_STATUS_BARS)
+        val flag = sut.invoke(thumbnailData) // 6
+        flag.assertContainsFlag(FLAG_LIGHT_STATUS)
+        flag.assertContainsFlag(FLAG_DARK_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_NAV)
+    }
+
+    @Test
+    fun onLightNavBarsAppearance_returns_LightTheme() {
+        val thumbnailData = ThumbnailData(appearance = APPEARANCE_LIGHT_NAVIGATION_BARS)
+        val flag = sut.invoke(thumbnailData)
+        flag.assertContainsFlag(FLAG_DARK_STATUS)
+        flag.assertContainsFlag(FLAG_LIGHT_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_NAV)
+    }
+
+    @Test
+    fun onLightStatusBarAndNavBarAppearance_returns_LightTheme() {
+        val thumbnailData =
+            ThumbnailData(
+                appearance = APPEARANCE_LIGHT_STATUS_BARS or APPEARANCE_LIGHT_NAVIGATION_BARS
+            )
+        val flag = sut.invoke(thumbnailData)
+        flag.assertContainsFlag(FLAG_LIGHT_NAV)
+        flag.assertContainsFlag(FLAG_LIGHT_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_NAV)
+    }
+
+    @Test
+    fun onLightAppearance_returns_LightTheme() {
+        val thumbnailData =
+            ThumbnailData(
+                appearance =
+                    APPEARANCE_LIGHT_CAPTION_BARS or
+                        APPEARANCE_LIGHT_STATUS_BARS or
+                        APPEARANCE_LIGHT_NAVIGATION_BARS
+            )
+        val flag = sut.invoke(thumbnailData)
+        flag.assertContainsFlag(FLAG_LIGHT_NAV)
+        flag.assertContainsFlag(FLAG_LIGHT_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_NAV)
+    }
+
+    @Test
+    fun onDarkAppearance_returns_DarkTheme() {
+        val thumbnailData = ThumbnailData(appearance = 0)
+        val flag = sut.invoke(thumbnailData)
+        flag.assertContainsFlag(FLAG_DARK_STATUS)
+        flag.assertContainsFlag(FLAG_DARK_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_STATUS)
+    }
+
+    @Test
+    fun onUnrelatedDarkAppearance_returns_DarkTheme() {
+        val thumbnailData = ThumbnailData(appearance = 1)
+        val flag = sut.invoke(thumbnailData)
+        flag.assertContainsFlag(FLAG_DARK_STATUS)
+        flag.assertContainsFlag(FLAG_DARK_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_STATUS)
+    }
+
+    @Test
+    fun whenThumbnailIsNull_returns_default() {
+        val flag = sut.invoke(null)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_NAV)
+        flag.assertDoesNotContainsFlag(FLAG_LIGHT_STATUS)
+        flag.assertDoesNotContainsFlag(FLAG_DARK_NAV)
+    }
+
+    private fun Int.assertContainsFlag(flag: Int) {
+        assertThat(this and flag).isNotEqualTo(0)
+    }
+
+    private fun Int.assertDoesNotContainsFlag(flag: Int) {
+        assertThat(this and flag).isEqualTo(0)
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/mapper/TaskUiStateMapperTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/mapper/TaskUiStateMapperTest.kt
new file mode 100644
index 0000000..124045f
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/mapper/TaskUiStateMapperTest.kt
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2025 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.ui.mapper
+
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.drawable.ShapeDrawable
+import android.platform.test.annotations.EnableFlags
+import android.view.Surface
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.Flags
+import com.android.quickstep.recents.ui.viewmodel.TaskData
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.LiveTile
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Snapshot
+import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.ThumbnailHeader
+import com.android.systemui.shared.recents.model.ThumbnailData
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class TaskUiStateMapperTest {
+
+    @Test
+    fun taskData_isNull_returns_Uninitialized() {
+        val result =
+            TaskUiStateMapper.toTaskThumbnailUiState(
+                taskData = null,
+                isLiveTile = false,
+                hasHeader = false,
+            )
+        assertThat(result).isEqualTo(TaskThumbnailUiState.Uninitialized)
+    }
+
+    @Test
+    fun taskData_isLiveTile_returns_LiveTile() {
+        val inputs =
+            listOf(TASK_DATA, TASK_DATA.copy(thumbnailData = null), TASK_DATA.copy(isLocked = true))
+        inputs.forEach { input ->
+            val result =
+                TaskUiStateMapper.toTaskThumbnailUiState(
+                    taskData = input,
+                    isLiveTile = true,
+                    hasHeader = false,
+                )
+            assertThat(result).isEqualTo(LiveTile.WithoutHeader)
+        }
+    }
+
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
+    @Test
+    fun taskData_isLiveTileWithHeader_returns_LiveTileWithHeader() {
+        val inputs =
+            listOf(
+                TASK_DATA,
+                TASK_DATA.copy(thumbnailData = null),
+                TASK_DATA.copy(isLocked = true),
+                TASK_DATA.copy(title = null),
+            )
+        val expected =
+            LiveTile.WithHeader(header = ThumbnailHeader(TASK_ICON, TASK_TITLE_DESCRIPTION))
+        inputs.forEach { taskData ->
+            val result =
+                TaskUiStateMapper.toTaskThumbnailUiState(
+                    taskData = taskData,
+                    isLiveTile = true,
+                    hasHeader = true,
+                )
+            assertThat(result).isEqualTo(expected)
+        }
+    }
+
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
+    @Test
+    fun taskData_isLiveTileWithHeader_missingHeaderData_returns_LiveTileWithoutHeader() {
+        val inputs =
+            listOf(
+                TASK_DATA.copy(icon = null),
+                TASK_DATA.copy(titleDescription = null),
+                TASK_DATA.copy(icon = null, titleDescription = null),
+            )
+
+        inputs.forEach { taskData ->
+            val result =
+                TaskUiStateMapper.toTaskThumbnailUiState(
+                    taskData = taskData,
+                    isLiveTile = true,
+                    hasHeader = true,
+                )
+            assertThat(result).isEqualTo(LiveTile.WithoutHeader)
+        }
+    }
+
+    @Test
+    fun taskData_isStaticTile_returns_SnapshotSplash() {
+        val result =
+            TaskUiStateMapper.toTaskThumbnailUiState(
+                taskData = TASK_DATA,
+                isLiveTile = false,
+                hasHeader = false,
+            )
+
+        val expected =
+            TaskThumbnailUiState.SnapshotSplash(
+                snapshot =
+                    Snapshot.WithoutHeader(
+                        backgroundColor = TASK_BACKGROUND_COLOR,
+                        bitmap = TASK_THUMBNAIL,
+                        thumbnailRotation = Surface.ROTATION_0,
+                    ),
+                splash = TASK_ICON,
+            )
+
+        assertThat(result).isEqualTo(expected)
+    }
+
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
+    @Test
+    fun taskData_isStaticTile_withHeader_returns_SnapshotSplashWithHeader() {
+        val inputs = listOf(TASK_DATA, TASK_DATA.copy(title = null))
+        val expected =
+            TaskThumbnailUiState.SnapshotSplash(
+                snapshot =
+                    Snapshot.WithHeader(
+                        backgroundColor = TASK_BACKGROUND_COLOR,
+                        bitmap = TASK_THUMBNAIL,
+                        thumbnailRotation = Surface.ROTATION_0,
+                        header = ThumbnailHeader(TASK_ICON, TASK_TITLE_DESCRIPTION),
+                    ),
+                splash = TASK_ICON,
+            )
+        inputs.forEach { taskData ->
+            val result =
+                TaskUiStateMapper.toTaskThumbnailUiState(
+                    taskData = taskData,
+                    isLiveTile = false,
+                    hasHeader = true,
+                )
+            assertThat(result).isEqualTo(expected)
+        }
+    }
+
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
+    @Test
+    fun taskData_isStaticTile_missingHeaderData_returns_SnapshotSplashWithoutHeader() {
+        val inputs =
+            listOf(
+                TASK_DATA.copy(titleDescription = null, icon = null),
+                TASK_DATA.copy(titleDescription = null),
+                TASK_DATA.copy(icon = null),
+            )
+        val expected =
+            Snapshot.WithoutHeader(
+                backgroundColor = TASK_BACKGROUND_COLOR,
+                thumbnailRotation = Surface.ROTATION_0,
+                bitmap = TASK_THUMBNAIL,
+            )
+        inputs.forEach { taskData ->
+            val result =
+                TaskUiStateMapper.toTaskThumbnailUiState(
+                    taskData = taskData,
+                    isLiveTile = false,
+                    hasHeader = true,
+                )
+
+            assertThat(result).isInstanceOf(TaskThumbnailUiState.SnapshotSplash::class.java)
+            result as TaskThumbnailUiState.SnapshotSplash
+            assertThat(result.snapshot).isEqualTo(expected)
+        }
+    }
+
+    @Test
+    fun taskData_thumbnailIsNull_returns_BackgroundOnly() {
+        val result =
+            TaskUiStateMapper.toTaskThumbnailUiState(
+                taskData = TASK_DATA.copy(thumbnailData = null),
+                isLiveTile = false,
+                hasHeader = false,
+            )
+
+        val expected = TaskThumbnailUiState.BackgroundOnly(TASK_BACKGROUND_COLOR)
+        assertThat(result).isEqualTo(expected)
+    }
+
+    @Test
+    fun taskData_isLocked_returns_BackgroundOnly() {
+        val result =
+            TaskUiStateMapper.toTaskThumbnailUiState(
+                taskData = TASK_DATA.copy(isLocked = true),
+                isLiveTile = false,
+                hasHeader = false,
+            )
+
+        val expected = TaskThumbnailUiState.BackgroundOnly(TASK_BACKGROUND_COLOR)
+        assertThat(result).isEqualTo(expected)
+    }
+
+    private companion object {
+        const val TASK_TITLE_DESCRIPTION = "Title Description 1"
+        val TASK_ICON = ShapeDrawable()
+        val TASK_THUMBNAIL = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
+        val TASK_THUMBNAIL_DATA =
+            ThumbnailData(thumbnail = TASK_THUMBNAIL, rotation = Surface.ROTATION_0)
+        val TASK_BACKGROUND_COLOR = Color.rgb(1, 2, 3)
+        val TASK_DATA =
+            TaskData.Data(
+                1,
+                title = "Task 1",
+                titleDescription = TASK_TITLE_DESCRIPTION,
+                icon = TASK_ICON,
+                thumbnailData = TASK_THUMBNAIL_DATA,
+                backgroundColor = TASK_BACKGROUND_COLOR,
+                isLocked = false,
+            )
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt
index 54a27e9..c031150 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/ui/viewmodel/TaskViewModelTest.kt
@@ -18,11 +18,18 @@
 
 import android.graphics.Color
 import android.graphics.drawable.ShapeDrawable
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_CAPTION_BARS
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
+import android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_NAV
+import com.android.launcher3.util.SystemUiController.FLAG_LIGHT_STATUS
 import com.android.launcher3.util.TestDispatcherProvider
 import com.android.quickstep.recents.domain.model.TaskModel
+import com.android.quickstep.recents.domain.usecase.GetSysUiStatusNavFlagsUseCase
 import com.android.quickstep.recents.domain.usecase.GetTaskUseCase
 import com.android.quickstep.recents.viewmodel.RecentsViewData
+import com.android.quickstep.views.TaskViewType
 import com.android.systemui.shared.recents.model.ThumbnailData
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -45,15 +52,18 @@
 
     private val recentsViewData = RecentsViewData()
     private val getTaskUseCase = mock<GetTaskUseCase>()
-    private val sut =
-        TaskViewModel(
-            recentsViewData = recentsViewData,
-            getTaskUseCase = getTaskUseCase,
-            dispatcherProvider = TestDispatcherProvider(unconfinedTestDispatcher),
-        )
+    private lateinit var sut: TaskViewModel
 
     @Before
     fun setUp() {
+        sut =
+            TaskViewModel(
+                taskViewType = TaskViewType.SINGLE,
+                recentsViewData = recentsViewData,
+                getTaskUseCase = getTaskUseCase,
+                getSysUiStatusNavFlagsUseCase = GetSysUiStatusNavFlagsUseCase(),
+                dispatcherProvider = TestDispatcherProvider(unconfinedTestDispatcher),
+            )
         whenever(getTaskUseCase.invoke(TASK_MODEL_1.id)).thenReturn(flow { emit(TASK_MODEL_1) })
         whenever(getTaskUseCase.invoke(TASK_MODEL_2.id)).thenReturn(flow { emit(TASK_MODEL_2) })
         whenever(getTaskUseCase.invoke(TASK_MODEL_3.id)).thenReturn(flow { emit(TASK_MODEL_3) })
@@ -65,11 +75,41 @@
     fun singleTaskRetrieved_when_validTaskId() =
         testScope.runTest {
             sut.bind(TASK_MODEL_1.id)
-            val expectedResult = TaskTileUiState(listOf(TASK_MODEL_1.toUiState()), false)
+            val expectedResult =
+                TaskTileUiState(
+                    tasks = listOf(TASK_MODEL_1.toUiState()),
+                    isLiveTile = false,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_LIGHT_THEME,
+                )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
 
     @Test
+    fun hasHeader_when_taskViewTypeIsDesktop() =
+        testScope.runTest {
+            val expectedResults =
+                mapOf(
+                    TaskViewType.SINGLE to false,
+                    TaskViewType.GROUPED to false,
+                    TaskViewType.DESKTOP to true,
+                )
+
+            expectedResults.forEach { (type, expectedResult) ->
+                sut =
+                    TaskViewModel(
+                        taskViewType = type,
+                        recentsViewData = recentsViewData,
+                        getTaskUseCase = getTaskUseCase,
+                        getSysUiStatusNavFlagsUseCase = GetSysUiStatusNavFlagsUseCase(),
+                        dispatcherProvider = TestDispatcherProvider(unconfinedTestDispatcher),
+                    )
+                sut.bind(TASK_MODEL_1.id)
+                assertThat(sut.state.first().hasHeader).isEqualTo(expectedResult)
+            }
+        }
+
+    @Test
     fun multipleTasksRetrieved_when_validTaskIds() =
         testScope.runTest {
             sut.bind(TASK_MODEL_1.id, TASK_MODEL_2.id, TASK_MODEL_3.id, INVALID_TASK_ID)
@@ -83,6 +123,8 @@
                             TaskData.NoData(INVALID_TASK_ID),
                         ),
                     isLiveTile = false,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_LIGHT_THEME,
                 )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
@@ -103,6 +145,8 @@
                             TASK_MODEL_3.toUiState(),
                         ),
                     isLiveTile = true,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_LIGHT_THEME,
                 )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
@@ -123,6 +167,8 @@
                             TASK_MODEL_3.toUiState(),
                         ),
                     isLiveTile = false,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_LIGHT_THEME,
                 )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
@@ -142,6 +188,8 @@
                             TASK_MODEL_3.toUiState(),
                         ),
                     isLiveTile = false,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_LIGHT_THEME,
                 )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
@@ -157,6 +205,8 @@
                 TaskTileUiState(
                     tasks = listOf(TASK_MODEL_1.toUiState(), TASK_MODEL_2.toUiState()),
                     isLiveTile = false,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_LIGHT_THEME,
                 )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
@@ -166,7 +216,12 @@
         testScope.runTest {
             sut.bind(INVALID_TASK_ID)
             val expectedResult =
-                TaskTileUiState(listOf(TaskData.NoData(INVALID_TASK_ID)), isLiveTile = false)
+                TaskTileUiState(
+                    listOf(TaskData.NoData(INVALID_TASK_ID)),
+                    isLiveTile = false,
+                    hasHeader = false,
+                    sysUiStatusNavFlags = FLAGS_APPEARANCE_DEFAULT,
+                )
             assertThat(sut.state.first()).isEqualTo(expectedResult)
         }
 
@@ -174,21 +229,29 @@
         TaskData.Data(
             taskId = id,
             title = title,
+            titleDescription = titleDescription,
             icon = icon!!,
             thumbnailData = thumbnail,
             backgroundColor = backgroundColor,
             isLocked = isLocked,
         )
 
-    companion object {
+    private companion object {
         const val INVALID_TASK_ID = -1
+        const val FLAGS_APPEARANCE_LIGHT_THEME = FLAG_LIGHT_STATUS or FLAG_LIGHT_NAV
+        const val FLAGS_APPEARANCE_DEFAULT = 0
+        const val APPEARANCE_LIGHT_THEME =
+            APPEARANCE_LIGHT_CAPTION_BARS or
+                APPEARANCE_LIGHT_STATUS_BARS or
+                APPEARANCE_LIGHT_NAVIGATION_BARS
+
         val TASK_MODEL_1 =
             TaskModel(
                 1,
                 "Title 1",
                 "Content Description 1",
                 ShapeDrawable(),
-                ThumbnailData(),
+                ThumbnailData(appearance = APPEARANCE_LIGHT_THEME),
                 Color.BLACK,
                 false,
             )
@@ -198,7 +261,7 @@
                 "Title 2",
                 "Content Description 2",
                 ShapeDrawable(),
-                ThumbnailData(),
+                ThumbnailData(appearance = APPEARANCE_LIGHT_THEME),
                 Color.RED,
                 true,
             )
@@ -208,7 +271,7 @@
                 "Title 3",
                 "Content Description 3",
                 ShapeDrawable(),
-                ThumbnailData(),
+                ThumbnailData(appearance = APPEARANCE_LIGHT_THEME),
                 Color.BLUE,
                 false,
             )
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/SysUiStatusNavFlagsUseCaseTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/SysUiStatusNavFlagsUseCaseTest.kt
deleted file mode 100644
index 92f2efd..0000000
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/recents/usecase/SysUiStatusNavFlagsUseCaseTest.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.usecase
-
-import android.content.ComponentName
-import android.content.Intent
-import android.graphics.Bitmap
-import android.graphics.Color
-import com.android.quickstep.recents.data.FakeTasksRepository
-import com.android.systemui.shared.recents.model.Task
-import com.android.systemui.shared.recents.model.ThumbnailData
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.whenever
-
-/** Test for [SysUiStatusNavFlagsUseCase] */
-class SysUiStatusNavFlagsUseCaseTest {
-    private lateinit var tasksRepository: FakeTasksRepository
-    private lateinit var sysUiStatusNavFlagsUseCase: SysUiStatusNavFlagsUseCase
-
-    @Before
-    fun setup() {
-        tasksRepository = FakeTasksRepository()
-        sysUiStatusNavFlagsUseCase = SysUiStatusNavFlagsUseCase(tasksRepository)
-        initTaskRepository()
-    }
-
-    @Test
-    fun onLightAppearanceReturnExpectedFlags() {
-        assertThat(sysUiStatusNavFlagsUseCase.getSysUiStatusNavFlags(FIRST_TASK_ID))
-            .isEqualTo(FLAGS_APPEARANCE_LIGHT_THEME)
-    }
-
-    @Test
-    fun onDarkAppearanceReturnExpectedFlags() {
-        assertThat(sysUiStatusNavFlagsUseCase.getSysUiStatusNavFlags(SECOND_TASK_ID))
-            .isEqualTo(FLAGS_APPEARANCE_DARK_THEME)
-    }
-
-    @Test
-    fun whenThumbnailIsNullReturnDefault() {
-        assertThat(sysUiStatusNavFlagsUseCase.getSysUiStatusNavFlags(UNKNOWN_TASK_ID))
-            .isEqualTo(FLAGS_DEFAULT)
-    }
-
-    private fun initTaskRepository() {
-        val firstTask =
-            Task(Task.TaskKey(FIRST_TASK_ID, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
-                colorBackground = Color.BLACK
-            }
-        val firstThumbnailData =
-            ThumbnailData(
-                thumbnail =
-                    mock<Bitmap>().apply {
-                        whenever(width).thenReturn(THUMBNAIL_WIDTH)
-                        whenever(height).thenReturn(THUMBNAIL_HEIGHT)
-                    },
-                appearance = APPEARANCE_LIGHT_THEME,
-            )
-
-        val secondTask =
-            Task(Task.TaskKey(SECOND_TASK_ID, 0, Intent(), ComponentName("", ""), 0, 2005)).apply {
-                colorBackground = Color.BLACK
-            }
-        val secondThumbnailData =
-            ThumbnailData(
-                thumbnail =
-                    mock<Bitmap>().apply {
-                        whenever(width).thenReturn(THUMBNAIL_WIDTH)
-                        whenever(height).thenReturn(THUMBNAIL_HEIGHT)
-                    },
-                appearance = APPEARANCE_DARK_THEME,
-            )
-
-        tasksRepository.seedTasks(listOf(firstTask, secondTask))
-        tasksRepository.seedThumbnailData(
-            mapOf(FIRST_TASK_ID to firstThumbnailData, SECOND_TASK_ID to secondThumbnailData)
-        )
-        tasksRepository.setVisibleTasks(setOf(FIRST_TASK_ID, SECOND_TASK_ID))
-    }
-
-    companion object {
-        const val FIRST_TASK_ID = 0
-        const val SECOND_TASK_ID = 100
-        const val UNKNOWN_TASK_ID = 404
-        const val THUMBNAIL_WIDTH = 100
-        const val THUMBNAIL_HEIGHT = 200
-        const val APPEARANCE_LIGHT_THEME = 24
-        const val FLAGS_APPEARANCE_LIGHT_THEME = 5
-        const val APPEARANCE_DARK_THEME = 0
-        const val FLAGS_APPEARANCE_DARK_THEME = 10
-        const val FLAGS_DEFAULT = 0
-    }
-}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt
index a956c9c..aec586d 100644
--- a/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/task/thumbnail/TaskThumbnailViewModelImplTest.kt
@@ -16,39 +16,15 @@
 
 package com.android.quickstep.task.thumbnail
 
-import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
-import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
-import android.content.ComponentName
-import android.content.Intent
-import android.graphics.Bitmap
-import android.graphics.Color
 import android.graphics.Matrix
-import android.graphics.drawable.Drawable
-import android.platform.test.annotations.EnableFlags
 import android.platform.test.flag.junit.SetFlagsRule
-import android.view.Surface
 import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.launcher3.Flags
 import com.android.launcher3.util.TestDispatcherProvider
-import com.android.quickstep.recents.data.FakeRecentsDeviceProfileRepository
-import com.android.quickstep.recents.data.FakeTasksRepository
-import com.android.quickstep.recents.data.RecentsDeviceProfile
 import com.android.quickstep.recents.usecase.GetThumbnailPositionUseCase
 import com.android.quickstep.recents.usecase.ThumbnailPositionState.MatrixScaling
 import com.android.quickstep.recents.usecase.ThumbnailPositionState.MissingThumbnail
-import com.android.quickstep.recents.viewmodel.RecentsViewData
-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.ThumbnailHeader
-import com.android.quickstep.task.thumbnail.TaskThumbnailUiState.Uninitialized
-import com.android.quickstep.task.viewmodel.TaskContainerData
 import com.android.quickstep.task.viewmodel.TaskThumbnailViewModelImpl
-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.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
@@ -66,221 +42,18 @@
     private val dispatcher = StandardTestDispatcher()
     private val testScope = TestScope(dispatcher)
 
-    private val recentsViewData = RecentsViewData()
-    private val taskContainerData = TaskContainerData()
     private val dispatcherProvider = TestDispatcherProvider(dispatcher)
-    private val tasksRepository = FakeTasksRepository()
-    private val deviceProfileRepository = FakeRecentsDeviceProfileRepository()
     private val mGetThumbnailPositionUseCase = mock<GetThumbnailPositionUseCase>()
     private val splashAlphaUseCase: SplashAlphaUseCase = mock()
 
     private val systemUnderTest by lazy {
         TaskThumbnailViewModelImpl(
-            recentsViewData,
-            taskContainerData,
             dispatcherProvider,
-            tasksRepository,
-            deviceProfileRepository,
             mGetThumbnailPositionUseCase,
             splashAlphaUseCase,
         )
     }
 
-    private val fullscreenTaskIdRange: IntRange = 0..5
-    private val freeformTaskIdRange: IntRange = 6..10
-
-    private val fullscreenTasks = fullscreenTaskIdRange.map(::createTaskWithId)
-    private val freeformTasks = freeformTaskIdRange.map(::createFreeformTaskWithId)
-    private val tasks = fullscreenTasks + freeformTasks
-
-    @Test
-    fun initialStateIsUninitialized() =
-        testScope.runTest { assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized) }
-
-    @Test
-    fun bindRunningTask_thenStateIs_LiveTile() =
-        testScope.runTest {
-            val taskId = 1
-            tasksRepository.seedTasks(tasks)
-            tasksRepository.setVisibleTasks(setOf(taskId))
-            recentsViewData.runningTaskIds.value = setOf(taskId)
-            systemUnderTest.bind(taskId)
-
-            assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile.WithoutHeader)
-        }
-
-    @Test
-    fun bindRunningTaskShouldShowScreenshot_thenStateIs_SnapshotSplash() =
-        testScope.runTest {
-            val taskId = 1
-            val expectedThumbnailData = createThumbnailData()
-            tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
-            val expectedIconData = mock<Drawable>()
-            tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
-            tasksRepository.seedTasks(tasks)
-            tasksRepository.setVisibleTasks(setOf(taskId))
-            recentsViewData.runningTaskIds.value = setOf(taskId)
-            recentsViewData.runningTaskShowScreenshot.value = true
-            systemUnderTest.bind(taskId)
-
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(
-                    SnapshotSplash(
-                        Snapshot.WithoutHeader(
-                            backgroundColor = Color.rgb(1, 1, 1),
-                            bitmap = expectedThumbnailData.thumbnail!!,
-                            thumbnailRotation = Surface.ROTATION_0,
-                        ),
-                        expectedIconData,
-                    )
-                )
-        }
-
-    @Test
-    fun bindRunningTaskThenStoppedTaskWithoutThumbnail_thenStateChangesToBackgroundOnly() =
-        testScope.runTest {
-            val runningTaskId = 1
-            val stoppedTaskId = 2
-            tasksRepository.seedTasks(tasks)
-            tasksRepository.setVisibleTasks(setOf(runningTaskId, stoppedTaskId))
-            recentsViewData.runningTaskIds.value = setOf(runningTaskId)
-            systemUnderTest.bind(runningTaskId)
-            assertThat(systemUnderTest.uiState.first()).isEqualTo(LiveTile.WithoutHeader)
-
-            systemUnderTest.bind(stoppedTaskId)
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
-        }
-
-    @Test
-    fun bindStoppedTaskWithoutThumbnail_thenStateIs_BackgroundOnly_withAlphaRemoved() =
-        testScope.runTest {
-            val stoppedTaskId = 2
-            tasksRepository.seedTasks(tasks)
-            tasksRepository.setVisibleTasks(setOf(stoppedTaskId))
-
-            systemUnderTest.bind(stoppedTaskId)
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
-        }
-
-    @Test
-    fun bindLockedTaskWithThumbnail_thenStateIs_BackgroundOnly() =
-        testScope.runTest {
-            val taskId = 2
-            tasksRepository.seedThumbnailData(mapOf(taskId to createThumbnailData()))
-            tasks[taskId].isLocked = true
-            tasksRepository.seedTasks(tasks)
-            tasksRepository.setVisibleTasks(setOf(taskId))
-
-            systemUnderTest.bind(taskId)
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(BackgroundOnly(backgroundColor = Color.rgb(2, 2, 2)))
-        }
-
-    @Test
-    fun bindStoppedTaskWithThumbnail_thenStateIs_SnapshotSplash_withAlphaRemoved() =
-        testScope.runTest {
-            val taskId = 2
-            val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_270)
-            tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
-            val expectedIconData = mock<Drawable>()
-            tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
-            tasksRepository.seedTasks(tasks)
-            tasksRepository.setVisibleTasks(setOf(taskId))
-
-            systemUnderTest.bind(taskId)
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(
-                    SnapshotSplash(
-                        Snapshot.WithoutHeader(
-                            backgroundColor = Color.rgb(2, 2, 2),
-                            bitmap = expectedThumbnailData.thumbnail!!,
-                            thumbnailRotation = Surface.ROTATION_270,
-                        ),
-                        expectedIconData,
-                    )
-                )
-        }
-
-    @Test
-    fun bindNonVisibleStoppedTask_whenMadeVisible_thenStateIsSnapshotSplash() =
-        testScope.runTest {
-            val taskId = 2
-            val expectedThumbnailData = createThumbnailData()
-            tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
-            val expectedIconData = mock<Drawable>()
-            tasksRepository.seedIconData(taskId, "Task $taskId", "", expectedIconData)
-            tasksRepository.seedTasks(tasks)
-
-            systemUnderTest.bind(taskId)
-            assertThat(systemUnderTest.uiState.first()).isEqualTo(Uninitialized)
-
-            tasksRepository.setVisibleTasks(setOf(taskId))
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(
-                    SnapshotSplash(
-                        Snapshot.WithoutHeader(
-                            backgroundColor = Color.rgb(2, 2, 2),
-                            bitmap = expectedThumbnailData.thumbnail!!,
-                            thumbnailRotation = Surface.ROTATION_0,
-                        ),
-                        expectedIconData,
-                    )
-                )
-        }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
-    fun bindRunningTask_inDesktop_thenStateIs_LiveTile_withHeader() =
-        testScope.runTest {
-            deviceProfileRepository.setRecentsDeviceProfile(
-                RecentsDeviceProfile(isLargeScreen = true, canEnterDesktopMode = true)
-            )
-
-            val taskId = freeformTaskIdRange.first
-            val expectedIconData = mock<Drawable>()
-            tasksRepository.seedIconData(taskId, "Task $taskId", "Task $taskId", expectedIconData)
-            tasksRepository.seedTasks(freeformTasks)
-            tasksRepository.setVisibleTasks(setOf(taskId))
-            recentsViewData.runningTaskIds.value = setOf(taskId)
-            systemUnderTest.bind(taskId)
-
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(LiveTile.WithHeader(ThumbnailHeader(expectedIconData, "Task $taskId")))
-        }
-
-    @Test
-    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_EXPLODED_VIEW)
-    fun bindStoppedTaskWithThumbnail_inDesktop_thenStateIs_SnapshotSplash_withHeader() =
-        testScope.runTest {
-            deviceProfileRepository.setRecentsDeviceProfile(
-                RecentsDeviceProfile(isLargeScreen = true, canEnterDesktopMode = true)
-            )
-
-            val taskId = freeformTaskIdRange.first
-            val expectedThumbnailData = createThumbnailData(rotation = Surface.ROTATION_0)
-            tasksRepository.seedThumbnailData(mapOf(taskId to expectedThumbnailData))
-            val expectedIconData = mock<Drawable>()
-            tasksRepository.seedIconData(taskId, "Task $taskId", "Task $taskId", expectedIconData)
-            tasksRepository.seedTasks(freeformTasks)
-            tasksRepository.setVisibleTasks(setOf(taskId))
-
-            systemUnderTest.bind(taskId)
-            assertThat(systemUnderTest.uiState.first())
-                .isEqualTo(
-                    SnapshotSplash(
-                        Snapshot.WithHeader(
-                            backgroundColor = Color.rgb(taskId, taskId, taskId),
-                            bitmap = expectedThumbnailData.thumbnail!!,
-                            thumbnailRotation = Surface.ROTATION_0,
-                            header = ThumbnailHeader(expectedIconData, "Task $taskId"),
-                        ),
-                        expectedIconData,
-                    )
-                )
-        }
-
     @Test
     fun getSnapshotMatrix_MissingThumbnail() =
         testScope.runTest {
@@ -313,75 +86,7 @@
                 .isEqualTo(MATRIX)
         }
 
-    @Test
-    fun getForegroundScrimDimProgress_returnsForegroundMaxScrim() =
-        testScope.runTest {
-            recentsViewData.tintAmount.value = 0.32f
-            taskContainerData.taskMenuOpenProgress.value = 0f
-            assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.32f)
-        }
-
-    @Test
-    fun getTaskMenuScrimDimProgress_returnsTaskMenuScrim() =
-        testScope.runTest {
-            recentsViewData.tintAmount.value = 0f
-            taskContainerData.taskMenuOpenProgress.value = 1f
-            assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0.4f)
-        }
-
-    @Test
-    fun getForegroundScrimDimProgress_returnsNoScrim() =
-        testScope.runTest {
-            recentsViewData.tintAmount.value = 0f
-            taskContainerData.taskMenuOpenProgress.value = 0f
-            assertThat(systemUnderTest.dimProgress.first()).isEqualTo(0f)
-        }
-
-    private fun createTaskWithId(taskId: Int) =
-        Task(
-                Task.TaskKey(
-                    taskId,
-                    WINDOWING_MODE_FULLSCREEN,
-                    Intent(),
-                    ComponentName("", ""),
-                    0,
-                    2000,
-                )
-            )
-            .apply {
-                colorBackground = Color.argb(taskId, taskId, taskId, taskId)
-                titleDescription = "Task $taskId"
-                icon = mock<Drawable>()
-            }
-
-    private fun createFreeformTaskWithId(taskId: Int) =
-        Task(
-                Task.TaskKey(
-                    taskId,
-                    WINDOWING_MODE_FREEFORM,
-                    Intent(),
-                    ComponentName("", ""),
-                    0,
-                    2000,
-                )
-            )
-            .apply {
-                colorBackground = Color.argb(taskId, taskId, taskId, taskId)
-                titleDescription = "Task $taskId"
-                icon = mock<Drawable>()
-            }
-
-    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, rotation = rotation)
-    }
-
-    companion object {
-        const val THUMBNAIL_WIDTH = 100
-        const val THUMBNAIL_HEIGHT = 200
+    private companion object {
         const val CANVAS_WIDTH = 300
         const val CANVAS_HEIGHT = 600
         val MATRIX =
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index f57c35f..c215ff2 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -20,7 +20,6 @@
 
 import android.os.SystemProperties;
 
-import androidx.annotation.NonNull;
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.Until;
 
@@ -33,7 +32,6 @@
 import com.android.quickstep.fallback.RecentsState;
 import com.android.quickstep.fallback.window.RecentsWindowManager;
 import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.RecentsViewContainer;
 
 import org.junit.rules.RuleChain;
 import org.junit.rules.TestRule;
@@ -78,23 +76,12 @@
         waitForRecentsWindowCondition(message, condition, TestUtil.DEFAULT_UI_TIMEOUT);
     }
 
-    protected <T> T getFromRecentsWindowManager(Function<RecentsWindowManager, T> f) {
+    protected <T> T getFromRecentsWindow(Function<RecentsWindowManager, T> f) {
         if (!TestHelpers.isInLauncherProcess()) return null;
-        return getOnUiThread(
-                () -> f.apply(RecentsWindowManager.getRecentsWindowTracker().getCreatedContext()));
-    }
-
-    protected void executeOnRecentsWindow(Consumer<RecentsWindowManager> f) {
-        getFromRecentsWindowManager(recentsWindow -> {
-            f.accept(recentsWindow);
-            return null;
-        });
-    }
-
-    protected void executeOnRecentsViewContainerInTearDown(
-            @NonNull Consumer<RecentsViewContainer> f) {
-        executeOnRecentsWindow(container -> {
-            if (container != null) f.accept(container);
+        return getOnUiThread(() -> {
+            RecentsWindowManager recentsWindowManager =
+                    RecentsWindowManager.getRecentsWindowTracker().getCreatedContext();
+            return recentsWindowManager != null ? f.apply(recentsWindowManager) : null;
         });
     }
 
@@ -104,12 +91,12 @@
             String message, Function<RecentsWindowManager, Boolean> condition, long timeout) {
         verifyKeyguardInvisible();
         if (!TestHelpers.isInLauncherProcess()) return;
-        Wait.atMost(message, () -> getFromRecentsWindowManager(condition), mLauncher, timeout);
+        Wait.atMost(message, () -> getFromRecentsWindow(condition), mLauncher, timeout);
     }
 
     protected boolean isInRecentsWindowState(Supplier<RecentsState> state) {
         if (!TestHelpers.isInLauncherProcess()) return true;
-        return getFromRecentsWindowManager(
+        return getFromRecentsWindow(
                 recentsWindow -> recentsWindow.getStateManager().getState() == state.get());
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
index 52bd2ea..76aab39 100644
--- a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
@@ -19,6 +19,7 @@
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
+import android.content.pm.PackageManager
 import android.platform.test.annotations.EnableFlags
 import android.view.Display.DEFAULT_DISPLAY
 import androidx.test.platform.app.InstrumentationRegistry
@@ -72,7 +73,7 @@
     private val overlayFactory: TaskOverlayFactory = mock()
     private val factory: TaskShortcutFactory =
         DesktopSystemShortcut.createFactory(abstractFloatingViewHelper)
-    private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
+    private val context: Context = spy(InstrumentationRegistry.getInstrumentation().targetContext)
 
     private lateinit var mockitoSession: StaticMockitoSession
 
@@ -151,6 +152,32 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY)
+    fun createDesktopTaskShortcutFactory_defaultHomeTask() {
+        val packageManager: PackageManager = mock()
+        val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
+        whenever(context.packageManager).thenReturn(packageManager)
+        whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)
+        val taskKey =
+            TaskKey(
+                /* id */ 1,
+                /* windowingMode */ 0,
+                Intent(),
+                homeActivities,
+                /* userId */ 0,
+                /* lastActiveTime */ 2000,
+                DEFAULT_DISPLAY,
+                homeActivities,
+                /* numActivities */ 1,
+                /* isTopActivityNoDisplay */ false,
+                /* isActivityStackTransparent */ false,
+            )
+        val taskContainer = createTaskContainer(Task(taskKey).apply { isDockable = true })
+        val shortcuts = factory.getShortcuts(launcher, taskContainer)
+        assertThat(shortcuts).isNull()
+    }
+
+    @Test
     fun createDesktopTaskShortcutFactory_undockable() {
         val unDockableTask = createTask().apply { isDockable = false }
         val taskContainer = createTaskContainer(unDockableTask)
diff --git a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
index f923142..c78fe1c 100644
--- a/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
+++ b/quickstep/tests/src/com/android/quickstep/DigitalWellBeingToastTest.java
@@ -21,6 +21,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import android.app.PendingIntent;
@@ -93,7 +94,8 @@
         final TaskView task = getOnceNotNull("No latest task", launcher -> getLatestTask(launcher));
 
         return getFromLauncher(launcher -> {
-            TaskContainer taskContainer = task.getTaskContainers().get(0);
+            TaskContainer taskContainer = task.getFirstTaskContainer();
+            assertNotNull(taskContainer);
             assertTrue("Latest task is not Calculator", calculatorPackage.equals(
                     taskContainer.getTask().getTopComponent().getPackageName()));
             return taskContainer.getDigitalWellBeingToast();
diff --git a/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt
index 4111dec..818841a 100644
--- a/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/ExternalDisplaySystemShortcutTest.kt
@@ -19,6 +19,7 @@
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
+import android.content.pm.PackageManager
 import android.platform.test.annotations.EnableFlags
 import android.platform.test.flag.junit.SetFlagsRule
 import android.view.Display.DEFAULT_DISPLAY
@@ -75,7 +76,7 @@
     private val overlayFactory: TaskOverlayFactory = mock()
     private val factory: TaskShortcutFactory =
         ExternalDisplaySystemShortcut.createFactory(abstractFloatingViewHelper)
-    private val context: Context = InstrumentationRegistry.getInstrumentation().targetContext
+    private val context: Context = spy(InstrumentationRegistry.getInstrumentation().targetContext)
 
     private lateinit var mockitoSession: StaticMockitoSession
 
@@ -161,6 +162,35 @@
     }
 
     @Test
+    @EnableFlags(
+        Flags.FLAG_MOVE_TO_EXTERNAL_DISPLAY_SHORTCUT,
+        Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODALS_POLICY,
+    )
+    fun createExternalDisplayTaskShortcut_defaultHomeTask() {
+        val packageManager: PackageManager = mock()
+        val homeActivities = ComponentName("defaultHomePackage", /* class */ "")
+        whenever(context.packageManager).thenReturn(packageManager)
+        whenever(packageManager.getHomeActivities(any())).thenReturn(homeActivities)
+        val taskKey =
+            TaskKey(
+                /* id */ 1,
+                /* windowingMode */ 0,
+                Intent(),
+                homeActivities,
+                /* userId */ 0,
+                /* lastActiveTime */ 2000,
+                DEFAULT_DISPLAY,
+                homeActivities,
+                /* numActivities */ 1,
+                /* isTopActivityNoDisplay */ false,
+                /* isActivityStackTransparent */ false,
+            )
+        val taskContainer = createTaskContainer(Task(taskKey).apply { isDockable = true })
+        val shortcuts = factory.getShortcuts(launcher, taskContainer)
+        assertThat(shortcuts).isNull()
+    }
+
+    @Test
     @EnableFlags(Flags.FLAG_MOVE_TO_EXTERNAL_DISPLAY_SHORTCUT)
     fun externalDisplaySystemShortcutClicked() {
         val task = createTask()
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index ff0ad53..a0ec635 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -43,6 +43,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.launcher3.testing.shared.ResourceUtils;
+import com.android.launcher3.util.DaggerSingletonTracker;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.RotationUtils;
 import com.android.launcher3.util.WindowBounds;
@@ -301,7 +302,8 @@
         final DisplayController displayController = mock(DisplayController.class);
         doReturn(mInfo).when(displayController).getInfo();
         final SimpleOrientationTouchTransformer transformer =
-                new SimpleOrientationTouchTransformer(getApplicationContext(), displayController);
+                new SimpleOrientationTouchTransformer(getApplicationContext(), displayController,
+                        mock(DaggerSingletonTracker.class));
         final MotionEvent move1 = generateMotionEvent(MotionEvent.ACTION_MOVE, 100, 10);
         transformer.transform(move1, Surface.ROTATION_90);
         // The position is transformed to 90 degree.
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 15038a4..e0560e2 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -55,7 +55,6 @@
 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
 import com.android.quickstep.fallback.RecentsState;
 import com.android.quickstep.views.RecentsView;
-import com.android.quickstep.views.RecentsViewContainer;
 
 import org.junit.After;
 import org.junit.Before;
@@ -64,6 +63,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.function.Consumer;
+import java.util.function.Function;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
@@ -91,17 +91,16 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
-        executeOnRecentsViewContainer(container -> {
-            RecentsView recentsView = container.getOverviewPanel();
-            recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(true);
-        });
+        runOnRecentsView(recentsView ->
+                recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(true));
     }
 
     @After
     public void tearDown() {
-        executeOnRecentsViewContainerInTearDown(container -> {
-            RecentsView recentsView = container.getOverviewPanel();
-            recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(false);
+        runOnRecentsView(recentsView -> {
+            if (recentsView != null) {
+                recentsView.getPagedViewOrientedState().forceAllowRotationForTesting(false);
+            }
         });
     }
 
@@ -111,14 +110,6 @@
         startTestActivity(2);
     }
 
-    private void startTestAppsWithCheck() throws Exception {
-        startTestApps();
-        executeOnLauncher(launcher -> assertTrue(
-                "Launcher activity is the top activity; expecting another activity to be the top "
-                        + "one",
-                isInLaunchedApp(launcher)));
-    }
-
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -137,25 +128,24 @@
         Overview overview = mLauncher.goHome().switchToOverview();
         assertIsInState(
                 "Launcher internal state didn't switch to Overview", ExpectedState.OVERVIEW);
-        executeOnRecentsViewContainer(container -> assertTrue(
-                "Don't have at least 3 tasks", getTaskCount(container) >= 3));
+        runOnRecentsView(recentsView -> assertTrue("Don't have at least 3 tasks",
+                recentsView.getTaskViewCount() >= 3));
 
         // Test flinging forward and backward.
-        executeOnRecentsViewContainer(container -> assertEquals("Current task in Overview is not 0",
-                0, getCurrentOverviewPage(container)));
+        runOnRecentsView(recentsView -> assertEquals("Current task in Overview is not 0",
+                0, recentsView.getCurrentPage()));
 
         overview.flingForward();
         assertIsInState("Launcher internal state is not Overview", ExpectedState.OVERVIEW);
-        final Integer currentTaskAfterFlingForward = getFromLauncher(
-                launcher -> getCurrentOverviewPage(launcher));
-        executeOnRecentsViewContainer(container -> assertTrue(
-                "Current task in Overview is still 0", currentTaskAfterFlingForward > 0));
+        final Integer currentTaskAfterFlingForward =
+                getFromRecentsView(RecentsView::getCurrentPage);
+        runOnRecentsView(recentsView -> assertTrue("Current task in Overview is still 0",
+                currentTaskAfterFlingForward > 0));
 
         overview.flingBackward();
         assertIsInState("Launcher internal state is not Overview", ExpectedState.OVERVIEW);
-        executeOnRecentsViewContainer(container -> assertTrue(
-                "Flinging back in Overview did nothing",
-                getCurrentOverviewPage(container) < currentTaskAfterFlingForward));
+        runOnRecentsView(recentsView -> assertTrue("Flinging back in Overview did nothing",
+                recentsView.getCurrentPage() < currentTaskAfterFlingForward));
 
         // Test opening a task.
         OverviewTask task = mLauncher.goHome().switchToOverview().getCurrentTask();
@@ -164,29 +154,25 @@
         assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject(
                         By.pkg(getAppPackageName()).text("TestActivity2")),
                 TestUtil.DEFAULT_UI_TIMEOUT));
-        executeOnLauncher(launcher -> assertTrue(
-                "Launcher activity is the top activity; expecting another activity to be the top "
-                        + "one",
-                isInLaunchedApp(launcher)));
+        expectLaunchedAppState();
 
         // Test dismissing a task.
         overview = mLauncher.goHome().switchToOverview();
-        assertIsInState(
-                "Launcher internal state didn't switch to Overview", ExpectedState.OVERVIEW);
-        final Integer numTasks = getFromLauncher(launcher -> getTaskCount(launcher));
+        assertIsInState("Launcher internal state didn't switch to Overview",
+                ExpectedState.OVERVIEW);
+        final Integer numTasks = getFromRecentsView(RecentsView::getTaskViewCount);
         task = overview.getCurrentTask();
         assertNotNull("overview.getCurrentTask() returned null (2)", task);
         task.dismiss();
-        executeOnRecentsViewContainer(
-                container -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
-                        numTasks - 1, getTaskCount(container)));
+        runOnRecentsView(recentsView -> assertEquals(
+                "Dismissing a task didn't remove 1 task from Overview",
+                numTasks - 1, recentsView.getTaskViewCount()));
 
         // Test dismissing all tasks.
         mLauncher.goHome().switchToOverview().dismissAllTasks();
         assertIsInState("Launcher internal state is not Home", ExpectedState.HOME);
-        executeOnRecentsViewContainer(
-                container -> assertEquals("Still have tasks after dismissing all",
-                        0, getTaskCount(container)));
+        runOnRecentsView(recentsView -> assertEquals("Still have tasks after dismissing all",
+                0, recentsView.getTaskViewCount()));
     }
 
     /**
@@ -263,26 +249,6 @@
         overview.launchFocusedTaskByEnterKey(CALCULATOR_APP_PACKAGE); // Assert app is focused.
     }
 
-    private RecentsView getOverviewPanel(RecentsViewContainer recentsViewContainer) {
-        return recentsViewContainer.getOverviewPanel();
-    }
-
-    private int getCurrentOverviewPage(RecentsViewContainer recentsViewContainer) {
-        return getOverviewPanel(recentsViewContainer).getCurrentPage();
-    }
-
-    private int getTaskCount(RecentsViewContainer recentsViewContainer) {
-        return getOverviewPanel(recentsViewContainer).getTaskViewCount();
-    }
-
-    private int getTopRowTaskCountForTablet(RecentsViewContainer recentsViewContainer) {
-        return getOverviewPanel(recentsViewContainer).getTopRowTaskCountForTablet();
-    }
-
-    private int getBottomRowTaskCountForTablet(RecentsViewContainer recentsViewContainer) {
-        return getOverviewPanel(recentsViewContainer).getBottomRowTaskCountForTablet();
-    }
-
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -320,19 +286,6 @@
                 "Launcher internal state didn't switch to Overview", ExpectedState.OVERVIEW);
     }
 
-    private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
-        final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
-        if (toRight) {
-            launchedAppState.quickSwitchToPreviousApp();
-        } else {
-            launchedAppState.quickSwitchToPreviousAppSwipeLeft();
-        }
-
-        // While enable shell transition, Launcher can be resumed due to transient launch.
-        waitForLauncherCondition("Launcher shouldn't stay in resume forever",
-                this::isInLaunchedApp, 3000 /* timeout */);
-    }
-
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -403,11 +356,6 @@
         }
     }
 
-    private boolean isHardwareKeyboard() {
-        return Configuration.KEYBOARD_QWERTY
-                == mTargetContext.getResources().getConfiguration().keyboard;
-    }
-
     @Test
     @NavigationModeSwitch
     @PortraitLandscape
@@ -447,15 +395,14 @@
         }
 
         Overview overview = mLauncher.goHome().switchToOverview();
-        executeOnRecentsViewContainer(
-                container -> assertTrue("Don't have at least 13 tasks",
-                        getTaskCount(container) >= 13));
+        runOnRecentsView(recentsView -> assertTrue("Don't have at least 13 tasks",
+                recentsView.getTaskViewCount() >= 13));
 
         // Test scroll the first task off screen
         overview.scrollCurrentTaskOffScreen();
         assertIsInState("Launcher internal state is not Overview", ExpectedState.OVERVIEW);
-        executeOnRecentsViewContainer(container -> assertTrue("Current task in Overview is still 0",
-                getCurrentOverviewPage(container) > 0));
+        runOnRecentsView(recentsView -> assertTrue("Current task in Overview is still 0",
+                recentsView.getCurrentPage() > 0));
 
         // Test opening the task.
         overview.getCurrentTask().open();
@@ -470,19 +417,18 @@
         overview.scrollCurrentTaskOffScreen();
         assertIsInState(
                 "Launcher internal state is not Overview", ExpectedState.OVERVIEW);
-        executeOnRecentsViewContainer(container -> assertTrue("Current task in Overview is still 0",
-                getCurrentOverviewPage(container) > 0));
+        runOnRecentsView(recentsView -> assertTrue("Current task in Overview is still 0",
+                recentsView.getCurrentPage() > 0));
 
         // Test dismissing the later task.
-        final Integer numTasks = getFromLauncher(this::getTaskCount);
+        final Integer numTasks = getFromRecentsView(RecentsView::getTaskViewCount);
         overview.getCurrentTask().dismiss();
-        executeOnRecentsViewContainer(
-                container -> assertEquals("Dismissing a task didn't remove 1 task from Overview",
-                        numTasks - 1, getTaskCount(container)));
-        executeOnRecentsViewContainer(container -> assertTrue(
-                "Grid did not rebalance after dismissal",
-                (Math.abs(getTopRowTaskCountForTablet(container)
-                        - getBottomRowTaskCountForTablet(container)) <= 1)));
+        runOnRecentsView(recentsView -> assertEquals(
+                "Dismissing a task didn't remove 1 task from Overview",
+                numTasks - 1, recentsView.getTaskViewCount()));
+        runOnRecentsView(recentsView -> assertTrue("Grid did not rebalance after dismissal",
+                (Math.abs(recentsView.getTopRowTaskCountForTablet()
+                        - recentsView.getBottomRowTaskCountForTablet()) <= 1)));
 
         // TODO(b/308841019): Re-enable after fixing Overview jank when dismiss
 //        // Test dismissing more tasks.
@@ -492,17 +438,16 @@
 //        assertIsInState(
 //                "Launcher internal state didn't remain in Overview", ExpectedState.OVERVIEW);
 //        overview.getCurrentTask().dismiss();
-//        executeOnRecentsViewContainer(container -> assertTrue(
-//        "Grid did not rebalance after multiple dismissals",
-//                (Math.abs(getTopRowTaskCountForTablet(container)
-//                        - getBottomRowTaskCountForTablet(container)) <= 1)));
+//        runOnRecentsView(recentsView -> assertTrue(
+//                "Grid did not rebalance after multiple dismissals",
+//                (Math.abs(recentsView.getTopRowTaskCountForTablet()
+//                        - recentsView.getBottomRowTaskCountForTablet()) <= 1)));
 
         // Test dismissing all tasks.
         mLauncher.goHome().switchToOverview().dismissAllTasks();
         assertIsInState("Launcher internal state is not Home", ExpectedState.HOME);
-        executeOnRecentsViewContainer(
-                container -> assertEquals("Still have tasks after dismissing all",
-                        0, getTaskCount(container)));
+        runOnRecentsView(recentsView -> assertEquals("Still have tasks after dismissing all",
+                0, recentsView.getTaskViewCount()));
     }
 
     @Test
@@ -512,9 +457,8 @@
 
         Overview overview = mLauncher.goHome().switchToOverview();
         assertIsInState("Launcher internal state should be Overview", ExpectedState.OVERVIEW);
-        executeOnRecentsViewContainer(
-                container -> assertTrue("Should have at least 3 tasks",
-                        getTaskCount(container) >= 3));
+        runOnRecentsView(recentsView -> assertTrue("Should have at least 3 tasks",
+                recentsView.getTaskViewCount() >= 3));
 
         // It should not dismiss overview when tapping between tasks
         overview.touchBetweenTasks();
@@ -536,9 +480,8 @@
 
         Overview overview = mLauncher.goHome().switchToOverview();
         assertIsInState("Launcher internal state should be Overview", ExpectedState.OVERVIEW);
-        executeOnRecentsViewContainer(
-                container -> assertTrue("Should have at least 3 tasks",
-                        getTaskCount(container) >= 3));
+        runOnRecentsView(recentsView -> assertTrue("Should have at least 3 tasks",
+                recentsView.getTaskViewCount() >= 3));
 
         if (mLauncher.isTransientTaskbar()) {
             // On transient taskbar, it should dismiss when tapping outside taskbar bounds.
@@ -596,6 +539,29 @@
         }
     }
 
+    private void startTestAppsWithCheck() throws Exception {
+        startTestApps();
+        expectLaunchedAppState();
+    }
+
+    private void quickSwitchToPreviousAppAndAssert(boolean toRight) {
+        final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
+        if (toRight) {
+            launchedAppState.quickSwitchToPreviousApp();
+        } else {
+            launchedAppState.quickSwitchToPreviousAppSwipeLeft();
+        }
+
+        // While enable shell transition, Launcher can be resumed due to transient launch.
+        waitForLauncherCondition("Launcher shouldn't stay in resume forever",
+                this::isInLaunchedApp, 3000 /* timeout */);
+    }
+
+    private boolean isHardwareKeyboard() {
+        return Configuration.KEYBOARD_QWERTY
+                == mTargetContext.getResources().getConfiguration().keyboard;
+    }
+
     private void assertIsInState(
             @NonNull String failureMessage, @NonNull ExpectedState expectedState) {
         assertTrue(failureMessage, enableLauncherOverviewInWindow()
@@ -612,11 +578,26 @@
         }
     }
 
-    private void executeOnRecentsViewContainer(@NonNull Consumer<RecentsViewContainer> f) {
+    private void expectLaunchedAppState() {
+        executeOnLauncher(launcher -> assertTrue(
+                "Launcher activity is the top activity; expecting another activity to be the top "
+                        + "one",
+                isInLaunchedApp(launcher)));
+    }
+
+    private <T> T getFromRecentsView(Function<RecentsView, T> f) {
         if (enableLauncherOverviewInWindow()) {
-            executeOnRecentsWindow(f::accept);
+            return getFromRecentsWindow(
+                    recentsWindowManager -> f.apply(recentsWindowManager.getOverviewPanel()));
         } else {
-            executeOnLauncher(f::accept);
+            return getFromLauncher(launcher -> f.apply(launcher.getOverviewPanel()));
         }
     }
+
+    private void runOnRecentsView(Consumer<RecentsView> f) {
+        getFromRecentsView(recentsView -> {
+            f.accept(recentsView);
+            return null;
+        });
+    }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt b/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
index ae96c09c..9ca9fe4 100644
--- a/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/desktop/DesktopAppLaunchTransitionManagerTest.kt
@@ -29,7 +29,6 @@
 import androidx.test.filters.SmallTest
 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
 import com.android.quickstep.SystemUiProxy
-import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS
 import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX
 import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
 import com.google.common.truth.Truth.assertThat
@@ -75,10 +74,7 @@
     }
 
     @Test
-    @EnableFlags(
-        FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
-        FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
-    )
+    @EnableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
     fun registerTransitions_appLaunchFlagEnabled_registersTransition() {
         transitionManager.registerTransitions()
 
@@ -86,10 +82,7 @@
     }
 
     @Test
-    @DisableFlags(
-        FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
-        FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
-    )
+    @DisableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
     fun registerTransitions_appLaunchFlagDisabled_doesntRegisterTransition() {
         transitionManager.registerTransitions()
 
@@ -97,10 +90,7 @@
     }
 
     @Test
-    @EnableFlags(
-        FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS,
-        FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX,
-    )
+    @EnableFlags(FLAG_ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX)
     fun registerTransitions_usesCorrectFilter() {
         transitionManager.registerTransitions()
         val filterArgumentCaptor = argumentCaptor<TransitionFilter>()
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index b51feb5..f242f1e 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -46,7 +46,7 @@
     <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>
     <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d lai ja %3$d kõrge"</string>
-    <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Vidina teisaldamiseks avakuval puudutage vidinat pikalt"</string>
+    <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Vidina teisaldamiseks avakuval puudutage vidinat pikalt."</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Lisa avakuvale"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g> lisati avakuvale"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Soovitused"</string>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 315096c..d3684b2 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -29,6 +29,7 @@
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -63,6 +64,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 import androidx.annotation.VisibleForTesting;
@@ -366,11 +368,6 @@
         mDotScaleAnim.start();
     }
 
-    @UiThread
-    public void applyFromWorkspaceItem(WorkspaceItemInfo info) {
-        applyFromWorkspaceItem(info, null);
-    }
-
     @Override
     public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
         if (delegate instanceof BaseAccessibilityDelegate) {
@@ -384,10 +381,10 @@
     }
 
     @UiThread
-    public void applyFromWorkspaceItem(WorkspaceItemInfo info, PreloadIconDrawable icon) {
+    public void applyFromWorkspaceItem(WorkspaceItemInfo info) {
         applyIconAndLabel(info);
         setItemInfo(info);
-        applyLoadingState(icon);
+
         applyDotState(info, false /* animate */);
         setDownloadStateContentDescription(info, info.getProgressLevel());
     }
@@ -395,17 +392,11 @@
     @UiThread
     public void applyFromApplicationInfo(AppInfo info) {
         applyIconAndLabel(info);
-
-        // We don't need to check the info since it's not a WorkspaceItemInfo
         setItemInfo(info);
 
-
         // Verify high res immediately
         verifyHighRes();
 
-        if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
-            applyProgressLevel();
-        }
         applyDotState(info, false /* animate */);
         setDownloadStateContentDescription(info, info.getProgressLevel());
     }
@@ -449,6 +440,50 @@
     @VisibleForTesting
     @UiThread
     public void applyIconAndLabel(ItemInfoWithIcon info) {
+        FastBitmapDrawable oldIcon = mIcon;
+        if (!canReuseIcon(info)) {
+            setNonPendingIcon(info);
+        }
+        applyLabel(info);
+        maybeApplyProgressLevel(info, oldIcon);
+    }
+
+    /**
+     * Check if we can reuse icon so that any animation is preserved
+     */
+    private boolean canReuseIcon(ItemInfoWithIcon info) {
+        return mIcon instanceof PreloadIconDrawable p
+                && p.hasNotCompleted() && p.isSameInfo(info.bitmap);
+    }
+
+    /**
+     * Apply progress level to the icon if necessary
+     */
+    private void maybeApplyProgressLevel(ItemInfoWithIcon info, FastBitmapDrawable oldIcon) {
+        if (!shouldApplyProgressLevel(info, oldIcon)) {
+            return;
+        }
+        PreloadIconDrawable pendingIcon = applyProgressLevel(info);
+        boolean isNoLongerPending = info instanceof WorkspaceItemInfo wii
+                ? !wii.hasPromiseIconUi() : !info.isArchived();
+        if (isNoLongerPending && info.getProgressLevel() == 100 && pendingIcon != null) {
+            pendingIcon.maybePerformFinishedAnimation(
+                    (oldIcon instanceof PreloadIconDrawable p) ? p : pendingIcon,
+                    () -> setNonPendingIcon(
+                            (getTag() instanceof ItemInfoWithIcon iiwi) ? iiwi : info));
+        }
+    }
+
+    /**
+     * Check if progress level should be applied to the icon
+     */
+    private boolean shouldApplyProgressLevel(ItemInfoWithIcon info, FastBitmapDrawable oldIcon) {
+        return (info.runtimeStatusFlags & FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0
+                || (info instanceof WorkspaceItemInfo wii && wii.hasPromiseIconUi())
+                || (oldIcon instanceof PreloadIconDrawable p && p.hasNotCompleted());
+    }
+
+    private void setNonPendingIcon(ItemInfoWithIcon info) {
         ThemeManager themeManager = ThemeManager.INSTANCE.get(getContext());
         int flags = (shouldUseTheme()
                 && themeManager.isMonoThemeEnabled()) ? FLAG_THEMED : 0;
@@ -463,7 +498,6 @@
         mDotParams.appColor = iconDrawable.getIconColor();
         mDotParams.dotColor = Themes.getAttrColor(getContext(), R.attr.notificationDotColor);
         setIcon(iconDrawable);
-        applyLabel(info);
     }
 
     protected boolean shouldUseTheme() {
@@ -1070,38 +1104,10 @@
         mLongPressHelper.cancelLongPress();
     }
 
-    /**
-     * Applies the loading progress value to the progress bar.
-     *
-     * If this app is installing, the progress bar will be updated with the installation progress.
-     * If this app is installed and downloading incrementally, the progress bar will be updated
-     * with the total download progress.
-     */
-    public void applyLoadingState(PreloadIconDrawable icon) {
-        if (getTag() instanceof ItemInfoWithIcon) {
-            WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
-            if ((info.runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0
-                    || info.hasPromiseIconUi()
-                    || (info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0
-                    || (icon != null)) {
-                updateProgressBarUi(info.getProgressLevel() == 100 ? icon : null);
-            }
-        }
-    }
-
-    private void updateProgressBarUi(PreloadIconDrawable oldIcon) {
-        FastBitmapDrawable originalIcon = mIcon;
-        PreloadIconDrawable preloadDrawable = applyProgressLevel();
-        if (preloadDrawable != null && oldIcon != null) {
-            preloadDrawable.maybePerformFinishedAnimation(oldIcon, () -> setIcon(originalIcon));
-        }
-    }
-
     /** Applies the given progress level to the this icon's progress bar. */
     @Nullable
-    public PreloadIconDrawable applyProgressLevel() {
-        if (!(getTag() instanceof ItemInfoWithIcon info)
-                || ((ItemInfoWithIcon) getTag()).isInactiveArchive()) {
+    private PreloadIconDrawable applyProgressLevel(ItemInfoWithIcon info) {
+        if (info.isInactiveArchive()) {
             return null;
         }
 
@@ -1115,23 +1121,16 @@
             setContentDescription(getContext()
                     .getString(R.string.app_waiting_download_title, info.title));
         }
-        if (mIcon != null) {
-            PreloadIconDrawable preloadIconDrawable;
-            if (mIcon instanceof PreloadIconDrawable) {
-                preloadIconDrawable = (PreloadIconDrawable) mIcon;
-                preloadIconDrawable.setLevel(progressLevel);
-                preloadIconDrawable.setIsDisabled(isIconDisabled(info));
-            } else {
-                preloadIconDrawable = makePreloadIcon();
-                setIcon(preloadIconDrawable);
-                if (info.isArchived() && Flags.useNewIconForArchivedApps()) {
-                    // reapply text without cloud icon as soon as unarchiving is triggered
-                    applyLabel(info);
-                }
-            }
-            return preloadIconDrawable;
+        PreloadIconDrawable pid;
+        if (mIcon instanceof PreloadIconDrawable p) {
+            pid = p;
+            pid.setLevel(progressLevel);
+            pid.setIsDisabled(isIconDisabled(info));
+        } else {
+            pid = makePreloadIcon(info);
+            setIcon(pid);
         }
-        return null;
+        return pid;
     }
 
     /**
@@ -1140,11 +1139,11 @@
      */
     @Nullable
     public PreloadIconDrawable makePreloadIcon() {
-        if (!(getTag() instanceof ItemInfoWithIcon)) {
-            return null;
-        }
+        return getTag() instanceof ItemInfoWithIcon info ? makePreloadIcon(info) : null;
+    }
 
-        ItemInfoWithIcon info = (ItemInfoWithIcon) getTag();
+    @NonNull
+    private PreloadIconDrawable makePreloadIcon(ItemInfoWithIcon info) {
         int progressLevel = info.getProgressLevel();
         final PreloadIconDrawable preloadDrawable = newPendingIcon(getContext(), info);
 
@@ -1163,7 +1162,7 @@
 
 
     public void applyDotState(ItemInfo itemInfo, boolean animate) {
-        if (mIcon instanceof FastBitmapDrawable) {
+        if (mIcon != null) {
             boolean wasDotted = mDotInfo != null;
             mDotInfo = mActivity.getDotInfoForItem(itemInfo);
             boolean isDotted = mDotInfo != null;
@@ -1212,7 +1211,7 @@
                 setContentDescription(getContext().getString(
                         R.string.app_archived_title, info.title));
             }
-        } else if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK)
+        } else if ((info.runtimeStatusFlags & FLAG_SHOW_DOWNLOAD_PROGRESS_MASK)
                 != 0) {
             String percentageString = NumberFormat.getPercentInstance()
                     .format(progressLevel * 0.01);
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 988d164..257f911 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -173,6 +173,7 @@
 
     private boolean mDragging = false;
     public boolean mHasOnLayoutBeenCalled = false;
+    private boolean mPlayDragHaptics = false;
 
     private final TimeInterpolator mEaseOutInterpolator;
     protected final ShortcutAndWidgetContainer mShortcutsAndWidgets;
@@ -1183,7 +1184,8 @@
             DropTarget.DragObject dragObject) {
         if (mDragCell[0] != cellX || mDragCell[1] != cellY || mDragCellSpan[0] != spanX
                 || mDragCellSpan[1] != spanY) {
-            if (Flags.msdlFeedback()) {
+            determineIfDragHapticsPlay();
+            if (mPlayDragHaptics && Flags.msdlFeedback()) {
                 mMSDLPlayerWrapper.playToken(MSDLToken.DRAG_INDICATOR_DISCRETE);
             }
             mDragCell[0] = cellX;
@@ -1211,6 +1213,14 @@
         }
     }
 
+    private void determineIfDragHapticsPlay() {
+        if (mDragCell[0] != -1 || mDragCell[1] != -1
+                || mDragCellSpan[0] != -1 || mDragCellSpan[1] != -1) {
+            // The nearest cell is known and we can play haptics
+            mPlayDragHaptics = true;
+        }
+    }
+
     @SuppressLint("StringFormatMatches")
     public String getItemMoveDescription(int cellX, int cellY) {
         if (mContainerType == HOTSEAT) {
@@ -1812,6 +1822,7 @@
      * @param child The child that is being dropped
      */
     void onDropChild(View child) {
+        mPlayDragHaptics = false;
         if (child != null) {
             CellLayoutLayoutParams
                     lp = (CellLayoutLayoutParams) child.getLayoutParams();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7df4014..647d2ad 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -277,11 +277,11 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.function.Predicate;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
@@ -2598,25 +2598,12 @@
         mModelCallbacks.bindIncrementalDownloadProgressUpdated(app);
     }
 
-    @Override
-    public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets) {
-        mModelCallbacks.bindWidgetsRestored(widgets);
-    }
-
     /**
      * See {@code LauncherBindingDelegate}
      */
     @Override
-    public void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) {
-        mModelCallbacks.bindWorkspaceItemsChanged(updated);
-    }
-
-    /**
-     * See {@code LauncherBindingDelegate}
-     */
-    @Override
-    public void bindRestoreItemsChange(HashSet<ItemInfo> updates) {
-        mModelCallbacks.bindRestoreItemsChange(updates);
+    public void bindItemsUpdated(Set<ItemInfo> updates) {
+        mModelCallbacks.bindItemsUpdated(updates);
     }
 
     /**
diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt
index 5d32525..5338fb4 100644
--- a/src/com/android/launcher3/ModelCallbacks.kt
+++ b/src/com/android/launcher3/ModelCallbacks.kt
@@ -17,8 +17,6 @@
 import com.android.launcher3.model.StringCache
 import com.android.launcher3.model.data.AppInfo
 import com.android.launcher3.model.data.ItemInfo
-import com.android.launcher3.model.data.LauncherAppWidgetInfo
-import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.popup.PopupContainerWithArrow
 import com.android.launcher3.util.ComponentKey
 import com.android.launcher3.util.IntArray as LIntArray
@@ -215,29 +213,13 @@
         launcher.appsView.appsStore.updateProgressBar(app)
     }
 
-    override fun bindWidgetsRestored(widgets: ArrayList<LauncherAppWidgetInfo?>?) {
-        launcher.workspace.widgetsRestored(widgets)
-    }
-
-    /**
-     * Some shortcuts were updated in the background. Implementation of the method from
-     * LauncherModel.Callbacks.
-     *
-     * @param updated list of shortcuts which have changed.
-     */
-    override fun bindWorkspaceItemsChanged(updated: List<WorkspaceItemInfo?>) {
-        if (updated.isNotEmpty()) {
-            launcher.workspace.updateWorkspaceItems(updated, launcher)
-            PopupContainerWithArrow.dismissInvalidPopup(launcher)
-        }
-    }
-
     /**
      * Update the state of a package, typically related to install state. Implementation of the
      * method from LauncherModel.Callbacks.
      */
-    override fun bindRestoreItemsChange(updates: HashSet<ItemInfo?>?) {
-        launcher.workspace.updateRestoreItems(updates, launcher)
+    override fun bindItemsUpdated(updates: Set<ItemInfo>) {
+        launcher.workspace.updateContainerItems(updates, launcher)
+        PopupContainerWithArrow.dismissInvalidPopup(launcher)
     }
 
     /**
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 86c49d0..b41a425 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -53,8 +53,6 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.Message;
 import android.os.Parcelable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -125,13 +123,9 @@
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.util.WallpaperOffsetInterpolator;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
-import com.android.launcher3.widget.LauncherWidgetHolder;
-import com.android.launcher3.widget.LauncherWidgetHolder.ProviderChangedListener;
 import com.android.launcher3.widget.NavigableAppWidgetHostView;
 import com.android.launcher3.widget.PendingAddShortcutInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
-import com.android.launcher3.widget.PendingAppWidgetHostView;
-import com.android.launcher3.widget.WidgetManagerHelper;
 import com.android.launcher3.widget.util.WidgetSizes;
 import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayCallbacks;
 import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlayTouchProxy;
@@ -664,9 +658,6 @@
             bindAndInitFirstWorkspaceScreen();
         }
 
-        // Remove any deferred refresh callbacks
-        mLauncher.mHandler.removeCallbacksAndMessages(DeferredWidgetRefresh.class);
-
         // Re-enable the layout transitions
         enableLayoutTransitions();
     }
@@ -1771,7 +1762,7 @@
         }
 
         final DragView dv;
-        if (contentView instanceof View) {
+        if (contentView != null) {
             dv = mDragController.startDrag(
                     contentView,
                     draggableView,
@@ -3465,43 +3456,6 @@
         removeItemsByMatcher(matcher);
     }
 
-    public void widgetsRestored(final ArrayList<LauncherAppWidgetInfo> changedInfo) {
-        if (!changedInfo.isEmpty()) {
-            DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
-                    mLauncher.getAppWidgetHolder());
-
-            LauncherAppWidgetInfo item = changedInfo.get(0);
-            final AppWidgetProviderInfo widgetInfo;
-            WidgetManagerHelper widgetHelper = new WidgetManagerHelper(getContext());
-            if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
-                widgetInfo = widgetHelper.findProvider(item.providerName, item.user);
-            } else {
-                widgetInfo = widgetHelper.getLauncherAppWidgetInfo(item.appWidgetId,
-                        item.getTargetComponent());
-            }
-
-            if (widgetInfo != null) {
-                // Re-inflate the widgets which have changed status
-                widgetRefresh.run();
-            } else {
-                // widgetRefresh will automatically run when the packages are updated.
-                // For now just update the progress bars
-                mapOverItems(new ItemOperator() {
-                    @Override
-                    public boolean evaluate(ItemInfo info, View view) {
-                        if (view instanceof PendingAppWidgetHostView
-                                && changedInfo.contains(info)) {
-                            ((LauncherAppWidgetInfo) info).installProgress = 100;
-                            ((PendingAppWidgetHostView) view).applyState();
-                        }
-                        // process all the shortcuts
-                        return false;
-                    }
-                });
-            }
-        }
-    }
-
     public boolean isOverlayShown() {
         return mOverlayShown;
     }
@@ -3608,62 +3562,6 @@
         return mLauncher.getCellPosMapper();
     }
 
-    /**
-     * Used as a workaround to ensure that the AppWidgetService receives the
-     * PACKAGE_ADDED broadcast before updating widgets.
-     */
-    private class DeferredWidgetRefresh implements Runnable, ProviderChangedListener {
-        private final ArrayList<LauncherAppWidgetInfo> mInfos;
-        private final LauncherWidgetHolder mWidgetHolder;
-        private final Handler mHandler;
-
-        private boolean mRefreshPending;
-
-        DeferredWidgetRefresh(ArrayList<LauncherAppWidgetInfo> infos,
-                              LauncherWidgetHolder holder) {
-            mInfos = infos;
-            mWidgetHolder = holder;
-            mHandler = mLauncher.mHandler;
-            mRefreshPending = true;
-
-            mWidgetHolder.addProviderChangeListener(this);
-            // Force refresh after 10 seconds, if we don't get the provider changed event.
-            // This could happen when the provider is no longer available in the app.
-            Message msg = Message.obtain(mHandler, this);
-            msg.obj = DeferredWidgetRefresh.class;
-            mHandler.sendMessageDelayed(msg, 10000);
-        }
-
-        @Override
-        public void run() {
-            mWidgetHolder.removeProviderChangeListener(this);
-            mHandler.removeCallbacks(this);
-
-            if (!mRefreshPending) {
-                return;
-            }
-
-            mRefreshPending = false;
-
-            ArrayList<PendingAppWidgetHostView> views = new ArrayList<>(mInfos.size());
-            mapOverItems((info, view) -> {
-                if (view instanceof PendingAppWidgetHostView && mInfos.contains(info)) {
-                    views.add((PendingAppWidgetHostView) view);
-                }
-                // process all children
-                return false;
-            });
-            for (PendingAppWidgetHostView view : views) {
-                view.reInflate();
-            }
-        }
-
-        @Override
-        public void notifyWidgetProvidersChanged() {
-            run();
-        }
-    }
-
     private class StateTransitionListener extends AnimatorListenerAdapter
             implements AnimatorUpdateListener {
 
diff --git a/src/com/android/launcher3/allapps/AllAppsStore.java b/src/com/android/launcher3/allapps/AllAppsStore.java
index 9afe06c..d5a4022 100644
--- a/src/com/android/launcher3/allapps/AllAppsStore.java
+++ b/src/com/android/launcher3/allapps/AllAppsStore.java
@@ -17,7 +17,6 @@
 
 import static com.android.launcher3.model.data.AppInfo.COMPONENT_KEY_COMPARATOR;
 import static com.android.launcher3.model.data.AppInfo.EMPTY_ARRAY;
-import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK;
 
 import android.content.Context;
 import android.os.UserHandle;
@@ -229,11 +228,7 @@
     public void updateProgressBar(AppInfo app) {
         updateAllIcons((child) -> {
             if (child.getTag() == app) {
-                if ((app.runtimeStatusFlags & FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) == 0) {
-                    child.applyFromApplicationInfo(app);
-                } else {
-                    child.applyProgressLevel();
-                }
+                child.applyFromApplicationInfo(app);
             }
         });
     }
diff --git a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
index 0b7b20f..7bd7c3e 100644
--- a/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
+++ b/src/com/android/launcher3/dagger/LauncherBaseAppComponent.java
@@ -23,6 +23,7 @@
 import com.android.launcher3.graphics.ThemeManager;
 import com.android.launcher3.model.ItemInstallQueue;
 import com.android.launcher3.pm.InstallSessionHelper;
+import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.DaggerSingletonTracker;
 import com.android.launcher3.util.DisplayController;
@@ -67,6 +68,7 @@
     WindowManagerProxy getWmProxy();
     LauncherPrefs getLauncherPrefs();
     ThemeManager getThemeManager();
+    UserCache getUserCache();
     DisplayController getDisplayController();
     WallpaperColorHints getWallpaperColorHints();
     LockedUserState getLockedUserState();
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index d9eefeb..0ed8787 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -176,12 +176,16 @@
         FolderIcon icon = inflateIcon(resId, activityContext, group, folderInfo);
         folder.setFolderIcon(icon);
         folder.bind(folderInfo);
+
         icon.setFolder(folder);
+        folderInfo.addListener(icon);
         return icon;
     }
 
     /**
-     * Builds a FolderIcon to be added to the Launcher
+     * Builds a FolderIcon to be added to the activity.
+     * This method doesn't add any listeners to the FolderInfo, and hence any changes to the info
+     * will not be reflected in the folder.
      */
     public static FolderIcon inflateIcon(int resId, ActivityContext activity,
             @Nullable ViewGroup group, FolderInfo folderInfo) {
@@ -227,8 +231,6 @@
         icon.mPreviewVerifier.setFolderInfo(folderInfo);
         icon.updatePreviewItems(false);
 
-        folderInfo.addListener(icon);
-
         return icon;
     }
 
diff --git a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
index 9bd1268..c9e688b 100644
--- a/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
+++ b/src/com/android/launcher3/graphics/GridCustomizationsProvider.java
@@ -53,9 +53,10 @@
 import com.android.launcher3.util.RunnableList;
 import com.android.systemui.shared.Flags;
 
+import java.lang.ref.WeakReference;
 import java.util.Collections;
 import java.util.Set;
-import java.util.WeakHashMap;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 
 /**
@@ -121,7 +122,7 @@
 
     // Set of all active previews used to track duplicate memory allocations
     private final Set<PreviewLifecycleObserver> mActivePreviews =
-            Collections.newSetFromMap(new WeakHashMap<>());
+            Collections.newSetFromMap(new ConcurrentHashMap<>());
 
     @Override
     public boolean onCreate() {
@@ -313,8 +314,15 @@
             Bundle result = new Bundle();
             result.putParcelable(KEY_SURFACE_PACKAGE, renderer.getSurfacePackage());
 
-            Messenger messenger =
-                    new Messenger(new Handler(UI_HELPER_EXECUTOR.getLooper(), observer));
+            mActivePreviews.add(observer);
+            lifeCycleTracker.add(() -> mActivePreviews.remove(observer));
+
+            // Wrap the callback in a weak reference. This ensures that the callback is not kept
+            // alive due to the Messenger's IBinder
+            Messenger messenger = new Messenger(new Handler(
+                    UI_HELPER_EXECUTOR.getLooper(),
+                    new WeakCallbackWrapper(observer)));
+
             Message msg = Message.obtain();
             msg.replyTo = messenger;
             result.putParcelable(KEY_CALLBACK, msg);
@@ -392,4 +400,34 @@
                     && plo.renderer.getDisplayId() == renderer.getDisplayId();
         }
     }
+
+    /**
+     * A WeakReference wrapper around Handler.Callback to avoid passing hard-reference over IPC
+     * when using a Messenger
+     */
+    private static class WeakCallbackWrapper implements Handler.Callback {
+
+        private final WeakReference<Handler.Callback> mActual;
+        private final Message mCleanupMessage;
+
+        WeakCallbackWrapper(Handler.Callback actual) {
+            mActual = new WeakReference<>(actual);
+            mCleanupMessage = new Message();
+        }
+
+        @Override
+        public boolean handleMessage(Message message) {
+            Handler.Callback actual = mActual.get();
+            return actual != null && actual.handleMessage(message);
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            super.finalize();
+            Handler.Callback actual = mActual.get();
+            if (actual != null) {
+                actual.handleMessage(mCleanupMessage);
+            }
+        }
+    }
 }
diff --git a/src/com/android/launcher3/graphics/IconShape.kt b/src/com/android/launcher3/graphics/IconShape.kt
index 0938a5a..e62936c 100644
--- a/src/com/android/launcher3/graphics/IconShape.kt
+++ b/src/com/android/launcher3/graphics/IconShape.kt
@@ -114,7 +114,6 @@
         ): ValueAnimator where T : View, T : ClipPathView
     }
 
-    @VisibleForTesting
     class Circle : RoundedSquare(1f) {
 
         override fun drawShape(
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 7da4e65..50d6d1c 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -24,7 +24,6 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -33,12 +32,14 @@
 import android.graphics.Rect;
 import android.util.Property;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.core.graphics.ColorUtils;
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorListeners;
+import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.util.Themes;
@@ -63,8 +64,6 @@
 
     private static final int DEFAULT_PATH_SIZE = 100;
     private static final int MAX_PAINT_ALPHA = 255;
-    private static final int TRACK_ALPHA = (int) (0.27f * MAX_PAINT_ALPHA);
-    private static final int DISABLED_ICON_ALPHA = (int) (0.6f * MAX_PAINT_ALPHA);
 
     private static final long DURATION_SCALE = 500;
     private static final long SCALE_AND_ALPHA_ANIM_DURATION = 500;
@@ -284,20 +283,25 @@
                     (long) ((finalProgress - mInternalStateProgress) * DURATION_SCALE));
             mCurrentAnim.setInterpolator(LINEAR);
             if (isFinish) {
-                if (onFinishCallback != null) {
-                    mCurrentAnim.addListener(AnimatorListeners.forEndCallback(onFinishCallback));
-                }
                 mCurrentAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
                         mRanFinishAnimation = true;
                     }
                 });
+                if (onFinishCallback != null) {
+                    mCurrentAnim.addListener(AnimatorListeners.forEndCallback(onFinishCallback));
+                }
             }
             mCurrentAnim.start();
         }
     }
 
+    @VisibleForTesting
+    public ObjectAnimator getActiveAnimation() {
+        return mCurrentAnim;
+    }
+
     /**
      * Sets the internal progress and updates the UI accordingly
      *   for progress <= 0:
@@ -358,8 +362,7 @@
     @Override
     public FastBitmapConstantState newConstantState() {
         return new PreloadIconConstantState(
-                mBitmap,
-                mIconColor,
+                mBitmapInfo,
                 mItem,
                 mIndicatorColor,
                 new int[] {mSystemAccentColor, mSystemBackgroundColor},
@@ -377,14 +380,13 @@
         private final Path mShapePath;
 
         public PreloadIconConstantState(
-                Bitmap bitmap,
-                int iconColor,
+                BitmapInfo bitmapInfo,
                 ItemInfoWithIcon info,
                 int indicatorColor,
                 int[] preloadColors,
                 boolean isDarkMode,
                 Path shapePath) {
-            super(bitmap, iconColor);
+            super(bitmapInfo);
             mInfo = info;
             mIndicatorColor = indicatorColor;
             mPreloadColors = preloadColors;
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index a4b681b..7a60814 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -97,7 +97,6 @@
 
     @Nullable private Boolean mDarkMode;
     private boolean mDestroyed = false;
-    private LauncherPreviewRenderer mRenderer;
     private boolean mHideQsb;
     @Nullable private FrameLayout mViewRoot = null;
 
@@ -240,9 +239,8 @@
      * @param hide True to hide and false to show.
      */
     public void hideBottomRow(boolean hide) {
-        if (mRenderer != null) {
-            mRenderer.hideBottomRow(hide);
-        }
+        mHideQsb = hide;
+        loadAsync();
     }
 
     /**
@@ -388,15 +386,16 @@
         if (mDestroyed) {
             return;
         }
+        LauncherPreviewRenderer renderer;
         if (Flags.newCustomizationPickerUi()) {
-            mRenderer = new LauncherPreviewRenderer(inflationContext, idp, mPreviewColorOverride,
+            renderer = new LauncherPreviewRenderer(inflationContext, idp, mPreviewColorOverride,
                     mWallpaperColors, launcherWidgetSpanInfo);
         } else {
-            mRenderer = new LauncherPreviewRenderer(inflationContext, idp,
+            renderer = new LauncherPreviewRenderer(inflationContext, idp,
                     mWallpaperColors, launcherWidgetSpanInfo);
         }
-        mRenderer.hideBottomRow(mHideQsb);
-        View view = mRenderer.getRenderedView(dataModel, widgetProviderInfoMap);
+        renderer.hideBottomRow(mHideQsb);
+        View view = renderer.getRenderedView(dataModel, widgetProviderInfoMap);
         // This aspect scales the view to fit in the surface and centers it
         final float scale = Math.min(mWidth / (float) view.getMeasuredWidth(),
                 mHeight / (float) view.getMeasuredHeight());
diff --git a/src/com/android/launcher3/icons/LauncherIconProvider.java b/src/com/android/launcher3/icons/LauncherIconProvider.java
index e40f526..482360c 100644
--- a/src/com/android/launcher3/icons/LauncherIconProvider.java
+++ b/src/com/android/launcher3/icons/LauncherIconProvider.java
@@ -19,14 +19,18 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.graphics.ThemeManager;
 import com.android.launcher3.util.ApiWrapper;
 
@@ -49,9 +53,14 @@
 
     private Map<String, ThemeData> mThemedIconMap;
 
+    private final ApiWrapper mApiWrapper;
+    private final IconShape mIconShape;
+
     public LauncherIconProvider(Context context) {
         super(context);
         setIconThemeSupported(ThemeManager.INSTANCE.get(context).isMonoThemeEnabled());
+        mApiWrapper = ApiWrapper.INSTANCE.get(context);
+        mIconShape = IconShape.INSTANCE.get(context);
     }
 
     /**
@@ -75,7 +84,25 @@
 
     @Override
     protected String getApplicationInfoHash(@NonNull ApplicationInfo appInfo) {
-        return ApiWrapper.INSTANCE.get(mContext).getApplicationInfoHash(appInfo);
+        return mApiWrapper.getApplicationInfoHash(appInfo);
+    }
+
+    @Nullable
+    @Override
+    protected Drawable loadAppInfoIcon(ApplicationInfo info, Resources resources, int density) {
+        // Tries to load the round icon res, if the app defines it as an adaptive icon
+        if (mIconShape.getShape() instanceof IconShape.Circle) {
+            int roundIconRes = mApiWrapper.getRoundIconRes(info);
+            if (roundIconRes != 0 && roundIconRes != info.icon) {
+                try {
+                    Drawable d = resources.getDrawableForDensity(roundIconRes, density);
+                    if (d instanceof AdaptiveIconDrawable) {
+                        return d;
+                    }
+                } catch (Resources.NotFoundException exc) { }
+            }
+        }
+        return super.loadAppInfoIcon(info, resources, density);
     }
 
     private Map<String, ThemeData> getThemedIconMap() {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index a04cbfb..ddc775d 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -49,7 +49,6 @@
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.CollectionInfo;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.shortcuts.ShortcutKey;
@@ -70,7 +69,6 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -419,9 +417,9 @@
          * Binds updated incremental download progress
          */
         default void bindIncrementalDownloadProgressUpdated(AppInfo app) { }
-        default void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) { }
-        default void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets) { }
-        default void bindRestoreItemsChange(HashSet<ItemInfo> updates) { }
+
+        /** Called when a runtime property of the ItemInfo is updated due to some system event */
+        default void bindItemsUpdated(Set<ItemInfo> updates) { }
         default void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) { }
 
         /**
diff --git a/src/com/android/launcher3/model/CacheDataUpdatedTask.java b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
index b544b91..48934e2 100644
--- a/src/com/android/launcher3/model/CacheDataUpdatedTask.java
+++ b/src/com/android/launcher3/model/CacheDataUpdatedTask.java
@@ -15,6 +15,9 @@
  */
 package com.android.launcher3.model;
 
+import static com.android.launcher3.icons.cache.CacheLookupFlag.DEFAULT_LOOKUP_FLAG;
+import static com.android.launcher3.model.ModelUtils.WIDGET_FILTER;
+
 import android.content.ComponentName;
 import android.os.UserHandle;
 
@@ -23,6 +26,8 @@
 import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 
 import java.util.ArrayList;
@@ -55,7 +60,7 @@
     public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
             @NonNull AllAppsList apps) {
         IconCache iconCache = taskController.getApp().getIconCache();
-        ArrayList<WorkspaceItemInfo> updatedShortcuts = new ArrayList<>();
+        ArrayList<ItemInfo> updatedItems = new ArrayList<>();
 
         synchronized (dataModel) {
             dataModel.forAllWorkspaceItemInfos(mUser, si -> {
@@ -64,12 +69,25 @@
                         && isValidShortcut(si) && cn != null
                         && mPackages.contains(cn.getPackageName())) {
                     iconCache.getTitleAndIcon(si, si.getMatchingLookupFlag());
-                    updatedShortcuts.add(si);
+                    updatedItems.add(si);
                 }
             });
+
+            dataModel.itemsIdMap.stream()
+                    .filter(WIDGET_FILTER)
+                    .filter(item -> mUser.equals(item.user))
+                    .map(item -> (LauncherAppWidgetInfo) item)
+                    .filter(widget -> mPackages.contains(widget.providerName.getPackageName())
+                            && widget.pendingItemInfo != null)
+                    .forEach(widget -> {
+                        iconCache.getTitleAndIconForApp(
+                                widget.pendingItemInfo, DEFAULT_LOOKUP_FLAG);
+                        updatedItems.add(widget);
+                    });
+
             apps.updateIconsAndLabels(mPackages, mUser);
         }
-        taskController.bindUpdatedWorkspaceItems(updatedShortcuts);
+        taskController.bindUpdatedWorkspaceItems(updatedItems);
         taskController.bindApplicationsIfNeeded();
     }
 
diff --git a/src/com/android/launcher3/model/GridSizeMigrationDBController.java b/src/com/android/launcher3/model/GridSizeMigrationDBController.java
index 8cbe764..d256d1b 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationDBController.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationDBController.java
@@ -24,7 +24,7 @@
 import static com.android.launcher3.model.LoaderTask.SMARTSPACE_ON_HOME_SCREEN;
 import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
 import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
-import static com.android.launcher3.provider.LauncherDbUtils.shiftTableByXCells;
+import static com.android.launcher3.provider.LauncherDbUtils.shiftWorkspaceByXCells;
 
 import android.content.ComponentName;
 import android.content.ContentValues;
@@ -143,7 +143,7 @@
                 // We want to add the extra row(s) to the top of the screen, so we shift the grid
                 // down.
                 if (oneGridSpecs()) {
-                    shiftTableByXCells(
+                    shiftWorkspaceByXCells(
                             target.getWritableDatabase(),
                             (destDeviceState.getRows() - srcDeviceState.getRows()),
                             TABLE_NAME);
@@ -159,8 +159,8 @@
             DbReader destReader = new DbReader(t.getDb(), TABLE_NAME, context);
 
             Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
-            migrate(target, srcReader, destReader, destDeviceState.getNumHotseat(),
-                    targetSize, srcDeviceState, destDeviceState);
+            migrate(target, srcReader, destReader, srcDeviceState.getNumHotseat(),
+                    destDeviceState.getNumHotseat(), targetSize, srcDeviceState, destDeviceState);
             dropTable(t.getDb(), TMP_TABLE);
             t.commit();
             return true;
@@ -181,19 +181,26 @@
     public static boolean migrate(
             @NonNull DatabaseHelper helper,
             @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
-            final int destHotseatSize, @NonNull final Point targetSize,
+            final int srcHotseatSize, final int destHotseatSize, @NonNull final Point targetSize,
             @NonNull final DeviceGridState srcDeviceState,
             @NonNull final DeviceGridState destDeviceState) {
 
         final List<DbEntry> srcHotseatItems = srcReader.loadHotseatEntries();
         final List<DbEntry> srcWorkspaceItems = srcReader.loadAllWorkspaceEntries();
         final List<DbEntry> dstHotseatItems = destReader.loadHotseatEntries();
+        // We want to filter out the hotseat items that are placed beyond the size of the source
+        // grid as we always want to keep those extra items from the destination grid.
+        List<DbEntry> filteredDstHotseatItems = dstHotseatItems;
+        if (srcHotseatSize < destHotseatSize) {
+            filteredDstHotseatItems = filteredDstHotseatItems.stream()
+                    .filter(entry -> entry.screenId < srcHotseatSize).toList();
+        }
         final List<DbEntry> dstWorkspaceItems = destReader.loadAllWorkspaceEntries();
         final List<DbEntry> hotseatToBeAdded = new ArrayList<>(1);
         final List<DbEntry> workspaceToBeAdded = new ArrayList<>(1);
         final IntArray toBeRemoved = new IntArray();
 
-        calcDiff(srcHotseatItems, dstHotseatItems, hotseatToBeAdded, toBeRemoved);
+        calcDiff(srcHotseatItems, filteredDstHotseatItems, hotseatToBeAdded, toBeRemoved);
         calcDiff(srcWorkspaceItems, dstWorkspaceItems, workspaceToBeAdded, toBeRemoved);
 
         final int trgX = targetSize.x;
@@ -421,12 +428,13 @@
     }
 
     private static void solveHotseatPlacement(
-            @NonNull final DatabaseHelper helper, final int hotseatSize,
+            @NonNull final DatabaseHelper helper,
+            final int dstHotseatSize,
             @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
             @NonNull final List<DbEntry> placedHotseatItems,
             @NonNull final List<DbEntry> itemsToPlace, List<Integer> idsInUse) {
 
-        final boolean[] occupied = new boolean[hotseatSize];
+        final boolean[] occupied = new boolean[dstHotseatSize];
         for (DbEntry entry : placedHotseatItems) {
             occupied[entry.screenId] = true;
         }
diff --git a/src/com/android/launcher3/model/GridSizeMigrationLogic.kt b/src/com/android/launcher3/model/GridSizeMigrationLogic.kt
index dfda8e4..876919a 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationLogic.kt
+++ b/src/com/android/launcher3/model/GridSizeMigrationLogic.kt
@@ -35,7 +35,7 @@
 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction
 import com.android.launcher3.provider.LauncherDbUtils.copyTable
 import com.android.launcher3.provider.LauncherDbUtils.dropTable
-import com.android.launcher3.provider.LauncherDbUtils.shiftTableByXCells
+import com.android.launcher3.provider.LauncherDbUtils.shiftWorkspaceByXCells
 import com.android.launcher3.util.CellAndSpan
 import com.android.launcher3.util.GridOccupancy
 import com.android.launcher3.util.IntArray
@@ -82,7 +82,7 @@
                 if (shouldMigrateToStrtictlyTallerGrid) {
                     Log.d(TAG, "Migrating to strictly taller grid")
                     if (oneGridSpecs()) {
-                        shiftTableByXCells(
+                        shiftWorkspaceByXCells(
                             target.writableDatabase,
                             (destDeviceState.rows - srcDeviceState.rows),
                             TABLE_NAME,
@@ -107,7 +107,14 @@
                 val idsInUse = mutableListOf<Int>()
 
                 // Migrate hotseat.
-                migrateHotseat(destDeviceState.numHotseat, srcReader, destReader, target, idsInUse)
+                migrateHotseat(
+                    srcDeviceState.numHotseat,
+                    destDeviceState.numHotseat,
+                    srcReader,
+                    destReader,
+                    target,
+                    idsInUse,
+                )
                 // Migrate workspace.
                 migrateWorkspace(srcReader, destReader, target, targetSize, idsInUse)
 
@@ -134,6 +141,7 @@
     /** Handles hotseat migration. */
     @VisibleForTesting
     fun migrateHotseat(
+        srcHotseatSize: Int,
         destHotseatSize: Int,
         srcReader: DbReader,
         destReader: DbReader,
@@ -143,17 +151,24 @@
         val srcHotseatItems = srcReader.loadHotseatEntries()
         val dstHotseatItems = destReader.loadHotseatEntries()
 
-        val hotseatToBeAdded = getItemsToBeAdded(srcHotseatItems, dstHotseatItems)
-        val toBeRemoved = IntArray()
-        toBeRemoved.addAll(getItemsToBeRemoved(srcHotseatItems, dstHotseatItems))
+        // We want to filter out the hotseat items that are placed beyond the size of the source
+        // grid as we always want to keep those extra items from the destination grid.
+        var filteredDstHotseatItems = dstHotseatItems
+        if (srcHotseatSize < destHotseatSize) {
+            filteredDstHotseatItems =
+                filteredDstHotseatItems.filter { entry -> entry.screenId < srcHotseatSize }
+        }
+
+        val itemsToBeAdded = getItemsToBeAdded(srcHotseatItems, filteredDstHotseatItems)
+        val itemsToBeRemoved = getItemsToBeRemoved(srcHotseatItems, filteredDstHotseatItems)
 
         if (DEBUG) {
             Log.d(
                 TAG,
                 """Start hotseat migration:
-            |Removing Hotseat Items: [${dstHotseatItems.filter { toBeRemoved.contains(it.id) }
+            |Removing Hotseat Items: [${filteredDstHotseatItems.filter { itemsToBeRemoved.contains(it.id) }
                 .joinToString(",\n") { it.toString() }}]
-            |Adding Hotseat Items: [${hotseatToBeAdded
+            |Adding Hotseat Items: [${itemsToBeAdded
                 .joinToString(",\n") { it.toString() }}]
             |"""
                     .trimMargin(),
@@ -161,16 +176,16 @@
         }
 
         // Removes the items that we need to remove from the destination DB.
-        if (!toBeRemoved.isEmpty) {
+        if (!itemsToBeRemoved.isEmpty) {
             GridSizeMigrationDBController.removeEntryFromDb(
                 destReader.mDb,
                 destReader.mTableName,
-                toBeRemoved,
+                itemsToBeRemoved,
             )
         }
 
         placeHotseatItems(
-            hotseatToBeAdded,
+            itemsToBeAdded,
             dstHotseatItems,
             destHotseatSize,
             helper,
diff --git a/src/com/android/launcher3/model/ModelTaskController.kt b/src/com/android/launcher3/model/ModelTaskController.kt
index fc53343..40ea17d 100644
--- a/src/com/android/launcher3/model/ModelTaskController.kt
+++ b/src/com/android/launcher3/model/ModelTaskController.kt
@@ -22,7 +22,6 @@
 import com.android.launcher3.celllayout.CellPosMapper
 import com.android.launcher3.model.BgDataModel.FixedContainerItems
 import com.android.launcher3.model.data.ItemInfo
-import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.util.PackageUserKey
 import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder
 import java.util.Objects
@@ -51,18 +50,17 @@
      */
     fun getModelWriter() = model.getWriter(false /* verifyChanges */, CellPosMapper.DEFAULT, null)
 
-    fun bindUpdatedWorkspaceItems(allUpdates: List<WorkspaceItemInfo>) {
+    fun bindUpdatedWorkspaceItems(allUpdates: Collection<ItemInfo>) {
         // Bind workspace items
-        val workspaceUpdates =
-            allUpdates.stream().filter { info -> info.id != ItemInfo.NO_ID }.toList()
+        val workspaceUpdates = allUpdates.filter { it.id != ItemInfo.NO_ID }.toSet()
         if (workspaceUpdates.isNotEmpty()) {
-            scheduleCallbackTask { it.bindWorkspaceItemsChanged(workspaceUpdates) }
+            scheduleCallbackTask { it.bindItemsUpdated(workspaceUpdates) }
         }
 
         // Bind extra items if any
         allUpdates
             .stream()
-            .mapToInt { info: WorkspaceItemInfo -> info.container }
+            .mapToInt { it.container }
             .distinct()
             .mapToObj { dataModel.extraItems.get(it) }
             .filter { Objects.nonNull(it) }
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 4103937..a216042 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -99,8 +99,7 @@
                     });
 
             if (!updates.isEmpty()) {
-                taskController.scheduleCallbackTask(
-                        callbacks -> callbacks.bindRestoreItemsChange(updates));
+                taskController.bindUpdatedWorkspaceItems(updates);
             }
         }
     }
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 1153f48..6bef292 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -214,8 +214,7 @@
 
         // Update shortcut infos
         if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
-            final ArrayList<WorkspaceItemInfo> updatedWorkspaceItems = new ArrayList<>();
-            final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<>();
+            final ArrayList<ItemInfo> updatedWorkspaceItems = new ArrayList<>();
 
             // For system apps, package manager send OP_UPDATE when an app is enabled.
             final boolean isNewApkAvailable = mOp == OP_ADD || mOp == OP_UPDATE;
@@ -364,8 +363,8 @@
                             // if the widget has a config activity. In case there is no config
                             // activity, it will be marked as 'restored' during bind.
                             widgetInfo.restoreStatus |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
-
-                            widgets.add(widgetInfo);
+                            widgetInfo.installProgress = 100;
+                            updatedWorkspaceItems.add(widgetInfo);
                             taskController.getModelWriter().updateItemInDatabase(widgetInfo);
                         });
             }
@@ -377,10 +376,6 @@
                         "removing shortcuts with invalid target components."
                                 + " ids=" + removedShortcuts);
             }
-
-            if (!widgets.isEmpty()) {
-                taskController.scheduleCallbackTask(c -> c.bindWidgetsRestored(widgets));
-            }
         }
 
         final HashSet<String> removedPackages = new HashSet<>();
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
deleted file mode 100644
index b5a7382..0000000
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2016 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.model;
-
-import android.content.Context;
-import android.content.pm.ShortcutInfo;
-import android.os.UserHandle;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel.ModelUpdateTask;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.icons.CacheableShortcutInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.util.ApplicationInfoWrapper;
-import com.android.launcher3.util.ItemInfoMatcher;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-/**
- * Handles changes due to shortcut manager updates (deep shortcut changes)
- */
-public class ShortcutsChangedTask implements ModelUpdateTask {
-
-    @NonNull
-    private final String mPackageName;
-
-    @NonNull
-    private final List<ShortcutInfo> mShortcuts;
-
-    @NonNull
-    private final UserHandle mUser;
-
-    private final boolean mUpdateIdMap;
-
-    public ShortcutsChangedTask(@NonNull final String packageName,
-            @NonNull final List<ShortcutInfo> shortcuts, @NonNull final UserHandle user,
-            final boolean updateIdMap) {
-        mPackageName = packageName;
-        mShortcuts = shortcuts;
-        mUser = user;
-        mUpdateIdMap = updateIdMap;
-    }
-
-    @Override
-    public void execute(@NonNull ModelTaskController taskController, @NonNull BgDataModel dataModel,
-            @NonNull AllAppsList apps) {
-        final LauncherAppState app = taskController.getApp();
-        final Context context = app.getContext();
-        // Find WorkspaceItemInfo's that have changed on the workspace.
-        ArrayList<WorkspaceItemInfo> matchingWorkspaceItems = new ArrayList<>();
-
-        synchronized (dataModel) {
-            dataModel.forAllWorkspaceItemInfos(mUser, si -> {
-                if ((si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
-                        && mPackageName.equals(si.getIntent().getPackage())) {
-                    matchingWorkspaceItems.add(si);
-                }
-            });
-        }
-
-        if (!matchingWorkspaceItems.isEmpty()) {
-            ApplicationInfoWrapper infoWrapper =
-                    new ApplicationInfoWrapper(context, mPackageName, mUser);
-            if (mShortcuts.isEmpty()) {
-                // Verify that the app is indeed installed.
-                if (!infoWrapper.isInstalled() && !infoWrapper.isArchived()) {
-                    // App is not installed or archived, ignoring package events
-                    return;
-                }
-            }
-            // Update the workspace to reflect the changes to updated shortcuts residing on it.
-            List<String> allLauncherKnownIds = matchingWorkspaceItems.stream()
-                    .map(WorkspaceItemInfo::getDeepShortcutId)
-                    .distinct()
-                    .collect(Collectors.toList());
-            List<ShortcutInfo> shortcuts = new ShortcutRequest(context, mUser)
-                    .forPackage(mPackageName, allLauncherKnownIds)
-                    .query(ShortcutRequest.ALL);
-
-            Set<String> nonPinnedIds = new HashSet<>(allLauncherKnownIds);
-            ArrayList<WorkspaceItemInfo> updatedWorkspaceItemInfos = new ArrayList<>();
-            for (ShortcutInfo fullDetails : shortcuts) {
-                if (!fullDetails.isPinned()) {
-                    continue;
-                }
-                String sid = fullDetails.getId();
-                nonPinnedIds.remove(sid);
-                matchingWorkspaceItems
-                        .stream()
-                        .filter(itemInfo -> sid.equals(itemInfo.getDeepShortcutId()))
-                        .forEach(workspaceItemInfo -> {
-                            workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context);
-                            app.getIconCache().getShortcutIcon(workspaceItemInfo,
-                                    new CacheableShortcutInfo(fullDetails, infoWrapper));
-                            updatedWorkspaceItemInfos.add(workspaceItemInfo);
-                        });
-            }
-
-            taskController.bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
-            if (!nonPinnedIds.isEmpty()) {
-                taskController.deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(
-                        nonPinnedIds.stream()
-                                .map(id -> new ShortcutKey(mPackageName, mUser, id))
-                                .collect(Collectors.toSet())),
-                        "removed because the shortcut is no longer available in shortcut service");
-            }
-        }
-
-        if (mUpdateIdMap) {
-            // Update the deep shortcut map if the list of ids has changed for an activity.
-            dataModel.updateDeepShortcutCounts(mPackageName, mUser, mShortcuts);
-            taskController.bindDeepShortcuts(dataModel);
-        }
-    }
-}
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.kt b/src/com/android/launcher3/model/ShortcutsChangedTask.kt
new file mode 100644
index 0000000..2e4f75f
--- /dev/null
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2025 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.model
+
+import android.content.pm.ShortcutInfo
+import android.os.UserHandle
+import com.android.launcher3.LauncherModel.ModelUpdateTask
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+import com.android.launcher3.icons.CacheableShortcutInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.shortcuts.ShortcutKey
+import com.android.launcher3.shortcuts.ShortcutRequest
+import com.android.launcher3.util.ApplicationInfoWrapper
+import com.android.launcher3.util.ItemInfoMatcher
+
+/** Handles changes due to shortcut manager updates (deep shortcut changes) */
+class ShortcutsChangedTask(
+    private val packageName: String,
+    private val shortcuts: List<ShortcutInfo>,
+    private val user: UserHandle,
+    private val shouldUpdateIdMap: Boolean,
+) : ModelUpdateTask {
+
+    override fun execute(
+        taskController: ModelTaskController,
+        dataModel: BgDataModel,
+        apps: AllAppsList,
+    ) {
+        val app = taskController.app
+        val context = app.context
+        // Find WorkspaceItemInfo's that have changed on the workspace.
+        val matchingWorkspaceItems = ArrayList<WorkspaceItemInfo>()
+
+        synchronized(dataModel) {
+            dataModel.forAllWorkspaceItemInfos(user) { wai: WorkspaceItemInfo ->
+                if (
+                    (wai.itemType == ITEM_TYPE_DEEP_SHORTCUT) &&
+                        packageName == wai.getIntent().getPackage()
+                ) {
+                    matchingWorkspaceItems.add(wai)
+                }
+            }
+        }
+
+        if (matchingWorkspaceItems.isNotEmpty()) {
+            val infoWrapper = ApplicationInfoWrapper(context, packageName, user)
+            if (shortcuts.isEmpty()) {
+                // Verify that the app is indeed installed.
+                if (!infoWrapper.isInstalled() && !infoWrapper.isArchived()) {
+                    // App is not installed or archived, ignoring package events
+                    return
+                }
+            }
+            // Update the workspace to reflect the changes to updated shortcuts residing on it.
+            val allLauncherKnownIds =
+                matchingWorkspaceItems.map { item -> item.deepShortcutId }.distinct()
+            val shortcuts: List<ShortcutInfo> =
+                ShortcutRequest(context, user)
+                    .forPackage(packageName, allLauncherKnownIds)
+                    .query(ShortcutRequest.ALL)
+
+            val nonPinnedIds: MutableSet<String> = HashSet(allLauncherKnownIds)
+            val updatedWorkspaceItemInfos = ArrayList<WorkspaceItemInfo>()
+            for (fullDetails in shortcuts) {
+                if (!fullDetails.isPinned) {
+                    continue
+                }
+                val shortcutId = fullDetails.id
+                nonPinnedIds.remove(shortcutId)
+                matchingWorkspaceItems
+                    .filter { itemInfo: WorkspaceItemInfo -> shortcutId == itemInfo.deepShortcutId }
+                    .forEach { workspaceItemInfo: WorkspaceItemInfo ->
+                        workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context)
+                        app.iconCache.getShortcutIcon(
+                            workspaceItemInfo,
+                            CacheableShortcutInfo(fullDetails, infoWrapper),
+                        )
+                        updatedWorkspaceItemInfos.add(workspaceItemInfo)
+                    }
+            }
+
+            taskController.bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos)
+            if (nonPinnedIds.isNotEmpty()) {
+                taskController.deleteAndBindComponentsRemoved(
+                    ItemInfoMatcher.ofShortcutKeys(
+                        nonPinnedIds
+                            .map { id: String? -> ShortcutKey(packageName, user, id) }
+                            .toSet()
+                    ),
+                    "removed because the shortcut is no longer available in shortcut service",
+                )
+            }
+        }
+
+        if (shouldUpdateIdMap) {
+            // Update the deep shortcut map if the list of ids has changed for an activity.
+            dataModel.updateDeepShortcutCounts(packageName, user, shortcuts)
+            taskController.bindDeepShortcuts(dataModel)
+        }
+    }
+}
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index c22a8a5..588e759 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -439,8 +439,7 @@
         LauncherAtom.ItemInfo.Builder itemBuilder = LauncherAtom.ItemInfo.newBuilder();
         itemBuilder.setIsKidsMode(
                 SettingsCache.INSTANCE.get(context).getValue(NAV_BAR_KIDS_MODE, 0));
-        UserCache.INSTANCE.executeIfCreated(cache ->
-                itemBuilder.setUserType(getUserType(cache.getUserInfo(user))));
+        itemBuilder.setUserType(getUserType(UserCache.INSTANCE.get(context).getUserInfo(user)));
         itemBuilder.setRank(rank);
         itemBuilder.addAllItemAttributes(mAttributeList);
         return itemBuilder;
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index e861961..0b18a87 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -32,11 +32,15 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.annotation.WorkerThread;
 
+import com.android.launcher3.dagger.ApplicationContext;
+import com.android.launcher3.dagger.LauncherAppSingleton;
+import com.android.launcher3.dagger.LauncherBaseAppComponent;
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.UserBadgeDrawable;
 import com.android.launcher3.util.ApiWrapper;
+import com.android.launcher3.util.DaggerSingletonObject;
+import com.android.launcher3.util.DaggerSingletonTracker;
 import com.android.launcher3.util.FlagOp;
-import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.launcher3.util.UserIconInfo;
@@ -47,10 +51,16 @@
 import java.util.Map;
 import java.util.function.BiConsumer;
 
+import javax.inject.Inject;
+
 /**
  * Class which manages a local cache of user handles to avoid system rpc
  */
-public class UserCache implements SafeCloseable {
+@LauncherAppSingleton
+public class UserCache {
+
+    public static DaggerSingletonObject<UserCache> INSTANCE =
+            new DaggerSingletonObject<>(LauncherBaseAppComponent::getUserCache);
 
     public static final String ACTION_PROFILE_ADDED = ATLEAST_U
             ? Intent.ACTION_PROFILE_ADDED : Intent.ACTION_MANAGED_PROFILE_ADDED;
@@ -65,9 +75,6 @@
     public static final String ACTION_PROFILE_UNAVAILABLE =
             "android.intent.action.PROFILE_UNAVAILABLE";
 
-    public static final MainThreadInitializedObject<UserCache> INSTANCE =
-            new MainThreadInitializedObject<>(UserCache::new);
-
     /** Returns an instance of UserCache bound to the context provided. */
     public static UserCache getInstance(Context context) {
         return INSTANCE.get(context);
@@ -78,6 +85,7 @@
             new SimpleBroadcastReceiver(MODEL_EXECUTOR, this::onUsersChanged);
 
     private final Context mContext;
+    private final ApiWrapper mApiWrapper;
 
     @NonNull
     private Map<UserHandle, UserIconInfo> mUserToSerialMap;
@@ -85,15 +93,17 @@
     @NonNull
     private Map<UserHandle, List<String>> mUserToPreInstallAppMap;
 
-    private UserCache(Context context) {
+    @Inject
+    public UserCache(
+            @ApplicationContext Context context,
+            DaggerSingletonTracker tracker,
+            ApiWrapper apiWrapper
+    ) {
         mContext = context;
+        mApiWrapper = apiWrapper;
         mUserToSerialMap = Collections.emptyMap();
         MODEL_EXECUTOR.execute(this::initAsync);
-    }
-
-    @Override
-    public void close() {
-        MODEL_EXECUTOR.execute(() -> mUserChangeReceiver.unregisterReceiverSafely(mContext));
+        tracker.addCloseable(() -> mUserChangeReceiver.unregisterReceiverSafely(mContext));
     }
 
     @WorkerThread
@@ -124,7 +134,7 @@
 
     @WorkerThread
     private void updateCache() {
-        mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers();
+        mUserToSerialMap = mApiWrapper.queryAllUsers();
         mUserToPreInstallAppMap = fetchPreInstallApps();
     }
 
@@ -134,7 +144,7 @@
         mUserToSerialMap.forEach((userHandle, userIconInfo) -> {
             // Fetch only for private profile, as other profiles have no usages yet.
             List<String> preInstallApp = userIconInfo.isPrivate()
-                    ? ApiWrapper.INSTANCE.get(mContext).getPreInstalledSystemPackages(userHandle)
+                    ? mApiWrapper.getPreInstalledSystemPackages(userHandle)
                     : new ArrayList<>();
             userToPreInstallApp.put(userHandle, preInstallApp);
         });
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.kt b/src/com/android/launcher3/provider/LauncherDbUtils.kt
index 6f1d0dd..c92328d 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.kt
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.kt
@@ -28,6 +28,7 @@
 import android.text.TextUtils
 import com.android.launcher3.LauncherAppState
 import com.android.launcher3.LauncherSettings
+import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP
 import com.android.launcher3.Utilities
 import com.android.launcher3.icons.IconCache
 import com.android.launcher3.model.LoaderCursor
@@ -132,8 +133,10 @@
     }
 
     @JvmStatic
-    fun shiftTableByXCells(db: SQLiteDatabase, x: Int, toTable: String) {
-        db.run { execSQL("UPDATE $toTable SET cellY = cellY + $x") }
+    fun shiftWorkspaceByXCells(db: SQLiteDatabase, x: Int, toTable: String) {
+        db.run {
+            execSQL("UPDATE $toTable SET cellY = cellY + $x WHERE container = $CONTAINER_DESKTOP")
+        }
     }
 
     /**
diff --git a/src/com/android/launcher3/search/StringMatcherUtility.java b/src/com/android/launcher3/search/StringMatcherUtility.java
index 7446314..20b4d0b 100644
--- a/src/com/android/launcher3/search/StringMatcherUtility.java
+++ b/src/com/android/launcher3/search/StringMatcherUtility.java
@@ -127,17 +127,17 @@
             if (query == null || target == null) {
                 return false;
             }
-            switch (mCollator.compare(query, target)) {
-                case 0:
-                    return true;
-                case -1:
-                    // The target string can contain a modifier which would make it larger than
-                    // the query string (even though the length is same). If the query becomes
-                    // larger after appending a unicode character, it was originally a prefix of
-                    // the target string and hence should match.
-                    return mCollator.compare(query + MAX_UNICODE, target) > -1;
-                default:
-                    return false;
+            int compare = mCollator.compare(query, target);
+            if (compare == 0) {
+                return true;
+            } else if (compare < 0) {
+                // The target string can contain a modifier which would make it larger than
+                // the query string (even though the length is same). If the query becomes
+                // larger after appending a unicode character, it was originally a prefix of
+                // the target string and hence should match.
+                return mCollator.compare(query + MAX_UNICODE, target) >= 0;
+            } else {
+                return false;
             }
         }
 
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 78709b8..381d17a 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -228,10 +228,9 @@
     private static void onClickPendingAppItem(View v, Launcher launcher, String packageName,
             boolean downloadStarted) {
         ItemInfo item = (ItemInfo) v.getTag();
-        CompletableFuture<SessionInfo> siFuture;
-        siFuture = CompletableFuture.supplyAsync(() ->
-                        InstallSessionHelper.INSTANCE.get(launcher)
-                                .getActiveSessionInfo(item.user, packageName),
+        CompletableFuture<SessionInfo> siFuture = CompletableFuture.supplyAsync(() ->
+                InstallSessionHelper.INSTANCE.get(launcher)
+                        .getActiveSessionInfo(item.user, packageName),
                 UI_HELPER_EXECUTOR);
         Consumer<SessionInfo> marketLaunchAction = sessionInfo -> {
             if (sessionInfo != null) {
@@ -245,8 +244,8 @@
                 }
             }
             // Fallback to using custom market intent.
-            Intent intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent(
-                    packageName, Process.myUserHandle());
+            Intent intent = ApiWrapper.INSTANCE.get(launcher).getMarketSearchIntent(
+                    packageName, item.user);
             launcher.startActivitySafely(v, intent, item);
         };
 
@@ -358,9 +357,7 @@
         // Check for abandoned promise
         if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()
                 && (!Flags.enableSupportForArchiving() || !shortcut.isArchived())) {
-            String packageName = shortcut.getIntent().getComponent() != null
-                    ? shortcut.getIntent().getComponent().getPackageName()
-                    : shortcut.getIntent().getPackage();
+            String packageName = shortcut.getTargetPackage();
             if (!TextUtils.isEmpty(packageName)) {
                 onClickPendingAppItem(
                         v,
diff --git a/src/com/android/launcher3/util/ApiWrapper.java b/src/com/android/launcher3/util/ApiWrapper.java
index 467a7ec..48e033a 100644
--- a/src/com/android/launcher3/util/ApiWrapper.java
+++ b/src/com/android/launcher3/util/ApiWrapper.java
@@ -28,6 +28,7 @@
 import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.ColorDrawable;
 import android.net.Uri;
+import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.ArrayMap;
@@ -120,6 +121,21 @@
      * Activity).
      */
     public Intent getAppMarketActivityIntent(String packageName, UserHandle user) {
+        return createMarketIntent(packageName);
+    }
+
+    /**
+     * Returns an intent which can be used to start a search for a package on app market
+     */
+    public Intent getMarketSearchIntent(String packageName, UserHandle user) {
+        // If we are search for the current user, just launch the market directly as the
+        // system won't have the installer details either
+        return  (Process.myUserHandle().equals(user))
+                ? createMarketIntent(packageName)
+                : getAppMarketActivityIntent(packageName, user);
+    }
+
+    private static Intent createMarketIntent(String packageName) {
         return new Intent(Intent.ACTION_VIEW)
                 .setData(new Uri.Builder()
                         .scheme("market")
@@ -171,6 +187,13 @@
         return appInfo.sourceDir;
     }
 
+    /**
+     * Returns the round icon resource Id if defined by the app
+     */
+    public int getRoundIconRes(@NonNull ApplicationInfo appInfo) {
+        return 0;
+    }
+
     private static class NoopDrawable extends ColorDrawable {
         @Override
         public int getIntrinsicHeight() {
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 9472f5f..475dc04 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -69,6 +69,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.StringJoiner;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.inject.Inject;
 
@@ -114,7 +115,8 @@
 
     // The callback in this listener updates DeviceProfile, which other listeners might depend on
     private DisplayInfoChangeListener mPriorityListener;
-    private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
+    private final CopyOnWriteArrayList<DisplayInfoChangeListener> mListeners =
+            new CopyOnWriteArrayList<>();
 
     // We will register broadcast receiver on main thread to ensure not missing changes on
     // TARGET_OVERLAY_PACKAGE and ACTION_OVERLAY_CHANGED.
diff --git a/src/com/android/launcher3/util/LauncherBindableItemsContainer.java b/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
index 02779ce..20e3eaf 100644
--- a/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
+++ b/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
@@ -15,24 +15,20 @@
  */
 package com.android.launcher3.util;
 
-import android.graphics.drawable.Drawable;
 import android.view.View;
 
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.apppairs.AppPairIcon;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.graphics.PreloadIconDrawable;
 import com.android.launcher3.model.data.AppPairInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.widget.PendingAppWidgetHostView;
 
-import java.util.HashSet;
-import java.util.List;
+import java.util.Set;
 
 /**
  * Interface representing a container which can bind Launcher items with some utility methods
@@ -41,27 +37,22 @@
 
     /**
      * Called to update workspace items as a result of
-     * {@link com.android.launcher3.model.BgDataModel.Callbacks#bindWorkspaceItemsChanged(List)}
+     * {@link com.android.launcher3.model.BgDataModel.Callbacks#bindItemsUpdated(Set)}
      */
-    default void updateWorkspaceItems(List<WorkspaceItemInfo> shortcuts, ActivityContext context) {
-        final HashSet<WorkspaceItemInfo> updates = new HashSet<>(shortcuts);
+    default void updateContainerItems(Set<ItemInfo> updates, ActivityContext context) {
         ItemOperator op = (info, v) -> {
-            if (v instanceof BubbleTextView && updates.contains(info)) {
-                WorkspaceItemInfo si = (WorkspaceItemInfo) info;
-                BubbleTextView shortcut = (BubbleTextView) v;
-                Drawable oldIcon = shortcut.getIcon();
-                boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
-                        && ((PreloadIconDrawable) oldIcon).hasNotCompleted();
-                shortcut.applyFromWorkspaceItem(
-                        si,
-                        si.isPromise() != oldPromiseState
-                                && oldIcon instanceof PreloadIconDrawable
-                                ? (PreloadIconDrawable) oldIcon
-                                : null);
-            } else if (info instanceof FolderInfo && v instanceof FolderIcon) {
-                ((FolderIcon) v).updatePreviewItems(updates::contains);
+            if (v instanceof BubbleTextView shortcut
+                    && info instanceof WorkspaceItemInfo wii
+                    && updates.contains(info)) {
+                shortcut.applyFromWorkspaceItem(wii);
+            } else if (info instanceof FolderInfo && v instanceof FolderIcon folderIcon) {
+                folderIcon.updatePreviewItems(updates::contains);
             } else if (info instanceof AppPairInfo && v instanceof AppPairIcon appPairIcon) {
                 appPairIcon.maybeRedrawForWorkspaceUpdate(updates::contains);
+            } else if (v instanceof PendingAppWidgetHostView pendingView
+                    && updates.contains(info)) {
+                pendingView.applyState();
+                pendingView.postProviderAvailabilityCheck();
             }
 
             // Iterate all items
@@ -76,35 +67,6 @@
     }
 
     /**
-     * Called to update restored items as a result of
-     * {@link com.android.launcher3.model.BgDataModel.Callbacks#bindRestoreItemsChange(HashSet)}}
-     */
-    default void updateRestoreItems(final HashSet<ItemInfo> updates, ActivityContext context) {
-        ItemOperator op = (info, v) -> {
-            if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
-                    && updates.contains(info)) {
-                ((BubbleTextView) v).applyLoadingState(null);
-            } else if (v instanceof PendingAppWidgetHostView
-                    && info instanceof LauncherAppWidgetInfo
-                    && updates.contains(info)) {
-                ((PendingAppWidgetHostView) v).applyState();
-            } else if (v instanceof FolderIcon && info instanceof FolderInfo) {
-                ((FolderIcon) v).updatePreviewItems(updates::contains);
-            } else if (info instanceof AppPairInfo && v instanceof AppPairIcon appPairIcon) {
-                appPairIcon.maybeRedrawForWorkspaceUpdate(updates::contains);
-            }
-            // process all the shortcuts
-            return false;
-        };
-
-        mapOverItems(op);
-        Folder folder = Folder.getOpen(context);
-        if (folder != null) {
-            folder.iterateOverItems(op);
-        }
-    }
-
-    /**
      * Map the operator over the shortcuts and widgets.
      *
      * @param op the operator to map over the shortcuts
diff --git a/src/com/android/launcher3/util/MSDLPlayerWrapper.java b/src/com/android/launcher3/util/MSDLPlayerWrapper.java
index 8a1d923..fc3fa72 100644
--- a/src/com/android/launcher3/util/MSDLPlayerWrapper.java
+++ b/src/com/android/launcher3/util/MSDLPlayerWrapper.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher3.util;
 
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
 import android.content.Context;
 import android.os.Vibrator;
 
@@ -50,7 +48,9 @@
     @Inject
     public MSDLPlayerWrapper(@ApplicationContext Context context) {
         Vibrator vibrator = context.getSystemService(Vibrator.class);
-        mMSDLPlayer = MSDLPlayer.Companion.createPlayer(vibrator, UI_HELPER_EXECUTOR, null);
+        mMSDLPlayer = MSDLPlayer.Companion.createPlayer(vibrator,
+                java.util.concurrent.Executors.newSingleThreadExecutor(),
+                null /* useHapticFeedbackForToken */);
     }
 
     /** Perform MSDL feedback for a token with interaction properties */
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 9c9b80d..cd8e457 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -21,7 +21,7 @@
 import static android.graphics.Paint.FILTER_BITMAP_FLAG;
 
 import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
-import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
+import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import android.appwidget.AppWidgetProviderInfo;
@@ -37,6 +37,9 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.text.Layout;
 import android.text.StaticLayout;
 import android.text.TextPaint;
@@ -60,8 +63,10 @@
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.widget.LauncherWidgetHolder.ProviderChangedListener;
 
 import java.util.List;
 
@@ -81,6 +86,8 @@
     private final Matrix mMatrix = new Matrix();
     private final RectF mPreviewBitmapRect = new RectF();
     private final RectF mCanvasRect = new RectF();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final RunnableList mOnDetachCleanup = new RunnableList();
 
     private final LauncherWidgetHolder mWidgetHolder;
     private final LauncherAppWidgetProviderInfo mAppwidget;
@@ -90,7 +97,6 @@
     private final CharSequence mLabel;
 
     private OnClickListener mClickListener;
-    private SafeCloseable mOnDetachCleanup;
 
     private int mDragFlags;
 
@@ -210,16 +216,15 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
+        mOnDetachCleanup.executeAllAndClear();
         if ((mAppwidget != null)
                 && !mInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)
                 && mInfo.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED) {
             // If the widget is not completely restored, but has a valid ID, then listen of
             // updates from provider app for potential restore complete.
-            if (mOnDetachCleanup != null) {
-                mOnDetachCleanup.close();
-            }
-            mOnDetachCleanup = mWidgetHolder.addOnUpdateListener(
+            SafeCloseable updateCleanup = mWidgetHolder.addOnUpdateListener(
                     mInfo.appWidgetId, mAppwidget, this::checkIfRestored);
+            mOnDetachCleanup.add(updateCleanup::close);
             checkIfRestored();
         }
     }
@@ -227,10 +232,7 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
-        if (mOnDetachCleanup != null) {
-            mOnDetachCleanup.close();
-            mOnDetachCleanup = null;
-        }
+        mOnDetachCleanup.executeAllAndClear();
     }
 
     /**
@@ -295,43 +297,30 @@
             mCenterDrawable.setCallback(null);
             mCenterDrawable = null;
         }
-        mDragFlags = 0;
-        if (info.bitmap.icon != null) {
-            mDragFlags = FLAG_DRAW_ICON;
+        mDragFlags = FLAG_DRAW_ICON;
 
-            Drawable widgetCategoryIcon = getWidgetCategoryIcon();
-            // The view displays three modes,
-            //   1) App icon in the center
-            //   2) Preload icon in the center
-            //   3) App icon in the center with a setup icon on the top left corner.
-            if (mDisabledForSafeMode) {
-                if (widgetCategoryIcon == null) {
-                    FastBitmapDrawable disabledIcon = info.newIcon(getContext());
-                    disabledIcon.setIsDisabled(true);
-                    mCenterDrawable = disabledIcon;
-                } else {
-                    widgetCategoryIcon.setColorFilter(getDisabledColorFilter());
-                    mCenterDrawable = widgetCategoryIcon;
-                }
-                mSettingIconDrawable = null;
-            } else if (isReadyForClickSetup()) {
-                mCenterDrawable = widgetCategoryIcon == null
-                        ? info.newIcon(getContext())
-                        : widgetCategoryIcon;
-                mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
-                updateSettingColor(info.bitmap.color);
+        // The view displays three modes,
+        //   1) App icon in the center
+        //   2) Preload icon in the center
+        //   3) App icon in the center with a setup icon on the top left corner.
+        if (mDisabledForSafeMode) {
+            FastBitmapDrawable disabledIcon = info.newIcon(getContext());
+            disabledIcon.setIsDisabled(true);
+            mCenterDrawable = disabledIcon;
+            mSettingIconDrawable = null;
+        } else if (isReadyForClickSetup()) {
+            mCenterDrawable = info.newIcon(getContext());
+            mSettingIconDrawable = getResources().getDrawable(R.drawable.ic_setting).mutate();
+            updateSettingColor(info.bitmap.color);
 
-                mDragFlags |= FLAG_DRAW_SETTINGS | FLAG_DRAW_LABEL;
-            } else {
-                mCenterDrawable = widgetCategoryIcon == null
-                        ? newPendingIcon(getContext(), info)
-                        : widgetCategoryIcon;
-                mSettingIconDrawable = null;
-                applyState();
-            }
-            mCenterDrawable.setCallback(this);
-            mDrawableSizeChanged = true;
+            mDragFlags |= FLAG_DRAW_SETTINGS | FLAG_DRAW_LABEL;
+        } else {
+            mCenterDrawable = newPendingIcon(getContext(), info);
+            mSettingIconDrawable = null;
+            applyState();
         }
+        mCenterDrawable.setCallback(this);
+        mDrawableSizeChanged = true;
         invalidate();
     }
 
@@ -350,6 +339,11 @@
     }
 
     public void applyState() {
+        if (mCenterDrawable instanceof FastBitmapDrawable fb
+                && mInfo.pendingItemInfo != null
+                && !fb.isSameInfo(mInfo.pendingItemInfo.bitmap)) {
+            reapplyItemInfo(mInfo.pendingItemInfo);
+        }
         if (mCenterDrawable != null) {
             mCenterDrawable.setLevel(Math.max(mInfo.installProgress, 0));
         }
@@ -486,16 +480,72 @@
     }
 
     /**
-     * Returns the widget category icon for {@link #mInfo}.
-     *
-     * <p>If {@link #mInfo}'s category is {@code PackageItemInfo#NO_CATEGORY} or unknown, returns
-     * {@code null}.
+     * Creates a runnable runnable which tries to refresh the widget if it is restored
      */
-    @Nullable
-    private Drawable getWidgetCategoryIcon() {
-        if (mInfo.pendingItemInfo.widgetCategory == WidgetSections.NO_CATEGORY) {
-            return null;
+    public void postProviderAvailabilityCheck() {
+        if (!mInfo.hasRestoreFlag(FLAG_PROVIDER_NOT_READY) && getAppWidgetInfo() == null) {
+            // If the info state suggests that the provider is ready, but there is no
+            // provider info attached on this pending view, recreate when the provider is available
+            DeferredWidgetRefresh restoreRunnable = new DeferredWidgetRefresh();
+            mOnDetachCleanup.add(restoreRunnable::cleanup);
+            mHandler.post(restoreRunnable::notifyWidgetProvidersChanged);
         }
-        return mInfo.pendingItemInfo.newIcon(getContext());
+    }
+
+    /**
+     * Used as a workaround to ensure that the AppWidgetService receives the
+     * PACKAGE_ADDED broadcast before updating widgets.
+     *
+     * This class will periodically check for the availability of the WidgetProvider as a result
+     * of providerChanged callback from the host. When the provider is available or a timeout of
+     * 10-sec is reached, it reinflates the pending-widget which in-turn goes through the process
+     * of re-evaluating the pending state of the widget,
+     */
+    private class DeferredWidgetRefresh implements Runnable, ProviderChangedListener {
+        private boolean mRefreshPending = true;
+
+        DeferredWidgetRefresh() {
+            mWidgetHolder.addProviderChangeListener(this);
+            // Force refresh after 10 seconds, if we don't get the provider changed event.
+            // This could happen when the provider is no longer available in the app.
+            Message msg = Message.obtain(getHandler(), this);
+            msg.obj = DeferredWidgetRefresh.class;
+            mHandler.sendMessageDelayed(msg, 10000);
+        }
+
+        /**
+         * Reinflate the widget if it is still attached.
+         */
+        @Override
+        public void run() {
+            cleanup();
+            if (mRefreshPending) {
+                reInflate();
+                mRefreshPending = false;
+            }
+        }
+
+        @Override
+        public void notifyWidgetProvidersChanged() {
+            final AppWidgetProviderInfo widgetInfo;
+            WidgetManagerHelper widgetHelper = new WidgetManagerHelper(getContext());
+            if (mInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
+                widgetInfo = widgetHelper.findProvider(mInfo.providerName, mInfo.user);
+            } else {
+                widgetInfo = widgetHelper.getLauncherAppWidgetInfo(mInfo.appWidgetId,
+                        mInfo.getTargetComponent());
+            }
+            if (widgetInfo != null) {
+                run();
+            }
+        }
+
+        /**
+         * Removes any scheduled callbacks and change listeners, no-op if nothing is scheduled
+         */
+        public void cleanup() {
+            mWidgetHolder.removeProviderChangeListener(this);
+            mHandler.removeCallbacks(this);
+        }
     }
 }
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
index 4c366c3..a13d63b 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 267
 	bottomSheetWorkspaceScale: 1.0
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 788.0px (300.1905dp)
+	allAppsShiftRange: 2400.0px (914.2857dp)
 	allAppsOpenDuration: 600
 	allAppsCloseDuration: 300
 	allAppsIconSizePx: 147.0px (56.0dp)
@@ -66,7 +66,7 @@
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
 	numShownAllAppsColumns: 5
-	allAppsPadding.top: 0.0px (0.0dp)
+	allAppsPadding.top: 118.0px (44.95238dp)
 	allAppsPadding.left: 0.0px (0.0dp)
 	allAppsPadding.right: 0.0px (0.0dp)
 	allAppsLeftRightMargin: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
index 6db9534..3c24885 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 267
 	bottomSheetWorkspaceScale: 1.0
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 788.0px (300.1905dp)
+	allAppsShiftRange: 2400.0px (914.2857dp)
 	allAppsOpenDuration: 600
 	allAppsCloseDuration: 300
 	allAppsIconSizePx: 147.0px (56.0dp)
@@ -66,7 +66,7 @@
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
 	numShownAllAppsColumns: 5
-	allAppsPadding.top: 0.0px (0.0dp)
+	allAppsPadding.top: 118.0px (44.95238dp)
 	allAppsPadding.left: 0.0px (0.0dp)
 	allAppsPadding.right: 0.0px (0.0dp)
 	allAppsLeftRightMargin: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
index 6e76b13..5e06513 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 267
 	bottomSheetWorkspaceScale: 1.0
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 788.0px (300.1905dp)
+	allAppsShiftRange: 1080.0px (411.42856dp)
 	allAppsOpenDuration: 600
 	allAppsCloseDuration: 300
 	allAppsIconSizePx: 147.0px (56.0dp)
@@ -66,7 +66,7 @@
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
 	numShownAllAppsColumns: 5
-	allAppsPadding.top: 0.0px (0.0dp)
+	allAppsPadding.top: 74.0px (28.190475dp)
 	allAppsPadding.left: 0.0px (0.0dp)
 	allAppsPadding.right: 0.0px (0.0dp)
 	allAppsLeftRightMargin: 0.0px (0.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
index 1af9215..d107988 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
@@ -55,7 +55,7 @@
 	bottomSheetCloseDuration: 267
 	bottomSheetWorkspaceScale: 1.0
 	bottomSheetDepth: 0.0
-	allAppsShiftRange: 788.0px (300.1905dp)
+	allAppsShiftRange: 1080.0px (411.42856dp)
 	allAppsOpenDuration: 600
 	allAppsCloseDuration: 300
 	allAppsIconSizePx: 147.0px (56.0dp)
@@ -66,7 +66,7 @@
 	allAppsBorderSpacePxX: 42.0px (16.0dp)
 	allAppsBorderSpacePxY: 42.0px (16.0dp)
 	numShownAllAppsColumns: 5
-	allAppsPadding.top: 0.0px (0.0dp)
+	allAppsPadding.top: 74.0px (28.190475dp)
 	allAppsPadding.left: 0.0px (0.0dp)
 	allAppsPadding.right: 0.0px (0.0dp)
 	allAppsLeftRightMargin: 0.0px (0.0dp)
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt
index eee6191..adf38fe 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/GridSizeMigrationTest.kt
@@ -134,6 +134,7 @@
             var gridSizeMigrationLogic = GridSizeMigrationLogic()
             val idsInUse = mutableListOf<Int>()
             gridSizeMigrationLogic.migrateHotseat(
+                5,
                 idp.numDatabaseHotseatIcons,
                 srcReader,
                 destReader,
@@ -152,6 +153,7 @@
                 dbHelper,
                 srcReader,
                 destReader,
+                5,
                 idp.numDatabaseHotseatIcons,
                 Point(idp.numColumns, idp.numRows),
                 DeviceGridState(context),
@@ -277,6 +279,7 @@
             var gridSizeMigrationLogic = GridSizeMigrationLogic()
             val idsInUse = mutableListOf<Int>()
             gridSizeMigrationLogic.migrateHotseat(
+                5,
                 idp.numDatabaseHotseatIcons,
                 readerGridA,
                 readerGridB,
@@ -295,6 +298,7 @@
                 dbHelper,
                 readerGridA,
                 readerGridB,
+                5,
                 idp.numDatabaseHotseatIcons,
                 Point(idp.numColumns, idp.numRows),
                 DeviceGridState(context),
@@ -317,8 +321,8 @@
         // 2 1 3 4
         verifyHotseat(
             c,
-            idp,
             mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
+            4,
         )
 
         // Check workspace items in grid B
@@ -348,7 +352,7 @@
         addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9)
 
         // migrate from B -> A
-        migrateGrid(dbHelper, readerGridB, readerGridA, 5, 5, 5)
+        migrateGrid(dbHelper, readerGridB, readerGridA, 4, 5, 5, 5)
 
         // Check hotseat items in grid A
         c =
@@ -362,11 +366,12 @@
                 null,
             ) ?: throw IllegalStateException()
         // Expected hotseat items in grid A
-        // 1 2 _ 3 4
+        // 1 2 4 3 4
         verifyHotseat(
             c,
-            idp,
-            mutableListOf(testPackage1, testPackage2, null, testPackage3, testPackage4).toList(),
+            mutableListOf(testPackage1, testPackage2, testPackage4, testPackage3, testPackage4)
+                .toList(),
+            5,
         )
 
         // Check workspace items in grid A
@@ -404,6 +409,7 @@
             dbHelper,
             readerGridA,
             readerGridB,
+            5,
             idp.numDatabaseHotseatIcons,
             idp.numColumns,
             idp.numRows,
@@ -424,8 +430,8 @@
         // 2 1 3 4
         verifyHotseat(
             c,
-            idp,
             mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
+            4,
         )
 
         // Check workspace items in grid B
@@ -452,10 +458,150 @@
         assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2))
     }
 
+    @Test
+    @Throws(Exception::class)
+    @EnableFlags(Flags.FLAG_GRID_MIGRATION_REFACTOR)
+    fun testHotseatMigrationToSmallerGridBackAndForthFlagOn() {
+        testHotseatMigrationToSmallerGridBackAndForth()
+    }
+
+    @Test
+    @Throws(Exception::class)
+    @DisableFlags(Flags.FLAG_GRID_MIGRATION_REFACTOR)
+    fun testHotseatMigrationToSmallerGridBackAndForthFlagOff() {
+        testHotseatMigrationToSmallerGridBackAndForth()
+    }
+
+    /** Old migration logic, should be modified once is not needed anymore */
+    @Throws(Exception::class)
+    fun testHotseatMigrationToSmallerGridBackAndForth() {
+        // Hotseat items in grid A
+        // 1 2 3 4 5
+        addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+        addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+        addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
+
+        // Hotseat items in grid B
+        // 2 _ _ _
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+
+        idp.numDatabaseHotseatIcons = 4
+        idp.numColumns = 4
+        idp.numRows = 4
+        val readerGridA = DbReader(db, TMP_TABLE, context)
+        val readerGridB = DbReader(db, TABLE_NAME, context)
+        // migrate from A -> B
+        if (Flags.gridMigrationRefactor()) {
+            var gridSizeMigrationLogic = GridSizeMigrationLogic()
+            val idsInUse = mutableListOf<Int>()
+            gridSizeMigrationLogic.migrateHotseat(
+                5,
+                idp.numDatabaseHotseatIcons,
+                readerGridA,
+                readerGridB,
+                dbHelper,
+                idsInUse,
+            )
+            gridSizeMigrationLogic.migrateWorkspace(
+                readerGridA,
+                readerGridB,
+                dbHelper,
+                Point(idp.numColumns, idp.numRows),
+                idsInUse,
+            )
+        } else {
+            GridSizeMigrationDBController.migrate(
+                dbHelper,
+                readerGridA,
+                readerGridB,
+                5,
+                idp.numDatabaseHotseatIcons,
+                Point(idp.numColumns, idp.numRows),
+                DeviceGridState(context),
+                DeviceGridState(idp),
+            )
+        }
+
+        // Check hotseat items in grid B
+        var c =
+            db.query(
+                TABLE_NAME,
+                arrayOf(SCREEN, INTENT),
+                "container=$CONTAINER_HOTSEAT",
+                null,
+                SCREEN,
+                null,
+                null,
+            ) ?: throw IllegalStateException()
+        // Expected hotseat items in grid B
+        // 2 1 3 4
+        verifyHotseat(
+            c,
+            mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
+            4,
+        )
+
+        // migrate from B -> A
+        migrateGrid(dbHelper, readerGridB, readerGridA, idp.numDatabaseHotseatIcons, 5, 5, 5)
+
+        // Check hotseat items in grid A
+        c =
+            db.query(
+                TMP_TABLE,
+                arrayOf(SCREEN, INTENT),
+                "container=$CONTAINER_HOTSEAT",
+                null,
+                SCREEN,
+                null,
+                null,
+            ) ?: throw IllegalStateException()
+        // Expected hotseat items in grid A
+        // 1 2 3 4 5
+        verifyHotseat(
+            c,
+            mutableListOf(testPackage1, testPackage2, testPackage3, testPackage4, testPackage5)
+                .toList(),
+            5,
+        )
+
+        // migrate from A -> B
+        migrateGrid(
+            dbHelper,
+            readerGridA,
+            readerGridB,
+            5,
+            idp.numDatabaseHotseatIcons,
+            idp.numColumns,
+            idp.numRows,
+        )
+
+        // Check hotseat items in grid B
+        c =
+            db.query(
+                TABLE_NAME,
+                arrayOf(SCREEN, INTENT),
+                "container=$CONTAINER_HOTSEAT",
+                null,
+                SCREEN,
+                null,
+                null,
+            ) ?: throw IllegalStateException()
+        // Expected hotseat items in grid B
+        // 2 1 3 4
+        verifyHotseat(
+            c,
+            mutableListOf(testPackage2, testPackage1, testPackage3, testPackage4).toList(),
+            4,
+        )
+    }
+
     private fun migrateGrid(
         dbHelper: DatabaseHelper,
         srcReader: DbReader,
         destReader: DbReader,
+        srcHotseatSize: Int,
         destHotseatSize: Int,
         pointX: Int,
         pointY: Int,
@@ -464,7 +610,8 @@
             var gridSizeMigrationLogic = GridSizeMigrationLogic()
             val idsInUse = mutableListOf<Int>()
             gridSizeMigrationLogic.migrateHotseat(
-                idp.numDatabaseHotseatIcons,
+                srcHotseatSize,
+                destHotseatSize,
                 srcReader,
                 destReader,
                 dbHelper,
@@ -482,6 +629,7 @@
                 dbHelper,
                 srcReader,
                 destReader,
+                srcHotseatSize,
                 destHotseatSize,
                 Point(pointX, pointY),
                 DeviceGridState(idp),
@@ -490,8 +638,8 @@
         }
     }
 
-    private fun verifyHotseat(c: Cursor, idp: InvariantDeviceProfile, expected: List<String?>) {
-        assertThat(c.count).isEqualTo(idp.numDatabaseHotseatIcons)
+    private fun verifyHotseat(c: Cursor, expected: List<String?>, expectedCount: Int) {
+        assertThat(c.count).isEqualTo(expectedCount)
         val screenIndex = c.getColumnIndex(SCREEN)
         val intentIndex = c.getColumnIndex(INTENT)
         expected.forEachIndexed { idx, pkg ->
@@ -584,6 +732,7 @@
             dbHelper,
             srcReader,
             destReader,
+            4,
             idp.numDatabaseHotseatIcons,
             idp.numColumns,
             idp.numRows,
@@ -651,6 +800,7 @@
             dbHelper,
             srcReader,
             destReader,
+            6,
             idp.numDatabaseHotseatIcons,
             idp.numColumns,
             idp.numRows,
@@ -729,6 +879,7 @@
             dbHelper,
             srcReader,
             destReader,
+            2,
             idp.numDatabaseHotseatIcons,
             idp.numColumns,
             idp.numRows,
@@ -801,6 +952,7 @@
             dbHelper,
             srcReader,
             destReader,
+            5,
             idp.numDatabaseHotseatIcons,
             idp.numColumns,
             idp.numRows,
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt
new file mode 100644
index 0000000..fb6d038
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/model/ShortcutsChangedTaskTest.kt
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2025 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.model
+
+import android.content.ComponentName
+import android.content.Intent
+import android.content.pm.ApplicationInfo
+import android.content.pm.ApplicationInfo.FLAG_INSTALLED
+import android.content.pm.LauncherApps
+import android.content.pm.ShortcutInfo
+import android.os.Process.myUserHandle
+import android.os.UserHandle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+import com.android.launcher3.icons.BitmapInfo
+import com.android.launcher3.icons.CacheableShortcutInfo
+import com.android.launcher3.icons.IconCache
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.shortcuts.ShortcutKey
+import com.android.launcher3.util.ComponentKey
+import com.android.launcher3.util.IntSparseArrayMap
+import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
+import com.google.common.truth.Truth.assertThat
+import java.util.function.Predicate
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ShortcutsChangedTaskTest {
+    private lateinit var shortcutsChangedTask: ShortcutsChangedTask
+    private lateinit var modelHelper: LauncherModelHelper
+    private lateinit var context: SandboxModelContext
+    private lateinit var launcherApps: LauncherApps
+    private var shortcuts: List<ShortcutInfo> = emptyList()
+
+    private val expectedPackage: String = "expected"
+    private val expectedShortcutId: String = "shortcut_id"
+    private val user: UserHandle = myUserHandle()
+    private val mockTaskController: ModelTaskController = mock()
+    private val mockAllApps: AllAppsList = mock()
+    private val mockAppState: LauncherAppState = mock()
+    private val mockIconCache: IconCache = mock()
+
+    private val expectedWai =
+        WorkspaceItemInfo().apply {
+            id = 1
+            itemType = ITEM_TYPE_DEEP_SHORTCUT
+            intent =
+                Intent().apply {
+                    `package` = expectedPackage
+                    putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, expectedShortcutId)
+                }
+        }
+
+    @Before
+    fun setup() {
+        modelHelper = LauncherModelHelper()
+        modelHelper.loadModelSync()
+        context = modelHelper.sandboxContext
+        launcherApps = context.spyService(LauncherApps::class.java)
+        whenever(mockTaskController.app).thenReturn(mockAppState)
+        whenever(mockAppState.context).thenReturn(context)
+        whenever(mockAppState.iconCache).thenReturn(mockIconCache)
+        whenever(mockIconCache.getShortcutIcon(eq(expectedWai), any<CacheableShortcutInfo>()))
+            .then { _ -> { expectedWai.bitmap = BitmapInfo.LOW_RES_INFO } }
+        shortcuts = emptyList()
+        shortcutsChangedTask = ShortcutsChangedTask(expectedPackage, shortcuts, user, false)
+    }
+
+    @After
+    fun teardown() {
+        modelHelper.destroy()
+    }
+
+    @Test
+    fun `When installed pinned shortcut is found then keep in workspace`() {
+        // Given
+        shortcuts =
+            listOf(
+                mock<ShortcutInfo>().apply {
+                    whenever(isPinned).thenReturn(true)
+                    whenever(id).thenReturn(expectedShortcutId)
+                }
+            )
+        val items: IntSparseArrayMap<ItemInfo> = modelHelper.bgDataModel.itemsIdMap
+        items.put(expectedWai.id, expectedWai)
+        doReturn(
+                ApplicationInfo().apply {
+                    enabled = true
+                    flags = flags or FLAG_INSTALLED
+                    isArchived = false
+                }
+            )
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        doReturn(shortcuts).whenever(launcherApps).getShortcuts(any(), eq(user))
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        verify(mockAppState.iconCache)
+            .getShortcutIcon(eq(expectedWai), any<CacheableShortcutInfo>())
+        verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai))
+    }
+
+    @Test
+    fun `When installed unpinned shortcut is found then remove from workspace`() {
+        // Given
+        shortcuts =
+            listOf(
+                mock<ShortcutInfo>().apply {
+                    whenever(isPinned).thenReturn(false)
+                    whenever(id).thenReturn(expectedShortcutId)
+                }
+            )
+        val items: IntSparseArrayMap<ItemInfo> = modelHelper.bgDataModel.itemsIdMap
+        items.put(expectedWai.id, expectedWai)
+        doReturn(
+                ApplicationInfo().apply {
+                    enabled = true
+                    flags = flags or FLAG_INSTALLED
+                    isArchived = false
+                }
+            )
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        doReturn(shortcuts).whenever(launcherApps).getShortcuts(any(), eq(user))
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        verify(mockTaskController)
+            .deleteAndBindComponentsRemoved(
+                any<Predicate<ItemInfo?>>(),
+                eq("removed because the shortcut is no longer available in shortcut service"),
+            )
+    }
+
+    @Test
+    fun `When shortcut app is uninstalled then skip handling`() {
+        // Given
+        shortcuts =
+            listOf(
+                mock<ShortcutInfo>().apply {
+                    whenever(isPinned).thenReturn(true)
+                    whenever(id).thenReturn(expectedShortcutId)
+                }
+            )
+        val items: IntSparseArrayMap<ItemInfo> = modelHelper.bgDataModel.itemsIdMap
+        items.put(expectedWai.id, expectedWai)
+        doReturn(
+                ApplicationInfo().apply {
+                    enabled = true
+                    flags = flags and FLAG_INSTALLED.inv()
+                    isArchived = false
+                }
+            )
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        doReturn(shortcuts).whenever(launcherApps).getShortcuts(any(), eq(user))
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        verify(mockTaskController, times(0)).deleteAndBindComponentsRemoved(any(), any())
+        verify(mockTaskController, times(0)).bindUpdatedWorkspaceItems(any())
+    }
+
+    @Test
+    fun `When archived pinned shortcut is found then keep in workspace`() {
+        // Given
+        shortcuts =
+            listOf(
+                mock<ShortcutInfo>().apply {
+                    whenever(isPinned).thenReturn(true)
+                    whenever(id).thenReturn(expectedShortcutId)
+                }
+            )
+        val items: IntSparseArrayMap<ItemInfo> = modelHelper.bgDataModel.itemsIdMap
+        items.put(expectedWai.id, expectedWai)
+        doReturn(
+                ApplicationInfo().apply {
+                    enabled = true
+                    flags = flags or FLAG_INSTALLED
+                    isArchived = true
+                }
+            )
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        doReturn(shortcuts).whenever(launcherApps).getShortcuts(any(), eq(user))
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        verify(mockAppState.iconCache)
+            .getShortcutIcon(eq(expectedWai), any<CacheableShortcutInfo>())
+        verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai))
+    }
+
+    @Test
+    fun `When archived unpinned shortcut is found then keep in workspace`() {
+        // Given
+        shortcuts =
+            listOf(
+                mock<ShortcutInfo>().apply {
+                    whenever(isPinned).thenReturn(true)
+                    whenever(id).thenReturn(expectedShortcutId)
+                }
+            )
+        val items: IntSparseArrayMap<ItemInfo> = modelHelper.bgDataModel.itemsIdMap
+        items.put(expectedWai.id, expectedWai)
+        doReturn(
+                ApplicationInfo().apply {
+                    enabled = true
+                    flags = flags or FLAG_INSTALLED
+                    isArchived = true
+                }
+            )
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        doReturn(shortcuts).whenever(launcherApps).getShortcuts(any(), eq(user))
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        verify(mockAppState.iconCache)
+            .getShortcutIcon(eq(expectedWai), any<CacheableShortcutInfo>())
+        verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWai))
+    }
+
+    @Test
+    fun `When updateIdMap true then trigger deep shortcut binding`() {
+        // Given
+        val expectedShortcut =
+            mock<ShortcutInfo>().apply {
+                whenever(isEnabled).thenReturn(true)
+                whenever(isDeclaredInManifest).thenReturn(true)
+                whenever(activity).thenReturn(ComponentName(expectedPackage, "expectedClass"))
+                whenever(id).thenReturn(expectedShortcutId)
+                whenever(userHandle).thenReturn(user)
+            }
+        shortcuts = listOf(expectedShortcut)
+        val expectedKey = ComponentKey(expectedShortcut.activity, expectedShortcut.userHandle)
+        doReturn(ApplicationInfo())
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        shortcutsChangedTask =
+            ShortcutsChangedTask(
+                packageName = expectedPackage,
+                shortcuts = shortcuts,
+                user = user,
+                shouldUpdateIdMap = true,
+            )
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        assertThat(modelHelper.bgDataModel.deepShortcutMap).containsEntry(expectedKey, 1)
+        verify(mockTaskController).bindDeepShortcuts(eq(modelHelper.bgDataModel))
+    }
+
+    @Test
+    fun `When updateIdMap false then do not trigger deep shortcut binding`() {
+        // Given
+        val expectedShortcut =
+            mock<ShortcutInfo>().apply {
+                whenever(isEnabled).thenReturn(true)
+                whenever(isDeclaredInManifest).thenReturn(true)
+                whenever(activity).thenReturn(ComponentName(expectedPackage, "expectedClass"))
+                whenever(id).thenReturn(expectedShortcutId)
+                whenever(userHandle).thenReturn(user)
+            }
+        shortcuts = listOf(expectedShortcut)
+        val expectedKey = ComponentKey(expectedShortcut.activity, expectedShortcut.userHandle)
+        doReturn(ApplicationInfo())
+            .whenever(launcherApps)
+            .getApplicationInfo(eq(expectedPackage), any(), eq(user))
+        shortcutsChangedTask =
+            ShortcutsChangedTask(
+                packageName = expectedPackage,
+                shortcuts = shortcuts,
+                user = user,
+                shouldUpdateIdMap = false,
+            )
+        // When
+        shortcutsChangedTask.execute(mockTaskController, modelHelper.bgDataModel, mockAllApps)
+        // Then
+        assertThat(modelHelper.bgDataModel.deepShortcutMap).doesNotContainKey(expectedKey)
+        verify(mockTaskController, times(0)).bindDeepShortcuts(eq(modelHelper.bgDataModel))
+    }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
index b96dbcd..1d1e7eb 100644
--- a/tests/multivalentTests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
+++ b/tests/multivalentTests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
@@ -138,6 +138,7 @@
                 val gridSizeMigrationLogic = GridSizeMigrationLogic()
                 val idsInUse = mutableListOf<Int>()
                 gridSizeMigrationLogic.migrateHotseat(
+                    srcGrid.size.x,
                     dstGrid.size.x,
                     GridSizeMigrationDBController.DbReader(it.db, srcGrid.tableName, context),
                     GridSizeMigrationDBController.DbReader(it.db, dstGrid.tableName, context),
@@ -156,6 +157,7 @@
                     dbHelper,
                     GridSizeMigrationDBController.DbReader(it.db, srcGrid.tableName, context),
                     GridSizeMigrationDBController.DbReader(it.db, dstGrid.tableName, context),
+                    srcGrid.size.x,
                     dstGrid.size.x,
                     dstGrid.size,
                     srcGrid.toGridState(),
diff --git a/tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java
index f51871b..5c326f9 100644
--- a/tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java
+++ b/tests/multivalentTests/src/com/android/launcher3/ui/BubbleTextViewTest.java
@@ -28,6 +28,7 @@
 import static com.android.launcher3.Flags.FLAG_USE_NEW_ICON_FOR_ARCHIVED_APPS;
 import static com.android.launcher3.LauncherPrefs.ENABLE_TWOLINE_ALLAPPS_TOGGLE;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ARCHIVED;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -39,6 +40,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
 import android.graphics.Typeface;
 import android.os.Build;
 import android.os.UserHandle;
@@ -57,13 +60,17 @@
 import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.graphics.PreloadIconDrawable;
+import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
+import com.android.launcher3.pm.PackageInstallInfo;
 import com.android.launcher3.search.StringMatcherUtility;
 import com.android.launcher3.util.ActivityContextWrapper;
 import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext;
+import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.views.BaseDragLayer;
 
 import org.junit.After;
@@ -485,4 +492,38 @@
 
         assertThat(mBubbleTextView.getIcon().hasBadge()).isEqualTo(true);
     }
+
+    @Test
+    public void applyingPendingIcon_preserves_last_icon() throws Exception {
+        mItemInfoWithIcon.bitmap =
+                BitmapInfo.fromBitmap(Bitmap.createBitmap(100, 100, Config.ARGB_8888));
+        mItemInfoWithIcon.setProgressLevel(30, PackageInstallInfo.STATUS_INSTALLING);
+
+        TestUtil.runOnExecutorSync(MAIN_EXECUTOR,
+                () -> mBubbleTextView.applyIconAndLabel(mItemInfoWithIcon));
+        assertThat(mBubbleTextView.getIcon()).isInstanceOf(PreloadIconDrawable.class);
+        assertThat(mBubbleTextView.getIcon().getLevel()).isEqualTo(30);
+        PreloadIconDrawable oldIcon = (PreloadIconDrawable) mBubbleTextView.getIcon();
+
+        // Same icon is used when progress changes
+        mItemInfoWithIcon.setProgressLevel(50, PackageInstallInfo.STATUS_INSTALLING);
+        TestUtil.runOnExecutorSync(MAIN_EXECUTOR,
+                () -> mBubbleTextView.applyIconAndLabel(mItemInfoWithIcon));
+        assertThat(mBubbleTextView.getIcon()).isSameInstanceAs(oldIcon);
+        assertThat(mBubbleTextView.getIcon().getLevel()).isEqualTo(50);
+
+        // Icon is replaced with a non pending icon when download finishes
+        mItemInfoWithIcon.setProgressLevel(100, PackageInstallInfo.STATUS_INSTALLED);
+
+        TestUtil.runOnExecutorSync(MAIN_EXECUTOR, () -> {
+            mBubbleTextView.applyIconAndLabel(mItemInfoWithIcon);
+            assertThat(mBubbleTextView.getIcon()).isSameInstanceAs(oldIcon);
+            assertThat(oldIcon.getActiveAnimation()).isNotNull();
+            oldIcon.getActiveAnimation().end();
+        });
+
+        // Assert that the icon is replaced with a non-pending icon
+        assertThat(mBubbleTextView.getIcon()).isNotInstanceOf(PreloadIconDrawable.class);
+    }
+
 }
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/LauncherBindableItemsContainerTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/LauncherBindableItemsContainerTest.kt
new file mode 100644
index 0000000..93be5f5
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/util/LauncherBindableItemsContainerTest.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2025 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.util
+
+import android.content.ComponentName
+import android.content.pm.LauncherApps
+import android.graphics.Bitmap
+import android.graphics.Bitmap.Config.ARGB_8888
+import android.os.Process.myUserHandle
+import android.platform.uiautomatorhelpers.DeviceHelpers.context
+import android.view.View
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.BubbleTextView
+import com.android.launcher3.graphics.PreloadIconDrawable
+import com.android.launcher3.icons.BitmapInfo
+import com.android.launcher3.icons.FastBitmapDrawable
+import com.android.launcher3.icons.PlaceHolderIconDrawable
+import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.model.data.AppInfo.makeLaunchIntent
+import com.android.launcher3.model.data.ItemInfo
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.pm.PackageInstallInfo
+import com.android.launcher3.util.Executors.MAIN_EXECUTOR
+import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator
+import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
+import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2
+import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3
+import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LauncherBindableItemsContainerTest {
+
+    private val icon1 by lazy { getLAI(TEST_ACTIVITY) }
+    private val icon2 by lazy { getLAI(TEST_ACTIVITY2) }
+    private val icon3 by lazy { getLAI(TEST_ACTIVITY3) }
+
+    private val container = TestContainer()
+
+    @Test
+    fun `icon bitmap is updated`() {
+        container.addIcon(icon1)
+        container.addIcon(icon2)
+        container.addIcon(icon3)
+
+        assertThat(container.getAppIcon(icon1).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon2).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon3).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+
+        icon2.bitmap = BitmapInfo.fromBitmap(Bitmap.createBitmap(200, 200, ARGB_8888))
+        TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {
+            container.updateContainerItems(setOf(icon2), container)
+        }
+
+        assertThat(container.getAppIcon(icon1).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon3).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon2).icon)
+            .isNotInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon2).icon).isInstanceOf(FastBitmapDrawable::class.java)
+    }
+
+    @Test
+    fun `icon download progress updated`() {
+        container.addIcon(icon1)
+        container.addIcon(icon2)
+        assertThat(container.getAppIcon(icon1).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon2).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+
+        icon1.status = WorkspaceItemInfo.FLAG_RESTORED_ICON
+        icon1.bitmap = BitmapInfo.fromBitmap(Bitmap.createBitmap(200, 200, ARGB_8888))
+        icon1.setProgressLevel(30, PackageInstallInfo.STATUS_INSTALLING)
+        TestUtil.runOnExecutorSync(MAIN_EXECUTOR) {
+            container.updateContainerItems(setOf(icon1), container)
+        }
+
+        assertThat(container.getAppIcon(icon2).icon)
+            .isInstanceOf(PlaceHolderIconDrawable::class.java)
+        assertThat(container.getAppIcon(icon1).icon).isInstanceOf(PreloadIconDrawable::class.java)
+        val oldIcon = container.getAppIcon(icon1).icon as PreloadIconDrawable
+        assertThat(oldIcon.level).isEqualTo(30)
+    }
+
+    private fun getLAI(className: String): WorkspaceItemInfo =
+        AppInfo(
+                context,
+                context
+                    .getSystemService(LauncherApps::class.java)!!
+                    .resolveActivity(
+                        makeLaunchIntent(ComponentName(TEST_PACKAGE, className)),
+                        myUserHandle(),
+                    )!!,
+                myUserHandle(),
+            )
+            .makeWorkspaceItem(context)
+
+    class TestContainer : ActivityContextWrapper(context), LauncherBindableItemsContainer {
+
+        val items = mutableMapOf<ItemInfo, View>()
+
+        override fun mapOverItems(op: ItemOperator) {
+            items.forEach { (item, view) -> if (op.evaluate(item, view)) return@forEach }
+        }
+
+        fun addIcon(info: WorkspaceItemInfo) {
+            val btv = BubbleTextView(this)
+            btv.applyFromWorkspaceItem(info)
+            items[info] = btv
+        }
+
+        fun getAppIcon(info: WorkspaceItemInfo) = items[info] as BubbleTextView
+    }
+}
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java b/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
index 71637f1..393282f 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/TestSandboxModelContextWrapper.java
@@ -64,7 +64,7 @@
 
     public TestSandboxModelContextWrapper(SandboxContext base) {
         super(base);
-        mUserCache = base.getObject(UserCache.INSTANCE);
+        mUserCache = UserCache.getInstance(base);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
                 mAppsView = new ActivityAllAppsContainerView<>(this));
         mAppsList = mAppsView.getPersonalAppList();
diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
index f6aa31a..f490bd6 100644
--- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
@@ -36,7 +36,6 @@
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.util.Wait;
-import com.android.launcher3.util.rule.ScreenRecordRule;
 
 import org.junit.Test;
 
@@ -128,7 +127,6 @@
      */
     @Test
     @PlatinumTest(focusArea = "launcher")
-    @ScreenRecordRule.ScreenRecord // b/319501259
     public void uninstallWorkspaceIcon() throws IOException {
         Point[] gridPositions = TestUtil.getCornersAndCenterPositions(mLauncher);
         StringBuilder sb = new StringBuilder();
diff --git a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
index f04688d..dba7603 100644
--- a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
@@ -23,20 +23,23 @@
 import com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT
 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR
 import com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER
+import com.android.launcher3.dagger.LauncherAppComponent
+import com.android.launcher3.dagger.LauncherAppSingleton
 import com.android.launcher3.icons.IconCache
 import com.android.launcher3.icons.cache.CachingLogic
 import com.android.launcher3.icons.cache.IconCacheUpdateHandler
 import com.android.launcher3.pm.UserCache
 import com.android.launcher3.provider.RestoreDbTask
 import com.android.launcher3.ui.TestViewHelpers
+import com.android.launcher3.util.AllModulesForTest
 import com.android.launcher3.util.Executors.MODEL_EXECUTOR
 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext
 import com.android.launcher3.util.LooperIdleLock
 import com.android.launcher3.util.TestUtil
 import com.android.launcher3.util.UserIconInfo
 import com.google.common.truth.Truth
-import java.util.concurrent.CountDownLatch
-import java.util.function.Predicate
+import dagger.BindsInstance
+import dagger.Component
 import junit.framework.Assert.assertEquals
 import org.junit.After
 import org.junit.Before
@@ -59,6 +62,8 @@
 import org.mockito.kotlin.verify
 import org.mockito.kotlin.whenever
 import org.mockito.quality.Strictness
+import java.util.concurrent.CountDownLatch
+import java.util.function.Predicate
 
 private const val INSERTION_STATEMENT_FILE = "databases/workspace_items.sql"
 
@@ -130,8 +135,9 @@
         `when`(idleLock.awaitLocked(1000)).thenReturn(false)
         `when`(iconCache.getUpdateHandler()).thenReturn(iconCacheUpdateHandler)
         `when`(widgetsFilterDataProvider.getDefaultWidgetsFilter()).thenReturn(Predicate { true })
-        context.putObject(UserCache.INSTANCE, userCache)
-
+        context.initDaggerComponent(
+            DaggerLoaderTaskTest_TestComponent.builder().bindUserCache(userCache)
+        )
         TestUtil.grantWriteSecurePermission()
     }
 
@@ -473,6 +479,17 @@
         // Then
         verify(spyContext, times(0)).sendBroadcast(any())
     }
+
+    @LauncherAppSingleton
+    @Component(modules = [AllModulesForTest::class])
+    interface TestComponent : LauncherAppComponent {
+        @Component.Builder
+        interface Builder : LauncherAppComponent.Builder {
+            @BindsInstance fun bindUserCache(userCache: UserCache): Builder
+
+            override fun build(): TestComponent
+        }
+    }
 }
 
 private fun LoaderTask.runSyncOnBackgroundThread() {
diff --git a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
index 075f667..2531f6b 100644
--- a/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
+++ b/tests/src/com/android/launcher3/popup/SystemShortcutTest.java
@@ -62,12 +62,15 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.PrivateProfileManager;
+import com.android.launcher3.dagger.LauncherAppComponent;
+import com.android.launcher3.dagger.LauncherAppSingleton;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.AllModulesForTest;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.LauncherModelHelper.SandboxModelContext;
 import com.android.launcher3.util.LauncherMultivalentJUnit;
@@ -88,6 +91,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import dagger.BindsInstance;
+import dagger.Component;
+
 @SmallTest
 @RunWith(LauncherMultivalentJUnit.class)
 public class SystemShortcutTest {
@@ -113,7 +119,9 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mSandboxContext.putObject(UserCache.INSTANCE, mUserCache);
+        mSandboxContext.initDaggerComponent(
+                DaggerSystemShortcutTest_TestComponent.builder().bindUserCache(mUserCache)
+        );
         mTestContext = new TestSandboxModelContextWrapper(mSandboxContext) {
             @Override
             public StatsLogManager getStatsLogManager() {
@@ -402,4 +410,15 @@
         systemShortcut.onClick(mView);
         verify(mSandboxContext).startActivity(any());
     }
+
+    @LauncherAppSingleton
+    @Component(modules = { AllModulesForTest.class })
+    interface TestComponent extends LauncherAppComponent {
+        @Component.Builder
+        interface Builder extends LauncherAppComponent.Builder {
+            @BindsInstance
+            SystemShortcutTest.TestComponent.Builder bindUserCache(UserCache userCache);
+            @Override LauncherAppComponent build();
+        }
+    }
 }
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
index 342eedf..1338e60 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
@@ -21,7 +21,6 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.Launcher;
 
 import org.junit.Test;
@@ -31,9 +30,8 @@
 @RunWith(AndroidJUnit4.class)
 public class TaplTestsLauncher3Test extends AbstractLauncherUiTest<Launcher> {
 
-    @ScreenRecord // b/322823478
     @Test
-    public void testDevicePressMenu() throws Exception {
+    public void testDevicePressMenu() {
         mDevice.pressMenu();
         mDevice.waitForIdle();
         executeOnLauncher(
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index edca6dc..abf46e7 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -211,6 +211,8 @@
     private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
     private int mPointerCount = 0;
 
+    private boolean mWaitingForMotionUpEvent;
+
     private static Pattern getKeyEventPattern(String action, String keyCode) {
         return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode);
     }
@@ -752,7 +754,29 @@
         }
     }
 
+    private void cleanUpInputStream() {
+        if (!mWaitingForMotionUpEvent) {
+            return;
+        }
+        long downTime = SystemClock.uptimeMillis();
+        MotionEvent cleanUpEvent = getMotionEvent(
+                downTime,
+                downTime,
+                MotionEvent.ACTION_UP,
+                0,
+                0,
+                InputDevice.SOURCE_TOUCHSCREEN,
+                Configurator.getInstance().getToolType());
+        log("Test failed while a ACTION_UP event was still pending. "
+                + "Cleaning up the input stream by sending an ACTION_UP event forcefully: "
+                + "event= " + cleanUpEvent);
+
+        injectEventUnchecked(cleanUpEvent);
+        mWaitingForMotionUpEvent = false;
+    }
+
     void fail(String message) {
+        cleanUpInputStream();
         checkForAnomaly();
         if (mOnFailure != null) mOnFailure.run();
         Assert.fail(formatSystemHealthMessage(formatErrorWithEvents(
@@ -2022,8 +2046,38 @@
     }
 
     private void injectEvent(InputEvent event) {
-        assertTrue("injectInputEvent failed: event=" + event,
-                mInstrumentation.getUiAutomation().injectInputEvent(event, true, false));
+        if (event instanceof MotionEvent motionEvent) {
+            switch (motionEvent.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    assertTrue("Attempting to inject a second ACTION_DOWN event before a "
+                                    + "ACTION_UP event: " + event,
+                            !mWaitingForMotionUpEvent);
+                    mWaitingForMotionUpEvent = true;
+                    break;
+                case MotionEvent.ACTION_CANCEL:
+                case MotionEvent.ACTION_UP:
+                    assertTrue("Attempting to inject an unexpected ACTION_UP event: " + event,
+                            mWaitingForMotionUpEvent);
+                    mWaitingForMotionUpEvent = false;
+
+                    break;
+                default:
+                    // Nothing to do
+                    break;
+            }
+        }
+        assertTrue("injectInputEvent failed: event=" + event, injectEventUnchecked(event));
+    }
+
+    private boolean injectEventUnchecked(InputEvent event) {
+        boolean result = mInstrumentation.getUiAutomation().injectInputEvent(event, true, false);
+
+        // Only MotionEvents need to be recycled.
+        if (event instanceof MotionEvent motionEvent) {
+            motionEvent.recycle();
+        }
+
+        return result;
     }
 
     public void sendPointer(long downTime, long currentTime, int action, Point point,