[automerger skipped] Merge "Allow app pairs in folders" into 24D1-dev am: 559aeb2c45 -s ours

am skip reason: Merged-In I73732fcaefbdc61bf6e02a5be365962b8bbc3e41 with SHA-1 a596f589c4 is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/26907722

Change-Id: Iddd6c4d87cae874ddcc0450c3448334fbe12e323
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 78db013..c4ea48a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -17,10 +17,12 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-min_launcher3_sdk_version = "26"
+min_launcher3_sdk_version = "30"
 
 // Common source files used to build launcher (java and kotlin)
 // All sources are split so they can be reused in many other libraries/apps in other folders
+
+// Main Launcher source, excluding the build config
 filegroup {
     name: "launcher-src",
     srcs: [
@@ -29,6 +31,7 @@
     ],
 }
 
+// Source code for quickstep build, on top of launcher-src
 filegroup {
     name: "launcher-quickstep-src",
     srcs: [
@@ -37,51 +40,20 @@
     ],
 }
 
+// Alternate source when quickstep is not included
 filegroup {
-    name: "launcher-go-src",
+    name: "launcher-src_no_quickstep",
     srcs: [
-        "go/src/**/*.java",
-        "go/src/**/*.kt",
+        "src_no_quickstep/**/*.java",
+        "src_no_quickstep/**/*.kt",
     ],
 }
 
+// Default build config for Launcher3
 filegroup {
-    name: "launcher-go-quickstep-src",
+    name: "launcher-build-config",
     srcs: [
-        "go/quickstep/src/**/*.java",
-        "go/quickstep/src/**/*.kt",
-    ],
-}
-
-filegroup {
-    name: "launcher-src_shortcuts_overrides",
-    srcs: [
-        "src_shortcuts_overrides/**/*.java",
-        "src_shortcuts_overrides/**/*.kt",
-    ],
-}
-
-filegroup {
-    name: "launcher-src_ui_overrides",
-    srcs: [
-        "src_ui_overrides/**/*.java",
-        "src_ui_overrides/**/*.kt",
-    ],
-}
-
-filegroup {
-    name: "launcher-ext_tests",
-    srcs: [
-        "ext_tests/**/*.java",
-        "ext_tests/**/*.kt",
-    ],
-}
-
-filegroup {
-    name: "launcher-quickstep-ext_tests",
-    srcs: [
-        "quickstep/ext_tests/**/*.java",
-        "quickstep/ext_tests/**/*.kt",
+        "src_build_config/**/*.java",
     ],
 }
 
@@ -103,7 +75,7 @@
         "androidx.test.uiautomator_uiautomator",
         "androidx.preference_preference",
         "SystemUISharedLib",
-        "animationlib",
+        "//frameworks/libs/systemui:animationlib",
         "launcher-testing-shared",
     ],
     srcs: [
@@ -178,39 +150,26 @@
         "androidx.cardview_cardview",
         "androidx.window_window",
         "com.google.android.material_material",
-        "iconloader_base",
-        "view_capture",
-        "animationlib",
-    ],
-    manifest: "AndroidManifest-common.xml",
-    sdk_version: "current",
-    min_sdk_version: min_launcher3_sdk_version,
-    lint: {
-        baseline_filename: "lint-baseline2.xml",
-    },
-}
-
-//
-// Build rule for Launcher3 dependencies lib.
-//
-android_library {
-    name: "Launcher3CommonDepsLib",
-    srcs: ["src_build_config/**/*.java"],
-    static_libs: [
+        "//frameworks/libs/systemui:iconloader_base",
+        "//frameworks/libs/systemui:view_capture",
+        "//frameworks/libs/systemui:animationlib",
         "SystemUI-statsd",
-        "Launcher3ResLib",
         "launcher-testing-shared",
-        "animationlib",
+        "androidx.lifecycle_lifecycle-common-java8",
+        "androidx.lifecycle_lifecycle-extensions",
+        "androidx.lifecycle_lifecycle-runtime-ktx",
+        "kotlinx_coroutines_android",
+        "kotlinx_coroutines",
         "com_android_launcher3_flags_lib",
         "com_android_wm_shell_flags_lib",
         "android.appwidget.flags-aconfig-java",
         "com.android.window.flags.window-aconfig-java",
     ],
+    manifest: "AndroidManifest-common.xml",
     sdk_version: "current",
     min_sdk_version: min_launcher3_sdk_version,
-    manifest: "AndroidManifest-common.xml",
     lint: {
-        baseline_filename: "lint-baseline2.xml",
+        baseline_filename: "lint-baseline.xml",
     },
 }
 
@@ -221,17 +180,14 @@
     name: "Launcher3",
 
     static_libs: [
-        "Launcher3CommonDepsLib",
+        "Launcher3ResLib",
     ],
     srcs: [
         ":launcher-src",
-        ":launcher-src_shortcuts_overrides",
-        ":launcher-src_ui_overrides",
-        ":launcher-ext_tests",
+        ":launcher-src_no_quickstep",
+        ":launcher-build-config",
     ],
-    resource_dirs: [
-        "ext_tests/res",
-    ],
+
     optimize: {
         proguard_flags_files: ["proguard.flags"],
         // Proguard is disable for testing. Derivarive prjects to keep proguard enabled
@@ -276,24 +232,21 @@
         "lottie",
         "SystemUISharedLib",
         "SettingsLibSettingsTheme",
-        "SystemUI-statsd",
-        "animationlib",
     ],
     manifest: "quickstep/AndroidManifest.xml",
     min_sdk_version: "current",
 }
 
-// Library with all the dependencies for building Launcher Go
+// Library with all the source code and dependencies for building Launcher Go
 android_library {
-    name: "LauncherGoResLib",
+    name: "Launcher3GoLib",
     srcs: [
         ":launcher-src",
         ":launcher-quickstep-src",
-        ":launcher-go-src",
-        ":launcher-go-quickstep-src",
+        "go/quickstep/src/**/*.java",
+        "go/quickstep/src/**/*.kt",
     ],
     resource_dirs: [
-        "go/res",
         "go/quickstep/res",
     ],
     // Note the ordering here is important when it comes to resource
@@ -301,7 +254,6 @@
     // in QuickstepResLib to take precendece, so it should be the final
     // dependency. See b/205278434 for how this can go wrong.
     static_libs: [
-        "Launcher3CommonDepsLib",
         "QuickstepResLib",
         "androidx.room_room-runtime",
     ],
@@ -316,13 +268,13 @@
     use_resource_processor: false,
 }
 
-// Build rule for Quickstep library
+// Library with all the source code and dependencies for building Quickstep
 android_library {
     name: "Launcher3QuickStepLib",
     srcs: [
         ":launcher-src",
         ":launcher-quickstep-src",
-        ":launcher-src_shortcuts_overrides",
+        ":launcher-build-config",
     ],
     resource_dirs: [],
     libs: [
@@ -334,10 +286,7 @@
     // dependency. See b/208647810 for how this can go wrong.
     static_libs: [
         "SystemUI-statsd",
-        "SystemUISharedLib",
-        "Launcher3CommonDepsLib",
         "QuickstepResLib",
-        "animationlib",
     ],
     manifest: "quickstep/AndroidManifest.xml",
     platform_apis: true,
@@ -346,49 +295,6 @@
     use_resource_processor: false,
 }
 
-// Build rule for Launcher3 Go app for Android Go devices.
-android_app {
-    name: "Launcher3Go",
-
-    static_libs: ["Launcher3CommonDepsLib"],
-
-    srcs: [
-        ":launcher-src",
-        ":launcher-go-src",
-        ":launcher-src_ui_overrides",
-    ],
-
-    resource_dirs: ["go/res"],
-
-    optimize: {
-        proguard_flags_files: ["proguard.flags"],
-    },
-
-    sdk_version: "current",
-    min_sdk_version: "current",
-    target_sdk_version: "current",
-    privileged: true,
-    system_ext_specific: true,
-    overrides: [
-        "Home",
-        "Launcher2",
-        "Launcher3",
-        "Launcher3QuickStep",
-    ],
-    required: ["privapp_whitelist_com.android.launcher3"],
-
-    additional_manifests: [
-        "AndroidManifest.xml",
-        "AndroidManifest-common.xml",
-    ],
-
-    manifest: "go/AndroidManifest.xml",
-    jacoco: {
-        include_filter: ["com.android.launcher3.*"],
-    },
-
-}
-
 // Build rule for Quickstep app.
 android_app {
     name: "Launcher3QuickStep",
@@ -425,28 +331,19 @@
 
 }
 
-// Build rule for Launcher3 Go app with quickstep for Android Go devices.
-android_app {
-    name: "Launcher3QuickStepGo",
 
-    static_libs: [
-        "SystemUI-statsd",
-        "SystemUISharedLib",
-        "LauncherGoResLib",
-    ],
+// Build rule for Launcher3 Go app with quickstep for Android Go devices.
+// Note that the following two rules are exactly same, and should
+// eventually be merged into a single target
+android_app {
+    name: "Launcher3Go",
+
+    static_libs: ["Launcher3GoLib"],
 
     platform_apis: true,
     min_sdk_version: "current",
     target_sdk_version: "current",
 
-    srcs: [],
-
-    resource_dirs: [
-        "go/quickstep/res",
-        "go/res",
-        "quickstep/res",
-    ],
-
     optimize: {
         proguard_flags_files: ["proguard.flags"],
         enabled: true,
@@ -472,5 +369,39 @@
     jacoco: {
         include_filter: ["com.android.launcher3.*"],
     },
+}
+android_app {
+    name: "Launcher3QuickStepGo",
 
+    static_libs: ["Launcher3GoLib"],
+
+    platform_apis: true,
+    min_sdk_version: "current",
+    target_sdk_version: "current",
+
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+        enabled: true,
+    },
+
+    privileged: true,
+    system_ext_specific: true,
+    overrides: [
+        "Home",
+        "Launcher2",
+        "Launcher3",
+        "Launcher3QuickStep",
+    ],
+    required: ["privapp_whitelist_com.android.launcher3"],
+
+    additional_manifests: [
+        "go/AndroidManifest.xml",
+        "go/AndroidManifest-launcher.xml",
+        "AndroidManifest-common.xml",
+    ],
+
+    manifest: "quickstep/AndroidManifest.xml",
+    jacoco: {
+        include_filter: ["com.android.launcher3.*"],
+    },
 }
diff --git a/OWNERS b/OWNERS
index 31e4610..654493f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -11,6 +11,7 @@
 winsonc@google.com
 jonmiranda@google.com
 awickham@google.com
+agvard@google.com
 
 # Launcher workspace eng team
 captaincole@google.com
@@ -38,5 +39,12 @@
 patmanning@google.com
 helencheuk@google.com
 
+# Widget Picker team
+shamalip@google.com
+zakcohen@google.com
+
 per-file FeatureFlags.java, globs = set noparent
 per-file FeatureFlags.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com, captaincole@google.com
+
+per-file DeviceConfigWrapper.java, globs = set noparent
+per-file DeviceConfigWrapper.java = sunnygoyal@google.com, winsonc@google.com, adamcohen@google.com, hyunyoungs@google.com
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index 462d947..8274bd6 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -171,6 +171,13 @@
 }
 
 flag {
+  name: "force_monochrome_app_icons"
+  namespace: "launcher"
+  description: "Enable the ability to generate monochromatic icons, if it is not provided by the app"
+  bug: "270396209"
+}
+
+flag {
   name: "enable_add_app_widget_via_config_activity_v2"
   namespace: "launcher"
   description: "When adding app widget through config activity, directly add it to workspace to reduce flicker"
@@ -188,21 +195,37 @@
 }
 
 flag {
-    name: "grid_migration_fix"
+    name: "enable_grid_migration_fix"
     namespace: "launcher"
     description: "Keep items in place when migrating to a bigger grid"
     bug: "325286145"
+    is_fixed_read_only: true
     metadata {
       purpose: PURPOSE_BUGFIX
     }
 }
 
 flag {
-    name: "narrow_grid_restore"
+    name: "enable_narrow_grid_restore"
     namespace: "launcher"
     description: "Using only the most recent workspace when restoring to avoid confusion."
+    is_fixed_read_only: true
     bug: "325285743"
     metadata {
       purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "enable_scaling_reveal_home_animation"
+    namespace: "launcher"
+    description: "Enables the Home gesture animation"
+    bug: "308801666"
+}
+
+flag {
+    name: "enable_widget_tap_to_add"
+    namespace: "launcher"
+    description: "Enables an add button in the widget picker"
+    bug: "323886237"
+}
diff --git a/buglist.txt b/buglist.txt
deleted file mode 100644
index 53dcc35..0000000
--- a/buglist.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-171450807
-170675311
-170338029
-170338170
-160544577
-171171594
-170488559
-171131394
-171131394
-171026321
-170648272
-170752716
-170611866
-170702596
-170487752
-170665892
-168608912
-170636685
-169771796
-141126144
-166614700
-168805872
-170263425
-169221288
-143965596
-169221287
-167259591
-156044202
-169438169
-164926736
-168653219
-169963211
-170121063
-169988381
-169980192
-169221288
-169385783
-168167693
-169796517
-169330678
-168818961
-168608912
diff --git a/buglist_unique.txt b/buglist_unique.txt
deleted file mode 100644
index 93dbefb..0000000
--- a/buglist_unique.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-141126144
-143965596
-156044202
-160544577
-164926736
-166614700
-167259591
-168167693
-168608912
-168653219
-168805872
-168818961
-169221287
-169221288
-169330678
-169385783
-169438169
-169771796
-169796517
-169963211
-169980192
-169988381
-170121063
-170263425
-170338029
-170338170
-170487752
-170488559
-170611866
-170636685
-170648272
-170665892
-170675311
-170702596
-170752716
-171026321
-171131394
-171171594
-171450807
diff --git a/build.gradle b/build.gradle
deleted file mode 100644
index a453bfd..0000000
--- a/build.gradle
+++ /dev/null
@@ -1,188 +0,0 @@
-buildscript {
-    repositories {
-        mavenCentral()
-        google()
-    }
-    dependencies {
-        classpath GRADLE_CLASS_PATH
-        classpath PROTOBUF_CLASS_PATH
-    }
-}
-
-final String ANDROID_TOP = "${rootDir}/../../.."
-final String FRAMEWORK_PREBUILTS_DIR = "${ANDROID_TOP}/prebuilts/framework_intermediates/"
-
-apply plugin: 'com.android.application'
-apply plugin: 'com.google.protobuf'
-
-android {
-    compileSdkVersion COMPILE_SDK
-    buildToolsVersion BUILD_TOOLS_VERSION
-
-    defaultConfig {
-        minSdkVersion 30
-        targetSdkVersion 33
-        versionCode 1
-        versionName "1.0"
-
-        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
-        vectorDrawables.useSupportLibrary = true
-    }
-    buildTypes {
-        debug {
-            minifyEnabled false
-        }
-    }
-
-    compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_8
-        targetCompatibility JavaVersion.VERSION_1_8
-    }
-
-    // The flavor dimensions for build variants (e.g. aospWithQuickstep, aospWithoutQuickstep)
-    // See: https://developer.android.com/studio/build/build-variants#flavor-dimensions
-    flavorDimensions "app", "recents"
-
-    productFlavors {
-        aosp {
-            dimension "app"
-            applicationId 'com.android.launcher3'
-            testApplicationId 'com.android.launcher3.tests'
-        }
-
-        l3go {
-            dimension "app"
-            applicationId 'com.android.launcher3'
-            testApplicationId 'com.android.launcher3.tests'
-        }
-
-        withQuickstep {
-            dimension "recents"
-
-            minSdkVersion 28
-        }
-
-        withoutQuickstep {
-            dimension "recents"
-        }
-    }
-
-    // Disable release builds for now
-    android.variantFilter { variant ->
-        if (variant.buildType.name.endsWith('release')) {
-            variant.setIgnore(true)
-        }
-    }
-
-    sourceSets {
-        main {
-            res.srcDirs = ['res']
-            java.srcDirs = ['src', 'src_plugins']
-            manifest.srcFile 'AndroidManifest-common.xml'
-            proto {
-                srcDirs = ['protos/', 'protos_overrides/']
-            }
-        }
-
-        androidTest {
-            res.srcDirs = ['tests/res']
-            java.srcDirs = ['tests/src', 'tests/tapl']
-            manifest.srcFile "tests/AndroidManifest-common.xml"
-        }
-
-        androidTestDebug {
-            manifest.srcFile "tests/AndroidManifest.xml"
-        }
-
-        aosp {
-            java.srcDirs = ['src_flags', 'src_shortcuts_overrides']
-        }
-
-        aospWithoutQuickstep {
-            manifest.srcFile "AndroidManifest.xml"
-        }
-
-        aospWithQuickstep {
-            manifest.srcFile "quickstep/AndroidManifest-launcher.xml"
-        }
-
-        l3go {
-            res.srcDirs = ['go/res']
-            java.srcDirs = ['go/src']
-            manifest.srcFile "go/AndroidManifest.xml"
-        }
-
-        l3goWithoutQuickstepDebug {
-            manifest.srcFile "AndroidManifest.xml"
-        }
-
-        l3goWithQuickstepDebug {
-            manifest.srcFile "quickstep/AndroidManifest-launcher.xml"
-        }
-
-        withoutQuickstep {
-            java.srcDirs = ['src_ui_overrides']
-        }
-
-        withQuickstep {
-            res.srcDirs = ['quickstep/res', 'quickstep/recents_ui_overrides/res']
-            java.srcDirs = ['quickstep/src', 'quickstep/recents_ui_overrides/src']
-            manifest.srcFile "quickstep/AndroidManifest.xml"
-        }
-    }
-}
-
-allprojects {
-    repositories {
-        maven { url "../../../prebuilts/sdk/current/androidx/m2repository" }
-        maven { url "../../../prebuilts/fullsdk-darwin/extras/android/m2repository" }
-        maven { url "../../../prebuilts/fullsdk-linux/extras/android/m2repository" }
-        mavenCentral()
-        google()
-    }
-}
-
-dependencies {
-    implementation "androidx.dynamicanimation:dynamicanimation:${ANDROID_X_VERSION}"
-    implementation "androidx.recyclerview:recyclerview:${ANDROID_X_VERSION}"
-    implementation "androidx.preference:preference:${ANDROID_X_VERSION}"
-    implementation project(':IconLoader')
-    implementation project(':UiTestsLibLauncher')
-    withQuickstepImplementation project(':SharedLibWrapper')
-
-    // Recents lib dependency
-    withQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/quickstep/libs", include: 'sysui_shared.jar')
-
-    // Required for AOSP to compile. This is already included in the sysui_shared.jar
-    withoutQuickstepImplementation fileTree(dir: "${FRAMEWORK_PREBUILTS_DIR}/libs", include: 'plugin_core.jar')
-
-    testImplementation 'junit:junit:4.12'
-    testImplementation libs.mockitoInlineExtended
-    androidTestImplementation libs.mockitoInlineExtended
-    androidTestImplementation "org.mockito:mockito-core:1.9.5"
-    androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
-    androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
-    androidTestImplementation 'com.android.support.test:runner:1.0.0'
-    androidTestImplementation 'com.android.support.test:rules:1.0.0'
-    androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
-    androidTestImplementation "androidx.annotation:annotation:${ANDROID_X_VERSION}"
-
-    api 'com.airbnb.android:lottie:3.3.0'
-}
-
-protobuf {
-    // Configure the protoc executable
-    protoc {
-        artifact = "com.google.protobuf:protoc:${protocVersion}${PROTO_ARCH_SUFFIX}"
-    }
-    generateProtoTasks {
-        all().each { task ->
-            task.builtins {
-                remove java
-                java {
-                    option "lite"
-                }
-            }
-        }
-    }
-}
diff --git a/commitlist.txt b/commitlist.txt
deleted file mode 100644
index 27b8bac..0000000
--- a/commitlist.txt
+++ /dev/null
@@ -1,934 +0,0 @@
-COMMAND>> git log f99351888c3e5a128559678304fefd647472bc7f..4c3952dc60fc78d3816012a86d7e71747ef34c74
-commit 4c3952dc60fc78d3816012a86d7e71747ef34c74
-Merge: cb403d9e5 70e8b1572
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Fri Oct 23 00:27:39 2020 +0000
-
-    Merge "Minor stylistic changes in Workspace.java." into ub-launcher3-master
-
-commit cb403d9e5235c7323bc2fdffe6a264d17bb6d0a6
-Author: Pinyao Ting <pinyaoting@google.com>
-Date:   Thu Oct 22 16:07:08 2020 -0700
-
-    flip default value of minimal device feature flag
-    
-    Test: manual
-    Change-Id: Iaf46dffb935bdf4b46e7c57d547bdc697250ec56
-
-commit a97557a15eb111616d868120a9f4659f1b451fa2
-Merge: f5ce80b8a 932a327eb
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Thu Oct 22 18:22:56 2020 +0000
-
-    Merge "Consider overscroll adjustment of RecentsView for live tile" into ub-launcher3-master
-
-commit 932a327ebf0587b8324b9fea7d31328b2f6719a8
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Wed Oct 21 23:29:00 2020 -0700
-
-    Consider overscroll adjustment of RecentsView for live tile
-    
-    Fixes: 171450807
-    Test: manual
-    Change-Id: I83eebf1f6b61c67f289db51aabe5a971815d0df1
-
-commit f5ce80b8a0a1636fc8159475177a07b281492c88
-Author: Hilary Huo <hhuo@google.com>
-Date:   Wed Oct 14 16:35:55 2020 -0700
-
-    [pixel-search] Latency analysis, add logging statement in launcher
-    
-    Bug: b/170675311
-    Change-Id: I229ace399085bea1c3f9535eb713edd329dff8bd
-
-commit 31b03941ef3aa17edc08c1b509d4fa23766f2d2c
-Merge: e0a50c9e3 0731273d5
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Wed Oct 21 20:03:57 2020 +0000
-
-    Merge "Track live tile better by considering resistance animation" into ub-launcher3-master
-
-commit 0731273d5409149fca32dfb2ad76eab45f6ea79a
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Wed Oct 21 12:03:40 2020 -0700
-
-    Track live tile better by considering resistance animation
-    
-    Fixes: 170338029
-    Test: Manual
-    Change-Id: I66536bae567aa94385d5e0352cec9d46d512927a
-
-commit e0a50c9e3f1d4b9f113d6afae01ff2c4ed452fba
-Merge: d2c27a595 acfac6187
-Author: Alex Chau <alexchau@google.com>
-Date:   Wed Oct 21 17:02:57 2020 +0000
-
-    Merge "Use Diplay.getMetrics in DisplayController" into ub-launcher3-master
-
-commit d2c27a595065d43bbea37dd2a512d37080f5233e
-Merge: ff8febabb 8b488ccc2
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Wed Oct 21 07:19:48 2020 +0000
-
-    Merge "[Live Tile] Support launching running task animation" into ub-launcher3-master
-
-commit 8b488ccc2e433a708c8b06f0b6866f2a305e4b0a
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Wed Oct 14 12:13:04 2020 -0700
-
-    [Live Tile] Support launching running task animation
-    
-    Fixes: 170338170
-    Test: manual
-    Change-Id: I2526b7cfbacaea7899b8e2ed233f913630071d36
-
-commit 70e8b157219e9090ba5e47fdfa51b2b92e98449d
-Author: Andy Wickham <awickham@google.com>
-Date:   Wed Oct 7 23:00:06 2020 -0700
-
-    Minor stylistic changes in Workspace.java.
-    
-    Change-Id: Ib07611f27cbc427d11abccd8b74ea144485752f7
-
-commit acfac6187dd9d13d55b566a77a5da867a1813573
-Author: Alex Chau <alexchau@google.com>
-Date:   Mon Oct 19 18:00:39 2020 +0100
-
-    Use Diplay.getMetrics in DisplayController
-    
-    - This is a workaround of b/163815566, where DisplayMetrics is stale
-      when onDisplayChanged is called.
-    - Instead of relying on stale DisplayConext, get the DisplayMetrics
-      from the Display directly.
-    - Also optimized how DisplayController.Info is created by passing in
-      Display only
-    - Use mDisplayContext.getDisplay directly if availalbe
-    
-    Bug: 163815566, 160544577
-    Test: DPI looks correct on device boot
-    Change-Id: I2a7454bb8cf2073ce592e8662781b87fc998444f
-    (cherry picked from commit 177c38243dc3bf245d1f7db3c265dfb56522f441)
-
-commit ff8febabb039a3c27ee068f85119860a048b917c
-Merge: b03d2b416 102746823
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Tue Oct 20 17:46:09 2020 +0000
-
-    Merge "Makes Plugin Settings gear adjust to dark mode." into ub-launcher3-master
-
-commit b03d2b41616d479ba360fa4f97e57722c7f57b8e
-Merge: fb79f5541 caa1e9c39
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Tue Oct 20 15:25:56 2020 +0000
-
-    Merge "Search query method should support multiple consumers" into ub-launcher3-master
-
-commit fb79f5541dcbe587002756bb40a3c632d38cc25a
-Merge: f6b05068d cf0b275a4
-Author: Schneider Victor-tulias <victortulias@google.com>
-Date:   Tue Oct 20 13:51:06 2020 +0000
-
-    Merge "Add the ability to specify a list of tutorial steps in the gesture sandbox tutorial intent." into ub-launcher3-master
-
-commit f6b05068d901d4e989b2e107c06f9c7a6e7b113f
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Tue Oct 20 00:19:29 2020 -0700
-
-    Invert the badging
-    
-    Bug: 171171594
-    Change-Id: If84fdc03254105c843e16f39f479505b16e1cd5f
-
-commit caa1e9c39978cb3b467b5ac441eb39b5e883fa2e
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Mon Oct 12 13:56:02 2020 -0700
-
-    Search query method should support multiple consumers
-    
-    Bug: 170488559
-    Change-Id: I64bef9523d3c3950c4ca3a4b9ce1d506d1672200
-
-commit 10274682339bb60cb24c50536b4f48f921970f3c
-Author: Andy Wickham <awickham@google.com>
-Date:   Mon Oct 19 19:06:52 2020 -0700
-
-    Makes Plugin Settings gear adjust to dark mode.
-    
-    It wasn't visible in dark mode before because it was
-    black on black. This makes it adjust automatically.
-    
-    Change-Id: I5176cffc01842509ddafc4f30ff5029a0c4b8050
-
-commit 744a0fbeae8efaa942d21c61e25012d86f5ff81e
-Merge: 29c79947e 71f24588c
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 19 22:17:26 2020 +0000
-
-    Merge "Call click event on IME quick select for SearchResultIcon" into ub-launcher3-master
-
-commit 29c79947ecf82f662d02004ba9a7289017fc0783
-Merge: 13a2a010d a68ac3e5d
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 19 18:42:05 2020 +0000
-
-    Merge "Removing condition for CUJ tracing/metrics" into ub-launcher3-master
-
-commit 71f24588c0a66449a0c68bcb360a8c671914ce75
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Mon Oct 19 10:19:31 2020 -0700
-
-    Call click event on IME quick select for SearchResultIcon
-    
-    Bug: 171131394
-    Change-Id: I8a703e8d0ca10570e3f774510610d3fb4c0eaab8
-
-commit 13a2a010decd87eeaf8932430c692f587d2de165
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Sun Oct 18 21:19:57 2020 -0700
-
-    Handle IME event for SearchResultIcon
-    
-    Bug: 171131394
-    Test: Manual
-    Change-Id: I2ed1c61053c78aaecc3324418229d69634a72ae4
-
-commit 1f79eeda76246534697e92740defc7f73c3c8d14
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Fri Oct 16 02:01:31 2020 -0700
-
-    Remove hardcoded itemTypes from SearchTarget
-    
-    - Introduces componentName and userHandle members to SearchTarget
-    - SearchTargetEvent now has searchTarget member
-    - Builder pattern for SearchTarget and SearchTargetEvent
-    - Search backend should add headers manually instead of launcher inferring sections
-    
-    Bug: 171026321
-    Test: Manual
-    Change-Id: I28e0455e82b925277a17703b9aa061c8f9f15262
-
-commit a68ac3e5dd23095cea7c872c0ff1c5042d1695ba
-Author: vadimt <vadimt@google.com>
-Date:   Fri Oct 16 10:48:28 2020 -0700
-
-    Removing condition for CUJ tracing/metrics
-    
-    Is doesn't reflect whether jank monitors is collecting metrics,
-    which will eventually be always true anyways.
-    
-    Change-Id: Iaebdc838ed2b2cebd32c8c48d7e45bdd93f76fb4
-
-commit 9228ff53c2fb26850b7bd92d86214a6aaebb11d3
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Mon Oct 12 13:43:51 2020 -0700
-
-    Trimming activity and task label
-    
-    Bug: 170648272
-    Change-Id: Icd099acee65305e0aa0f98a2a301a0df8a27cf07
-
-commit 7a09177e500a53205f9969bb6cbd4251d54e8fde
-Merge: 37ed5ead3 314761a80
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Thu Oct 15 22:36:14 2020 +0000
-
-    Merge "Setup SearchResultIcon for single cell results" into ub-launcher3-master
-
-commit 37ed5ead391df5747003b2d3a345be0347362f19
-Merge: d5bbe6809 702ed2788
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Thu Oct 15 22:06:12 2020 +0000
-
-    Merge "Fix the issue where shortcuts are removed in minimal device mode" into ub-launcher3-master
-
-commit 314761a80819a6e64a136161f51eebb0f0528c4d
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Wed Oct 14 10:15:07 2020 -0700
-
-    Setup SearchResultIcon for single cell results
-    
-    SearchResultIcon will be able to render apps, shortcuts and remote actions. It can also handle its own focused state drawing.
-    
-    Screenshot: https://screenshot.googleplex.com/C3KgjJtLQTBPgaf
-    
-    Bug: 170752716
-    Test: Manual
-    Change-Id: I460a9c128ea3f5814784e342c5d5fa5b7e310882
-
-commit 702ed2788678ac744c768aad6a6302e7cf91a26b
-Author: Pinyao Ting <pinyaoting@google.com>
-Date:   Wed Oct 14 11:17:04 2020 -0700
-
-    Fix the issue where shortcuts are removed in minimal device mode
-    
-    When loading the workspace, Launcher pins/unpins shortcuts in comply
-    with the loaded workspace. Since minimal device mode creates a mostly
-    empty workspace, existing shortcuts are getting unpinned as a result.
-    
-    To mitigate the issue this CL compares the db name and only invoke
-    sanitizeData when it matches the one defined in InvariantDeviceProfile.
-    
-    Bug: 170611866
-    Test: manual
-    1. add some deep shortcut in workspace (e.g. long tap on chrome, drag
-    "incognito tab" to workspace)
-    2. opt-in to sunshine fishfood (g/sunshine-teamfood)
-    3. enable bedtime mode with minimal device in Settings -> Digital
-    Wellbeing -> Show Your Data -> Bedtime mode -> Customize -> minimal
-    device
-    4. toggle bedtime mode, wait for apps in minimal device to show, then
-    toggle off bedtime mode
-    5. verify the deep shortcut still exist
-    
-    Change-Id: Ie18216ecb288e7481aa2404c4cb3ea418aee85cb
-
-commit cf0b275a48d3c9f91a346f7fc24b9604f6dde25a
-Author: Schneider Victor-tulias <victortulias@google.com>
-Date:   Tue Oct 6 09:33:40 2020 -0400
-
-    Add the ability to specify a list of tutorial steps in the gesture sandbox tutorial intent.
-    
-    Added tutorial_steps string array in the intent to allow specifying an ordered list of tutorial steps.
-    
-    Change-Id: Ic42a65598a74a64f8441a22f58c6cd988a5762e3
-
-commit d5bbe6809dcc056fbfc307909b171651f0fb3044
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Wed Oct 14 15:39:38 2020 -0700
-
-    Rename shrotcut container to deep-shrotcuts
-    
-    Change-Id: If94f0dfa447235f3b1a652f7b6c749695b42d97c
-
-commit 26c1105fa04c2bcc156051e51df90a6a253349bb
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Tue Oct 13 01:12:03 2020 -0700
-
-    [search api part 1] Setup centralized SearchEventTracker
-    
-    - Rename AdapterItemWIthPayload to SearchAdapterItem, PayloadResultHandler to SearchTargetHandler
-    - Setup SliceViewWrapper for self contained slices
-    
-    Bug: 170702596
-    Change-Id: I0baf984ec8123c95011abcc17372f8d055e98ad7
-
-commit 057f2d0d7df67e3680e479ac76b48b30d8bcf884
-Merge: 4bb65ff51 9a6145efb
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Tue Oct 13 01:57:47 2020 +0000
-
-    Merge "Introduce shortcut container for hotseat event reporting" into ub-launcher3-master
-
-commit 4bb65ff516c6d9a429971ab7e04780792d5cb751
-Merge: 69740e62b 2afcab804
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Tue Oct 13 00:07:36 2020 +0000
-
-    Merge "Search UI clean up" into ub-launcher3-master
-
-commit 2afcab804b638ff3b9da5bad40c8f70bdcaae78d
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Mon Oct 12 15:38:14 2020 -0700
-
-    Search UI clean up
-    
-    - Resolve spacing issue when work profile is installed
-    - Cache play icons and use icon shape
-    - Only draw focus indicator for the first result
-    
-    Bug: 170487752
-    Bug: 170665892
-    Change-Id: I864d2e796786637132e127ef9b418c0a76c74d6e
-
-commit 69740e62be3800fc918648009645f7a8e52cb73d
-Merge: 2d7bfc878 979da64d8
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 12 20:53:29 2020 +0000
-
-    Merge "Add app start source info of apps launched from launcher" into ub-launcher3-master
-
-commit 2d7bfc8782e9ed01178672aeb09ba2a6a07f4f4c
-Author: Jon Miranda <jonmiranda@google.com>
-Date:   Mon Oct 12 12:09:22 2020 -0700
-
-    Fix shadowRadius not being used in swipe up animation.
-    
-    Bug: 168608912
-    Change-Id: I08f7bb057237e5061d5f1fc29afb488b204ee385
-
-commit a433fe1fb34715efb38ed094f39da49fce8cd51e
-Merge: 2de606fe7 0471b9836
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Mon Oct 12 18:08:35 2020 +0000
-
-    Merge "Using FrameCallbacks instead of windowCallbacks for surface removal" into ub-launcher3-master
-
-commit 9a6145efb85f2bbdaccc07166a55e22c15fe27db
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Mon Oct 12 09:33:00 2020 -0700
-
-    Introduce shortcut container for hotseat event reporting
-    
-    Bug: 170636685
-    Test: Manual
-    Change-Id: I5abeb17976bbafdc8cc74fb8b9a586d544c682fc
-
-commit 2de606fe731573c081fd2d6ba166e21ea6aa2e9c
-Author: Yogisha Dixit <ydixit@google.com>
-Date:   Mon Oct 12 15:36:07 2020 +0100
-
-    Delete the minimal database to force refresh.
-    
-    Bug: 169771796
-    Test: manual
-    Change-Id: Ic2188bb162f295c208346861fddc137ace19ddcb
-
-commit 0471b9836c9e382dc14bdc3abdf8502fb2b9f266
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Wed Sep 23 13:54:37 2020 -0700
-
-    Using FrameCallbacks instead of windowCallbacks for surface removal
-    
-    WindowCallbacks is called during the draw pass, before the frame has
-    been sent to the surfaceFlinger. Frame callback will provide a closer
-    approximation for when the frame is actually rendered on screen.
-    
-    Bug: 141126144
-    Change-Id: I62aab526c2ca24b00b5e7b312b36080f26c7b439
-
-commit 2727434c44d06882925369bf4b43687a06be4a3f
-Merge: 59f532fe9 1b9e199b3
-Author: Schneider Victor-tulias <victortulias@google.com>
-Date:   Fri Oct 9 20:09:08 2020 +0000
-
-    Merge "Fix hotseat and prediction row to allow updates when empty." into ub-launcher3-master
-
-commit 59f532fe9e2b1817c094641f3c7c517f42e4faf0
-Merge: d2bfce71f b5334e3f0
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Fri Oct 9 19:52:54 2020 +0000
-
-    Merge "Improve search section header" into ub-launcher3-master
-
-commit 979da64d8254599c332d83bf94f3f1fc3fe45fef
-Author: Riddle Hsu <riddlehsu@google.com>
-Date:   Tue Sep 22 21:52:40 2020 +0800
-
-    Add app start source info of apps launched from launcher
-    
-    Bug: 166614700
-    Test: Enable statsd log: "adb shell cmd stats print-logs"
-          adb logcat | grep statsd | grep "(48)"
-          The line may contain 0x100000->1[I] 0x110000->10[I]
-          that means 1=from launcher and 10=latency 10ms.
-    Change-Id: Iddaff7066b66e241ba58ec87129ddbe2c531dc7e
-    (cherry picked from commit 7bdf3574a3bff06a377b4364877687bfa7619d06)
-
-commit d2bfce71f776fd05633dfd915dfc664309274677
-Merge: ed4530fed 222afb970
-Author: Winson Chung <winsonc@google.com>
-Date:   Fri Oct 9 16:39:06 2020 +0000
-
-    Merge "Comply with the ISystemUiProxy.aidl change" into ub-launcher3-master
-
-commit ed4530fedda0bf876f91d0745fc70d0f30d42991
-Merge: 692d2109a 9d4a96ed0
-Author: Winson Chung <winsonc@google.com>
-Date:   Fri Oct 9 16:39:06 2020 +0000
-
-    Merge "Add latency metrics for recents gesture" into ub-launcher3-master
-
-commit 1b9e199b3d9c81c793758d96bb03e0c51c1b3fb1
-Author: Schneider Victor-tulias <victortulias@google.com>
-Date:   Thu Oct 8 15:50:22 2020 -0400
-
-    Fix hotseat and prediction row to allow updates when empty.
-    
-    Rotating the screen in the homescreen empties the hotseat, however it does not get populated while it is visible to the user. The user should not be able to see an empty hotseat or prediction row if predictions are available. It should therefore be possible to populate these when they are empty even if they are visible to the user.
-    
-    Change-Id: I8e5252bd29050c2cd9d443aedcb3f3e305c0e2d7
-
-commit b5334e3f07f0561808a2d6e9bba55f1e3a89191e
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Fri Oct 9 00:50:48 2020 -0700
-
-    Improve search section header
-    
-    Change-Id: I47cf207f0d0ab792c0e7a47c9d1185eec087ec88
-
-commit 692d2109a6702706d24b3b819d115882f7362509
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Thu Oct 8 18:42:48 2020 -0700
-
-    invalidate itemDecoration on predictedRow focus draw
-    
-    Change-Id: I66c731f00ae1c1292c51ff281957f05fd2d70dfa
-
-commit 8d5b118060bff7f7518a9a14c0be5d265621f14c
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Thu Oct 8 13:11:25 2020 -0700
-
-    Revert PredictionRow shuoldDraw check
-    
-    + Show Rounded play result icons
-    
-    Bug: 168805872
-    Test: Manual
-    Change-Id: I663c7f7ca1f1ac072e5e9c441deabef7c3fbd97b
-
-commit 86f8df6cf954ac27ab092b9ef8a4db3c9979c4cb
-Merge: 4d19854b2 16045060c
-Author: Hilary Huo <hhuo@google.com>
-Date:   Thu Oct 8 18:43:51 2020 +0000
-
-    Merge "[pixel-search] add escape hatch" into ub-launcher3-master
-
-commit 4d19854b25a54599fe9b0ac8be9d60cf6c21d7ba
-Merge: 0827e1e32 ab9ad20be
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Thu Oct 8 18:40:56 2020 +0000
-
-    Merge "Search UI cleanup" into ub-launcher3-master
-
-commit 16045060c35639aea85afc572bea768d16e6c9f9
-Author: Hilary Huo <hhuo@google.com>
-Date:   Thu Oct 8 10:18:41 2020 -0700
-
-    [pixel-search] add escape hatch
-    
-    Change-Id: I33ffea1fc0859564955380d7d1db317293d1a2cb
-
-commit 0827e1e32a5f99fa02418dae37270c6db8c989d2
-Merge: 3463f0a87 68d7a6e5b
-Author: Andy Wickham <awickham@google.com>
-Date:   Thu Oct 8 16:53:29 2020 +0000
-
-    Merge "Adds feature flag for BC Smartspace." into ub-launcher3-master
-
-commit ab9ad20be600d1cbdc6b54a491d5fbb4c2cf9c16
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Wed Oct 7 15:18:24 2020 -0700
-
-    Search UI cleanup
-    
-    - offset all apps header padding with search input margin
-    - avoid check shouldDraw check on HeaderRow. (race condition)
-    
-    Bug: 170263425
-    Change-Id: I11a1fbb448aa6afd18ec0984af9bb8b1d7600f69
-
-commit 68d7a6e5b28af8cc55bdae7efc24cc7ebee81257
-Author: Andy Wickham <awickham@google.com>
-Date:   Wed Oct 7 14:27:17 2020 -0700
-
-    Adds feature flag for BC Smartspace.
-    
-    Change-Id: Iaf9fb7507d0ccd004a4e00188c75dadd6a059246
-
-commit 3463f0a876ff486ce03e160134e0504158271a92
-Merge: 2470d812a 4b7f38b8f
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Wed Oct 7 20:09:04 2020 +0000
-
-    Merge "Align fallback result query with result text" into ub-launcher3-master
-
-commit 2470d812a1ae989e67781e5056b534ad9a960819
-Merge: cae7d74d8 7a6e4c931
-Author: Vadim Tryshev <vadimt@google.com>
-Date:   Wed Oct 7 20:04:09 2020 +0000
-
-    Merge "Annotating Quick Switch CUJ for 3-button mode" into ub-launcher3-master
-
-commit cae7d74d898769727105850ea5473c2c0ae25fdb
-Merge: e9bf2bd14 1fddddb4f
-Author: Tony Wickham <twickham@google.com>
-Date:   Wed Oct 7 18:32:48 2020 +0000
-
-    Merge "Update launcher_trace.proto for quick switch" into ub-launcher3-master
-
-commit 7a6e4c931f13b369bfa4328196b4632d6d848a19
-Author: vadimt <vadimt@google.com>
-Date:   Tue Oct 6 14:09:16 2020 -0700
-
-    Annotating Quick Switch CUJ for 3-button mode
-    
-    Bug: 169221288
-    Change-Id: Ief62345fe6004dde699f44aa0c90329b7cd84e8b
-
-commit 4b7f38b8fa004b514244304fcc07ff514a2fa46b
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Tue Oct 6 18:37:46 2020 -0700
-
-    Align fallback result query with result text
-    
-    screenshot: https://screenshot.googleplex.com/6Daj5vdmz2jmznX
-    bug: 169438169
-    test: Manual
-    Change-Id: Ie621ed3c834aec5e9467607da4f685d05d152183
-
-commit 222afb970434c7972589adfc509bd2c256ca6556
-Author: Hongwei Wang <hwwang@google.com>
-Date:   Fri Oct 2 13:51:36 2020 -0700
-
-    Comply with the ISystemUiProxy.aidl change
-    
-    Two methods are added to support communications between Launcher and
-    SysUI when user swipes an auto PiP-able Activity to home.
-    
-    Bug: 143965596
-    Test: N/A
-    Change-Id: I2c73a287a094e882bde3cd71c27f9f66ae20e64a
-    (cherry picked from commit 88ddae38db924f700082a113670ce5a719116a95)
-
-commit 9d4a96ed029fdad1e369d5eedd082938f0dc9e01
-Author: Riddle Hsu <riddlehsu@google.com>
-Date:   Wed Sep 30 00:32:04 2020 +0800
-
-    Add latency metrics for recents gesture
-    
-    Pass the touch down time to RecentsAnimation#startRecentsActivity.
-    
-    Bug: 169221287
-    Test: Enable statsd log: "adb shell cmd stats print-logs"
-          Touch gesture navigation bar.
-          adb logcat | grep statsd | grep "(48)"
-          The line may contain 0x100000->4[I] 0x110000->20[I]
-          that means 4=by recents and 20=latency 20ms.
-    Change-Id: I81ee804895b7712f4d925736f5b4694c11a12cbe
-    (cherry picked from commit 63623967b83edad56db58173ebb6687c685b9177)
-
-commit e9bf2bd14c9a7a48f8f93687932d41b1418cf4e4
-Merge: 73ae75474 d028937e7
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Wed Oct 7 02:19:04 2020 +0000
-
-    Merge "[Live tile] Finish recents animation when the phone goes to sleep in live tile mode" into ub-launcher3-master
-
-commit 1fddddb4f30505e0fc9bb2e7c0d88b38ad900e54
-Author: Tony Wickham <twickham@google.com>
-Date:   Tue Sep 29 17:29:06 2020 -0700
-
-    Update launcher_trace.proto for quick switch
-    
-    Sample output from one entry:
-    entry {
-      elapsed_realtime_nanos: 440461382888540
-      launcher {
-        touch_interaction_service {
-          service_connected: true
-          overview_component_obvserver {
-            overview_activity_started: true
-            overview_activity_resumed: false
-          }
-          input_consumer {
-            name: "TYPE_OTHER_ACTIVITY:TYPE_ONE_HANDED"
-            swipe_handler {
-              gesture_state {
-                endTarget: NEW_TASK
-              }
-              is_recents_attached_to_app_window: true
-              scroll_offset: 846
-              app_to_overview_progress: 0
-            }
-          }
-        }
-      }
-    }
-    
-    Bug: 167259591
-    Change-Id: I7f199d88f1d736efcea6b9165b8c4b77a5d27c58
-
-commit 73ae75474ec1dd8807d814ea6c22323905d2070c
-Merge: 8a6f3e40d 0ebbc1880
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Tue Oct 6 23:18:44 2020 +0000
-
-    Merge "Removing tracing for a gone flake" into ub-launcher3-master
-
-commit 8a6f3e40d0321217c624055db7929c397e455e0c
-Merge: e29a9f796 565ed4ff6
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Tue Oct 6 22:49:40 2020 +0000
-
-    Merge "Update Search UI" into ub-launcher3-master
-
-commit 0ebbc18803aaf8ef2f6db7d628d7ae1ce322e842
-Author: vadimt <vadimt@google.com>
-Date:   Tue Oct 6 14:52:27 2020 -0700
-
-    Removing tracing for a gone flake
-    
-    Bug: 156044202
-    Change-Id: Ice142bb941fee7b731f46c2073fab17d83bbc871
-
-commit 565ed4ff69b534812818a2b9aa8789a1aea210eb
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Wed Sep 30 10:42:07 2020 -0700
-
-    Update Search UI
-    
-    [preview attached to bug]
-    
-    Bug: 169438169
-    Test: Manual
-    Change-Id: I085f3dd38ac373c1afab82a637ec08715a6e0cc5
-
-commit e29a9f7961e6db0915bc028ef7e871dcb2c8bde0
-Merge: 2c5ed10ff be17bdcd2
-Author: Jayaprakash Sundararaj <jayaprakashs@google.com>
-Date:   Tue Oct 6 21:00:20 2020 +0000
-
-    Merge "[Search] Add logging to People and badding as to icons." into ub-launcher3-master
-
-commit be17bdcd221f501c45876abe2249c1007858d0c0
-Author: jayaprakashs <jayaprakashs@google.com>
-Date:   Mon Oct 5 09:01:52 2020 -0700
-
-    [Search] Add logging to People and badding as to icons.
-    
-    Change-Id: I65948a2faca436216a94aa46139d425b8eade827
-
-commit 2c5ed10ffa1a870de35f9b3c0c558270aff498dd
-Merge: b2b65a1ef 8ed9707cf
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Tue Oct 6 18:40:57 2020 +0000
-
-    Merge "[Live Tile] Support launching another task (other than the current running task) in Overview" into ub-launcher3-master
-
-commit b2b65a1ef58b020923d112051535b6eb83b582df
-Merge: 3cf264f49 4c14f4b9e
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Tue Oct 6 17:45:35 2020 +0000
-
-    Merge "Avoid double search item highlight" into ub-launcher3-master
-
-commit 8ed9707cf3a4300cb61942f08f0752c80eed086b
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Mon Sep 14 23:25:37 2020 -0700
-
-    [Live Tile] Support launching another task (other than the current running task) in Overview
-    
-    - Get rid of the defer cancelation logic
-    - Render animation on the task view of the task being launched upon task view appeared callback
-    - Finish the recents animation upon the end of the recents window animation
-    
-    Fixes: 164926736
-    Test: manual
-    Change-Id: Ibffb6a9c74c235efc8615a22b0306551532c7b61
-
-commit 3cf264f498e37c482fa4c559bf48ffa791279585
-Author: Schneider Victor-tulias <victortulias@google.com>
-Date:   Tue Sep 22 12:58:38 2020 -0700
-
-    Prevent hotseat updates if it is visible to the user.
-    
-    Test: manual
-    
-    Fixes: 168653219
-    
-    Changing app icons under the user's finger could be disruptive. Added a checks for whether the hotseatand all apps predictions are visible and callbacks to update them when they become hidden.
-    
-    Change-Id: Ib9e6e904e9f662ecfaeea6a2fe21d1d81ba39b96
-
-commit b6aff1f56d55a36256446ec3970d92e9da39b98c
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Mon Oct 5 16:08:35 2020 -0700
-
-    Fix NPE inside RecentsOrientedState
-    
-    Bug: 169963211
-    Change-Id: I86dd337dc1b862f3fa99b91b47fa250076233f96
-
-commit eab40983b9a48b933bde5ca95a82ebd4d83b233d
-Merge: 83ce7c0b5 020e628f2
-Author: Jonathan Miranda <jonmiranda@google.com>
-Date:   Mon Oct 5 22:20:27 2020 +0000
-
-    Merge "Add shadow radius to windows during app launch / close animations." into ub-launcher3-master
-
-commit 83ce7c0b5e461386bb92883a8d6cefe8365cd9ae
-Merge: 679d920bf d6b1f3c08
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 5 19:18:39 2020 +0000
-
-    Merge "Action icon should be used as a badge instead of main icon" into ub-launcher3-master
-
-commit 679d920bf5151cffed4e8186c12c25d8d7907af9
-Merge: e108cc609 0c943966d
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 5 19:13:50 2020 +0000
-
-    Merge "Add null check for input receiver before updating batching" into ub-launcher3-master
-
-commit e108cc609d0a7fd58f0c7e16ce45fa79be6dd272
-Merge: 470403eb5 f622e42bf
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 5 18:39:58 2020 +0000
-
-    Merge "Removing unused proto extensions" into ub-launcher3-master
-
-commit 470403eb58879380e2edac2262dc7f40327b2a15
-Merge: a5130482a 1d7ed30db
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 5 18:29:54 2020 +0000
-
-    Merge "Remove widgets that no longer fit the workspace in their current spans." into ub-launcher3-master
-
-commit 4c14f4b9eda8332347c81e0cf51c5de4dbc06399
-Author: Samuel Fufa <sfufa@google.com>
-Date:   Mon Oct 5 10:50:00 2020 -0700
-
-    Avoid double search item highlight
-    
-    Change-Id: Ic2e28b18f6d5e3ed32cd5646bc3bb4789c378e57
-
-commit 0c943966d373d8ae7eef2b08e88ac44bf57d8a8d
-Author: Winson Chung <winsonc@google.com>
-Date:   Mon Oct 5 10:23:27 2020 -0700
-
-    Add null check for input receiver before updating batching
-    
-    - A change in the system (ie. sysui crash or nav mode change) could
-      cause the input monitor to be disposed before the swipe animation
-      settles
-    
-    Bug: 170121063
-    Test: Kill sysui while swiping up
-    
-    Change-Id: I1417b109fecdb98fae6197c7038dbe9307470853
-
-commit a5130482aee1b0592661bc1c6e178a0de7a163da
-Merge: b21819e18 7fcd74abb
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Mon Oct 5 17:14:21 2020 +0000
-
-    Merge "Suggest result should launch Bug: 169980192" into ub-launcher3-master
-
-commit d028937e74a9ea6d36e463de4c87ed37283bbdf6
-Author: Tracy Zhou <tracyzhou@google.com>
-Date:   Sat Oct 3 00:36:53 2020 -0700
-
-    [Live tile] Finish recents animation when the phone goes to sleep in live tile mode
-    
-    Fixes: 169988381
-    Test: manual
-    Change-Id: Ic71d3e6767eadb6854dbd46581bf9d3242c161a4
-
-commit 7fcd74abb399100ac8243be6ca28c09cc8adc8c8
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Fri Oct 2 19:20:11 2020 -0700
-
-    Suggest result should launch
-    Bug: 169980192
-    
-    Change-Id: I762245a5cc4740d093c9cb3b44a508e9e3f2b763
-
-commit b21819e181e99504c22c6ca028261a1f2665c6f9
-Merge: 931bce369 a762b0241
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Fri Oct 2 22:07:12 2020 +0000
-
-    Merge "Annotating Quick Switch CUJ for non-3-button modes" into ub-launcher3-master
-
-commit a762b02418695f5a1ff2f96586660de8c3610280
-Author: vadimt <vadimt@google.com>
-Date:   Fri Oct 2 13:56:28 2020 -0700
-
-    Annotating Quick Switch CUJ for non-3-button modes
-    
-    Bug: 169221288
-    Change-Id: I7145a9e28a2f0a789d19d2a0e3d15630c6e50f6a
-
-commit 931bce3697595a214023bc72923dad47a61d5711
-Merge: c935ba6b8 733e3c609
-Author: TreeHugger Robot <treehugger-gerrit@google.com>
-Date:   Fri Oct 2 19:19:50 2020 +0000
-
-    Merge "Moving some initializations to the background thread" into ub-launcher3-master
-
-commit c935ba6b8a2ec163533c0b19309dacb6199e6552
-Merge: a4111f250 58804ac52
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Fri Oct 2 18:26:06 2020 +0000
-
-    Merge "Adding stats log for add item flow" into ub-launcher3-master
-
-commit 733e3c609b7653a36e58747c881458ec00d98df8
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Tue Sep 29 10:32:32 2020 -0700
-
-    Moving some initializations to the background thread
-    
-    HandlerThread.getLooper blocks until the thread is ready. Instead
-    moving all looper dependency to the new thread itself.
-    
-    Change-Id: I240e8c56b855a991433a7fe93875059e6dab146b
-
-commit 58804ac5257f45dddbf7a6db35cf8f369ee1e88e
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Wed Sep 16 16:27:40 2020 -0700
-
-    Adding stats log for add item flow
-    
-    Bug: 169385783
-    Bug: 168167693
-    Change-Id: I37395f1b118727f67e0f14c02f945b8213b165c8
-
-commit a4111f250003328d1aef8bbaab59512208ec46cb
-Merge: 8d14dbe04 f6b72c4ad
-Author: Hilary Huo <hhuo@google.com>
-Date:   Fri Oct 2 17:41:22 2020 +0000
-
-    Merge "[pixel-search] Bug fix: automatically launch screenshot + center&crop remoteaction icon" into ub-launcher3-master
-
-commit f622e42bf6983d3adb95386bfd6375d281f1d4f2
-Author: Sunny Goyal <sunnygoyal@google.com>
-Date:   Fri Oct 2 10:35:56 2020 -0700
-
-    Removing unused proto extensions
-    
-    Change-Id: I6d0319c99934dad5176b6f70b895a4ca772ec45f
-
-commit d6b1f3c086f9ac097cd03e1ee898b153478ec11a
-Author: Hyunyoung Song <hyunyoungs@google.com>
-Date:   Fri Oct 2 00:26:35 2020 -0700
-
-    Action icon should be used as a badge instead of main icon
-    
-    Bug: 169796517
-    Change-Id: I3f07fdc2ae6e1af463701f942c26c3ca5d836ee2
-
-commit f6b72c4ad1d2e082441a64c4d6a5a02ee8a251ca
-Author: Hilary Huo <hhuo@google.com>
-Date:   Thu Oct 1 12:26:48 2020 -0700
-
-    [pixel-search] Bug fix: automatically launch screenshot + center&crop remoteaction icon
-    
-    Bug: b/169330678
-    Change-Id: Id5f8a0ce6d68f7ed9e4d1ff258ee3772229eb63b
-
-commit 1d7ed30dba4b2c71fc7b0981532a872a13e5aedb
-Author: Jon Miranda <jonmiranda@google.com>
-Date:   Wed Sep 23 12:15:43 2020 -0700
-
-    Remove widgets that no longer fit the workspace in their current spans.
-    
-    This can happen when display size changes.
-    We compare span sizes of widget in the db to the min sizes of the widget
-    in the current display size. If the widget can no longer fit in its existing
-    spans, we remove it.
-    
-    Also update test widgets to have minWidth/minHeight of 1dp. This ensures that
-    the spanX, spanY, min* values remain consistent between different test devices.
-    
-    Bug: 168818961
-    Change-Id: I723372e4582658f78b2f23ced9073cb77977a6b8
-
-commit 020e628f22cc7975beab439c6da26af2f9ebc15b
-Author: Jon Miranda <jonmiranda@google.com>
-Date:   Mon Sep 28 17:01:42 2020 -0700
-
-    Add shadow radius to windows during app launch / close animations.
-    
-    Bug: 168608912
-    Change-Id: I2ec50b0b3711c0861659f9c641bbc05fcdeaab45
diff --git a/ext_tests/res/values/overrides.xml b/ext_tests/res/values/overrides.xml
deleted file mode 100644
index 3f071d4..0000000
--- a/ext_tests/res/values/overrides.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="test_information_handler_class" translatable="false">com.android.launcher3.testing.DebugTestInformationHandler</string>
-</resources>
-
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
deleted file mode 100644
index 6e7a82a..0000000
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2020 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.testing;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-
-import android.app.Activity;
-import android.app.Application;
-import android.content.Context;
-import android.os.Binder;
-import android.os.Bundle;
-import android.system.Os;
-
-import androidx.annotation.Keep;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
-import com.android.launcher3.ShortcutAndWidgetContainer;
-import com.android.launcher3.icons.ClockDrawableWrapper;
-import com.android.launcher3.testing.shared.TestProtocol;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.WeakHashMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Class to handle requests from tests, including debug ones.
- */
-public class DebugTestInformationHandler extends TestInformationHandler {
-    private static Collection<String> sEvents;
-    private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks;
-    private static final Map<Activity, Boolean> sActivities =
-            Collections.synchronizedMap(new WeakHashMap<>());
-    private static int sActivitiesCreatedCount = 0;
-
-    public DebugTestInformationHandler(Context context) {
-        init(context);
-        if (sActivityLifecycleCallbacks == null) {
-            sActivityLifecycleCallbacks = new Application.ActivityLifecycleCallbacks() {
-                @Override
-                public void onActivityCreated(Activity activity, Bundle bundle) {
-                    sActivities.put(activity, true);
-                    ++sActivitiesCreatedCount;
-                }
-
-                @Override
-                public void onActivityStarted(Activity activity) {
-                }
-
-                @Override
-                public void onActivityResumed(Activity activity) {
-                }
-
-                @Override
-                public void onActivityPaused(Activity activity) {
-                }
-
-                @Override
-                public void onActivityStopped(Activity activity) {
-                }
-
-                @Override
-                public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
-                }
-
-                @Override
-                public void onActivityDestroyed(Activity activity) {
-                }
-            };
-            ((Application) context.getApplicationContext())
-                    .registerActivityLifecycleCallbacks(sActivityLifecycleCallbacks);
-        }
-    }
-
-    private static void runGcAndFinalizersSync() {
-        Runtime.getRuntime().gc();
-        Runtime.getRuntime().runFinalization();
-
-        final CountDownLatch fence = new CountDownLatch(1);
-        createFinalizationObserver(fence);
-        try {
-            do {
-                Runtime.getRuntime().gc();
-                Runtime.getRuntime().runFinalization();
-            } while (!fence.await(100, TimeUnit.MILLISECONDS));
-        } catch (InterruptedException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    // Create the observer in the scope of a method to minimize the chance that
-    // it remains live in a DEX/machine register at the point of the fence guard.
-    // This must be kept to avoid R8 inlining it.
-    @Keep
-    private static void createFinalizationObserver(CountDownLatch fence) {
-        new Object() {
-            @Override
-            protected void finalize() throws Throwable {
-                try {
-                    fence.countDown();
-                } finally {
-                    super.finalize();
-                }
-            }
-        };
-    }
-
-    @Override
-    public Bundle call(String method, String arg, @Nullable Bundle extras) {
-        final Bundle response = new Bundle();
-        switch (method) {
-            case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: {
-                return getLauncherUIProperty(Bundle::putInt,
-                        l -> l.getAppsView().getAppsStore().getDeferUpdatesFlags());
-            }
-
-            case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
-                TestProtocol.sDebugTracing = true;
-                ClockDrawableWrapper.sRunningInTest = true;
-                return response;
-
-            case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
-                TestProtocol.sDebugTracing = false;
-                ClockDrawableWrapper.sRunningInTest = false;
-                return response;
-
-            case TestProtocol.REQUEST_PID: {
-                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid());
-                return response;
-            }
-
-            case TestProtocol.REQUEST_FORCE_GC: {
-                runGcAndFinalizersSync();
-                return response;
-            }
-
-            case TestProtocol.REQUEST_START_EVENT_LOGGING: {
-                sEvents = new ArrayList<>();
-                TestLogging.setEventConsumer(
-                        (sequence, event) -> {
-                            final Collection<String> events = sEvents;
-                            if (events != null) {
-                                synchronized (events) {
-                                    events.add(sequence + '/' + event);
-                                }
-                            }
-                        });
-                return response;
-            }
-
-            case TestProtocol.REQUEST_STOP_EVENT_LOGGING: {
-                TestLogging.setEventConsumer(null);
-                sEvents = null;
-                return response;
-            }
-
-            case TestProtocol.REQUEST_GET_TEST_EVENTS: {
-                if (sEvents == null) {
-                    // sEvents can be null if Launcher died and restarted after
-                    // REQUEST_START_EVENT_LOGGING.
-                    return response;
-                }
-
-                synchronized (sEvents) {
-                    response.putStringArrayList(
-                            TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents));
-                }
-                return response;
-            }
-
-            case TestProtocol.REQUEST_REINITIALIZE_DATA: {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    MODEL_EXECUTOR.execute(() -> {
-                        LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
-                        model.getModelDbController().createEmptyDB();
-                        MAIN_EXECUTOR.execute(model::forceReload);
-                    });
-                    return response;
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-
-            case TestProtocol.REQUEST_CLEAR_DATA: {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    MODEL_EXECUTOR.execute(() -> {
-                        LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
-                        model.getModelDbController().createEmptyDB();
-                        model.getModelDbController().clearEmptyDbFlag();
-                        MAIN_EXECUTOR.execute(model::forceReload);
-                    });
-                    return response;
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
-            }
-
-            case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: {
-                return getLauncherUIProperty(Bundle::putStringArrayList, l -> {
-                    ShortcutAndWidgetContainer hotseatIconsContainer =
-                            l.getHotseat().getShortcutsAndWidgets();
-                    ArrayList<String> hotseatIconNames = new ArrayList<>();
-
-                    for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) {
-                        // Use unchecked cast to catch changes in hotseat layout
-                        BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i);
-                        hotseatIconNames.add((String) icon.getText());
-                    }
-
-                    return hotseatIconNames;
-                });
-            }
-
-            case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: {
-                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount);
-                return response;
-            }
-
-            case TestProtocol.REQUEST_GET_ACTIVITIES: {
-                response.putStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD,
-                        sActivities.keySet().stream().map(
-                                a -> a.getClass().getSimpleName() + " ("
-                                        + (a.isDestroyed() ? "destroyed" : "current") + ")")
-                                .toArray(String[]::new));
-                return response;
-            }
-
-            case TestProtocol.REQUEST_MODEL_QUEUE_CLEARED:
-                return getFromExecutorSync(MODEL_EXECUTOR, Bundle::new);
-
-            default:
-                return super.call(method, arg, extras);
-        }
-    }
-}
diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml
index 796d14d..147dd96 100644
--- a/go/quickstep/res/values/config.xml
+++ b/go/quickstep/res/values/config.xml
@@ -21,4 +21,7 @@
     <bool name="enable_niu_actions">true</bool>
 
     <string name="task_overlay_factory_class" translatable="false">com.android.quickstep.TaskOverlayFactoryGo</string>
+
+    <!-- String representing the intent to delete a package. -->
+    <string name="delete_package_intent" translatable="false">#Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;B.android.intent.extra.RETURN_RESULT=true;end</string>
 </resources>
\ No newline at end of file
diff --git a/go/res/xml/device_profiles.xml b/go/quickstep/res/xml/device_profiles.xml
similarity index 100%
rename from go/res/xml/device_profiles.xml
rename to go/quickstep/res/xml/device_profiles.xml
diff --git a/go/quickstep/src/com/android/launcher3/BuildConfig.java b/go/quickstep/src/com/android/launcher3/BuildConfig.java
new file mode 100644
index 0000000..cfcda39
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/BuildConfig.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2018 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;
+
+public final class BuildConfig {
+    public static final String APPLICATION_ID = "com.android.launcher3";
+
+    public static final boolean IS_STUDIO_BUILD = false;
+    /**
+     * Flag to state if the QSB is on the first screen and placed on the top,
+     * this can be overwritten in other launchers with a different value, if needed.
+     */
+    public static final boolean QSB_ON_FIRST_SCREEN = true;
+
+    /**
+     * Flag to state if the widget on the top of the first screen should be shown.
+     */
+    public static final boolean WIDGET_ON_FIRST_SCREEN = false;
+
+    /**
+     * Flag to control various developer centric features
+     */
+    public static final boolean IS_DEBUG_DEVICE = false;
+
+    // Flag to control widgets support in Launcher
+    public static final boolean WIDGETS_ENABLED = false;
+    // Flag to control notification dots support in Launcher
+    public static final boolean NOTIFICATION_DOTS_ENABLED = false;
+}
diff --git a/go/res/values-v26/bools.xml b/go/res/values-v26/bools.xml
deleted file mode 100644
index 1584734..0000000
--- a/go/res/values-v26/bools.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<resources>
-    <bool name="notification_dots_enabled">false</bool>
-</resources>
-
diff --git a/go/res/values/override.xml b/go/res/values/override.xml
deleted file mode 100644
index 268cb98..0000000
--- a/go/res/values/override.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-* Copyright (C) 2017 The Android Open Source Project
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*      http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
--->
-<resources>
-    <!-- String representing the intent to delete a package. -->
-    <string name="delete_package_intent" translatable="false">#Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;B.android.intent.extra.RETURN_RESULT=true;end</string>
-</resources>
\ No newline at end of file
diff --git a/go/src/com/android/launcher3/model/LauncherBinder.java b/go/src/com/android/launcher3/model/LauncherBinder.java
deleted file mode 100644
index 7a0dce8..0000000
--- a/go/src/com/android/launcher3/model/LauncherBinder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 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 static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.model.BgDataModel.Callbacks;
-
-/**
- * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
- */
-public class LauncherBinder extends BaseLauncherBinder {
-
-    public LauncherBinder(LauncherAppState app, BgDataModel dataModel,
-            AllAppsList allAppsList, Callbacks[] callbacks) {
-        super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
-    }
-
-    @Override
-    public void bindDeepShortcuts() {
-    }
-
-    @Override
-    public void bindWidgets() {
-    }
-
-    @Override
-    public void bindSmartspaceWidget() {
-    }
-}
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
deleted file mode 100644
index 3a28444..0000000
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2018 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.Context;
-import android.os.UserHandle;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.ComponentWithLabelAndIcon;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.util.PackageUserKey;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-
-/**
- * Widgets data model that is used by the adapters of the widget views and controllers.
- *
- * <p> The widgets and shortcuts are organized using package name as its index.
- */
-public class WidgetsModel {
-
-    // True is the widget support is disabled.
-    public static final boolean GO_DISABLE_WIDGETS = true;
-    public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
-
-    private static final ArrayList<WidgetsListBaseEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
-
-    /**
-     * Returns a list of {@link WidgetsListBaseEntry} filtered using given widget item filter. All
-     * {@link WidgetItem}s in a single row are sorted (based on label and user), but the overall
-     * list of {@link WidgetsListBaseEntry}s is not sorted.
-     *
-     * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
-     */
-    public synchronized ArrayList<WidgetsListBaseEntry> getFilteredWidgetsListForPicker(
-            Context context,
-            Predicate<WidgetItem> widgetItemFilter) {
-        return EMPTY_WIDGET_LIST;
-    }
-
-    /**
-     * Returns a list of {@link WidgetsListBaseEntry}. All {@link WidgetItem} in a single row are
-     * sorted (based on label and user), but the overall list of {@link WidgetsListBaseEntry}s is
-     * not sorted. This list is sorted at the UI when using
-     * {@link com.android.launcher3.widget.picker.WidgetsDiffReporter}
-     *
-     * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
-     */
-    public synchronized ArrayList<WidgetsListBaseEntry> getWidgetsListForPicker(Context context) {
-        return EMPTY_WIDGET_LIST;
-    }
-
-    /** Returns a mapping of packages to their widgets without static shortcuts. */
-    public synchronized Map<PackageUserKey, List<WidgetItem>> getAllWidgetsWithoutShortcuts() {
-        return Map.of();
-    }
-
-    /**
-     * @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise
-     *                    only widgets and shortcuts associated with the package/user are.
-     */
-    public List<ComponentWithLabelAndIcon> update(LauncherAppState app,
-            @Nullable PackageUserKey packageUser) {
-        return Collections.emptyList();
-    }
-
-
-    public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
-            LauncherAppState app) {
-    }
-
-    public WidgetItem getWidgetProviderInfoByProviderName(
-            ComponentName providerName, UserHandle user) {
-        return null;
-    }
-
-    /** Returns {@link PackageItemInfo} of a pending widget. */
-    public static PackageItemInfo newPendingItemInfo(
-            Context context, ComponentName provider, UserHandle userHandle) {
-        return new PackageItemInfo(provider.getPackageName(), userHandle);
-    }
-}
diff --git a/go/src/com/android/launcher3/util/AbsGridOccupancy.java b/go/src/com/android/launcher3/util/AbsGridOccupancy.java
deleted file mode 100644
index 4a46bd1..0000000
--- a/go/src/com/android/launcher3/util/AbsGridOccupancy.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-/**
- * Defines method to find the next vacant cell on a grid.
- * This uses the default top-down, left-right approach and can be over-written through
- * code swaps in different launchers.
- */
-public abstract class AbsGridOccupancy {
-
-    /**
-     * Find the first vacant cell, if there is one.
-     *
-     * @param vacantOut Holds the x and y coordinate of the vacant cell
-     * @param spanX Horizontal cell span.
-     * @param spanY Vertical cell span.
-     *
-     * @return true if a vacant cell was found
-     */
-    protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY,
-            int spanX, int spanY) {
-        for (int y = 0; (y + spanY) <= countY; y++) {
-            for (int x = 0; (x + spanX) <= countX; x++) {
-                boolean available = !cells[x][y];
-                out:
-                for (int i = x; i < x + spanX; i++) {
-                    for (int j = y; j < y + spanY; j++) {
-                        available = available && !cells[i][j];
-                        if (!available) break out;
-                    }
-                }
-                if (available) {
-                    vacantOut[0] = x;
-                    vacantOut[1] = y;
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-}
diff --git a/gradle.properties b/gradle.properties
deleted file mode 100644
index d5c1d77..0000000
--- a/gradle.properties
+++ /dev/null
@@ -1,14 +0,0 @@
-# Until all the dependencies move to android X
-android.useAndroidX = true
-android.enableJetifier = true
-org.gradle.parallel=true
-
-ANDROID_X_VERSION=1+
-
-GRADLE_CLASS_PATH=com.android.tools.build:gradle:3.5.1
-
-PROTOBUF_CLASS_PATH=com.google.protobuf:protobuf-gradle-plugin:0.8.8
-PROTOBUF_DEPENDENCY=com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7
-
-BUILD_TOOLS_VERSION=28.0.3
-COMPILE_SDK=android-S
diff --git a/lint-baseline.xml b/lint-baseline.xml
index fe005ca..2ee9531 100644
--- a/lint-baseline.xml
+++ b/lint-baseline.xml
@@ -3,13 +3,13 @@
 
     <issue
         id="NewApi"
-        message="Call requires API level 29 (current min is 26): `android.content.res.Resources#getFloat`"
-        errorLine1="        return mContext.getResources().getFloat(resId);"
-        errorLine2="                                       ~~~~~~~~">
+        message="`@android:dimen/system_app_widget_background_radius` requires API level 31 (current min is 26)"
+        errorLine1='    &lt;corners android:radius="@android:dimen/system_app_widget_background_radius" /&gt;'
+        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/util/DynamicResource.java"
-            line="73"
-            column="40"/>
+            file="packages/apps/Launcher3/res/drawable/widget_resize_frame.xml"
+            line="20"
+            column="14"/>
     </issue>
 
     <issue
@@ -34,136 +34,4 @@
             column="18"/>
     </issue>
 
-    <issue
-        id="NewApi"
-        message="Call requires API level 28 (current min is 26): `android.app.Person#getKey`"
-        errorLine1="        return people.stream().filter(person -&gt; person.getKey() != null)"
-        errorLine2="                                                       ~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/notification/NotificationKeyData.java"
-            line="72"
-            column="56"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Method reference requires API level 28 (current min is 26): `Person::getKey`"
-        errorLine1="                .map(Person::getKey).sorted().toArray(String[]::new);"
-        errorLine2="                     ~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/notification/NotificationKeyData.java"
-            line="73"
-            column="22"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_LEFT`"
-        errorLine1="                AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_LEFT"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
-            line="1814"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_RIGHT`"
-        errorLine1="                : AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_RIGHT);"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
-            line="1815"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_RIGHT`"
-        errorLine1="                AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_RIGHT"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
-            line="1823"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level 29 (current min is 26): `android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction#ACTION_PAGE_LEFT`"
-        errorLine1="                : AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_LEFT);"
-        errorLine2="                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/PagedView.java"
-            line="1824"
-            column="19"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 30 (current min is 26): `android.graphics.Outline#setPath`"
-        errorLine1="        outline.setPath(mPath);"
-        errorLine2="                ~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/popup/RoundedArrowDrawable.java"
-            line="114"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Field requires API level 28 (current min is 26): `android.appwidget.AppWidgetProviderInfo#widgetFeatures`"
-        errorLine1="        int featureFlags = mProviderInfo.widgetFeatures;"
-        errorLine2="                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/widget/WidgetAddFlowHandler.java"
-            line="93"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 30 (current min is 26): `android.view.View#getWindowInsetsController`"
-        errorLine1="        WindowInsetsController insetsController = getWindowInsetsController();"
-        errorLine2="                                                  ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java"
-            line="820"
-            column="51"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 30 (current min is 26): `android.view.WindowInsets.Type#ime`"
-        errorLine1="            insetsController.hide(WindowInsets.Type.ime());"
-        errorLine2="                                                    ~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java"
-            line="822"
-            column="53"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Call requires API level 30 (current min is 26): `android.view.WindowInsetsController#hide`"
-        errorLine1="            insetsController.hide(WindowInsets.Type.ime());"
-        errorLine2="                             ~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java"
-            line="822"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="Method reference requires API level 28 (current min is 26): `Person::getKey`"
-        errorLine1="            : Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new);"
-        errorLine2="                                         ~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/src/com/android/launcher3/model/data/WorkspaceItemInfo.java"
-            line="194"
-            column="42"/>
-    </issue>
-
 </issues>
\ No newline at end of file
diff --git a/lint-baseline2.xml b/lint-baseline2.xml
deleted file mode 100644
index 84f1b15..0000000
--- a/lint-baseline2.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01">
-
-    <issue
-        id="NewApi"
-        message="`?android:attr/dialogCornerRadius` requires API level 28 (current min is 26)"
-        errorLine1='        android:topLeftRadius="?android:attr/dialogCornerRadius"'
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/res/drawable/add_item_dialog_background.xml"
-            line="6"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="`?android:attr/dialogCornerRadius` requires API level 28 (current min is 26)"
-        errorLine1='        android:topRightRadius="?android:attr/dialogCornerRadius" /&gt;'
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/res/drawable/add_item_dialog_background.xml"
-            line="7"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="NewApi"
-        message="`@android:dimen/system_app_widget_background_radius` requires API level 31 (current min is 26)"
-        errorLine1='    &lt;corners android:radius="@android:dimen/system_app_widget_background_radius" /&gt;'
-        errorLine2="             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="packages/apps/Launcher3/res/drawable/widget_resize_frame.xml"
-            line="20"
-            column="14"/>
-    </issue>
-
-</issues>
\ No newline at end of file
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index ec4f6fc..f14cebd 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -23,15 +23,23 @@
 }
 
 filegroup {
-    name: "launcher3-quickstep-robolectric-src",
-    path: "robolectric_tests",
-    srcs: ["robolectric_tests/src/**/*.java"],
+    name: "launcher3-quickstep-robo-src",
+    path: "tests/multivalentTests",
+    srcs: [
+        "tests/multivalentTests/src/**/*.java",
+        "tests/multivalentTests/src/**/*.kt",
+    ],
 }
 
 filegroup {
     name: "launcher3-quickstep-tests-src",
     path: "tests",
-    srcs: ["tests/src/**/*.java", "tests/src/**/*.kt"],
+    srcs: [
+        "tests/multivalentTests/src/**/*.java",
+        "tests/multivalentTests/src/**/*.kt",
+        "tests/src/**/*.java",
+        "tests/src/**/*.kt",
+    ],
 }
 
 filegroup {
@@ -44,5 +52,6 @@
         "tests/src/com/android/quickstep/TaplOverviewIconTest.java",
         "tests/src/com/android/quickstep/TaplTestsQuickstep.java",
         "tests/src/com/android/quickstep/TaplTestsSplitscreen.java",
-    ]
+        "tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java"
+    ],
 }
diff --git a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
deleted file mode 100644
index 0b17a7b..0000000
--- a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import android.content.Context;
-import android.os.Bundle;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.testing.DebugTestInformationHandler;
-import com.android.launcher3.testing.shared.TestProtocol;
-
-/**
- * Class to handle requests from tests, including debug ones, to Quickstep Launcher builds.
- */
-public abstract class DebugQuickstepTestInformationHandler extends QuickstepTestInformationHandler {
-
-    private final DebugTestInformationHandler mDebugTestInformationHandler;
-
-    public DebugQuickstepTestInformationHandler(Context context) {
-        super(context);
-        mDebugTestInformationHandler = new DebugTestInformationHandler(context);
-    }
-
-    @Override
-    public Bundle call(String method, String arg, @Nullable Bundle extras) {
-        Bundle response = new Bundle();
-        if (TestProtocol.REQUEST_RECREATE_TASKBAR.equals(method)) {
-            // Allow null-pointer to catch illegal states.
-            runOnTISBinder(tisBinder -> tisBinder.getTaskbarManager().recreateTaskbar());
-            return response;
-        }
-        response = super.call(method, arg, extras);
-        if (response != null) return response;
-        return mDebugTestInformationHandler.call(method, arg, extras);
-    }
-}
-
diff --git a/quickstep/res/color/bubblebar_drop_target_bg_color.xml b/quickstep/res/color/bubblebar_drop_target_bg_color.xml
new file mode 100644
index 0000000..ca37c7f
--- /dev/null
+++ b/quickstep/res/color/bubblebar_drop_target_bg_color.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+    <item android:alpha="0.35" android:color="?androidprv:attr/materialColorPrimaryContainer" />
+</selector>
\ No newline at end of file
diff --git a/quickstep/res/drawable/bg_bubble_bar_drop_target.xml b/quickstep/res/drawable/bg_bubble_bar_drop_target.xml
new file mode 100644
index 0000000..79e4318
--- /dev/null
+++ b/quickstep/res/drawable/bg_bubble_bar_drop_target.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/bubblebar_drop_target_corner_radius" />
+    <solid android:color="@color/bubblebar_drop_target_bg_color" />
+    <stroke
+        android:width="1dp"
+        android:color="?androidprv:attr/materialColorPrimaryContainer" />
+</shape>
diff --git a/quickstep/res/drawable/bg_overview_clear_all_button.xml b/quickstep/res/drawable/bg_overview_clear_all_button.xml
index f3ff6ce..143761f 100644
--- a/quickstep/res/drawable/bg_overview_clear_all_button.xml
+++ b/quickstep/res/drawable/bg_overview_clear_all_button.xml
@@ -20,7 +20,7 @@
     <item>
         <shape android:shape="rectangle"
             android:tint="?colorButtonNormal">
-            <corners android:radius="24dp" />
+            <corners android:radius="@dimen/recents_clear_all_outline_radius" />
             <solid android:color="?androidprv:attr/materialColorSurfaceBright"/>
         </shape>
     </item>
diff --git a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml b/quickstep/res/drawable/keyboard_quick_switch_thumbnail_background.xml
similarity index 66%
copy from quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
copy to quickstep/res/drawable/keyboard_quick_switch_thumbnail_background.xml
index dde9cac..961f5aa 100644
--- a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
+++ b/quickstep/res/drawable/keyboard_quick_switch_thumbnail_background.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
+<!-- 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.
@@ -13,11 +13,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<ImageView
+<shape
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:scaleType="centerCrop"
-    android:background="@drawable/keyboard_quick_switch_task_view_background"
-    android:clipToOutline="true"
-    android:importantForAccessibility="no"/>
+    android:shape="rectangle">
+    <solid android:color="@android:color/white" />
+    <corners android:radius="@dimen/keyboard_quick_switch_task_view_radius" />
+</shape>
diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
index 69e1574..38df756 100644
--- a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
@@ -36,19 +36,19 @@
         app:layout_constraintEnd_toEndOf="parent">
 
         <include
-            layout="@layout/keyboard_quick_switch_thumbnail"
-            android:id="@+id/thumbnail1"
+            layout="@layout/keyboard_quick_switch_taskview_thumbnail"
+            android:id="@+id/thumbnail_1"
             android:layout_width="0dp"
             android:layout_height="match_parent"
 
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toStartOf="@id/thumbnail2"/>
+            app:layout_constraintEnd_toStartOf="@id/thumbnail_2"/>
 
         <include
-            layout="@layout/keyboard_quick_switch_thumbnail"
-            android:id="@+id/thumbnail2"
+            layout="@layout/keyboard_quick_switch_taskview_thumbnail"
+            android:id="@+id/thumbnail_2"
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:visibility="gone"
@@ -56,31 +56,33 @@
 
             app:layout_constraintTop_toTopOf="parent"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toEndOf="@id/thumbnail1"
+            app:layout_constraintStart_toEndOf="@id/thumbnail_1"
             app:layout_constraintEnd_toEndOf="parent"/>
 
         <ImageView
-            android:id="@+id/icon1"
+            android:id="@+id/icon_1"
             android:layout_width="@dimen/keyboard_quick_switch_taskview_icon_size"
             android:layout_height="@dimen/keyboard_quick_switch_taskview_icon_size"
-            android:layout_marginTop="@dimen/keyboard_quick_switch_taskview_icon_margin"
-            android:layout_marginStart="@dimen/keyboard_quick_switch_taskview_icon_margin"
             android:importantForAccessibility="no"
+            android:scaleType="centerCrop"
 
-            app:layout_constraintTop_toTopOf="@id/thumbnail1"
-            app:layout_constraintStart_toStartOf="@id/thumbnail1"/>
+            app:layout_constraintTop_toTopOf="@id/thumbnail_1"
+            app:layout_constraintBottom_toBottomOf="@id/thumbnail_1"
+            app:layout_constraintStart_toStartOf="@id/thumbnail_1"
+            app:layout_constraintEnd_toEndOf="@id/thumbnail_1"/>
 
         <ImageView
-            android:id="@+id/icon2"
+            android:id="@+id/icon_2"
             android:layout_width="@dimen/keyboard_quick_switch_taskview_icon_size"
             android:layout_height="@dimen/keyboard_quick_switch_taskview_icon_size"
-            android:layout_marginTop="@dimen/keyboard_quick_switch_taskview_icon_margin"
-            android:layout_marginStart="@dimen/keyboard_quick_switch_taskview_icon_margin"
             android:importantForAccessibility="no"
             android:visibility="gone"
+            android:scaleType="centerCrop"
 
-            app:layout_constraintTop_toTopOf="@id/thumbnail2"
-            app:layout_constraintStart_toStartOf="@id/thumbnail2"/>
+            app:layout_constraintTop_toTopOf="@id/thumbnail_2"
+            app:layout_constraintBottom_toBottomOf="@id/thumbnail_2"
+            app:layout_constraintStart_toStartOf="@id/thumbnail_2"
+            app:layout_constraintEnd_toEndOf="@id/thumbnail_2"/>
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 
diff --git a/quickstep/res/layout/bubble_bar_drop_target.xml b/quickstep/res/layout/bubble_bar_drop_target.xml
new file mode 100644
index 0000000..23f240c
--- /dev/null
+++ b/quickstep/res/layout/bubble_bar_drop_target.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="@dimen/bubblebar_size"
+    android:layout_height="@dimen/bubblebar_size"
+    android:background="@drawable/bg_bubble_bar_drop_target"
+    android:elevation="@dimen/bubblebar_elevation" />
\ No newline at end of file
diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview.xml b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
index 6ed3c6e..c0ace9a 100644
--- a/quickstep/res/layout/keyboard_quick_switch_taskview.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
@@ -36,51 +36,53 @@
         app:layout_constraintEnd_toEndOf="parent">
 
         <include
-            layout="@layout/keyboard_quick_switch_thumbnail"
-            android:id="@+id/thumbnail1"
+            layout="@layout/keyboard_quick_switch_taskview_thumbnail"
+            android:id="@+id/thumbnail_1"
             android:layout_width="match_parent"
             android:layout_height="0dp"
 
             app:layout_constraintTop_toTopOf="parent"
-            app:layout_constraintBottom_toTopOf="@id/thumbnail2"
+            app:layout_constraintBottom_toTopOf="@id/thumbnail_2"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"/>
 
         <include
-            layout="@layout/keyboard_quick_switch_thumbnail"
-            android:id="@+id/thumbnail2"
+            layout="@layout/keyboard_quick_switch_taskview_thumbnail"
+            android:id="@+id/thumbnail_2"
             android:layout_width="match_parent"
             android:layout_height="0dp"
             android:visibility="gone"
             android:layout_marginTop="@dimen/keyboard_quick_switch_split_view_spacing"
 
-            app:layout_constraintTop_toBottomOf="@id/thumbnail1"
+            app:layout_constraintTop_toBottomOf="@id/thumbnail_1"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"/>
 
         <ImageView
-            android:id="@+id/icon1"
+            android:id="@+id/icon_1"
             android:layout_width="@dimen/keyboard_quick_switch_taskview_icon_size"
             android:layout_height="@dimen/keyboard_quick_switch_taskview_icon_size"
-            android:layout_marginTop="@dimen/keyboard_quick_switch_taskview_icon_margin"
-            android:layout_marginStart="@dimen/keyboard_quick_switch_taskview_icon_margin"
             android:importantForAccessibility="no"
+            android:scaleType="centerCrop"
 
-            app:layout_constraintTop_toTopOf="@id/thumbnail1"
-            app:layout_constraintStart_toStartOf="@id/thumbnail1"/>
+            app:layout_constraintTop_toTopOf="@id/thumbnail_1"
+            app:layout_constraintBottom_toBottomOf="@id/thumbnail_1"
+            app:layout_constraintStart_toStartOf="@id/thumbnail_1"
+            app:layout_constraintEnd_toEndOf="@id/thumbnail_1"/>
 
         <ImageView
-            android:id="@+id/icon2"
+            android:id="@+id/icon_2"
             android:layout_width="@dimen/keyboard_quick_switch_taskview_icon_size"
             android:layout_height="@dimen/keyboard_quick_switch_taskview_icon_size"
-            android:layout_marginTop="@dimen/keyboard_quick_switch_taskview_icon_margin"
-            android:layout_marginStart="@dimen/keyboard_quick_switch_taskview_icon_margin"
             android:importantForAccessibility="no"
             android:visibility="gone"
+            android:scaleType="centerCrop"
 
-            app:layout_constraintTop_toTopOf="@id/thumbnail2"
-            app:layout_constraintStart_toStartOf="@id/thumbnail2"/>
+            app:layout_constraintTop_toTopOf="@id/thumbnail_2"
+            app:layout_constraintBottom_toBottomOf="@id/thumbnail_2"
+            app:layout_constraintStart_toStartOf="@id/thumbnail_2"
+            app:layout_constraintEnd_toEndOf="@id/thumbnail_2"/>
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 
diff --git a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml b/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml
similarity index 92%
rename from quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
rename to quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml
index dde9cac..8cd8560 100644
--- a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview_thumbnail.xml
@@ -18,6 +18,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:scaleType="centerCrop"
-    android:background="@drawable/keyboard_quick_switch_task_view_background"
+    android:background="@drawable/keyboard_quick_switch_thumbnail_background"
     android:clipToOutline="true"
     android:importantForAccessibility="no"/>
diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml
index da94c3a..3380ea4 100644
--- a/quickstep/res/layout/overview_clear_all_button.xml
+++ b/quickstep/res/layout/overview_clear_all_button.xml
@@ -17,10 +17,12 @@
 <com.android.quickstep.views.ClearAllButton
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto"
     style="@style/OverviewClearAllButton"
     android:id="@+id/clear_all"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/recents_clear_all"
     android:textColor="?androidprv:attr/materialColorOnSurface"
+    launcher:focusBorderColor="?androidprv:attr/materialColorOutline"
     android:textSize="14sp" />
\ No newline at end of file
diff --git a/quickstep/res/layout/task_menu_with_arrow.xml b/quickstep/res/layout/task_menu_with_arrow.xml
index 38573fd..c9108a5 100644
--- a/quickstep/res/layout/task_menu_with_arrow.xml
+++ b/quickstep/res/layout/task_menu_with_arrow.xml
@@ -23,11 +23,17 @@
     android:orientation="vertical"
     android:visibility="invisible">
 
-    <LinearLayout
-        android:id="@+id/menu_option_layout"
+    <ScrollView
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical"
-        android:showDividers="middle" />
+        android:layout_height="wrap_content">
+
+        <LinearLayout
+            android:id="@+id/menu_option_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:showDividers="middle" />
+
+    </ScrollView>
 
 </com.android.quickstep.views.TaskMenuViewWithArrow>
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_all_apps_button.xml b/quickstep/res/layout/taskbar_all_apps_button.xml
index c50db2e..94596cb 100644
--- a/quickstep/res/layout/taskbar_all_apps_button.xml
+++ b/quickstep/res/layout/taskbar_all_apps_button.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2022 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -15,10 +14,9 @@
 -->
 
 <!-- Note: The actual size will match the taskbar icon sizes in TaskbarView#onLayout(). -->
-<com.android.launcher3.views.IconButtonView
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.views.IconButtonView xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/BaseIcon.Workspace.Taskbar"
     android:layout_width="@dimen/taskbar_icon_min_touch_size"
     android:layout_height="@dimen/taskbar_icon_min_touch_size"
-    android:contentDescription="@string/all_apps_button_label"
     android:backgroundTint="@android:color/transparent"
-    />
+    android:contentDescription="@string/all_apps_button_label" />
diff --git a/quickstep/res/layout/taskbar_divider.xml b/quickstep/res/layout/taskbar_divider.xml
index 0a92fa9..330f85f 100644
--- a/quickstep/res/layout/taskbar_divider.xml
+++ b/quickstep/res/layout/taskbar_divider.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2023 The Android Open Source Project
 
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
@@ -13,9 +12,9 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.views.IconButtonView
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.views.IconButtonView xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/BaseIcon.Workspace.Taskbar"
     android:layout_width="@dimen/taskbar_icon_min_touch_size"
     android:layout_height="@dimen/taskbar_icon_min_touch_size"
-    android:contentDescription="@string/taskbar_divider_a11y_title"
-    android:backgroundTint="@android:color/transparent" />
\ No newline at end of file
+    android:backgroundTint="@android:color/transparent"
+    android:contentDescription="@string/taskbar_divider_a11y_title" />
\ No newline at end of file
diff --git a/quickstep/res/layout/taskbar_edu_circle_to_search.xml b/quickstep/res/layout/taskbar_edu_circle_to_search.xml
new file mode 100644
index 0000000..6c95f25
--- /dev/null
+++ b/quickstep/res/layout/taskbar_edu_circle_to_search.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <TextView
+        android:id="@+id/title"
+        style="@style/TextAppearance.TaskbarEduTooltip.Title"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:text="@string/taskbar_edu_circle_to_search_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toTopOf="@+id/circle_to_search_animation" />
+
+    <com.airbnb.lottie.LottieAnimationView
+        android:id="@+id/circle_to_search_animation"
+        android:layout_width="@dimen/taskbar_edu_swipe_lottie_width"
+        android:layout_height="@dimen/taskbar_edu_swipe_lottie_height"
+        android:layout_marginTop="@dimen/taskbar_edu_tooltip_vertical_margin"
+        app:layout_constraintBottom_toTopOf="@id/circle_to_search_text"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/title"
+        app:lottie_rawRes="@raw/taskbar_edu_circle_to_search"
+        app:lottie_autoPlay="true"
+        app:lottie_loop="true" />
+
+    <TextView
+        android:id="@+id/circle_to_search_text"
+        style="@style/TextAppearance.TaskbarEduTooltip.Subtext"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:textSize="@dimen/taskbar_edu_circle_to_search_subtitle_text_size"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/circle_to_search_animation"
+        app:layout_constraintBottom_toBottomOf="parent" />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml
index 6af7cf4..3c6878a 100644
--- a/quickstep/res/layout/transient_taskbar.xml
+++ b/quickstep/res/layout/transient_taskbar.xml
@@ -41,9 +41,10 @@
     <com.android.launcher3.taskbar.bubbles.BubbleBarView
         android:id="@+id/taskbar_bubbles"
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/bubblebar_size"
+        android:layout_height="@dimen/bubblebar_size_with_pointer"
         android:layout_gravity="bottom|end"
-        android:layout_marginEnd="@dimen/transient_taskbar_bottom_margin"
+        android:layout_marginHorizontal="@dimen/transient_taskbar_bottom_margin"
+        android:paddingTop="@dimen/bubblebar_pointer_size"
         android:paddingEnd="@dimen/taskbar_icon_spacing"
         android:paddingStart="@dimen/taskbar_icon_spacing"
         android:visibility="gone"
diff --git a/quickstep/res/raw/taskbar_edu_circle_to_search.json b/quickstep/res/raw/taskbar_edu_circle_to_search.json
new file mode 100644
index 0000000..0dcccd6
--- /dev/null
+++ b/quickstep/res/raw/taskbar_edu_circle_to_search.json
@@ -0,0 +1 @@
+{"v":"5.12.1","fr":60,"ip":0,"op":431,"w":348,"h":218,"nm":"Omni_EDU_05_matted","ddd":0,"assets":[{"id":"comp_0","nm":"Omni_EDU_05","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".black","cl":"black","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-140,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,-48,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0,0],"y":[1,1]},"o":{"x":[0.2,0.2],"y":[0,0]},"t":174,"s":[0,0]},{"i":{"x":[0,0],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":192,"s":[17,17]},{"i":{"x":[0.999,0.999],"y":[1,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":237,"s":[17,17]},{"t":249,"s":[0,0]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-48],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":174,"op":249,"st":40,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"c2s null","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":193,"s":[-56.933,-189.286,0],"to":[-0.023,-0.021,0],"ti":[0.092,0.088,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":194,"s":[-57.069,-189.414,0],"to":[-0.092,-0.088,0],"ti":[0.189,0.184,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":195,"s":[-57.488,-189.813,0],"to":[-0.189,-0.184,0],"ti":[0.29,0.293,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":196,"s":[-58.204,-190.519,0],"to":[-0.29,-0.293,0],"ti":[0.392,0.419,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":197,"s":[-59.226,-191.574,0],"to":[-0.392,-0.419,0],"ti":[0.492,0.566,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":198,"s":[-60.555,-193.035,0],"to":[-0.492,-0.566,0],"ti":[0.582,0.741,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":199,"s":[-62.177,-194.971,0],"to":[-0.582,-0.741,0],"ti":[0.641,0.957,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":200,"s":[-64.048,-197.48,0],"to":[-0.641,-0.957,0],"ti":[0.644,1.22,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":201,"s":[-66.021,-200.712,0],"to":[-0.644,-1.22,0],"ti":[0.59,1.52,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":202,"s":[-67.912,-204.803,0],"to":[-0.59,-1.52,0],"ti":[0.478,1.841,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":203,"s":[-69.561,-209.83,0],"to":[-0.478,-1.841,0],"ti":[0.309,2.174,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":204,"s":[-70.781,-215.849,0],"to":[-0.309,-2.174,0],"ti":[0.095,2.509,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":205,"s":[-71.414,-222.876,0],"to":[-0.095,-2.509,0],"ti":[-0.149,2.838,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":206,"s":[-71.348,-230.903,0],"to":[0.149,-2.838,0],"ti":[-0.493,3.137,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":207,"s":[-70.519,-239.902,0],"to":[0.493,-3.137,0],"ti":[-0.971,3.37,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":208,"s":[-68.392,-249.724,0],"to":[0.971,-3.37,0],"ti":[-1.521,3.501,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":209,"s":[-64.693,-260.12,0],"to":[1.521,-3.501,0],"ti":[-2.183,3.438,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":210,"s":[-59.267,-270.731,0],"to":[2.183,-3.438,0],"ti":[-3.014,2.996,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":211,"s":[-51.596,-280.747,0],"to":[3.014,-2.996,0],"ti":[-3.718,2.327,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":212,"s":[-41.184,-288.709,0],"to":[3.718,-2.327,0],"ti":[-4.093,1.634,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":213,"s":[-29.289,-294.708,0],"to":[4.093,-1.634,0],"ti":[-4.243,0.814,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":214,"s":[-16.628,-298.511,0],"to":[4.243,-0.814,0],"ti":[-4.168,-0.028,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":215,"s":[-3.828,-299.591,0],"to":[4.168,0.028,0],"ti":[-3.907,-0.628,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":216,"s":[8.377,-298.344,0],"to":[3.907,0.628,0],"ti":[-3.551,-1.009,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":217,"s":[19.614,-295.822,0],"to":[3.551,1.009,0],"ti":[-3.138,-1.314,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":218,"s":[29.681,-292.288,0],"to":[3.138,1.314,0],"ti":[-2.68,-1.566,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":219,"s":[38.443,-287.941,0],"to":[2.68,1.566,0],"ti":[-2.137,-1.816,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":220,"s":[45.761,-282.889,0],"to":[2.137,1.816,0],"ti":[-1.616,-1.954,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":221,"s":[51.267,-277.046,0],"to":[1.616,1.954,0],"ti":[-1.251,-1.903,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":222,"s":[55.456,-271.165,0],"to":[1.251,1.903,0],"ti":[-0.99,-1.774,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":223,"s":[58.77,-265.626,0],"to":[0.99,1.774,0],"ti":[-0.752,-1.637,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":224,"s":[61.394,-260.52,0],"to":[0.752,1.637,0],"ti":[-0.54,-1.496,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":225,"s":[63.282,-255.805,0],"to":[0.54,1.496,0],"ti":[-0.388,-1.34,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":226,"s":[64.634,-251.545,0],"to":[0.388,1.34,0],"ti":[-0.278,-1.183,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":227,"s":[65.61,-247.762,0],"to":[0.278,1.183,0],"ti":[-0.195,-1.031,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":228,"s":[66.303,-244.447,0],"to":[0.195,1.031,0],"ti":[-0.13,-0.885,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":229,"s":[66.778,-241.579,0],"to":[0.13,0.885,0],"ti":[-0.081,-0.748,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":230,"s":[67.085,-239.135,0],"to":[0.081,0.748,0],"ti":[-0.045,-0.619,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":231,"s":[67.265,-237.089,0],"to":[0.045,0.619,0],"ti":[-0.02,-0.498,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":232,"s":[67.354,-235.418,0],"to":[0.02,0.498,0],"ti":[-0.004,-0.385,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":233,"s":[67.382,-234.099,0],"to":[0.004,0.385,0],"ti":[0.004,-0.279,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":234,"s":[67.377,-233.109,0],"to":[-0.004,0.279,0],"ti":[0.006,-0.18,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":235,"s":[67.358,-232.425,0],"to":[-0.006,0.18,0],"ti":[0.004,-0.087,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":236,"s":[67.341,-232.028,0],"to":[-0.004,0.087,0],"ti":[0.001,-0.021,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":237,"s":[67.335,-231.9,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":248,"s":[67.335,-231.9,0],"to":[-0.008,0.042,0],"ti":[0.033,-0.177,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":249,"s":[67.289,-231.647,0],"to":[-0.033,0.177,0],"ti":[0.079,-0.372,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":250,"s":[67.135,-230.84,0],"to":[-0.079,0.372,0],"ti":[0.155,-0.591,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":251,"s":[66.815,-229.413,0],"to":[-0.155,0.591,0],"ti":[0.268,-0.834,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":252,"s":[66.203,-227.297,0],"to":[-0.268,0.834,0],"ti":[0.413,-1.109,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":253,"s":[65.206,-224.409,0],"to":[-0.413,1.109,0],"ti":[0.247,-0.628,0]},{"t":254,"s":[63.723,-220.641,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":193,"op":264,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","parent":12,"sr":1,"ks":{"o":{"a":0,"k":90,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.149,"y":0.701},"o":{"x":0.4,"y":0.002},"t":248,"s":[-8.212,-253.668,0],"to":[0,0,0],"ti":[0,0,0]},{"t":263,"s":[0,-227,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.149,"y":0.701},"o":{"x":0.4,"y":0.002},"t":248,"s":[{"i":[[3.564,-2.549],[3.809,-1.264],[12.238,3.984],[8.325,10.606],[-0.214,12.436],[-2.655,8.03],[-10.533,8.871],[-9.434,2.582],[-8.48,-3.643],[-9.227,-13.6],[-1.802,-9.359],[2.171,-9.596]],"o":[[-3.564,2.549],[-12.609,4.183],[-12.52,-4.076],[-7.722,-9.838],[0.146,-8.454],[4.364,-13.197],[5.142,-4.331],[9.891,-2.707],[11.828,5.081],[4.099,6.042],[2.254,11.707],[-3.907,17.266]],"v":[[53.514,60.456],[41.519,66.798],[2.462,64.221],[-33.286,39.729],[-45.626,-0.393],[-41.723,-21.691],[-18.543,-58.238],[5.442,-69.196],[39.994,-68.523],[68.082,-43.976],[77.052,-19.838],[77.406,14.145]],"c":true}]},{"t":263,"s":[{"i":[[7.701,-4.092],[8.127,0],[7.226,4.357],[4.092,7.701],[0,8.127],[-4.357,7.226],[-7.701,4.092],[-8.127,0],[-7.226,-4.357],[-4.092,-7.701],[0,-8.127],[4.357,-7.226]],"o":[[-6.709,3.565],[-9.053,0],[-7.447,-4.489],[-3.565,-6.709],[0,-9.053],[4.489,-7.447],[6.709,-3.565],[9.053,0],[7.447,4.489],[3.565,6.709],[0,9.053],[-4.489,7.447]],"v":[[22.492,42.415],[0,48],[-24.747,41.137],[-42.415,22.492],[-48,0],[-41.137,-24.747],[-22.492,-42.415],[0,-48],[24.747,-41.137],[42.415,-22.492],[48,0],[41.137,24.747]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":78.63,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector 303","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":193,"s":[0]},{"t":237,"s":[63],"h":1},{"i":{"x":[0.149],"y":[0.701]},"o":{"x":[0.4],"y":[0.002]},"t":248,"s":[63]},{"t":263,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":193,"op":263,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".black","cl":"black","parent":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":277,"s":[0]},{"t":289,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[2.625,-203,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[2.625,-221,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.5,1.3],[0,0],[0,0],[0,0],[-0.65,1.45],[-0.25,1.6],[0,0],[2.65,-2.25],[3.6,0],[2.9,2.85],[0,4.05],[-2.85,2.85],[-4.1,0],[-1.1,-0.3],[-1,-0.5],[0,0],[1.7,0.5],[1.8,0],[3.75,-3.75],[0,-5.3],[-3.75,-3.75],[-5.4,0],[-2,0.7]],"o":[[0,0],[0,0],[0,0],[1.05,-1.35],[0.7,-1.5],[0,0],[-0.7,3.35],[-2.6,2.2],[-4.1,0],[-2.85,-2.9],[0,-4.05],[2.9,-2.9],[1.2,0],[1.1,0.25],[0,0],[-1.45,-0.85],[-1.65,-0.5],[-5.35,0],[-3.75,3.75],[0,5.3],[3.75,3.75],[2.25,0],[2,-0.75]],"v":[[1.35,9.863],[21.075,29.587],[24.375,26.288],[4.575,6.637],[7.125,2.438],[8.55,-2.213],[3.975,-2.213],[-1.05,6.188],[-10.35,9.488],[-20.85,5.212],[-25.125,-5.213],[-20.85,-15.562],[-10.35,-19.913],[-6.9,-19.462],[-3.75,-18.337],[-0.45,-21.637],[-5.175,-23.663],[-10.35,-24.413],[-24,-18.788],[-29.625,-5.213],[-24,8.363],[-10.275,13.988],[-3.9,12.938]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-3.05,-3.05],[0,-4.4],[-3.05,3.05],[-4.4,0],[3.05,3.05],[0,4.4],[3.05,-3.05],[4.4,0]],"o":[[3.05,3.05],[0,-4.4],[3.05,-3.05],[-4.4,0],[-3.05,-3.05],[0,4.4],[-3.05,3.05],[4.4,0]],"v":[[9.3,-9.262],[13.875,1.913],[18.45,-9.262],[29.625,-13.837],[18.45,-18.413],[13.875,-29.587],[9.3,-18.413],[-1.875,-13.837]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"icon","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":263,"op":431,"st":60,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".black","cl":"black","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":270,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[0,-227,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[-100,-161,0]}],"ix":2,"l":2},"a":{"a":0,"k":[11,11,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[{"i":[[0,0],[7.26,-4.415],[4.064,-7.787],[0,-8]],"o":[[-9.118,0],[-7.478,4.547],[-3.462,6.633],[0,0]],"v":[[11,-37],[-13.903,-30.043],[-31.581,-11.176],[-37,11]],"c":false}]},{"t":290,"s":[{"i":[[0,0],[0,0],[0,-7.732],[0,0]],"o":[[0,0],[-7.732,0],[0,0],[0,0]],"v":[[11,-11],[3,-11],[-11,3],[-11,11]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Handle Top Left","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":263,"op":431,"st":63,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".black","cl":"black","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":180,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[0,-227,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[100,-161,0]}],"ix":2,"l":2},"a":{"a":0,"k":[11,11,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[{"i":[[0,0],[7.26,-4.415],[4.064,-7.787],[0,-8]],"o":[[-9.118,0],[-7.478,4.547],[-3.462,6.633],[0,0]],"v":[[11,-37],[-13.903,-30.043],[-31.581,-11.176],[-37,11]],"c":false}]},{"t":290,"s":[{"i":[[0,0],[0,0],[0,-7.732],[0,0]],"o":[[0,0],[-7.732,0],[0,0],[0,0]],"v":[[11,-11],[3,-11],[-11,3],[-11,11]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Handle Top Left","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":263,"op":431,"st":63,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".black","cl":"black","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[0,-227,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[100,-279,0]}],"ix":2,"l":2},"a":{"a":0,"k":[11,11,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[{"i":[[0,0],[7.26,-4.415],[4.064,-7.787],[0,-8]],"o":[[-9.118,0],[-7.478,4.547],[-3.462,6.633],[0,0]],"v":[[11,-37],[-13.903,-30.043],[-31.581,-11.176],[-37,11]],"c":false}]},{"t":290,"s":[{"i":[[0,0],[0,0],[0,-7.732],[0,0]],"o":[[0,0],[-7.732,0],[0,0],[0,0]],"v":[[11,-11],[3,-11],[-11,3],[-11,11]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Handle Top Left","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":263,"op":431,"st":63,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".black","cl":"black","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[0,-227,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[-100,-279,0]}],"ix":2,"l":2},"a":{"a":0,"k":[11,11,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[{"i":[[0,0],[7.26,-4.415],[4.064,-7.787],[0,-8]],"o":[[-9.118,0],[-7.478,4.547],[-3.462,6.633],[0,0]],"v":[[11,-37],[-13.903,-30.043],[-31.581,-11.176],[-37,11]],"c":false}]},{"t":290,"s":[{"i":[[0,0],[0,0],[0,-7.732],[0,0]],"o":[[0,0],[-7.732,0],[0,0],[0,0]],"v":[[11,-11],[3,-11],[-11,3],[-11,11]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Handle Top Left","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":263,"op":431,"st":63,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":0,"nm":"Search","parent":12,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[0,-166,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[0,-109,0]}],"ix":2,"l":2},"a":{"a":0,"k":[83,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":166,"h":45,"ip":135,"op":319,"st":135,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":0,"nm":"Flower","parent":12,"refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-2.5,-209,0],"ix":2,"l":2},"a":{"a":0,"k":[109,115,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":219,"h":231,"ip":122,"op":431,"st":122,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".blue50","cl":"blue50","parent":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":266,"s":[0]},{"t":278,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":263,"s":[0,-227,0],"to":[0,0,0],"ti":[0,0,0]},{"t":299,"s":[0,-220,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0,0],"y":[1,1]},"o":{"x":[0.2,0.2],"y":[0,0]},"t":263,"s":[92,92]},{"t":299,"s":[240,158]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":263,"s":[46]},{"t":299,"s":[12]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.909803921569,0.941176470588,0.996078431373,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":263,"op":431,"st":60,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":3,"nm":"pan up","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.15,"y":1},"o":{"x":0.653,"y":0},"t":99,"s":[174,109,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.15,"y":0.15},"o":{"x":0.546,"y":0.546},"t":169,"s":[174,327,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.15,"y":1},"o":{"x":0.653,"y":0},"t":357,"s":[174,327,0],"to":[0,0,0],"ti":[0,0,0]},{"t":427,"s":[174,109,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"Void","np":19,"mn":"Pseudo/250958","ix":1,"en":1,"ef":[{"ty":0,"nm":"Width","mn":"Pseudo/250958-0001","ix":1,"v":{"a":0,"k":100,"ix":1}},{"ty":0,"nm":"Height","mn":"Pseudo/250958-0002","ix":2,"v":{"a":0,"k":100,"ix":2}},{"ty":0,"nm":"Offset X","mn":"Pseudo/250958-0003","ix":3,"v":{"a":0,"k":0,"ix":3}},{"ty":0,"nm":"Offset Y","mn":"Pseudo/250958-0004","ix":4,"v":{"a":0,"k":0,"ix":4}},{"ty":0,"nm":"Roundness","mn":"Pseudo/250958-0005","ix":5,"v":{"a":0,"k":0,"ix":5}},{"ty":6,"nm":"About","mn":"Pseudo/250958-0006","ix":6,"v":0},{"ty":6,"nm":"Plague of null layers.","mn":"Pseudo/250958-0007","ix":7,"v":0},{"ty":6,"nm":"Void","mn":"Pseudo/250958-0008","ix":8,"v":0},{"ty":6,"nm":"Following projects","mn":"Pseudo/250958-0009","ix":9,"v":0},{"ty":6,"nm":"Void","mn":"Pseudo/250958-0010","ix":10,"v":0},{"ty":6,"nm":"through time.","mn":"Pseudo/250958-0011","ix":11,"v":0},{"ty":6,"nm":"Void","mn":"Pseudo/250958-0012","ix":12,"v":0},{"ty":6,"nm":"Be free of the past.","mn":"Pseudo/250958-0013","ix":13,"v":0},{"ty":6,"nm":"Void","mn":"Pseudo/250958-0014","ix":14,"v":0},{"ty":6,"nm":"Copyright 2023 Battle Axe Inc","mn":"Pseudo/250958-0015","ix":15,"v":0},{"ty":6,"nm":"Void","mn":"Pseudo/250958-0016","ix":16,"v":0},{"ty":6,"nm":"Void","mn":"Pseudo/250958-0017","ix":17,"v":0}]}],"ip":0,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"long Press Over - Outward","parent":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":95,"s":[100]},{"t":113,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,38,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.05,0.05],"y":[0.7,0.7]},"t":83,"s":[116,116]},{"t":113,"s":[136,136]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Long Pres Over","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":83,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"long Press Over","parent":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":33,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":83,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":86,"s":[100]},{"t":95,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,38,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.999,0.999],"y":[1,1]},"o":{"x":[0.001,0.001],"y":[0,0]},"t":33,"s":[40,40]},{"i":{"x":[0.8,0.8],"y":[0.15,0.15]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":83,"s":[120,120]},{"t":101,"s":[40,40]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.40000000596,0.615686297417,0.964705884457,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Long Pres Over","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":0,"nm":"Action Key","parent":12,"refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-11.539,38,0],"ix":2,"l":2},"a":{"a":0,"k":[53.5,53.5,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":107,"h":107,"ip":0,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"long Press Under","parent":12,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":83,"s":[100]},{"t":95,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,38,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0,0],"y":[1,1]},"o":{"x":[0.2,0.2],"y":[0,0]},"t":30,"s":[96,96]},{"i":{"x":[0.833,0.833],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":66,"s":[120,120]},{"i":{"x":[0.999,0.999],"y":[1,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":83,"s":[120,120]},{"t":101,"s":[106,106]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529422283,0.890196084976,0.988235294819,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Long Press Under","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":".grey800","cl":"grey800","parent":12,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,38,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[348,142],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294118524,0.250980407,0.262745112181,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Grey800","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue100","cl":"blue100","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[174,109,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[348,218],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.823529411765,0.890196078431,0.988235294118,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":431,"st":0,"ct":1,"bm":0}]},{"id":"comp_1","nm":"SearchPill","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"superG","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[0]},{"t":17,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"k":[{"s":[-3.898,0.128,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-4.239,0.128,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-5.311,0.128,0],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-7.286,0.128,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-10.519,0.128,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-15.81,0.128,0],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-25.898,0.128,0],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-37.431,0.128,0],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-43.055,0.128,0],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-46.404,0.128,0],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-48.712,0.128,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-50.434,0.128,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-51.781,0.128,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-52.869,0.128,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.768,0.128,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-54.522,0.128,0],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-55.162,0.128,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-55.71,0.128,0],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-56.182,0.128,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-56.591,0.128,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-56.947,0.128,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-57.257,0.128,0],"t":21,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-57.526,0.128,0],"t":22,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-57.761,0.128,0],"t":23,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-57.965,0.128,0],"t":24,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.142,0.128,0],"t":25,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.295,0.128,0],"t":26,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.425,0.128,0],"t":27,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.537,0.128,0],"t":28,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.63,0.128,0],"t":29,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.707,0.128,0],"t":30,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.769,0.128,0],"t":31,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.818,0.128,0],"t":32,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.854,0.128,0],"t":33,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.853,0.128,0],"t":129,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.679,0.128,0],"t":130,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-58.301,0.128,0],"t":131,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-57.701,0.128,0],"t":132,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-57.039,0.128,0],"t":133,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-56.46,0.128,0],"t":134,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-55.983,0.128,0],"t":135,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-55.588,0.128,0],"t":136,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-55.255,0.128,0],"t":137,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-54.97,0.128,0],"t":138,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-54.723,0.128,0],"t":139,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-54.507,0.128,0],"t":140,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-54.316,0.128,0],"t":141,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-54.147,0.128,0],"t":142,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.996,0.128,0],"t":143,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.861,0.128,0],"t":144,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.74,0.128,0],"t":145,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.631,0.128,0],"t":146,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.534,0.128,0],"t":147,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.446,0.128,0],"t":148,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.367,0.128,0],"t":149,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.297,0.128,0],"t":150,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.234,0.128,0],"t":151,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.178,0.128,0],"t":152,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.128,0.128,0],"t":153,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.084,0.128,0],"t":154,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.046,0.128,0],"t":155,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-53.012,0.128,0],"t":156,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-52.96,0.128,0],"t":158,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[-52.913,0.128,0],"t":161,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"a":{"a":0,"k":[24.102,22.628,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[1.788,0],[0.959,-2.878],[0,0],[-4.737,0],[-2.091,-1.959]],"o":[[-1.262,-1.202],[-3.161,0],[0,0],[1.99,-3.959],[3.272,0],[0,0]],"v":[[6.004,1.712],[1.358,-0.106],[-5.439,4.903],[-9.458,1.783],[1.358,-4.903],[9.458,-1.742]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.917647063732,0.262745112181,0.207843139768,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[23.001,15.411],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"g-red","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-0.808],[-0.252,-0.727],[0,0],[0,1.959],[-0.828,1.636],[0,0],[0,0]],"o":[[0,0.808],[0,0],[-0.828,-1.636],[0,-1.959],[0,0],[0,0],[-0.242,0.727]],"v":[[2.277,0],[2.661,2.313],[-1.358,5.434],[-2.661,0],[-1.358,-5.434],[2.661,-5.434],[2.661,-2.313]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.976470589638,0.670588254929,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[14.901,22.628],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"g-yellow","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[3.272,0],[1.99,3.959],[0,0],[0,0],[-3.161,0],[-1.091,0.727]],"o":[[-2,1.848],[-4.737,0],[0,0],[0,0],[0.959,2.878],[1.636,0],[0,0]],"v":[[9.413,1.964],[1.404,4.903],[-9.413,-1.783],[-9.413,-4.903],[-5.393,-4.903],[1.404,0.106],[5.514,-1.066]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.203921571374,0.658823549747,0.32549020648,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[22.955,29.844],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"g-green","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-0.798],[2.283,-2.111],[0,0],[0,0],[-0.293,1.495],[0,0],[0,0]],"o":[[0.121,0.737],[0,3.686],[0,0],[0,0],[1.273,-0.858],[0,0],[0,0],[0,0]],"v":[[5.61,-5.6],[5.802,-3.308],[2.207,5.6],[-1.692,5.6],[-1.692,2.57],[0.732,-1.045],[-5.802,-1.045],[-5.802,-5.6]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.258823543787,0.521568655968,0.956862747669,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[30.161,26.208],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"g-blue","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"mic","parent":3,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":11,"s":[0]},{"t":17,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"k":[{"s":[2.7,0.705,0],"t":0,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[3.041,0.705,0],"t":1,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[4.113,0.705,0],"t":2,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[6.088,0.705,0],"t":3,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[9.321,0.705,0],"t":4,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[14.611,0.705,0],"t":5,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[24.7,0.705,0],"t":6,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[36.233,0.705,0],"t":7,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[41.857,0.705,0],"t":8,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[45.206,0.705,0],"t":9,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[47.514,0.705,0],"t":10,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[49.235,0.705,0],"t":11,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[50.583,0.705,0],"t":12,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.671,0.705,0],"t":13,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.569,0.705,0],"t":14,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[53.323,0.705,0],"t":15,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[53.963,0.705,0],"t":16,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[54.511,0.705,0],"t":17,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[54.984,0.705,0],"t":18,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[55.393,0.705,0],"t":19,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[55.749,0.705,0],"t":20,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[56.058,0.705,0],"t":21,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[56.328,0.705,0],"t":22,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[56.563,0.705,0],"t":23,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[56.767,0.705,0],"t":24,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[56.944,0.705,0],"t":25,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.096,0.705,0],"t":26,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.227,0.705,0],"t":27,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.338,0.705,0],"t":28,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.431,0.705,0],"t":29,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.509,0.705,0],"t":30,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.571,0.705,0],"t":31,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.62,0.705,0],"t":32,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.656,0.705,0],"t":33,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.655,0.705,0],"t":129,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.48,0.705,0],"t":130,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[57.103,0.705,0],"t":131,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[56.503,0.705,0],"t":132,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[55.841,0.705,0],"t":133,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[55.262,0.705,0],"t":134,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[54.785,0.705,0],"t":135,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[54.39,0.705,0],"t":136,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[54.057,0.705,0],"t":137,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[53.772,0.705,0],"t":138,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[53.525,0.705,0],"t":139,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[53.309,0.705,0],"t":140,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[53.118,0.705,0],"t":141,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.949,0.705,0],"t":142,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.798,0.705,0],"t":143,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.663,0.705,0],"t":144,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.542,0.705,0],"t":145,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.433,0.705,0],"t":146,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.335,0.705,0],"t":147,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.248,0.705,0],"t":148,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.169,0.705,0],"t":149,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.098,0.705,0],"t":150,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[52.035,0.705,0],"t":151,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.979,0.705,0],"t":152,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.929,0.705,0],"t":153,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.886,0.705,0],"t":154,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.847,0.705,0],"t":155,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.814,0.705,0],"t":156,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.786,0.705,0],"t":157,"i":{"x":1,"y":1},"o":{"x":0,"y":0}},{"s":[51.742,0.705,0],"t":159,"i":{"x":1,"y":1},"o":{"x":0,"y":0}}],"l":2},"a":{"a":0,"k":[140.7,23.205,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-1.688,0],[0,0],[0.012,3.389],[0,0],[4.735,0],[1.554,1.554]],"o":[[1.113,1.113],[0,0],[3.377,0],[0,0],[0,4.723],[-2.361,0],[0,0]],"v":[[-5.573,0.049],[-1.242,1.848],[-1.242,1.848],[4.851,-4.282],[7.298,-4.282],[-1.242,4.282],[-7.298,1.774]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.917647063732,0.262745112181,0.207843139768,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[141.954,27.475],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"mic-red","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,2.361],[0,0],[0,0],[-1.101,-1.113],[0,0]],"o":[[0,0],[0,0],[0,1.688],[0,0],[-1.554,-1.554]],"v":[[-2.117,-3.028],[0.33,-3.028],[0.33,-3.028],[2.117,1.303],[0.392,3.028]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.976470589638,0.670588254929,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[134.264,26.233],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"mic-yellow","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[1.224,-1.884],[-1.224,-1.884],[-1.224,1.884],[1.224,1.884]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.203921571374,0.658823549747,0.32549020648,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[140.712,33.556],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"mic-green","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[2.031,0],[0,0],[0,2.031],[0,0],[-2.031,0],[0,-2.031]],"o":[[0,2.031],[0,0],[-2.031,0],[0,0],[0,-2.031],[2.031,0],[0,0]],"v":[[3.658,4.282],[0,7.953],[0,7.953],[-3.671,4.282],[-3.671,-4.282],[0,-7.953],[3.671,-4.282]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.258823543787,0.521568655968,0.956862747669,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[140.712,18.923],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"mic-blue","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey800","cl":"grey800","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":3,"s":[0]},{"t":12,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[83,22.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.8,0.8],"y":[0.15,1]},"o":{"x":[0.3,0.3],"y":[0,0]},"t":0,"s":[56,45]},{"i":{"x":[0.1,0.1],"y":[1,1]},"o":{"x":[0.05,0.05],"y":[0.7,0]},"t":6,"s":[100,45]},{"i":{"x":[0.833,0.833],"y":[1,1]},"o":{"x":[0.167,0.167],"y":[0,0]},"t":36,"s":[166,45]},{"i":{"x":[0,0],"y":[1,1]},"o":{"x":[0.2,0.2],"y":[0,0]},"t":128,"s":[166,45]},{"t":164,"s":[154,45]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":87,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.235294118524,0.250980407,0.262745112181,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Grey 800","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0}]},{"id":"comp_2","nm":"Flower","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".grey700","cl":"grey700","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[109.453,193.777,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[36.517,1.481],[-36.517,1.481]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":4,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[5.448,5.448],"ix":2},"p":{"a":0,"k":[-12.903,0.471],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"d":1,"ty":"el","s":{"a":0,"k":[5.448,5.448],"ix":2},"p":{"a":0,"k":[9.094,0.471],"ix":3},"nm":"Ellipse Path 2","mn":"ADBE Vector Shape - Ellipse","hd":false},{"d":1,"ty":"el","s":{"a":0,"k":[5.448,5.448],"ix":2},"p":{"a":0,"k":[2.554,0.471],"ix":3},"nm":"Ellipse Path 3","mn":"ADBE Vector Shape - Ellipse","hd":false},{"d":1,"ty":"el","s":{"a":0,"k":[6.588,6.588],"ix":2},"p":{"a":0,"k":[-8.927,-0.099],"ix":3},"nm":"Ellipse Path 4","mn":"ADBE Vector Shape - Ellipse","hd":false},{"d":1,"ty":"el","s":{"a":0,"k":[6.588,6.588],"ix":2},"p":{"a":0,"k":[5.118,-0.099],"ix":3},"nm":"Ellipse Path 5","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0.372549027205,0.388235300779,0.407843142748,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-0.5],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":7,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".black","cl":"black","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[64.952,63.598,0],"ix":2,"l":2},"a":{"a":0,"k":[24.952,23.598,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.753,0],[0,1.753],[1.753,0],[0,-1.753]],"o":[[1.753,0],[0,-1.753],[-1.753,0],[0,1.753]],"v":[[0,3.174],[3.174,0],[0,-3.174],[-3.174,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[21.137,19.31],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"flower 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.753,0],[0,1.753],[1.753,0],[0,-1.753]],"o":[[1.753,0],[0,-1.753],[-1.753,0],[0,1.753]],"v":[[0,3.174],[3.174,0],[0,-3.174],[-3.174,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[28.767,23.097],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"flower 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.753,0],[0,1.753],[1.753,0],[0,-1.753]],"o":[[1.753,0],[0,-1.753],[-1.753,0],[0,1.753]],"v":[[0,3.174],[3.174,0],[0,-3.174],[-3.174,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[21.75,27.886],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"flower 3","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".yellow400","cl":"yellow400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[63.114,63.125,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.392,1.281],[2.395,-2.283],[1.893,0.223],[0.557,-3.174],[1.726,-0.891],[-1.504,-2.896],[0.835,-1.671],[-2.951,-1.504],[-0.278,-1.782],[-3.341,0.446],[-1.392,-1.281],[-2.395,2.283],[-1.893,-0.278],[-0.557,3.174],[-1.726,0.891],[1.504,2.896],[-0.835,1.671],[2.951,1.504],[0.334,1.838],[3.341,-0.446]],"o":[[-2.45,-2.283],[-1.392,1.337],[-3.341,-0.501],[-0.334,1.838],[-2.951,1.504],[0.835,1.671],[-1.504,2.896],[1.671,0.835],[0.557,3.174],[1.949,-0.278],[2.45,2.283],[1.392,-1.281],[3.341,0.501],[0.334,-1.838],[2.951,-1.504],[-0.835,-1.671],[1.504,-2.896],[-1.726,-0.891],[-0.557,-3.174],[-1.949,0.278]],"v":[[4.316,-21.412],[-4.372,-21.412],[-9.551,-19.741],[-16.567,-14.841],[-19.797,-10.553],[-22.47,-2.59],[-22.47,2.701],[-19.797,10.664],[-16.623,14.897],[-9.606,19.797],[-4.372,21.412],[4.316,21.412],[9.551,19.797],[16.567,14.897],[19.797,10.609],[22.47,2.645],[22.47,-2.645],[19.797,-10.609],[16.567,-14.897],[9.551,-19.797]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.988235294819,0.78823530674,0.203921571374,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[97.335,135.554,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[10.748,5.402]],"o":[[0,0],[-0.891,-40.374],[0,0]],"v":[[16.706,59.315],[16.706,7.288],[-16.706,-59.315]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"▽ Right Flower","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[144.155,88.602,0],"ix":2,"l":2},"a":{"a":0,"k":[31.228,40.542,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".black","cl":"black","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[45.33,17.598,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-2.184,0],[0,2.184],[2.184,0],[0,-2.184]],"o":[[2.184,0],[0,-2.184],[-2.184,0],[0,2.184]],"v":[[0,3.954],[3.954,0],[0,-3.954],[-3.954,0]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".red400","cl":"red400","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[45.024,17.515,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.167,2.283],[4.678,-6.014],[2.283,-0.223],[-5.959,-4.733],[-0.167,-2.283],[-4.678,6.014],[-2.283,0.223],[5.959,4.733]],"o":[[-0.613,-7.574],[-1.448,1.782],[-7.629,0.668],[1.838,1.448],[0.613,7.574],[1.392,-1.838],[7.629,-0.668],[-1.838,-1.448]],"v":[[11.054,-9.829],[-3.87,-14.284],[-9.718,-11.11],[-14.228,3.926],[-11.054,9.829],[3.87,14.284],[9.718,11.11],[14.228,-3.926]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333337307,0.403921574354,0.360784322023,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".green400","cl":"green400","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[22.485,51.377,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[9.244,-14.2],[-4.678,11.138],[7.407,2.729]],"o":[[7.741,4.121],[1.002,-2.951],[-5.457,-1.448]],"v":[[-14.689,4.256],[14.269,2.642],[7.586,-8.663]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":".green400","cl":"green400","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[16.651,52.32,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-10.414,5.68]],"o":[[1.726,-32.355],[0,0]],"v":[[-16.651,28.763],[16.651,-28.763]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[85.004,158.386,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-17.306]],"o":[[34.304,21.05],[0,0]],"v":[[-23.31,-36.483],[23.31,36.483]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[55.116,132.289,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.847,-0.501],[1.281,-3.62],[-0.78,-2.172],[-3.341,-0.891],[-3.898,2.951],[-2.339,4.01],[1.114,0.501]],"o":[[-4.177,0.39],[-0.668,1.893],[1.169,3.341],[4.733,0.668],[3.731,-2.84],[-1.114,-0.501],[-5.29,-2.228]],"v":[[-5.506,-9.773],[-14.416,-3.09],[-14.361,3.147],[-7.065,9.607],[5.91,6.655],[14.931,-4.315],[11.59,-5.819]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[65.652,111.9,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[5.179,3.007],[0.724,0.167],[2.228,-1.392],[-0.446,-4.622],[-4.288,-3.341],[0,-0.056],[-0.724,4.901]],"o":[[-0.668,-0.39],[-2.562,-0.613],[-4.065,2.617],[0.557,5.513],[0.501,0.39],[2.172,-4.511],[0.78,-5.235]],"v":[[4.896,-14.778],[2.836,-15.613],[-4.849,-14.221],[-9.917,-1.97],[-1.731,11.284],[5.23,15.851],[9.685,1.483]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[133.059,138.554,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[3.731,-15.203]],"o":[[-27.844,11.695],[0,0]],"v":[[19.018,-18.878],[-19.018,18.878]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[164.078,125.618,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-6.404,-1.726],[-2.673,2.45],[-0.334,2.005],[0.446,1.392],[4.455,0.613],[1.671,-0.835],[0.223,-0.446],[-0.39,-0.501]],"o":[[3.397,0.891],[1.281,-1.169],[0.278,-1.448],[-1.392,-4.511],[-3.564,-0.501],[-0.446,0.223],[-0.223,0.501],[3.787,5.235]],"v":[[1.642,9.094],[11.777,7.256],[14.339,2.467],[14.061,-1.876],[4.705,-9.506],[-12.057,-5.942],[-14.452,-4.661],[-13.505,-2.879]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.35686275363,0.72549021244,0.454901963472,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":3.824,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0}]},{"id":"comp_3","nm":"Action Key","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"action icon","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[67.56,56.18,0],"ix":2,"l":2},"a":{"a":0,"k":[67.56,56.18,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,3.379],[3.379,0],[0,-3.379],[-3.379,0]],"o":[[0,-3.379],[-3.379,0],[0,3.379],[3.379,0]],"v":[[6.144,0],[0,-6.144],[-6.144,0],[0,6.144]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,6.789],[-6.789,0],[0,-6.789],[6.789,0]],"o":[[0,-6.789],[6.789,0],[0,6.789],[-6.789,0]],"v":[[-12.288,0],[0,-12.288],[12.288,0],[0,12.288]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"tr","p":{"a":0,"k":[-3.185,-3.229],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Vector","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-1.101,1.239],[-1.26,-1.207],[0,0],[1.215,-1.215],[1.205,1.15],[0,0]],"o":[[1.159,-1.304],[0,0],[1.241,1.189],[-1.177,1.177],[0,0],[-1.199,-1.144]],"v":[[1.548,2.22],[5.978,2.043],[14.529,10.239],[14.575,14.619],[10.291,14.669],[1.723,6.491]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100.469,100.469],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Union","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[84.621,73.217],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"mag","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24.577,24.577],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 2","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[81.029,35.842],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"top R","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24.577,24.577],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 3","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[47.241,69.628],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"bottom L","np":1,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[24.577,24.577],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[47.241,35.841],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"top L","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.603921592236,0.627451002598,0.65098041296,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Action (not dynamic)","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[53.25,53.25,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[106.5,106.5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":32,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Action (not dynamic)","np":1,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1200,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"matte","td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[174,109,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[348,218],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":16,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":431,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Omni_EDU_05","tt":1,"tp":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[174,109,0],"ix":2,"l":2},"a":{"a":0,"k":[174,109,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":348,"h":218,"ip":0,"op":431,"st":0,"ct":1,"bm":0}],"markers":[],"props":{}}
\ No newline at end of file
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index c0ffdbb..e1f52e7 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Speld vas"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Vormvry"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Geen onlangse items nie"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programgebruikinstellings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Vee alles uit"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Doen meer met die Taakbalk"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Wys altyd die Taakbalk"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Raak en hou die verdeler in om altyd die Taakbalk onderaan jou skerm te wys"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Raak en hou die aksiesleutel om te soek wat op jou skerm is"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Hierdie produk gebruik die deel van jou skerm wat gekies is om te soek. Google se <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>privaatheidsbeleid<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> en <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>diensbepalings<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> geld."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Maak toe"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Klaar"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Tuis"</string>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 1942a74..959d06c 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ሰካ"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ነፃ ቅጽ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ምንም የቅርብ ጊዜ ንጥሎች የሉም"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"የመተግበሪያ አጠቃቀም ቅንብሮች"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ሁሉንም አጽዳ"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"በተግባር አሞሌው ተጨማሪ ነገር ያድርጉ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"የተግባር አሞሌውን ሁልጊዜ አሳይ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"በማያ ገጽዎ ግርጌ ላይ ያለውን የተግባር አሞሌ ሁልጊዜ ለማሳየት፣ መክፈያን ይንኩ እና ይያዙ"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"በማያ ገጽዎ ላይ ያለውን ነገር ለመፈለግ የተግባር ቁልፉን ነክተው ይያዙ"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"ይህ ምርት የተመረጠውን የማያ ገጽዎን ክፍል ለመፈለግ ይጠቀማል። የGoogle <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>የግላዊነት መመሪያ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> እና <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>የአገልግሎት ውል<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ተፈጻሚ ናቸው።"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ዝጋ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ተጠናቅቋል"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"መነሻ"</string>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index fa41370..2eaea0c 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"تثبيت"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"شكل مجاني"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ما مِن عناصر تم استخدامها مؤخرًا"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"إعدادات استخدام التطبيق"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"محو الكل"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"إنجاز المزيد باستخدام شريط التطبيقات"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"عرض \"شريط التطبيقات\" دائمًا"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"انقر مع الاستمرار على أداة تقسيم الشاشة لعرض \"شريط التطبيقات\" دائمًا في أسفل الشاشة."</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"انقر مع الاستمرار على مفتاح الإجراء للبحث عن المحتوى الذي يظهر على شاشتك"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"‏يستخدم هذا المنتج الجزء المحدّد من الشاشة للبحث. تسري <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>سياسة خصوصية<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> Google و<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>بنود خدمتها<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"إغلاق"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"تم"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"الرئيسية"</string>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index 51068d9..72482ff 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"পিন"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"কোনো শেহতীয়া বস্তু নাই"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"এপে ব্যৱহাৰ কৰা ডেটাৰ ছেটিং"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"আটাইবোৰ মচক"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"টাস্কবাৰৰ জৰিয়তে অধিক কাৰ্য সম্পাদন কৰক"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"টাস্কবাৰডাল সদায় দেখুৱাওক"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"আপোনাৰ স্ক্ৰীনৰ তলত সদায় টাস্কবাৰডাল দেখুৱাবলৈ বিভাজকডাল স্পৰ্শ কৰি ধৰি ৰাখক"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"আপোনাৰ স্ক্ৰীনখনত থকা সমল সন্ধান কৰিবলৈ কাৰ্য কীটো স্পৰ্শ কৰি ধৰি ৰাখক"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"এই প্ৰ’ডাক্টটোৱে সন্ধান কৰিবলৈ আপোনাৰ স্ক্ৰীনখনৰ বাছনি কৰা অংশ ব্যৱহাৰ কৰে। Googleৰ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>গোপনীয়তাৰ নীতি<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> আৰু <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>সেৱাৰ চৰ্তাৱলী<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> প্ৰযোজ্য।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ কৰক"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"হ’ল"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"গৃহপৃষ্ঠা"</string>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index 4b52f0b..68fcb3c 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Sancın"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Sərbəst rejim"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Son elementlər yoxdur"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tətbiq istifadə ayarları"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hamısını silin"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Tapşırıq paneli ilə daha çox şey edin"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"İşləmə panelini həmişə göstərin"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"İşləmə panelini həmişə ekranın aşağısında göstərmək üçün ayırıcı üzərinə toxunun və saxlayın"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Ekranda axtarış etmək üçün fəaliyyət açarına toxunub saxlayın"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Bu məhsul axtarış üçün ekranın seçilmiş hissəsindən istifadə edir. Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Məxfilik Siyasəti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> və <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Xidmət Şərtləri<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> tətbiq edilir."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Bağlayın"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hazırdır"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ev"</string>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 89e27c8..6fb8f01 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Podešavanja korišćenja aplikacije"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Uvek prikazuj traku zadataka"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Da bi traka zadataka uvek bila prikazana u dnu ekrana, dodirnite i zadržite razdelnik"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Dodirnite i zadržite taster radnji da biste pretražili ono što je na ekranu"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Ovaj proizvod koristi izabrani deo ekrana za pretragu. Primenjuju se Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>politika privatnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>uslovi korišćenja usluge<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 8d874fd..344a3e6 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Замацаваць"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Адвольная форма"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Няма новых элементаў"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налады выкарыстання праграмы"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ачысціць усё"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Выкарыстоўвайце магчымасці панэлі задач"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Замацуйце панэль задач унізе экрана"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Для гэтага націсніце на раздзяляльнік і ўтрымлівайце яго"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрыць"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Гатова"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Галоўны экран"</string>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index bd677da..6ae8931 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Фиксиране"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Свободна форма"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Няма скорошни елементи"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки за използването на приложенията"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Изчистване на всички"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Правете повече неща с лентата на задачите"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Лентата на задачите да се показва винаги"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"За да фиксирате лентата на задачите най-долу на екрана, докоснете и задръжте разделителя"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затваряне"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Начало"</string>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 7ffbb64..dec05ff 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"পিন করুন"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ফ্রি-ফর্ম"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"কোনও সাম্প্রতিক আইটেম নেই"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"অ্যাপ ব্যবহারের সেটিংস"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"সবকিছু খালি করুন"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"\'টাস্কবার\' ফিচারের সাহায্যে আরও অনেক কিছু করুন"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"টাস্কবার সবসময় দেখানো"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"স্ক্রিনের নিচে টাস্কবার সবসময় দেখাতে ডিভাইডার টাচ করে ধরে থাকুন"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"বন্ধ করুন"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"হয়ে গেছে"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"হোম"</string>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index ccf6c36..83e4935 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Zakači"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodan oblik"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke korištenja aplikacije"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Obriši sve"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Uradite više pomoću trake zadataka"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Stalni prikaz trake zadataka"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Da se traka zadataka uvijek prikazuje na dnu ekrana, dodirnite i zadržite razdjelnik"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Dodirnite i zadržite tipku za radnju da biste pretražili što se nalazi na zaslonu"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Ovaj proizvod upotrebljava odabrani dio zaslona za pretraživanje. Primjenjuju se Googleova <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravila o privatnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>uvjeti pružanja usluge<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Dom"</string>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 5d6e0d8..d4c7d91 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixa"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Format lliure"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No hi ha cap element recent"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuració d\'ús d\'aplicacions"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Esborra-ho tot"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Treu més partit de la Barra de tasques"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostra sempre la Barra de tasques"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Perquè es mostri sempre la Barra de tasques a la part inferior de la pantalla, mantén premut el separador"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tanca"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Fet"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inici"</string>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 9c1dedf..743fc2b 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Připnout"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Neomezený režim"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Žádné položky z nedávné doby"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavení využití aplikací"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Vymazat vše"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Více možností s panelem aplikací"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Stálé zobrazení panelu aplikací"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pokud chcete, aby se panel aplikací vždy zobrazoval ve spodní části obrazovky, podržte oddělovač."</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zavřít"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Domů"</string>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index 623a0b7..cfe55cf 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fastgør"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Frit format"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Ingen nye elementer"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Indstillinger for appforbrug"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ryd alt"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Få mere fra hånden med proceslinjen"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vis altid proceslinjen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Hvis du vil have, at proceslinjen altid vises nederst på din skærm, skal du holde fingeren på skillelinjen"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Luk"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Luk"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Hjem"</string>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index c4371ee..1d012bb 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixieren"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform-Modus"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Keine kürzlich verwendeten Elemente"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Einstellungen zur App-Nutzung"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Alle Apps schließen"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Mehr Möglichkeiten mit der Taskleiste"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Taskleiste immer anzeigen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Damit die Taskleiste immer unten angezeigt wird, halte den Teiler gedrückt"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Schließen"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Fertig"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Startbildschirm"</string>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 69f1718..ae3bef8 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Καρφίτσωμα"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Ελεύθερη μορφή"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Δεν υπάρχουν πρόσφατα στοιχεία"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ρυθμίσεις χρήσης εφαρμογής"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Διαγραφή όλων"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Κάντε περισσότερα με τη Γραμμή εργαλείων"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Να εμφανίζεται πάντα η Γραμμή εργαλείων"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Για να εμφανίζεται πάντα η Γραμμή εργαλείων στο κάτω μέρος της οθόνης, αγγίξτε παρατεταμένα το διαχωριστικό"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Κλείσιμο"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Τέλος"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Αρχική σελίδα"</string>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index aa119ed..fea224b 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch and hold the divider"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 8da2f2d..37f4bce 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch &amp; hold the divider"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Touch &amp; hold the action key to search what\'s on your screen"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"This product uses the selected part of your screen to search. Google\'s <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Privacy Policy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> and <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Terms of Service<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> apply."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index aa119ed..fea224b 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch and hold the divider"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index aa119ed..fea224b 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Pin"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No recent items"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"App usage settings"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Clear all"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Do more with the Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Always show the Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"To always show the Taskbar on the bottom of your screen, touch and hold the divider"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Close"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Done"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 42223fe..c64c495 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎Pin‎‏‎‎‏‎"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‏‎Freeform‎‏‎‎‏‎"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎No recent items‎‏‎‎‏‎"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎App usage settings‎‏‎‎‏‎"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‏‎Clear all‎‏‎‎‏‎"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎Do more with the Taskbar‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎Always show the Taskbar‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‏‎‏‏‏‎‎‎‏‏‎To always show the Taskbar on the bottom of your screen, touch &amp; hold the divider‎‏‎‎‏‎"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‎Touch &amp; hold the action key to search what\'s on your screen‎‏‎‎‏‎"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎This product uses the selected part of your screen to search. Google\'s ‎‏‎‎‏‏‎<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>‎‏‎‎‏‏‏‎Privacy Policy‎‏‎‎‏‏‎<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>‎‏‎‎‏‏‏‎Terms of Service‎‏‎‎‏‏‎<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>‎‏‎‎‏‏‏‎ apply.‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‎‏‎Close‎‏‎‎‏‎"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎Done‎‏‎‎‏‎"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎Home‎‏‎‎‏‎"</string>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index 5d5c2c1..244c23f 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No hay elementos recientes"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración de uso de la app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Cerrar todo"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Aprovecha mejor la Barra de tareas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar siempre la Barra de tareas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Mantén presionado el divisor para mostrar siempre la Barra de tareas en la parte inferior de la pantalla"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Botón de inicio"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 79964d8..1bab3ac 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fijar"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Formato libre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"No hay nada reciente"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ajustes de uso de la aplicación"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Sácale más partido a la barra de tareas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar siempre la barra de tareas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para mostrar siempre la barra de tareas en la parte inferior, mantén pulsada la línea divisoria"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hecho"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 65f02eb..0a587d1 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Kinnita"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Vabavorm"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Hiljutisi üksusi pole"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Rakenduse kasutuse seaded"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Sule kõik"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Tehke tegumiriba abil enamat"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Alati kuvatud tegumiriba"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Puudutage pikalt jaoturit, et tegumiriba oleks ekraani allosas alati kuvatud"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sule"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Valmis"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Avaleht"</string>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index 6859498..e10a085 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Ainguratu"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Modu librea"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Ez dago azkenaldi honetako ezer"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Aplikazioen erabileraren ezarpenak"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Garbitu guztiak"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Egin gauza gehiago zereginen barrarekin"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Erakutsi beti zereginen barra"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pantailaren behealdeko zereginen barra beti erakusteko, eduki sakatuta zatitzailea"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Itxi"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Eginda"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Hasiera"</string>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index e8d0a00..958eecc 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"پین"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"چیز جدیدی اینجا نیست"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"تنظیمات استفاده از برنامه"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"پاک کردن همه"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"با «نوار وظیفه» می‌توانید کارهای بیشتر انجام دهید"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"همیشه نشان داده شدن «نوار وظیفه»"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"برای اینکه «نوار وظیفه» همیشه در پایین صفحه نشان داده شود، تقسیم‌کننده را لمس کنید و نگه دارید"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"برای جستجوی محتوای صفحه‌نمایش، دکمه کنش را لمس کنید و نگه دارید"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"‏این محصول از قسمت انتخاب‌شده صفحه‌نمایش شما برای جستجو استفاده می‌کند. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>خط‌مشی رازداری<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> و <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>شرایط خدمات<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google اعمال می‌شود."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"بستن"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"تمام"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"صفحه اصلی"</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index ca44b7a..d4a0d83 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Kiinnitä"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Vapaamuotoinen"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Ei viimeaikaisia kohteita"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Sovelluksen käyttöasetukset"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Poista kaikki"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Vinkkejä tehtäväpalkin tehokkaampaan käyttöön"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Näytä tehtäväpalkki aina"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Jos haluat tehtäväpalkin näkyvän aina näytön alaosassa, kosketa jakajaa pitkään"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sulje"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Valmis"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Etusivu"</string>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 6173bee..444bb83 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Épingler"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Forme libre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Aucun élément récent"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres d\'utilisation de l\'application"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Toujours afficher la Barre des tâches"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pour toujours afficher la Barre des tâches en bas de l\'écran, maintenez le doigt sur le séparateur"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"OK"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Accueil"</string>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 03714c4..0d70416 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Épingler"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Format libre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Aucun élément récent"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Paramètres de consommation de l\'application"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Tout effacer"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Faites-en plus avec la barre des tâches"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Toujours afficher la barre des tâches"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pour toujours afficher la barre des tâches en bas de votre écran, appuyez sur le séparateur de manière prolongée."</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fermer"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"OK"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Accueil"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index a336205..eadd73d 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Forma libre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Non hai elementos recentes"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configuración do uso de aplicacións"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Borrar todo"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Tira máis proveito da barra de tarefas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar sempre a barra de tarefas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para fixar a barra de tarefas na parte inferior, mantén premida a liña divisoria"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Pechar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Listo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 0e6f237..644240a 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"પિન કરો"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ફ્રિફોર્મ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"તાજેતરની કોઈ આઇટમ નથી"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ઍપ વપરાશનું સેટિંગ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"બધું સાફ કરો"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ટાસ્કબાર વડે બીજું ઘણું કરો"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ટાસ્કબાર હંમેશાં બતાવો"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ટાસ્કબાર હંમેશાં તમારી સ્ક્રીનમાં સૌથી નીચે દેખાય તે માટે વિભાજકને ટચ કરીને થોડીવાર દબાવી રાખો"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"તમારી સ્ક્રીન પર જે હોય તે શોધવા માટે, ઍક્શન કી ટચ કરીને દબાવી રાખો"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"શોધવા માટે, આ પ્રોડક્ટ તમારી સ્ક્રીનના પસંદ કરેલા ભાગનો ઉપયોગ કરે છે. Googleની <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>પ્રાઇવસી પૉલિસી<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> અને <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>સેવાની શરતો<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> લાગુ થાય છે."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"બંધ કરો"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"થઈ ગયું"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"હોમ"</string>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index e0a93f8..b2da5db 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करें"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"फ़्रीफ़ॉर्म"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"हाल ही का कोई आइटम नहीं है"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ऐप्लिकेशन इस्तेमाल की सेटिंग"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"सभी हटाएं"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार के साथ कई और काम करें"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"टास्कबार को हमेशा दिखाएं"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"टास्कबार को हमेशा अपनी स्क्रीन के नीचे दिखाने के लिए, डिवाइडर दबाकर रखें"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"स्क्रीन में दिख रहे कॉन्टेंट को खोजने के लिए, ऐक्शन बटन को दबाकर रखें"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"यह प्रॉडक्ट, कॉन्टेंट खोजने के लिए स्क्रीन पर चुनिंदा हिस्से का इस्तेमाल करता है. Google की <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>निजता नीति<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> और <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>सेवा की शर्तें<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> लागू होती हैं."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बंद करें"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"हो गया"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 34030dd..b68d961 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Prikvači"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Slobodni oblik"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nema nedavnih stavki"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Postavke upotrebe aplikacija"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Izbriši sve"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Učinite više pomoću trake sa zadacima"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Uvijek prikazuj traku sa zadacima"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Da bi se traka prikazivala, dodirnite i držite razdjelnik"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Dodirnite i zadržite tipku za radnju da biste pretražili što se nalazi na zaslonu"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Ovaj proizvod upotrebljava odabrani dio zaslona za pretraživanje. Primjenjuju se Googleova <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravila o privatnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>uvjeti pružanja usluge<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zatvori"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Početna"</string>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index a61da68..e69bc53 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Kitűzés"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Szabad forma"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nincsenek mostanában használt elemek"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Alkalmazáshasználati beállítások"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Összes törlése"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Jobban kihasználhatja a Feladatsávot"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mindig jelenjen meg a Feladatsáv"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ahhoz, hogy a Feladatsáv mindig megjelenjen a képernyő alján, érintse meg és tartsa lenyomva az elválasztót"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Bezárás"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Kész"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Kezdőlap"</string>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index e9af69c..1889a4e 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Ամրացնել"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Կամայական ձև"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Այստեղ դեռ ոչինչ չկա"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Հավելվածի օգտագործման կարգավորումներ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Փակել բոլորը"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Օգտվեք հավելվածների վահանակի բոլոր հնարավորություններից"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Ամրացրեք հավելվածների վահանակը"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Հավելվածների վահանակն էկրանի ներքևում ամրացնելու համար հպեք և պահեք բաժանիչը"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Փակել"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Պատրաստ է"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Սկիզբ"</string>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 64a8235..eec7e10 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Sematkan"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Format bebas"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Tidak ada item yang baru dibuka"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setelan penggunaan aplikasi"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hapus semua"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan lebih banyak hal dengan Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Selalu tampilkan Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Untuk selalu menampilkan Taskbar di bagian bawah layar Anda, sentuh &amp; tahan pembatasnya"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Sentuh &amp; tahan tombol tindakan untuk mencari konten di layar Anda"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Produk ini menggunakan bagian layar terpilih untuk menelusuri. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Kebijakan Privasi<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> dan <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Persyaratan Layanan<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google berlaku."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Selesai"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Layar utama"</string>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 47cf293..e023124 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Festa"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Frjálst snið"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Engin nýleg atriði"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Notkunarstillingar forrits"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hreinsa allt"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Nýttu forritastikuna betur"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Halda forritastikunni sýnilegri"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Haltu skjáskiptingunni neðst á skjánum inni til að halda forritastikunni sýnilegri"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Haltu aðgerðalyklinum inni til að leita að því sem er á skjánum"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Þessi vara notar valinn hluta skjásins til að leita. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Persónuverndarstefna<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> og <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>þjónustuskilmálar<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google gilda."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Loka"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Lokið"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Heim"</string>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index fc07b94..aeeb6a2 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Blocca su schermo"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Forma libera"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nessun elemento recente"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Impostazioni di utilizzo delle app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Cancella tutto"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Fai di più con la barra delle app"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostra sempre la barra delle app"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Per mostrare sempre la barra delle app in basso, tocca e tieni premuto il divisore"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Chiudi"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Fine"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index 0fbb4c7..3899f67 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"הצמדה"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"מצב חופשי"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"אין פריטים אחרונים"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"הגדרות שימוש באפליקציה"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ניקוי הכול"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"פעולות נוספות שאפשר לעשות עם סרגל האפליקציות"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"תמיד להציג את סרגל האפליקציות"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"כדי להציג תמיד את סרגל האפליקציות בתחתית המסך, יש ללחוץ לחיצה ארוכה על המחיצה"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"סגירה"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"סיום"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"בית"</string>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index 1d82852..8125ea4 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"フリーフォーム"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"最近のアイテムはありません"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"アプリの使用状況の設定"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"すべてクリア"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"タスクバーの各種機能"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"タスクバーを常に表示"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"タスクバーを画面下部に常に表示するには分割線を長押しします"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"閉じる"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完了"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ホーム"</string>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index f682e8d..14c0773 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ჩამაგრება"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"თავისუფალი ფორმა"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ბოლოს გამოყენებული ერთეულები არ არის"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"აპების გამოყენების პარამეტრები"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ყველას გასუფთავება"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"გააკეთეთ მეტი ამოცანათა ზოლის მეშვეობით"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ამოცანათა ზოლის მუდმივად ჩვენება"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"თქვენი ეკრანის ქვედა ნაწილში ამოცანათა ზოლის მუდმივად საჩვენებლად, ხანგრძლივად შეეხეთ გამყოფს"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"დახურვა"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"მზადაა"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"მთავარი"</string>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 8cdf151..9964105 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Бекіту"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Еркін форма"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Соңғы элементтер жоқ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Қолданбаны пайдалану параметрлері"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Барлығын өшіру"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапсырмалар жолағында мүмкіндік көп"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Тапсырмалар жолағын әрдайым көрсету"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Экранның төменгі жағында тапсырмалар жолағы әрдайым көрсетілуі үшін, бөлгішті басып тұрыңыз."</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Жабу"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Дайын"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Негізгі экран"</string>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index c599ccf..3b7180c 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ខ្ទាស់"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"មុខងារទម្រង់សេរី"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"មិនមានធាតុថ្មីៗទេ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ការកំណត់​ការប្រើប្រាស់​កម្មវិធី"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"សម្អាត​ទាំងអស់"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ធ្វើបានកាន់តែច្រើនដោយប្រើរបារកិច្ចការ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"បង្ហាញរបារកិច្ចការជានិច្ច"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ដើម្បីបង្ហាញរបារកិច្ចការនៅផ្នែកខាងក្រោមនៃអេក្រង់របស់អ្នកជានិច្ច សូមចុចបន្ទាត់ខណ្ឌចែកឱ្យជាប់"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"ចុចគ្រាប់ចុចសកម្មភាពឱ្យជាប់ ដើម្បីស្វែងរកអ្វីដែលមាននៅលើអេក្រង់របស់អ្នក"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"ផលិតផលនេះប្រើប្រាស់ផ្នែកដែលបានជ្រើសរើសនៃអេក្រង់របស់អ្នក ដើម្បីស្វែងរក។ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>គោលការណ៍​ឯកជនភាព<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> និង<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>លក្ខខណ្ឌ​ប្រើប្រាស់<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>របស់ Google ត្រូវបានអនុវត្ត។"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"បិទ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"រួចរាល់"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ទំព័រដើម"</string>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 6dd4d52..688098c 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ಪಿನ್ ಮಾಡಿ"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ಮುಕ್ತಸ್ವರೂಪ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ಆ್ಯಪ್‌ ಬಳಕೆಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ಟಾಸ್ಕ್‌ಬಾರ್ ಮೂಲಕ ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ಯಾವಾಗಲೂ ಟಾಸ್ಕ್‌ಬಾರ್ ಅನ್ನು ತೋರಿಸಿ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ಯಾವಾಗಲೂ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದಲ್ಲಿ ಟಾಸ್ಕ್ ಬಾರ್ ಅನ್ನು ತೋರಿಸಲು, ಡಿವೈಡರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಿ"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"ಮುಚ್ಚಿರಿ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ಆಯಿತು"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ಮುಖಪುಟ"</string>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 9a885c1..b8a131a 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"고정"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"자유 형식"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"최근 항목이 없습니다."</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"앱 사용 설정"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"모두 삭제"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"태스크 바 최대한 활용하기"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"태스크 바 항상 표시"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"화면 하단에 태스크 바를 항상 표시하려면 구분선을 길게 터치하세요."</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"닫기"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"완료"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"홈"</string>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index ee0aaa3..061952c 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Кадап коюу"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Эркин форма режими"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Акыркы колдонмолор жок"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Колдонмону пайдалануу параметрлери"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Баарын тазалоо"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Тапшырмалар тактасы менен көбүрөөк иш бүтүрөсүз"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Тапшырмалар панелин ар дайым көрсөтүү"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Тапшырмалар панелин экрандын ылдый жагында ар дайым көрсөтүү үчүн бөлгүчтү коё бербей басыңыз"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Экрандагы нерсени издөө үчүн аракет баскычын коё бербей кармап туруңуз"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Бул кызмат издөө үчүн экранда тандалган бөлүктү колдонот. Google\'дун <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Купуялык эрежелери<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> жана <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Тейлөө шарттары<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> колдонулат."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Жабуу"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Бүттү"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Башкы бет"</string>
diff --git a/quickstep/res/values-land/dimens.xml b/quickstep/res/values-land/dimens.xml
index 2b17b93..e862b9e 100644
--- a/quickstep/res/values-land/dimens.xml
+++ b/quickstep/res/values-land/dimens.xml
@@ -78,7 +78,8 @@
     <!--  Taskbar 3 button spacing  -->
     <dimen name="taskbar_button_margin_split">88dp</dimen>
     <dimen name="taskbar_button_margin_6_5">219.6dp</dimen>
-    <dimen name="taskbar_contextual_button_margin">48dp</dimen>
+    <dimen name="taskbar_contextual_button_suw_margin">48dp</dimen>
+    <dimen name="taskbar_contextual_button_suw_height">48dp</dimen>
     <dimen name="taskbar_suw_frame">96dp</dimen>
     <dimen name="taskbar_suw_insets">24dp</dimen>
 
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 0940368..211e9ed 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ປັກໝຸດ"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ຮູບແບບອິດສະຫລະ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ບໍ່ມີລາຍການຫຼ້າສຸດ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ການຕັ້ງຄ່າການນຳໃຊ້ແອັບ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ລຶບລ້າງທັງໝົດ"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ເຮັດສິ່ງຕ່າງໆໄດ້ຫຼາຍຂຶ້ນດ້ວຍແຖບໜ້າວຽກ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ສະແດງແຖບໜ້າວຽກສະເໝີ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ເພື່ອໃຫ້ແຖບໜ້າວຽກສະແດງຢູ່ລຸ່ມໜ້າຈໍຂອງທ່ານຢູ່ສະເໝີ, ໃຫ້ແຕະຕົວແບ່ງຄ້າງໄວ້"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"ແຕະປຸ່ມຄຳສັ່ງຄ້າງໄວ້ເພື່ອຊອກຫາສິ່ງທີ່ຢູ່ເທິງໜ້າຈໍຂອງທ່ານ"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"ສິນຄ້ານີ້ໃຊ້ສ່ວນທີ່ເລືອກຂອງໜ້າຈໍຂອງທ່ານເພື່ອຊອກຫາ. ເປັນໄປຕາມ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ນະໂຍບາຍຄວາມເປັນສ່ວນຕົວ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ແລະ <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ຂໍ້ກຳນົດບໍລິການ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ຂອງ Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ປິດ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ແລ້ວໆ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ໜ້າຫຼັກ"</string>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index 8a276da..e2f1af9 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Prisegti"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Laisva forma"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nėra jokių naujausių elementų"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Programos naudojimo nustatymai"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Išvalyti viską"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Atlikite daugiau naudodami Užduočių juostą"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Visada rodyti užduočių juostą"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Jei norite, kad užduočių juosta visada būtų rodoma ekrano apačioje, palieskite ir palaikykite daliklį"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Uždaryti"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Atlikta"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Pagrindinis"</string>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index cb211c0..6881a09 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Piespraust"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Brīva forma"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nav nesenu vienumu."</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Lietotņu izmantošanas iestatījumi"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Notīrīt visu"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Plašākas iespējas, izmantojot uzdevumu joslu"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vienmēr rādīt uzdevumu joslu"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Lai uzdevumu joslu rādītu apakšdaļā, pieskarieties atdalītājam un turiet"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Aizvērt"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gatavs"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Sākums"</string>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index bf2c798..6408a4d 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Закачи"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Нема неодамнешни ставки"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Поставки за користење на апликациите"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Избриши ги сите"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Правете сешто со „Лентата со задачи“"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Како секогаш да се прикажува „Лентата со задачи“"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Допрете и задржете го разделникот за да може „Лентата со задачи“ секогаш да се прикажува на дното на екранот"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Дома"</string>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index be61137..17380a0 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"പിൻ ചെയ്യുക"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ഫ്രീഫോം"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ആപ്പ് ഉപയോഗ ക്രമീകരണം"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"എല്ലാം മായ്‌ക്കുക"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ടാസ്‌ക്‌ബാർ ഉപയോഗിച്ച് കൂടുതൽ ചെയ്യുക"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"എല്ലായ്‌പ്പോഴും ടാസ്‌ക്‌ബാർ കാണിക്കുക"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ടാസ്‌ക്ബാർ എല്ലായ്‌പ്പോഴും നിങ്ങളുടെ സ്‌ക്രീനിന്റെ ചുവടെ കാണിക്കുന്നതിന് ഡിവൈഡറിൽ സ്‌പർശിച്ച് പിടിക്കുക"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"നിങ്ങളുടെ സ്‌ക്രീനിൽ എന്താണ് ഉള്ളതെന്ന് തിരയാൻ ആക്ഷൻ കീ സ്‌പർശിച്ച് പിടിക്കുക"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"തിരയുന്നതിന് ഈ ഉൽപ്പന്നം സ്‌ക്രീനിലെ തിരഞ്ഞെടുത്ത ഭാഗം ഉപയോഗിക്കുന്നു. Google-ന്റെ <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>സ്വകാര്യതാ നയവും<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>സേവന നിബന്ധനകളും<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ബാധകമാണ്."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"അടയ്ക്കുക"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"പൂർത്തിയായി"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ഹോം"</string>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index d4f7537..bc6a43b 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Бэхлэх"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Чөлөөтэй хувьсах"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Сүүлийн үеийн зүйл алга"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Апп ашиглалтын тохиргоо"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Бүгдийг арилгах"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Ажлын хэсгийн тусламжтай илүү ихийг хийгээрэй"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Ажлын хэсгийг үргэлж харуулах"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Дэлгэцийнхээ доод талд Ажлын хэсгийг үргэлж харуулахын тулд хуваагч дээр хүрээд удаан дарна уу"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Хаах"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Дууссан"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Гэр"</string>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index c8f147a..b0c6aca 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन करा"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"फ्रीफॉर्म"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"कोणतेही अलीकडील आयटम नाहीत"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"अ‍ॅप वापर सेटिंग्ज"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"सर्व साफ करा"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार चा पुरेपूर वापर करा"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"टास्कबार नेहमी दाखवा"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"टास्कबार नेहमी तुमच्या स्क्रीनच्या तळाशी दाखवण्यासाठी, विभाजकाला स्पर्श करून धरून ठेवा"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"बंद करा"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"पूर्ण झाले"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 575ce64..87c6e24 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Semat"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Bentuk bebas"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Tiada item terbaharu"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Tetapan penggunaan apl"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Kosongkan semua"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Lakukan lebih banyak perkara dengan Bar Tugas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Sentiasa paparkan Bar Tugas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Untuk sentiasa memaparkan Bar Tugas pada bahagian bawah skrin, sentuh &amp; tahan pembahagi"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Sentuh &amp; tahan kekunci tindakan untuk mencari kandungan yang dipaparkan pada skrin anda"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Produk ini menggunakan bahagian yang dipilih pada skrin untuk membuat carian. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Dasar Privasi<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> dan <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Syarat Perkhidmatan<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google digunakan."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Tutup"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Selesai"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Laman Utama"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 06ed2c5..d7c98d3 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ပင်ထိုးရန်"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"အလွတ်ပုံစံ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"မကြာမီကဖွင့်ထားသည်များ မရှိပါ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"အက်ပ်အသုံးပြုမှု ဆက်တင်များ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"အားလုံးရှင်းရန်"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Taskbar ဖြင့် ပိုမိုလုပ်ဆောင်နိုင်ခြင်း"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Taskbar ကို အမြဲပြပါ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Taskbar ကို စခရင်အောက်ခြေတွင် အမြဲပြရန် ခွဲခြားမျဉ်းကို တို့ထိ၍ ဖိထားပါ"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"ပိတ်ရန်"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ပြီးပြီ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ပင်မစာမျက်နှာ"</string>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 2383000..550bacc 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fest"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Ingen nylige elementer"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Innstillinger for appbruk"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Fjern alt"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Gjør mer med oppgavelinjen"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vis alltid oppgavelinjen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"For å alltid vise oppgavelinjen nederst på skjermen, trykk og hold på skillelinjen"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Lukk"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Ferdig"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Hjem"</string>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index a911a30..acfa2ce 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"पिन गर्नुहोस्"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"फ्रिफर्म"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"हालसालैको कुनै पनि वस्तु छैन"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"एपको उपयोगका सेटिङहरू"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"सबै मेटाउनुहोस्"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"टास्कबार प्रयोग गरेर अझ धेरै कार्य गर्नुहोस्"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"टास्कबार सधैँ देखाउनुहोस्"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"आफ्नो स्क्रिनको पुछारमा टास्कबार सधैँ देखाइराख्न डिभाइडर टच एन्ड होल्ड गर्नुहोस्"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"आफ्नो स्क्रिनमा भएका कुराहरू खोज्न एक्सन कीमा टच एण्ड होल्ड गर्नुहोस्"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"यो उत्पादनले तपाईंले चयन गर्नुभएको स्क्रिनको भाग प्रयोग गरेर खोजी गर्छ। Google को <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>गोपनीयता नीति<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> र <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>सेवाका सर्तहरू<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> लागू हुन्छन्।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"बन्द गर्नुहोस्"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"सम्पन्न भयो"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"होम"</string>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 74543a5..3032ade 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Vastzetten"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Vrije vorm"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Geen recente items"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Instellingen voor app-gebruik"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Alles wissen"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Doe meer met de taakbalk"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"De taakbalk altijd tonen"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Houd de scheidingslijn ingedrukt als je de taakbalk altijd onderaan je scherm wilt tonen"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Sluiten"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Klaar"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 1ddcdf2..a67cff9 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ପିନ୍‍"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ଫ୍ରିଫର୍ମ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ବର୍ତ୍ତମାନର କୌଣସି ଆଇଟମ ନାହିଁ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ଆପ ବ୍ୟବହାର ସେଟିଂସ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ସବୁ ଖାଲି କରନ୍ତୁ"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ଟାସ୍କବାର ମାଧ୍ୟମରେ ଆହୁରି ଅନେକ କିଛି କରନ୍ତୁ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ସର୍ବଦା ଟାସ୍କବାର ଦେଖାନ୍ତୁ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ଆପଣଙ୍କ ସ୍କ୍ରିନର ନିମ୍ନରେ ସର୍ବଦା ଟାସ୍କବାର ଦେଖାଇବା ପାଇଁ ଡିଭାଇଡରକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"ଆପଣଙ୍କ ସ୍କ୍ରିନରେ କଣ ଅଛି ତାହା ସର୍ଚ୍ଚ କରିବା ପାଇଁ ଆକ୍ସନ କୀ\'କୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"ସର୍ଚ୍ଚ କରିବା ପାଇଁ ଏହି ପ୍ରଡକ୍ଟ ଆପଣଙ୍କ ସ୍କ୍ରିନର ଚୟନିତ ଅଂଶକୁ ବ୍ୟବହାର କରେ। Googleର <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>ଗୋପନୀୟତା ନୀତି<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> ଏବଂ <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ସେବାର ସର୍ତ୍ତାବଳୀ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ଲାଗୁ ହୁଏ।"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ହୋଇଗଲା"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ହୋମ"</string>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index b28ce1c..38d2dac 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ਪਿੰਨ ਕਰੋ"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"ਫ੍ਰੀਫਾਰਮ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ਕੋਈ ਹਾਲੀਆ ਆਈਟਮ ਨਹੀਂ"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ਐਪ ਵਰਤੋਂ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ਸਭ ਕਲੀਅਰ ਕਰੋ"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ਟਾਸਕਬਾਰ ਦਾ ਹੋਰ ਲਾਹਾ ਲਓ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਉਣਾ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ਆਪਣੀ ਸਕ੍ਰੀਨ ਦੇ ਹੇਠਾਂ ਹਮੇਸ਼ਾਂ ਟਾਸਕਬਾਰ ਦਿਖਾਉਣ ਲਈ, ਵਿਭਾਜਕ ਨੂੰ ਸਪਰਸ਼ ਕਰ ਕੇ ਰੱਖੋ"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"ਬੰਦ ਕਰੋ"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ਸਮਝ ਲਿਆ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ਘਰ"</string>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index bf816fe..9a55b94 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Przypnij"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Tryb dowolny"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Brak ostatnich elementów"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ustawienia użycia aplikacji"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Wyczyść wszystko"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Wykorzystaj potencjał paska aplikacji"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Zawsze wyświetlaj pasek aplikacji"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Aby zawsze wyświetlać pasek aplikacji u dołu ekranu, naciśnij i przytrzymaj linię dzielenia ekranu"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Aby rozpocząć wyszukiwanie na podstawie zawartości ekranu, naciśnij i przytrzymaj klawisz działania"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Usługa przy wyszukiwaniu używa zaznaczonego fragmentu ekranu. Obowiązują zapisy <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Polityki prywatności<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> i <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Warunków korzystania z usług<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zamknij"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gotowe"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ekran główny"</string>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index b22b98c..202813b 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Definições de utilização de aplicações"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Limpar tudo"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Faça mais com a Barra de tarefas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostre sempre a Barra de tarefas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para mostrar sempre a Barra de tarefas no fundo do ecrã, toque sem soltar no divisor"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Toque sem soltar na tecla de ação para pesquisar o que está no ecrã"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Este produto usa a parte selecionada do ecrã para pesquisar. Aplicam-se a <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de Privacidade<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> e os <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Termos de Utilização<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> da Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Concluir"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Início"</string>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index 80f461a..532a598 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixar"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Forma livre"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nenhum item recente"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Configurações de uso do app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Remover tudo"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Aproveite ainda mais a Barra de tarefas"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Sempre mostrar a Barra de tarefas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Toque e pressione o divisor para sempre mostrar a Barra de tarefas na parte de baixo da tela"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Fechar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Concluído"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Início"</string>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 25307b0..ed7dfd8 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fixează"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Formă liberă"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Niciun element recent"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Setări de utilizare a aplicației"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Șterge tot"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Fă mai multe din Bara de activități"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Afișează întotdeauna Bara de activități"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Pentru a afișa mereu Bara de activități în partea de jos a ecranului, atinge lung separatorul"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Închide"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Gata"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ecran de pornire"</string>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 4e1a213..6f1d9e7 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Закрепить"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Произвольная форма"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Здесь пока ничего нет."</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Настройки использования приложения"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Очистить все"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Используйте все возможности панели задач"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Закрепите панель задач внизу экрана"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Для этого нажмите на разделитель и удерживайте его."</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Чтобы найти информацию об объекте на экране, нажмите и удерживайте клавишу действия"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Этот продукт использует выделенную часть экрана для поиска. При этом действуют <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Политика конфиденциальности<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> и <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Условия использования<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрыть"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Главный экран"</string>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 2e2151d..1335e0e 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"අමුණන්න"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"මෑත අයිතම නැත"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"යෙදුම් භාවිත සැකසීම්"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"සියල්ල හිස් කරන්න"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"කාර්ය තීරුව සමග තවත් කරන්න"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"සෑම විටම කාර්ය තීරුව පෙන්වන්න"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"සෑම විටම ඔබේ තිරයේ පතුලේ ඇති කාර්ය තීරුව පෙන්වීමට, බෙදුම්කරු ස්පර්ශ කර අල්ලාගෙන සිටින්න"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"වසන්න"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"නිමයි"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"මුල් පිටුව"</string>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index 0b9a0e3..48f7a9c 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Pripnúť"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Voľný režim"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Žiadne nedávne položky"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavenia využívania aplikácie"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Vymazať všetko"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Panel aplikácií vám ponúka ďalšie možnosti"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vždy zobrazovať panel aplikácií"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ak chcete, aby sa panel aplikácií vždy zobrazoval v dolnej časti obrazovky, pridržte rozdeľovač"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Ak chcete vyhľadávať, čo je na obrazovke, pridržte akčný kláves."</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Táto služba používa na účely vyhľadávania vybranú časť obrazovky. Uplatňujú sa <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravidlá ochrany súkromia<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> a <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>zmluvné podmienky<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> spoločnosti Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zavrieť"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hotovo"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Plocha"</string>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 1a34502..58e34f2 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Pripni"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Prosta oblika"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Ni nedavnih elementov"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Nastavitve uporabe aplikacij"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Počisti vse"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Naredite več z opravilno vrstico"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Stalni prikaz opravilne vrstice"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Če želite, da je opravilna vrstica vedno prikazana na dnu zaslona, pridržite razdelilno črto."</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Za iskanje po zaslonu se dotaknite in pridržite tipko za dejanja"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Ta izdelek za iskanje uporablja izbrani del zaslona. Veljajo Googlov <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>pravilnik o zasebnosti<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> in <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>pogoji storitve<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Zapri"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Končano"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Začetni zaslon"</string>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index 94e5c53..1cc11d2 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Gozhdo"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Formë e lirë"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Nuk ka asnjë artikull të fundit"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cilësimet e përdorimit të aplikacionit"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Pastroji të gjitha"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Bëj më shumë me \"Shiritin e detyrave\""</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Shfaq gjithmonë \"Shiritin e detyrave\""</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Prek e mbaj ndarësin dhe shfaq gjithmonë \"Shiritin e detyrave\" në fund të ekranit"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Mbyll"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"U krye"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Faqja kryesore"</string>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index 269614d..0164d67 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Закачи"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Слободни облик"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Нема недавних ставки"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Подешавања коришћења апликације"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Обриши све"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Урадите више помоћу траке задатака"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Увек приказуј траку задатака"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Да би трака задатака увек била приказана у дну екрана, додирните и задржите разделник"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Додирните и задржите тастер радњи да бисте претражили оно што је на екрану"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Овај производ користи изабрани део екрана за претрагу. Примењују се Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>политика приватности<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> и <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>услови коришћења услуге<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Затвори"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Почетна"</string>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 0464246..d994ef5 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Fäst"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Fritt format"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Listan är tom"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Inställningar för appanvändning"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Rensa alla"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Gör mer med aktivitetsfältet"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Visa alltid aktivitetsfältet"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Tryck länge på avgränsaren för att alltid visa aktivitetsfältet längst ned på skärmen"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Stäng"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Klar"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Startsida"</string>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index 9af3db5..9d925a5 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Bandika"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Muundo huru"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Hakuna vipengee vya hivi karibuni"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mipangilio ya matumizi ya programu"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Ondoa zote"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Kamilisha mengi kwa kutumia Upauzana huu"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Onyesha Upauzana kila wakati"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ili uonyeshe Upauzana kila wakati chini ya skrini yako, gusa na ushikilie kitenganishi"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Gusa na ushikilie kitufe cha vitendo ili utafute kilicho kwenye skrini yako"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Bidhaa hii hutumia sehemu uliyochagua kwenye skrini yako kutafuta. <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Sera ya Faragha<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> na <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Sheria na Masharti<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ya Google yatatumika."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Funga"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Imemaliza"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Mwanzo"</string>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index 279e9f9..2f458f4 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"பின் செய்தல்"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"குறிப்பிட்ட வடிவமில்லாத பயன்முறை"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"சமீபத்தியவை எதுவுமில்லை"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ஆப்ஸ் உபயோக அமைப்புகள்"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"எல்லாம் அழி"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"செயல் பட்டி மூலம் மேலும் பலவற்றைச் செய்யுங்கள்"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"செயல் பட்டியை எப்போதும் காட்டுதல்"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"திரையின் கீழ்ப்பகுதியில் செயல் பட்டியை எப்போதும் காட்டுவதற்கு, பிரிப்பானைத் தொட்டுப் பிடித்திருக்கவும்"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"மூடுக"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"முடிந்தது"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"முகப்பு"</string>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 9461d48..5f1feff 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"పిన్ చేయండి"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"సంప్రదాయేతర"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ఇటీవలి ఐటెమ్‌లు ఏవీ లేవు"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"యాప్ వినియోగ సెట్టింగ్‌లు"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"అన్నీ తీసివేయండి"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"టాస్క్‌బార్‌తో మరిన్ని చేయండి"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"టాస్క్‌బార్‌ను నిరంతరం చూపండి"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"మీ స్క్రీన్ దిగువున టాస్క్‌బార్‌ను నిరంతరం చూపడానికి, డివైడర్‌ను తాకి, నొక్కి ఉంచండి"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"మీ స్క్రీన్‌లో ఏం ఉందో సెర్చ్ చేయడానికి యాక్షన్ కీని తాకి ఉంచండి"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"ఈ ప్రోడక్ట్, సెర్చ్ చేయడానికి మీ స్క్రీన్‌లో ఎంచుకున్న భాగాన్ని ఉపయోగిస్తుంది. Google <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>గోప్యతా పాలసీ<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>, <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>సర్వీస్ నియమాలు<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> వర్తిస్తాయి."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"మూసివేయండి"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"పూర్తయింది"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"మొదటి ట్యాబ్"</string>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index 6eff112..ea6a285 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"ปักหมุด"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"รูปแบบอิสระ"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"ไม่มีรายการล่าสุด"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"การตั้งค่าการใช้แอป"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"ล้างทั้งหมด"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ทำสิ่งต่างๆ ได้มากขึ้นด้วยแถบงาน"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"แสดงแถบงานเสมอ"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"หากต้องการให้แถบงานแสดงที่ด้านล่างหน้าจออยู่เสมอ ให้แตะตัวแบ่งค้างไว้"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"แตะปุ่มดำเนินการค้างไว้เพื่อค้นหาสิ่งที่อยู่บนหน้าจอ"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"ผลิตภัณฑ์นี้ใช้ส่วนที่เลือกของหน้าจอเพื่อค้นหา เป็นไปตาม<xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>นโยบายความเป็นส่วนตัว<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g>และ<xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>ข้อกําหนดในการให้บริการ<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g>ของ Google"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"ปิด"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"เสร็จ"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"หน้าแรก"</string>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index a6106c8..5fbc57b 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"I-pin"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Walang kamakailang item"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Mga setting ng paggamit ng app"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"I-clear lahat"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Mas maraming magawa gamit ang Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Palaging ipakita ang Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para palaging ipakita ang Taskbar sa ibaba ng iyong screen, pindutin nang matagal ang divider"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"Pindutin nang matagal ang action key para hanapin kung ano ang nasa iyong screen"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"Ginagamit ng produktong ito ang piniling bahagi ng iyong screen para maghanap. Nalalapat ang <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Patakaran sa Privacy<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> at <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Mga Tuntunin ng Serbisyo<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> ng Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Isara"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Tapos na"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Home"</string>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index f562feb..a10d0e3 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Sabitle"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Serbest çalışma"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Yeni öğe yok"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Uygulama kullanım ayarları"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Tümünü temizle"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Görev çubuğuyla daha fazla şey yapın"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Görev çubuğunu sabitleyin"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ayırıcıya dokunup basılı tuttuğunuzda görev çubuğu ekranın alt kısmına sabitlenir"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Kapat"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Bitti"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ana ekran"</string>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 4df24d7..5e19342 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Закріпити"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Довільна форма"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Немає нещодавніх додатків"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Налаштування використання додатка"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Очистити все"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Більше можливостей завдяки панелі завдань"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Завжди показувати панель завдань"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Щоб завжди показувати панель завдань унизу екрана, натисніть і втримуйте роздільник"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Закрити"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Готово"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Головний екран"</string>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 3c5d22d..7b14045 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"پن کریں"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"فری فارم"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"کوئی حالیہ آئٹم نہیں"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"ایپ کے استعمال کی ترتیبات"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"سبھی کو صاف کریں"</string>
@@ -116,6 +118,8 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"ٹاسک بار سے بہت کچھ کریں"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"ہمیشہ ٹاسک بار دکھائیں"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"ٹاسک بار کو ہمیشہ اپنی اسکرین کے نیچے دکھانے کے لیے، ڈیوائیڈر کو ٹچ کریں اور دبائے رکھیں"</string>
+    <string name="taskbar_edu_circle_to_search_title" msgid="4322780398403949508">"آپ کی اسکرین پر جو کچھ ہے اسے تلاش کرنے کے لیے ایکشن کلید کو ٹچ کریں اور دبائے رکھیں"</string>
+    <string name="taskbar_edu_circle_to_search_disclosure" msgid="5841648785867787221">"‏یہ پروڈکٹ تلاش کرنے کے لیے آپ کی اسکرین کا منتخب حصہ استعمال کرتا ہے۔ Google کی <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>رازداری کی پالیسی<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> اور <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>سروس کی شرائط<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> لاگو ہوتی ہیں۔"</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"بند کریں"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"ہو گیا"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"ہوم"</string>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 1540ed5..efbb6a3 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Qadash"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Erkin shakl"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Yaqinda ishlatilgan ilovalar yo‘q"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Ilovadan foydalanish sozlamalari"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Hammasini tozalash"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Vazifalar panelidan maksimal darajada foydalaning"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Vazifalar paneli doim chiqarilsin"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Vazifalar panelini ekranning pastki qismida doim chiqib turishi uchun ajratkichni bosib turing"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Yopish"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Tayyor"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Bosh ekran"</string>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index fb28736..8d35279 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Ghim"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"Dạng tự do"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Không có mục gần đây nào"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Cài đặt mức sử dụng ứng dụng"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Xóa tất cả"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Làm nhiều việc hơn qua Thanh tác vụ"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Luôn hiện Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Để luôn hiện Taskbar ở cuối màn hình, hãy nhấn và giữ đường phân chia"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Đóng"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Xong"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Màn hình chính"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index fea79bb..b567c66 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"自由窗口"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"近期没有任何内容"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"应用使用设置"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"体验任务栏的更多功能"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"始终显示任务栏"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"若要始终在屏幕底部显示任务栏,请轻触并按住分隔线"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"关闭"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"主屏幕"</string>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index c1c78ab..b314def 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"最近沒有任何項目"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"工作列助你事半功倍"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"一律顯示工作列"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"如要持續在畫面底部顯示工作列,請按住分隔線"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"住宅"</string>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 2e89466..0864c55 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"固定"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"自由形式"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"最近沒有任何項目"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"應用程式使用情況設定"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"全部清除"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"充分發揮工作列的功用"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"一律顯示工作列"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"如要一律在畫面底部顯示工作列,請按住分隔線"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"關閉"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"完成"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"主畫面"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 0688082..e1c1f3a 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -21,6 +21,8 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="recent_task_option_pin" msgid="7929860679018978258">"Phina"</string>
     <string name="recent_task_option_freeform" msgid="48863056265284071">"I-Freeform"</string>
+    <!-- no translation found for recent_task_option_desktop (8280879717125435668) -->
+    <skip />
     <string name="recents_empty_message" msgid="7040467240571714191">"Azikho izinto zakamuva"</string>
     <string name="accessibility_app_usage_settings" msgid="6312864233673544149">"Izilungiselelo zokusetshenziswa kohlelo lokusebenza"</string>
     <string name="recents_clear_all" msgid="5328176793634888831">"Sula konke"</string>
@@ -116,6 +118,10 @@
     <string name="taskbar_edu_features" msgid="3320337287472848162">"Yenza okwengeziwe nge-Taskbar"</string>
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Bonisa njalo i-Taskbar"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Ukuze ubonise njalo i-Taskbar phansi kwesikrini sakho, thinta bese ubamba isihlukanisi"</string>
+    <!-- no translation found for taskbar_edu_circle_to_search_title (4322780398403949508) -->
+    <skip />
+    <!-- no translation found for taskbar_edu_circle_to_search_disclosure (5841648785867787221) -->
+    <skip />
     <string name="taskbar_edu_close" msgid="887022990168191073">"Vala"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Kwenziwe"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Ikhaya"</string>
diff --git a/quickstep/res/values/attrs.xml b/quickstep/res/values/attrs.xml
index 7288774..ccc7f18 100644
--- a/quickstep/res/values/attrs.xml
+++ b/quickstep/res/values/attrs.xml
@@ -30,6 +30,11 @@
         <attr name="hoverBorderColor" format="color" />
     </declare-styleable>
 
+    <declare-styleable name="ClearAllButton">
+        <!-- focus border color for overview clear all button views -->
+        <attr name="focusBorderColor" />
+    </declare-styleable>
+
     <!--
          Gesture nav edu specific attributes. These attributes are used to customize Gesture nav edu
          view lottie animation colors in XML files.
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index e45d9fd..c4ee11a 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -26,6 +26,19 @@
     <string name="test_information_handler_class" translatable="false">com.android.quickstep.QuickstepTestInformationHandler</string>
     <string name="window_manager_proxy_class" translatable="false">com.android.quickstep.util.SystemWindowManagerProxy</string>
     <string name="widget_holder_factory_class" translatable="false">com.android.launcher3.uioverrides.QuickstepWidgetHolder$QuickstepHolderFactory</string>
+    <string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
+    <string name="app_launch_tracker_class" translatable="false">com.android.launcher3.appprediction.PredictionAppTracker</string>
+    <string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
+    <string name="model_delegate_class" translatable="false">com.android.launcher3.model.QuickstepModelDelegate</string>
+    <string name="secondary_display_predictions_class" translatable="false">com.android.launcher3.secondarydisplay.SecondaryDisplayPredictionsImpl</string>
+    <string name="taskbar_model_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarModelCallbacksFactory</string>
+    <string name="taskbar_view_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarViewCallbacksFactory</string>
+    <string name="launcher_restore_event_logger_class" translatable="false">com.android.quickstep.LauncherRestoreEventLoggerImpl</string>
+
+    <string name="nav_handle_long_press_handler_class" translatable="false"></string>
+    <string name="assist_utils_class" translatable="false"></string>
+    <string name="assist_state_manager_class" translatable="false"></string>
+    <string name="api_wrapper_class" translatable="false">com.android.launcher3.uioverrides.SystemApiWrapper</string>
 
     <!-- The number of thumbnails and icons to keep in the cache. The thumbnail cache size also
          determines how many thumbnails will be fetched in the background. -->
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 3331321..69e07f2 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -98,6 +98,8 @@
     <dimen name="default_task_dismiss_drag_velocity_grid_focus_task">5dp</dimen>
 
     <dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
+    <dimen name="recents_clear_all_outline_radius">24dp</dimen>
+    <dimen name="recents_clear_all_outline_padding">2dp</dimen>
 
     <!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
              loading full resolution screenshots. -->
@@ -325,9 +327,9 @@
     <dimen name="taskbar_contextual_padding_top">8dp</dimen>
     <dimen name="taskbar_nav_buttons_size">44dp</dimen>
     <dimen name="taskbar_split_instructions_margin">48dp</dimen>
-    <dimen name="taskbar_contextual_button_margin">120dp</dimen>
+    <dimen name="taskbar_ime_switcher_button_margin_start">40dp</dimen>
     <dimen name="taskbar_suw_insets">48dp</dimen>
-    <dimen name="taskbar_suw_frame">48dp</dimen>
+    <dimen name="taskbar_suw_frame">96dp</dimen>
     <dimen name="taskbar_hotseat_nav_spacing">24dp</dimen>
     <dimen name="taskbar_contextual_buttons_size">35dp</dimen>
     <dimen name="taskbar_stashed_size">24dp</dimen>
@@ -346,6 +348,11 @@
     <dimen name="taskbar_icon_size_kids">32dp</dimen>
     <dimen name="taskbar_all_apps_button_translation_x_offset">6dp</dimen>
     <dimen name="taskbar_all_apps_search_button_translation_x_offset">6dp</dimen>
+    <dimen name="taskbar_contextual_button_suw_margin">64dp</dimen>
+    <dimen name="taskbar_contextual_button_suw_height">64dp</dimen>
+    <dimen name="taskbar_back_button_suw_start_margin">48dp</dimen>
+    <dimen name="taskbar_back_button_suw_bottom_margin">1dp</dimen>
+    <dimen name="taskbar_back_button_suw_height">72dp</dimen>
 
     <!-- Transient taskbar -->
     <dimen name="transient_taskbar_padding">12dp</dimen>
@@ -396,6 +403,7 @@
     <dimen name="taskbar_edu_features_tooltip_width_with_one_feature">412dp</dimen>
     <dimen name="taskbar_edu_features_tooltip_width_with_two_features">428dp</dimen>
     <dimen name="taskbar_edu_features_tooltip_width_with_three_features">624dp</dimen>
+    <dimen name="taskbar_edu_circle_to_search_subtitle_text_size">12sp</dimen>
 
     <!--- Taskbar Pinning -->
     <dimen name="taskbar_pinning_popup_menu_width">300dp</dimen>
@@ -413,7 +421,10 @@
     <dimen name="bubblebar_stashed_size">@dimen/transient_taskbar_stashed_height</dimen>
     <dimen name="bubblebar_stashed_handle_height">@dimen/taskbar_stashed_handle_height</dimen>
     <dimen name="bubblebar_pointer_size">8dp</dimen>
+    <!-- Container size with pointer included: bubblebar_size + bubblebar_pointer_size -->
+    <dimen name="bubblebar_size_with_pointer">80dp</dimen>
     <dimen name="bubblebar_elevation">1dp</dimen>
+    <dimen name="bubblebar_drag_elevation">2dp</dimen>
     <dimen name="bubblebar_hotseat_adjustment_threshold">90dp</dimen>
 
     <dimen name="bubblebar_icon_size">50dp</dimen>
@@ -429,6 +440,11 @@
     <dimen name="bubblebar_dismiss_target_icon_size">24dp</dimen>
     <dimen name="bubblebar_dismiss_target_bottom_margin">50dp</dimen>
     <dimen name="bubblebar_dismiss_floating_gradient_height">548dp</dimen>
+    <dimen name="bubblebar_dismiss_zone_width">192dp</dimen>
+    <dimen name="bubblebar_dismiss_zone_height">242dp</dimen>
+
+    <!-- Bubble bar drop target -->
+    <dimen name="bubblebar_drop_target_corner_radius">36dp</dimen>
 
     <!-- Launcher splash screen -->
     <!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
@@ -439,8 +455,7 @@
     <dimen name="keyboard_quick_switch_border_width">4dp</dimen>
     <dimen name="keyboard_quick_switch_taskview_width">104dp</dimen>
     <dimen name="keyboard_quick_switch_taskview_height">134dp</dimen>
-    <dimen name="keyboard_quick_switch_taskview_icon_size">28dp</dimen>
-    <dimen name="keyboard_quick_switch_taskview_icon_margin">4dp</dimen>
+    <dimen name="keyboard_quick_switch_taskview_icon_size">52dp</dimen>
     <dimen name="keyboard_quick_switch_recents_icon_size">20dp</dimen>
     <dimen name="keyboard_quick_switch_margin_top">56dp</dimen>
     <dimen name="keyboard_quick_switch_margin_ends">16dp</dimen>
diff --git a/quickstep/res/values/override.xml b/quickstep/res/values/override.xml
deleted file mode 100644
index cba1f5b..0000000
--- a/quickstep/res/values/override.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<!-- Class overrides for launcher with quickstep. -->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="instant_app_resolver_class" translatable="false">com.android.quickstep.InstantAppResolverImpl</string>
-
-  <string name="app_launch_tracker_class" translatable="false">com.android.launcher3.appprediction.PredictionAppTracker</string>
-
-  <string name="main_process_initializer_class" translatable="false">com.android.quickstep.QuickstepProcessInitializer</string>
-
-  <string name="model_delegate_class" translatable="false">com.android.launcher3.model.QuickstepModelDelegate</string>
-
-  <string name="nav_handle_long_press_handler_class" translatable="false"></string>
-
-  <string name="assist_utils_class" translatable="false"></string>
-
-  <string name="secondary_display_predictions_class" translatable="false">com.android.launcher3.secondarydisplay.SecondaryDisplayPredictionsImpl</string>
-
-  <string name="taskbar_model_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarModelCallbacksFactory</string>
-
-  <string name="taskbar_view_callbacks_factory_class" translatable="false">com.android.launcher3.taskbar.TaskbarViewCallbacksFactory</string>
-
-  <string name="assist_state_manager_class" translatable="false"></string>
-
-  <string name="launcher_restore_event_logger_class" translatable="false">com.android.quickstep.LauncherRestoreEventLoggerImpl</string>
-
-</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 75a4fc8..71855eb 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -26,6 +26,8 @@
     <string name="recent_task_option_pin">Pin</string>
     <!-- Title for an option to enter freeform mode for a given app -->
     <string name="recent_task_option_freeform">Freeform</string>
+    <!-- Title for an option to enter desktop windowing mode for a given app -->
+    <string name="recent_task_option_desktop">Desktop</string>
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
     <string name="recents_empty_message">No recent items</string>
@@ -273,6 +275,10 @@
     <string name="taskbar_edu_pinning_title">Always show the Taskbar</string>
     <!-- Text in dialog that shows a user how to pin the Taskbar. [CHAR_LIMIT 150] -->
     <string name="taskbar_edu_pinning_standalone">To always show the Taskbar on the bottom of your screen, touch &amp; hold the divider</string>
+    <!-- Title in dialog that shows a user how to invoke the Circle to Search feature. [CHAR_LIMIT 150] -->
+    <string name="taskbar_edu_circle_to_search_title">Touch &amp; hold the action key to search what\'s on your screen</string>
+    <!-- Message showed to user to disclose privacy information they need to accept in order to access the app. [CHAR LIMIT=200]-->
+    <string name="taskbar_edu_circle_to_search_disclosure">This product uses the selected part of your screen to search. Google\'s <xliff:g example="https://policies.google.com/privacy/embedded" id="begin_privacy_link">&lt;a href=\"%1$s\"&gt;</xliff:g>Privacy Policy<xliff:g id="end_privacy_link">&lt;/a&gt;</xliff:g> and <xliff:g example="https://policies.google.com/terms" id="begin_tos_link">&lt;a href=\"%2$s\"&gt;</xliff:g>Terms of Service<xliff:g id="end_tos_link">&lt;/a&gt;</xliff:g> apply.</string>
     <!-- Text on button to exit a tutorial [CHAR_LIMIT=16] -->
     <string name="taskbar_edu_close">Close</string>
     <!-- Text on button to finish a tutorial [CHAR_LIMIT=16] -->
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 350c752..16fb6d2 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -315,5 +315,6 @@
     <style name="WidgetPickerActivityTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
         <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="pageIndicatorDotColor">@color/page_indicator_dot_color_light</item>
     </style>
 </resources>
diff --git a/quickstep/src/com/android/launcher3/HomeTransitionController.java b/quickstep/src/com/android/launcher3/HomeTransitionController.java
deleted file mode 100644
index 2b50283..0000000
--- a/quickstep/src/com/android/launcher3/HomeTransitionController.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3;
-
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.quickstep.SystemUiProxy;
-import com.android.wm.shell.transition.IHomeTransitionListener;
-
-/**
- * Controls launcher response to home activity visibility changing.
- */
-public class HomeTransitionController {
-
-    @Nullable private QuickstepLauncher mLauncher;
-    @Nullable private IHomeTransitionListener mHomeTransitionListener;
-
-    public void registerHomeTransitionListener(QuickstepLauncher launcher) {
-        mLauncher = launcher;
-        mHomeTransitionListener = new IHomeTransitionListener.Stub() {
-            @Override
-            public void onHomeVisibilityChanged(boolean isVisible) {
-                MAIN_EXECUTOR.execute(() -> {
-                    if (mLauncher != null && mLauncher.getTaskbarUIController() != null) {
-                        mLauncher.getTaskbarUIController().onLauncherVisibilityChanged(isVisible);
-                    }
-                });
-            }
-        };
-
-        SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(mHomeTransitionListener);
-    }
-
-    public void unregisterHomeTransitionListener() {
-        SystemUiProxy.INSTANCE.get(mLauncher).setHomeTransitionListener(null);
-        mHomeTransitionListener = null;
-        mLauncher = null;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 569e95a..0697f47 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -43,6 +43,7 @@
 import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
 import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
 import static com.android.launcher3.BaseActivity.PENDING_INVISIBLE_BY_WALLPAPER_ANIMATION;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -172,6 +173,7 @@
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map.Entry;
 
 /**
  * Manages the opening and closing app transitions from Launcher
@@ -215,7 +217,8 @@
     public static final int TASKBAR_TO_APP_DURATION = 600;
     // TODO(b/236145847): Tune TASKBAR_TO_HOME_DURATION to 383 after conflict with unlock animation
     // is solved.
-    public static final int TASKBAR_TO_HOME_DURATION = 300;
+    private static final int TASKBAR_TO_HOME_DURATION_FAST = 300;
+    private static final int TASKBAR_TO_HOME_DURATION_SLOW = 1000;
     protected static final int CONTENT_SCALE_DURATION = 350;
     protected static final int CONTENT_SCRIM_DURATION = 350;
 
@@ -1704,6 +1707,14 @@
         return new Pair(rectFSpringAnim, anim);
     }
 
+    public static int getTaskbarToHomeDuration() {
+        if (enableScalingRevealHomeAnimation()) {
+            return TASKBAR_TO_HOME_DURATION_SLOW;
+        } else {
+            return TASKBAR_TO_HOME_DURATION_FAST;
+        }
+    }
+
     /**
      * Remote animation runner for animation from the app to Launcher, including recents.
      */
diff --git a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
index 8c4db4a..23cb8e9 100644
--- a/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
+++ b/quickstep/src/com/android/launcher3/WidgetPickerActivity.java
@@ -35,23 +35,31 @@
 import android.view.WindowManager;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.launcher3.dragndrop.SimpleDragLayer;
 import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.model.WidgetPredictionsRequester;
 import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.widget.BaseWidgetSheet;
 import com.android.launcher3.widget.WidgetCell;
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
+import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /** An Activity that can host Launcher's widget picker. */
 public class WidgetPickerActivity extends BaseActivity {
     private static final String TAG = "WidgetPickerActivity";
-
     /**
      * Name of the extra that indicates that a widget being dragged.
      *
@@ -64,14 +72,33 @@
     // the intent, then widgets will not be filtered for size.
     private static final String EXTRA_DESIRED_WIDGET_WIDTH = "desired_widget_width";
     private static final String EXTRA_DESIRED_WIDGET_HEIGHT = "desired_widget_height";
-
+    /**
+     * Widgets currently added by the user in the UI surface.
+     * <p>This allows widget picker to exclude existing widgets from suggestions.</p>
+     */
+    private static final String EXTRA_ADDED_APP_WIDGETS = "added_app_widgets";
+    /**
+     * A unique identifier of the surface hosting the widgets;
+     * <p>"widgets" is reserved for home screen surface.</p>
+     * <p>"widgets_hub" is reserved for glanceable hub surface.</p>
+     */
+    private static final String EXTRA_UI_SURFACE = "ui_surface";
+    private static final Pattern UI_SURFACE_PATTERN =
+            Pattern.compile("^(widgets|widgets_hub)$");
     private SimpleDragLayer<WidgetPickerActivity> mDragLayer;
     private WidgetsModel mModel;
+    private LauncherAppState mApp;
+    private WidgetPredictionsRequester mWidgetPredictionsRequester;
     private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {});
 
     private int mDesiredWidgetWidth;
     private int mDesiredWidgetHeight;
     private int mWidgetCategoryFilter;
+    @Nullable
+    private String mUiSurface;
+    // Widgets existing on the host surface.
+    @NonNull
+    private List<AppWidgetProviderInfo> mAddedWidgets = new ArrayList<>();
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -80,9 +107,8 @@
         getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
         getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER);
 
-        LauncherAppState app = LauncherAppState.getInstance(this);
-        InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
-
+        mApp = LauncherAppState.getInstance(this);
+        InvariantDeviceProfile idp = mApp.getInvariantDeviceProfile();
         mDeviceProfile = idp.getDeviceProfile(this);
         mModel = new WidgetsModel();
 
@@ -97,6 +123,11 @@
         widgetSheet.disableNavBarScrim(true);
         widgetSheet.addOnCloseListener(this::finish);
 
+        parseIntentExtras();
+        refreshAndBindWidgets();
+    }
+
+    private void parseIntentExtras() {
         // A value of 0 for either size means that no filtering will occur in that dimension. If
         // both values are 0, then no size filtering will occur.
         mDesiredWidgetWidth =
@@ -108,7 +139,15 @@
         mWidgetCategoryFilter =
                 getIntent().getIntExtra(AppWidgetManager.EXTRA_CATEGORY_FILTER, 0);
 
-        refreshAndBindWidgets();
+        String uiSurfaceParam = getIntent().getStringExtra(EXTRA_UI_SURFACE);
+        if (uiSurfaceParam != null && UI_SURFACE_PATTERN.matcher(uiSurfaceParam).matches()) {
+            mUiSurface = uiSurfaceParam;
+        }
+        ArrayList<AppWidgetProviderInfo> addedWidgets = getIntent().getParcelableArrayListExtra(
+                EXTRA_ADDED_APP_WIDGETS, AppWidgetProviderInfo.class);
+        if (addedWidgets != null) {
+            mAddedWidgets = addedWidgets;
+        }
     }
 
     @NonNull
@@ -179,11 +218,12 @@
         };
     }
 
+    /** Updates the model with widgets and provides them after applying the provided filter. */
     private void refreshAndBindWidgets() {
         MODEL_EXECUTOR.execute(() -> {
             LauncherAppState app = LauncherAppState.getInstance(this);
             mModel.update(app, null);
-            final ArrayList<WidgetsListBaseEntry> widgets =
+            final List<WidgetsListBaseEntry> allWidgets =
                     mModel.getFilteredWidgetsListForPicker(
                             app.getContext(),
                             /*widgetItemFilter=*/ widget -> {
@@ -193,10 +233,37 @@
                                 return verdict.isAcceptable;
                             }
                     );
-            MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(widgets));
+            bindWidgets(allWidgets);
+            if (mUiSurface != null) {
+                Map<PackageUserKey, List<WidgetItem>> allWidgetsMap = allWidgets.stream()
+                        .filter(WidgetsListHeaderEntry.class::isInstance)
+                        .collect(Collectors.toMap(
+                                entry -> PackageUserKey.fromPackageItemInfo(entry.mPkgItem),
+                                entry -> entry.mWidgets)
+                        );
+                mWidgetPredictionsRequester = new WidgetPredictionsRequester(app.getContext(),
+                        mUiSurface, allWidgetsMap);
+                mWidgetPredictionsRequester.request(mAddedWidgets, this::bindRecommendedWidgets);
+            }
         });
     }
 
+    private void bindWidgets(List<WidgetsListBaseEntry> widgets) {
+        MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(widgets));
+    }
+
+    private void bindRecommendedWidgets(List<ItemInfo> recommendedWidgets) {
+        MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setRecommendedWidgets(recommendedWidgets));
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        if (mWidgetPredictionsRequester != null) {
+            mWidgetPredictionsRequester.clear();
+        }
+    }
+
     private WidgetAcceptabilityVerdict isWidgetAcceptable(WidgetItem widget) {
         final AppWidgetProviderInfo info = widget.widgetInfo;
         if (info == null) {
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index b36fd66..70e01f5 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -37,7 +37,6 @@
 import com.android.launcher3.allapps.FloatingHeaderRow;
 import com.android.launcher3.allapps.FloatingHeaderView;
 import com.android.launcher3.anim.AlphaUpdateListener;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.keyboard.FocusIndicatorHelper;
 import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
 import com.android.launcher3.model.data.ItemInfo;
@@ -45,6 +44,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.views.ActivityContext;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -240,7 +240,11 @@
             icon.reset();
             if (predictionCount > i) {
                 icon.setVisibility(View.VISIBLE);
-                icon.applyFromWorkspaceItem(mPredictedApps.get(i));
+                WorkspaceItemInfo predictedItem = mPredictedApps.get(i);
+                predictedItem.rank = i;
+                predictedItem.cellX = i;
+                predictedItem.cellY = 0;
+                icon.applyFromWorkspaceItem(predictedItem);
             } else {
                 icon.setVisibility(predictionCount == 0 ? GONE : INVISIBLE);
             }
@@ -281,4 +285,11 @@
         return getChildAt(0);
     }
 
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(prefix + this.getClass().getSimpleName());
+        writer.println(prefix + "\tmPredictionsEnabled: " + mPredictionsEnabled);
+        writer.println(prefix + "\tmPredictionUiUpdatePaused: " + mPredictionUiUpdatePaused);
+        writer.println(prefix + "\tmNumPredictedAppsPerRow: " + mNumPredictedAppsPerRow);
+        writer.println(prefix + "\tmPredictedApps: " + mPredictedApps);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
index 10733fb..3ef8e54 100644
--- a/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
+++ b/quickstep/src/com/android/launcher3/desktop/DesktopRecentsTransitionController.kt
@@ -20,9 +20,9 @@
 import android.os.RemoteException
 import android.util.Log
 import android.view.SurfaceControl
-import android.window.IRemoteTransition
 import android.window.IRemoteTransitionFinishedCallback
 import android.window.RemoteTransition
+import android.window.RemoteTransitionStub
 import android.window.TransitionInfo
 import com.android.launcher3.statehandlers.DepthController
 import com.android.launcher3.statemanager.StateManager
@@ -56,12 +56,17 @@
         systemUiProxy.showDesktopApps(desktopTaskView.display.displayId, transition)
     }
 
+    /** Launch desktop tasks from recents view */
+    fun moveToDesktop(taskId: Int) {
+        systemUiProxy.moveToDesktop(taskId)
+    }
+
     private class RemoteDesktopLaunchTransitionRunner(
         private val desktopTaskView: DesktopTaskView,
         private val stateManager: StateManager<*>,
         private val depthController: DepthController?,
         private val successCallback: Consumer<Boolean>?
-    ) : IRemoteTransition.Stub() {
+    ) : RemoteTransitionStub() {
 
         override fun startAnimation(
             token: IBinder,
@@ -90,17 +95,6 @@
                 }
             }
         }
-
-        override fun mergeAnimation(
-            transition: IBinder,
-            info: TransitionInfo,
-            t: SurfaceControl.Transaction,
-            mergeTarget: IBinder,
-            finishCallback: IRemoteTransitionFinishedCallback
-        ) {}
-
-        override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {
-        }
     }
 
     companion object {
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 672bd1d..1c5a75d 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -499,7 +499,7 @@
 
         @Override
         public void onClick(View view) {
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             pinPrediction(mItemInfo);
         }
     }
diff --git a/quickstep/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
index a931f36..a621259 100644
--- a/quickstep/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -41,6 +41,7 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_ADD_BUTTON_TAP;
 import static com.android.launcher3.model.PredictionHelper.isTrackedForHotseatPrediction;
 import static com.android.launcher3.model.PredictionHelper.isTrackedForWidgetPrediction;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -184,6 +185,10 @@
             sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
         } else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) {
             sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION);
+        } else if (event == LAUNCHER_WIDGET_ADD_BUTTON_TAP) {
+            if (isTrackedForWidgetPrediction(atomInfo)) {
+                sendEvent(atomInfo, ACTION_PIN, CONTAINER_WIDGETS_PREDICTION);
+            }
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index c0e0587..bc35125 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -111,12 +111,11 @@
     private final InvariantDeviceProfile mIDP;
     private final AppEventProducer mAppEventProducer;
     private final StatsManager mStatsManager;
-    private final Context mContext;
 
     protected boolean mActive = false;
 
     public QuickstepModelDelegate(Context context) {
-        mContext = context;
+        super(context);
         mAppEventProducer = new AppEventProducer(context, this::onAppTargetEvent);
 
         mIDP = InvariantDeviceProfile.INSTANCE.get(context);
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index 3d04cb6..c345d6e 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -44,7 +44,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.popup.RemoteActionShortcut;
@@ -53,6 +52,7 @@
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
+import com.android.launcher3.views.ActivityContext;
 
 import java.util.Arrays;
 import java.util.HashMap;
@@ -147,7 +147,7 @@
 
     @MainThread
     private SystemShortcut getShortcutForApp(String packageName, int userId,
-            BaseDraggingActivity activity, ItemInfo info, View originalView) {
+            Context context, ItemInfo info, View originalView) {
         Preconditions.assertUIThread();
         // Work profile apps are not recognized by digital wellbeing.
         if (userId != UserHandle.myUserId()) {
@@ -171,7 +171,7 @@
                         "getShortcutForApp [" + packageName + "]: action: '" + action.getTitle()
                                 + "'");
             }
-            return new RemoteActionShortcut(action, activity, info, originalView);
+            return new RemoteActionShortcut(action, context, info, originalView);
         }
     }
 
@@ -305,9 +305,11 @@
     /**
      * Shortcut factory for generating wellbeing action
      */
-    public static final SystemShortcut.Factory<BaseDraggingActivity> SHORTCUT_FACTORY =
-            (activity, info, originalView) -> (info.getTargetComponent() == null) ? null
-                    : INSTANCE.get(activity).getShortcutForApp(
-                            info.getTargetComponent().getPackageName(), info.user.getIdentifier(),
-                            activity, info, originalView);
+    public static final SystemShortcut.Factory<ActivityContext> SHORTCUT_FACTORY =
+            (context, info, originalView) ->
+                    (info.getTargetComponent() == null) ? null
+                            : INSTANCE.get(originalView.getContext()).getShortcutForApp(
+                                    info.getTargetComponent().getPackageName(), info.user.getIdentifier(),
+                                    ActivityContext.lookupContext(originalView.getContext()),
+                                    info, originalView);
 }
diff --git a/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java b/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java
new file mode 100644
index 0000000..8431396
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/model/WidgetPredictionsRequester.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model;
+
+import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import android.app.prediction.AppPredictionContext;
+import android.app.prediction.AppPredictionManager;
+import android.app.prediction.AppPredictor;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Bundle;
+import android.text.TextUtils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
+import com.android.launcher3.widget.picker.WidgetRecommendationCategoryProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/**
+ * Works with app predictor to fetch and process widget predictions displayed in a standalone
+ * widget picker activity for a UI surface.
+ */
+public class WidgetPredictionsRequester {
+    private static final int NUM_OF_RECOMMENDED_WIDGETS_PREDICATION = 20;
+    private static final String BUNDLE_KEY_ADDED_APP_WIDGETS = "added_app_widgets";
+
+    @Nullable
+    private AppPredictor mAppPredictor;
+    private final Context mContext;
+    @NonNull
+    private final String mUiSurface;
+    @NonNull
+    private final Map<PackageUserKey, List<WidgetItem>> mAllWidgets;
+
+    public WidgetPredictionsRequester(Context context, @NonNull String uiSurface,
+            @NonNull Map<PackageUserKey, List<WidgetItem>> allWidgets) {
+        mContext = context;
+        mUiSurface = uiSurface;
+        mAllWidgets = Collections.unmodifiableMap(allWidgets);
+    }
+
+    /**
+     * Requests predictions from the app predictions manager and registers the provided callback to
+     * receive updates when predictions are available.
+     *
+     * @param existingWidgets widgets that are currently added to the surface;
+     * @param callback        consumer of prediction results to be called when predictions are
+     *                        available
+     */
+    public void request(List<AppWidgetProviderInfo> existingWidgets,
+            Consumer<List<ItemInfo>> callback) {
+        Bundle bundle = buildBundleForPredictionSession(existingWidgets, mUiSurface);
+        Predicate<WidgetItem> filter = notOnUiSurfaceFilter(existingWidgets);
+
+        MODEL_EXECUTOR.execute(() -> {
+            clear();
+            AppPredictionManager apm = mContext.getSystemService(AppPredictionManager.class);
+            if (apm == null) {
+                return;
+            }
+
+            mAppPredictor = apm.createAppPredictionSession(
+                    new AppPredictionContext.Builder(mContext)
+                            .setUiSurface(mUiSurface)
+                            .setExtras(bundle)
+                            .setPredictedTargetCount(NUM_OF_RECOMMENDED_WIDGETS_PREDICATION)
+                            .build());
+            mAppPredictor.registerPredictionUpdates(MODEL_EXECUTOR,
+                    targets -> bindPredictions(targets, filter, callback));
+            mAppPredictor.requestPredictionUpdate();
+        });
+    }
+
+    /**
+     * Returns a bundle that can be passed in a prediction session
+     *
+     * @param addedWidgets widgets that are already added by the user in the ui surface
+     * @param uiSurface    a unique identifier of the surface hosting widgets; format
+     *                     "widgets_xx"; note - "widgets" is reserved for home screen surface.
+     */
+    @VisibleForTesting
+    static Bundle buildBundleForPredictionSession(List<AppWidgetProviderInfo> addedWidgets,
+            String uiSurface) {
+        Bundle bundle = new Bundle();
+        ArrayList<AppTargetEvent> addedAppTargetEvents = new ArrayList<>();
+        for (AppWidgetProviderInfo info : addedWidgets) {
+            ComponentName componentName = info.provider;
+            AppTargetEvent appTargetEvent = buildAppTargetEvent(uiSurface, info, componentName);
+            addedAppTargetEvents.add(appTargetEvent);
+        }
+        bundle.putParcelableArrayList(BUNDLE_KEY_ADDED_APP_WIDGETS, addedAppTargetEvents);
+        return bundle;
+    }
+
+    /**
+     * Builds the AppTargetEvent for added widgets in a form that can be passed to the widget
+     * predictor.
+     * Also see {@link PredictionHelper}
+     */
+    private static AppTargetEvent buildAppTargetEvent(String uiSurface, AppWidgetProviderInfo info,
+            ComponentName componentName) {
+        AppTargetId appTargetId = new AppTargetId("widget:" + componentName.getPackageName());
+        AppTarget appTarget = new AppTarget.Builder(appTargetId, componentName.getPackageName(),
+                /*user=*/ info.getProfile()).setClassName(componentName.getClassName()).build();
+        return new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_PIN)
+                .setLaunchLocation(uiSurface).build();
+    }
+
+    /**
+     * Returns a filter to match {@link WidgetItem}s that don't exist on the UI surface.
+     */
+    @NonNull
+    @VisibleForTesting
+    static Predicate<WidgetItem> notOnUiSurfaceFilter(
+            List<AppWidgetProviderInfo> existingWidgets) {
+        Set<ComponentKey> existingComponentKeys = existingWidgets.stream().map(
+                widget -> new ComponentKey(widget.provider, widget.getProfile())).collect(
+                Collectors.toSet());
+        return widgetItem -> !existingComponentKeys.contains(widgetItem);
+    }
+
+    /** Provides the predictions returned by the predictor to the registered callback. */
+    @WorkerThread
+    private void bindPredictions(List<AppTarget> targets, Predicate<WidgetItem> filter,
+            Consumer<List<ItemInfo>> callback) {
+        List<WidgetItem> filteredPredictions = filterPredictions(targets, mAllWidgets, filter);
+        List<ItemInfo> mappedPredictions = mapWidgetItemsToItemInfo(filteredPredictions);
+
+        MAIN_EXECUTOR.execute(() -> callback.accept(mappedPredictions));
+    }
+
+    /**
+     * Applies the provided filter (e.g. widgets not on workspace) on the predictions returned by
+     * the predictor.
+     */
+    @VisibleForTesting
+    static List<WidgetItem> filterPredictions(List<AppTarget> predictions,
+            Map<PackageUserKey, List<WidgetItem>> allWidgets, Predicate<WidgetItem> filter) {
+        List<WidgetItem> servicePredictedItems = new ArrayList<>();
+        List<WidgetItem> localFilteredWidgets = new ArrayList<>();
+
+        for (AppTarget prediction : predictions) {
+            List<WidgetItem> widgetsInPackage = allWidgets.get(
+                    new PackageUserKey(prediction.getPackageName(), prediction.getUser()));
+            if (widgetsInPackage == null || widgetsInPackage.isEmpty()) {
+                continue;
+            }
+            String className = prediction.getClassName();
+            if (!TextUtils.isEmpty(className)) {
+                WidgetItem item = widgetsInPackage.stream()
+                        .filter(w -> className.equals(w.componentName.getClassName()))
+                        .filter(filter)
+                        .findFirst().orElse(null);
+                if (item != null) {
+                    servicePredictedItems.add(item);
+                    continue;
+                }
+            }
+            // No widget was added by the service, try local filtering
+            widgetsInPackage.stream().filter(filter).findFirst()
+                    .ifPresent(localFilteredWidgets::add);
+        }
+        if (servicePredictedItems.isEmpty()) {
+            servicePredictedItems.addAll(localFilteredWidgets);
+        }
+
+        return servicePredictedItems;
+    }
+
+    /**
+     * Converts the list of {@link WidgetItem}s to the list of {@link ItemInfo}s.
+     */
+    private List<ItemInfo> mapWidgetItemsToItemInfo(List<WidgetItem> widgetItems) {
+        List<ItemInfo> items;
+        if (enableCategorizedWidgetSuggestions()) {
+            WidgetRecommendationCategoryProvider categoryProvider =
+                    WidgetRecommendationCategoryProvider.newInstance(mContext);
+            items = widgetItems.stream()
+                    .map(it -> new PendingAddWidgetInfo(it.widgetInfo, CONTAINER_WIDGETS_PREDICTION,
+                            categoryProvider.getWidgetRecommendationCategory(mContext, it)))
+                    .collect(Collectors.toList());
+        } else {
+            items = widgetItems.stream().map(it -> new PendingAddWidgetInfo(it.widgetInfo,
+                    CONTAINER_WIDGETS_PREDICTION)).collect(Collectors.toList());
+        }
+        return items;
+    }
+
+    /** Cleans up any open prediction sessions. */
+    public void clear() {
+        if (mAppPredictor != null) {
+            mAppPredictor.destroy();
+            mAppPredictor = null;
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index 4741ddd..c0dacf1 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -19,7 +19,6 @@
 
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.os.Debug;
 import android.os.SystemProperties;
@@ -49,7 +48,7 @@
             "persist.wm.debug.desktop_stashing", false);
     private final Launcher mLauncher;
 
-    private int mVisibleFreeformTasksCount;
+    private int mVisibleDesktopTasksCount;
     private boolean mInOverviewState;
     private boolean mBackgroundStateEnabled;
     private boolean mGestureInProgress;
@@ -74,7 +73,7 @@
                         if (DEBUG) {
                             Log.d(TAG, "desktop visible tasks count changed=" + visibleTasksCount);
                         }
-                        setVisibleFreeformTasksCount(visibleTasksCount);
+                        setVisibleDesktopTasksCount(visibleTasksCount);
                     }
                 });
             }
@@ -109,54 +108,51 @@
     }
 
     /**
-     * Whether freeform windows are visible in desktop mode.
+     * Whether desktop tasks are visible in desktop mode.
      */
-    public boolean areFreeformTasksVisible() {
-        boolean freeformTasksVisible = mVisibleFreeformTasksCount > 0;
+    public boolean areDesktopTasksVisible() {
+        boolean desktopTasksVisible = mVisibleDesktopTasksCount > 0;
         if (DEBUG) {
-            Log.d(TAG, "areFreeformTasksVisible: freeformVisible=" + freeformTasksVisible
+            Log.d(TAG, "areDesktopTasksVisible: desktopVisible=" + desktopTasksVisible
                     + " overview=" + mInOverviewState);
         }
-        return freeformTasksVisible && !mInOverviewState;
+        return desktopTasksVisible && !mInOverviewState;
     }
 
     /**
-     * Number of visible freeform windows in desktop mode.
+     * Number of visible desktop windows in desktop mode.
      */
-    public int getVisibleFreeformTasksCount() {
-        return mVisibleFreeformTasksCount;
+    public int getVisibleDesktopTasksCount() {
+        return mVisibleDesktopTasksCount;
     }
 
     /**
-     * Sets the number of freeform windows that are visible and updates launcher visibility based on
+     * Sets the number of desktop windows that are visible and updates launcher visibility based on
      * it.
      */
-    public void setVisibleFreeformTasksCount(int visibleTasksCount) {
+    public void setVisibleDesktopTasksCount(int visibleTasksCount) {
         if (DEBUG) {
-            Log.d(TAG, "setVisibleFreeformTasksCount: visibleTasksCount=" + visibleTasksCount
-                    + " currentValue=" + mVisibleFreeformTasksCount);
-        }
-        if (!isDesktopModeSupported()) {
-            return;
+            Log.d(TAG, "setVisibleDesktopTasksCount: visibleTasksCount=" + visibleTasksCount
+                    + " currentValue=" + mVisibleDesktopTasksCount);
         }
 
-        if (visibleTasksCount != mVisibleFreeformTasksCount) {
-            final boolean wasVisible = mVisibleFreeformTasksCount > 0;
+        if (visibleTasksCount != mVisibleDesktopTasksCount) {
+            final boolean wasVisible = mVisibleDesktopTasksCount > 0;
             final boolean isVisible = visibleTasksCount > 0;
-            mVisibleFreeformTasksCount = visibleTasksCount;
+            mVisibleDesktopTasksCount = visibleTasksCount;
 
             if (wasVisible != isVisible) {
-                if (mVisibleFreeformTasksCount > 0) {
+                if (mVisibleDesktopTasksCount > 0) {
                     setLauncherViewsVisibility(View.INVISIBLE);
                     if (!mInOverviewState) {
-                        // When freeform is visible & we're not in overview, we want launcher to
-                        // appear paused, this ensures that taskbar displays.
+                        // When desktop tasks are visible & we're not in overview, we want launcher
+                        // to appear paused, this ensures that taskbar displays.
                         markLauncherPaused();
                     }
                 } else {
                     setLauncherViewsVisibility(View.VISIBLE);
-                    // If freeform isn't visible ensure that launcher appears resumed to behave
-                    // normally.
+                    // If desktop tasks aren't visible, ensure that launcher appears resumed to
+                    // behave normally.
                     markLauncherResumed();
                 }
             }
@@ -180,17 +176,14 @@
             Log.d(TAG, "setOverviewStateEnabled: enabled=" + overviewStateEnabled
                     + " currentValue=" + mInOverviewState);
         }
-        if (!isDesktopModeSupported()) {
-            return;
-        }
         if (overviewStateEnabled != mInOverviewState) {
             mInOverviewState = overviewStateEnabled;
             if (mInOverviewState) {
                 setLauncherViewsVisibility(View.VISIBLE);
                 markLauncherResumed();
-            } else if (areFreeformTasksVisible() && !mGestureInProgress) {
+            } else if (areDesktopTasksVisible() && !mGestureInProgress) {
                 // Switching out of overview state and gesture finished.
-                // If freeform tasks are still visible, hide launcher again.
+                // If desktop tasks are still visible, hide launcher again.
                 setLauncherViewsVisibility(View.INVISIBLE);
                 markLauncherPaused();
             }
@@ -202,16 +195,13 @@
             Log.d(TAG, "setBackgroundStateEnabled: enabled=" + backgroundStateEnabled
                     + " currentValue=" + mBackgroundStateEnabled);
         }
-        if (!isDesktopModeSupported()) {
-            return;
-        }
         if (backgroundStateEnabled != mBackgroundStateEnabled) {
             mBackgroundStateEnabled = backgroundStateEnabled;
             if (mBackgroundStateEnabled) {
                 setLauncherViewsVisibility(View.VISIBLE);
                 markLauncherResumed();
-            } else if (areFreeformTasksVisible() && !mGestureInProgress) {
-                // Switching out of background state. If freeform tasks are visible, pause launcher.
+            } else if (areDesktopTasksVisible() && !mGestureInProgress) {
+                // Switching out of background state. If desktop tasks are visible, pause launcher.
                 setLauncherViewsVisibility(View.INVISIBLE);
                 markLauncherPaused();
             }
@@ -229,9 +219,6 @@
      * Notify controller that recents gesture has started.
      */
     public void setRecentsGestureStart() {
-        if (!isDesktopModeSupported()) {
-            return;
-        }
         if (DEBUG) {
             Log.d(TAG, "setRecentsGestureStart");
         }
@@ -243,9 +230,6 @@
      * {@link com.android.quickstep.GestureState.GestureEndTarget}
      */
     public void setRecentsGestureEnd(@Nullable GestureState.GestureEndTarget endTarget) {
-        if (!isDesktopModeSupported()) {
-            return;
-        }
         if (DEBUG) {
             Log.d(TAG, "setRecentsGestureEnd: endTarget=" + endTarget);
         }
@@ -267,7 +251,7 @@
      * Handle launcher moving to home due to home gesture or home button press.
      */
     public void onHomeActionTriggered() {
-        if (IS_STASHING_ENABLED && areFreeformTasksVisible()) {
+        if (IS_STASHING_ENABLED && areDesktopTasksVisible()) {
             SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
         }
     }
@@ -286,7 +270,7 @@
             dragLayer.setVisibility(visibility);
         }
         if (mLauncher instanceof QuickstepLauncher ql && ql.getTaskbarUIController() != null
-                && mVisibleFreeformTasksCount != 0) {
+                && mVisibleDesktopTasksCount != 0) {
             ql.getTaskbarUIController().onLauncherVisibilityChanged(visibility == VISIBLE);
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt b/quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt
new file mode 100644
index 0000000..8aee1aa
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/BlurredBitmapDrawable.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.PixelFormat
+import android.graphics.RenderEffect
+import android.graphics.RenderNode
+import android.graphics.Shader
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.DrawableWrapper
+
+/* BitmapDrawable that can blur the given bitmap. */
+class BlurredBitmapDrawable(bitmap: Bitmap?, radiusX: Float, radiusY: Float) :
+    DrawableWrapper(BitmapDrawable(bitmap)) {
+    private val mBlurRenderNode: RenderNode = RenderNode("BlurredConstraintLayoutBlurNode")
+
+    constructor(bitmap: Bitmap?, radius: Float) : this(bitmap, radius, radius)
+
+    init {
+        mBlurRenderNode.setRenderEffect(
+            RenderEffect.createBlurEffect(radiusX, radiusY, Shader.TileMode.CLAMP)
+        )
+    }
+
+    override fun draw(canvas: Canvas) {
+        if (!canvas.isHardwareAccelerated) {
+            super.draw(canvas)
+            return
+        }
+        mBlurRenderNode.setPosition(bounds)
+        if (!mBlurRenderNode.hasDisplayList()) {
+            // Record render node if its display list is not recorded or discarded
+            // (which happens when it's no longer drawn by anything).
+            val recordingCanvas = mBlurRenderNode.beginRecording()
+            super.draw(recordingCanvas)
+            mBlurRenderNode.endRecording()
+        }
+        canvas.drawRenderNode(mBlurRenderNode)
+    }
+
+    override fun getOpacity(): Int {
+        return PixelFormat.OPAQUE
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index f15d12b..584106b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -15,8 +15,6 @@
  */
 package com.android.launcher3.taskbar;
 
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
-
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
 
@@ -97,7 +95,11 @@
 
     private void openQuickSwitchView(int currentFocusedIndex) {
         if (mQuickSwitchViewController != null) {
-            return;
+            if (!mQuickSwitchViewController.isCloseAnimationRunning()) {
+                return;
+            }
+            // Allow the KQS to be reopened during the close animation to make it more responsive
+            closeQuickSwitchView(false);
         }
         TaskbarOverlayContext overlayContext =
                 mControllers.taskbarOverlayController.requestWindow();
@@ -113,9 +115,7 @@
         DesktopVisibilityController desktopController =
                 LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
         final boolean onDesktop =
-                isDesktopModeSupported()
-                        && desktopController != null
-                        && desktopController.areFreeformTasksVisible();
+                desktopController != null && desktopController.areDesktopTasksVisible();
 
         if (mModel.isTaskListValid(mTaskListChangeId)) {
             // When we are opening the KQS with no focus override, check if the first task is
@@ -154,14 +154,12 @@
 
         // Hide all desktop tasks and show them on the hidden tile
         int hiddenDesktopTasks = 0;
-        if (isDesktopModeSupported()) {
-            DesktopTask desktopTask = findDesktopTask(tasks);
-            if (desktopTask != null) {
-                hiddenDesktopTasks = desktopTask.tasks.size();
-                tasks = tasks.stream()
-                        .filter(t -> !(t instanceof DesktopTask))
-                        .collect(Collectors.toCollection(ArrayList<GroupTask>::new));
-            }
+        DesktopTask desktopTask = findDesktopTask(tasks);
+        if (desktopTask != null) {
+            hiddenDesktopTasks = desktopTask.tasks.size();
+            tasks = tasks.stream()
+                    .filter(t -> !(t instanceof DesktopTask))
+                    .collect(Collectors.toCollection(ArrayList<GroupTask>::new));
         }
         mTasks = tasks.stream()
                 .limit(MAX_TASKS)
@@ -193,10 +191,14 @@
     }
 
     void closeQuickSwitchView() {
+        closeQuickSwitchView(true);
+    }
+
+    void closeQuickSwitchView(boolean animate) {
         if (mQuickSwitchViewController == null) {
             return;
         }
-        mQuickSwitchViewController.closeQuickSwitchView(true);
+        mQuickSwitchViewController.closeQuickSwitchView(animate);
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
index a9d50b9..48fc7d1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -23,6 +23,8 @@
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ImageView;
@@ -47,6 +49,8 @@
  */
 public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
 
+    private static final float THUMBNAIL_BLUR_RADIUS = 1f;
+
     @ColorInt private final int mBorderColor;
 
     @Nullable private BorderAnimator mBorderAnimator;
@@ -89,10 +93,10 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mThumbnailView1 = findViewById(R.id.thumbnail1);
-        mThumbnailView2 = findViewById(R.id.thumbnail2);
-        mIcon1 = findViewById(R.id.icon1);
-        mIcon2 = findViewById(R.id.icon2);
+        mThumbnailView1 = findViewById(R.id.thumbnail_1);
+        mThumbnailView2 = findViewById(R.id.thumbnail_2);
+        mIcon1 = findViewById(R.id.icon_1);
+        mIcon2 = findViewById(R.id.icon_2);
         mContent = findViewById(R.id.content);
 
         Resources resources = mContext.getResources();
@@ -167,34 +171,44 @@
             @Nullable ImageView thumbnailView,
             @Nullable Task task,
             @Nullable ThumbnailUpdateFunction updateFunction) {
-        if (thumbnailView == null) {
-            return;
-        }
-        if (task == null) {
+        if (thumbnailView == null || task == null) {
             return;
         }
         if (updateFunction == null) {
-            applyThumbnail(thumbnailView, task.thumbnail);
+            applyThumbnail(thumbnailView, task.colorBackground, task.thumbnail);
             return;
         }
-        updateFunction.updateThumbnailInBackground(
-                task, thumbnailData -> applyThumbnail(thumbnailView, thumbnailData));
+        updateFunction.updateThumbnailInBackground(task, thumbnailData ->
+                applyThumbnail(thumbnailView, task.colorBackground, thumbnailData));
     }
 
     private void applyThumbnail(
-            @NonNull ImageView thumbnailView, ThumbnailData thumbnailData) {
+            @NonNull ImageView thumbnailView,
+            @ColorInt int backgroundColor,
+            @Nullable ThumbnailData thumbnailData) {
         Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail;
 
-        thumbnailView.setVisibility(VISIBLE);
-        thumbnailView.setImageBitmap(bm);
+        if (thumbnailView.getVisibility() != VISIBLE) {
+            thumbnailView.setVisibility(VISIBLE);
+        }
+        thumbnailView.getBackground().setTint(bm == null ? backgroundColor : Color.TRANSPARENT);
+        thumbnailView.setImageDrawable(new BlurredBitmapDrawable(bm, THUMBNAIL_BLUR_RADIUS));
     }
 
     private void applyIcon(@Nullable ImageView iconView, @Nullable Task task) {
-        if (iconView == null || task == null) {
+        if (iconView == null || task == null || task.icon == null) {
             return;
         }
-        iconView.setVisibility(VISIBLE);
-        iconView.setImageDrawable(task.icon);
+        Drawable.ConstantState constantState = task.icon.getConstantState();
+        if (constantState == null) {
+            return;
+        }
+        if (iconView.getVisibility() != VISIBLE) {
+            iconView.setVisibility(VISIBLE);
+        }
+        // Use the bitmap directly since the drawable's scale can change
+        iconView.setImageDrawable(
+                constantState.newDrawable(getResources(), getContext().getTheme()));
     }
 
     protected interface ThumbnailUpdateFunction {
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index c830aa8..25a97d4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -94,8 +94,12 @@
                 mViewCallbacks);
     }
 
+    boolean isCloseAnimationRunning() {
+        return mCloseAnimation != null;
+    }
+
     protected void closeQuickSwitchView(boolean animate) {
-        if (mCloseAnimation != null) {
+        if (isCloseAnimationRunning()) {
             // Let currently-running animation finish.
             if (!animate) {
                 mCloseAnimation.end();
@@ -130,7 +134,7 @@
     }
 
     private int launchTaskAt(int index) {
-        if (mCloseAnimation != null) {
+        if (isCloseAnimationRunning()) {
             // Ignore taps on task views and alt key unpresses while the close animation is running.
             return -1;
         }
@@ -138,7 +142,7 @@
         // views have been added in the KeyboardQuickSwitchView.
         GroupTask task = mControllerCallbacks.getTaskAt(index);
         if (task == null) {
-            return Math.max(0, index);
+            return mOnDesktop ? 1 : Math.max(0, index);
         }
         if (mControllerCallbacks.isTaskRunning(task)) {
             // Ignore attempts to run the selected task if it is already running.
@@ -151,7 +155,8 @@
                 context.getDeviceProfile().overviewPageSpacing,
                 QuickStepContract.getWindowCornerRadius(context),
                 AnimationUtils.loadInterpolator(
-                        context, android.R.interpolator.fast_out_extra_slow_in)));
+                        context, android.R.interpolator.fast_out_extra_slow_in)),
+                "SlideInTransition");
         if (mOnDesktop) {
             UI_HELPER_EXECUTOR.execute(() ->
                     SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext())
@@ -185,7 +190,7 @@
         pw.println(prefix + "KeyboardQuickSwitchViewController:");
 
         pw.println(prefix + "\thasFocus=" + mKeyboardQuickSwitchView.hasFocus());
-        pw.println(prefix + "\tcloseAnimationRunning=" + (mCloseAnimation != null));
+        pw.println(prefix + "\tisCloseAnimationRunning=" + isCloseAnimationRunning());
         pw.println(prefix + "\tmCurrentFocusIndex=" + mCurrentFocusIndex);
     }
 
@@ -238,8 +243,7 @@
         }
 
         void launchTaskAt(int index) {
-            mCurrentFocusIndex = Utilities.boundToRange(
-                    index, 0, mKeyboardQuickSwitchView.getChildCount() - 1);
+            mCurrentFocusIndex = index;
             mControllers.taskbarActivityContext.launchKeyboardFocusedTask();
         }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 1e861d2..81f2c0f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -21,7 +21,6 @@
 import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
 import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_VISIBLE;
 import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -35,6 +34,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.QuickstepTransitionManager;
 import com.android.launcher3.R;
@@ -49,8 +49,10 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.OnboardingPrefs;
+import com.android.quickstep.HomeVisibilityState;
 import com.android.quickstep.LauncherActivityInterface;
 import com.android.quickstep.RecentsAnimationCallbacks;
+import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.GroupTask;
 import com.android.quickstep.util.TISBindHelper;
 import com.android.quickstep.views.RecentsView;
@@ -79,6 +81,7 @@
                     AnimatedFloat.VALUE, DISPLAY_PROGRESS_COUNT, Float::max);
 
     private final QuickstepLauncher mLauncher;
+    private final HomeVisibilityState mHomeState;
 
     private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
             dp -> {
@@ -87,6 +90,8 @@
                     mControllers.taskbarViewController.onRotationChanged(dp);
                 }
             };
+    private final HomeVisibilityState.VisibilityChangeListener  mVisibilityChangeListener =
+            this::onLauncherVisibilityChanged;
 
     // Initialized in init.
     private final TaskbarLauncherStateController
@@ -94,6 +99,7 @@
 
     public LauncherTaskbarUIController(QuickstepLauncher launcher) {
         mLauncher = launcher;
+        mHomeState =  SystemUiProxy.INSTANCE.get(mLauncher).getHomeVisibilityState();
     }
 
     @Override
@@ -104,8 +110,11 @@
                 mControllers.getSharedState().sysuiStateFlags);
 
         mLauncher.setTaskbarUIController(this);
-
-        onLauncherVisibilityChanged(mLauncher.hasBeenResumed(), true /* fromInit */);
+        mHomeState.addListener(mVisibilityChangeListener);
+        onLauncherVisibilityChanged(
+                Flags.useActivityOverlay()
+                        ? mHomeState.isHomeVisible() : mLauncher.hasBeenResumed(),
+                true /* fromInit */);
 
         onStashedInAppChanged(mLauncher.getDeviceProfile());
         mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
@@ -129,6 +138,7 @@
 
         mLauncher.setTaskbarUIController(null);
         mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
+        mHomeState.removeListener(mVisibilityChangeListener);
         updateTaskTransitionSpec(true);
     }
 
@@ -191,7 +201,7 @@
                         ? TRANSIENT_TASKBAR_TRANSITION_DURATION
                         : (!isVisible
                                 ? QuickstepTransitionManager.TASKBAR_TO_APP_DURATION
-                                : QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION));
+                                : QuickstepTransitionManager.getTaskbarToHomeDuration()));
     }
 
     @Nullable
@@ -209,19 +219,13 @@
         DesktopVisibilityController desktopController =
                 LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
         final boolean onDesktop =
-                isDesktopModeSupported()
-                        && desktopController != null
-                        && desktopController.areFreeformTasksVisible();
+                desktopController != null && desktopController.areDesktopTasksVisible();
         if (onDesktop) {
             isVisible = false;
         }
 
         mTaskbarLauncherStateController.updateStateForFlag(FLAG_VISIBLE, isVisible);
-        // TODO(b/308851855): Skip animation for launching split from home, will refine later
-        boolean skipAnimForSplit = enableSplitContextually() &&
-                mLauncher.areBothSplitAppsConfirmed() &&
-                mLauncher.getStateManager().getState() == LauncherState.NORMAL;
-        if (skipAnimForSplit || fromInit) {
+        if (fromInit) {
             duration = 0;
         }
         return mTaskbarLauncherStateController.applyState(duration, startAnimation);
@@ -234,7 +238,8 @@
 
     @Override
     public void refreshResumedState() {
-        onLauncherVisibilityChanged(mLauncher.hasBeenResumed());
+        onLauncherVisibilityChanged(Flags.useActivityOverlay()
+                ? mHomeState.isHomeVisible() : mLauncher.hasBeenResumed());
     }
 
     @Override
@@ -299,6 +304,8 @@
      */
     public void showEduOnAppLaunch() {
         if (!shouldShowEduOnAppLaunch()) {
+            // Called in case the edu finishes and circle to search edu is still pending
+            mControllers.taskbarEduTooltipController.maybeShowCircleToSearchEdu();
             return;
         }
 
@@ -312,6 +319,11 @@
         mControllers.taskbarEduTooltipController.maybeShowSwipeEdu();
     }
 
+    /** Will make the next onRecentsAnimationFinished() animation a no-op. */
+    public void setSkipNextRecentsAnimEnd() {
+        mTaskbarLauncherStateController.setSkipNextRecentsAnimEnd();
+    }
+
     /**
      * Returns {@code true} if a Taskbar education should be shown on application launch.
      */
@@ -409,8 +421,15 @@
     }
 
     @Override
-    protected boolean isInOverview() {
-        return mTaskbarLauncherStateController.isInOverview();
+    protected boolean isInOverviewUi() {
+        return mTaskbarLauncherStateController.isInOverviewUi();
+    }
+
+    @Override
+    protected boolean canToggleHomeAllApps() {
+        return mLauncher.isResumed()
+                && !mTaskbarLauncherStateController.isInOverviewUi()
+                && !mLauncher.areDesktopTasksVisible();
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 2f11fd7..2c5aeb3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -142,6 +142,9 @@
 
     private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
 
+    private static final double SQUARE_ASPECT_RATIO_BOTTOM_BOUND = 0.95;
+    private static final double SQUARE_ASPECT_RATIO_UPPER_BOUND = 1.05;
+
     public static final int ALPHA_INDEX_IMMERSIVE_MODE = 0;
     public static final int ALPHA_INDEX_KEYGUARD_OR_DISABLE = 1;
     public static final int ALPHA_INDEX_SUW = 2;
@@ -735,18 +738,39 @@
         // end-aligned, so start-align instead.
         FrameLayout.LayoutParams navButtonsLayoutParams = (FrameLayout.LayoutParams)
                 mNavButtonContainer.getLayoutParams();
+        FrameLayout.LayoutParams navButtonsViewLayoutParams = (FrameLayout.LayoutParams)
+                mNavButtonsView.getLayoutParams();
         Resources resources = mContext.getResources();
         DeviceProfile deviceProfile = mContext.getDeviceProfile();
-        int setupMargin = resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_margin);
-        navButtonsLayoutParams.setMarginStart(setupMargin);
-        navButtonsLayoutParams.bottomMargin = !deviceProfile.isLandscape
-                ? 0
-                : setupMargin -
-                        (resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2);
+
         navButtonsLayoutParams.setMarginEnd(0);
         navButtonsLayoutParams.gravity = Gravity.START;
-        mNavButtonsView.getLayoutParams().height =
-                mControllers.taskbarActivityContext.getSetupWindowSize();
+        mControllers.taskbarActivityContext.setTaskbarWindowSize(
+                mControllers.taskbarActivityContext.getSetupWindowSize());
+
+        // If SUW is on a large screen device that is landscape (or has a square aspect
+        // ratio) the back button has to be placed accordingly
+        if ((deviceProfile.isTablet && deviceProfile.isLandscape)
+                || (deviceProfile.aspectRatio > SQUARE_ASPECT_RATIO_BOTTOM_BOUND
+                && deviceProfile.aspectRatio < SQUARE_ASPECT_RATIO_UPPER_BOUND)) {
+            navButtonsLayoutParams.setMarginStart(
+                    resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_start_margin));
+            navButtonsViewLayoutParams.bottomMargin = resources.getDimensionPixelSize(
+                    R.dimen.taskbar_back_button_suw_bottom_margin);
+            navButtonsLayoutParams.height = resources.getDimensionPixelSize(
+                    R.dimen.taskbar_back_button_suw_height);
+        } else {
+            int phoneOrPortraitSetupMargin = resources.getDimensionPixelSize(
+                    R.dimen.taskbar_contextual_button_suw_margin);
+            navButtonsLayoutParams.setMarginStart(phoneOrPortraitSetupMargin);
+            navButtonsLayoutParams.bottomMargin = !deviceProfile.isLandscape
+                    ? 0
+                    : phoneOrPortraitSetupMargin - (resources.getDimensionPixelSize(
+                            R.dimen.taskbar_nav_buttons_size) / 2);
+            navButtonsViewLayoutParams.height = resources.getDimensionPixelSize(
+                    R.dimen.taskbar_contextual_button_suw_height);
+        }
+        mNavButtonsView.setLayoutParams(navButtonsViewLayoutParams);
         mNavButtonContainer.setLayoutParams(navButtonsLayoutParams);
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 1047374..49d4afe 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -17,6 +17,7 @@
 
 import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.os.Trace.TRACE_TAG_APP;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -36,14 +37,12 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
 import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_FULLSCREEN;
-import static com.android.launcher3.taskbar.TaskbarDragLayerController.TASKBAR_REAPPEAR_DELAY_MS;
 import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
 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 android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.ActivityOptions;
 import android.content.ActivityNotFoundException;
@@ -81,7 +80,6 @@
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.R;
-import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.apppairs.AppPairIcon;
 import com.android.launcher3.config.FeatureFlags;
@@ -101,6 +99,7 @@
 import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
 import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
 import com.android.launcher3.taskbar.bubbles.BubbleBarController;
+import com.android.launcher3.taskbar.bubbles.BubbleBarPinController;
 import com.android.launcher3.taskbar.bubbles.BubbleBarView;
 import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
 import com.android.launcher3.taskbar.bubbles.BubbleControllers;
@@ -114,8 +113,8 @@
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.touch.ItemClickHandler.ItemClickProxy;
-import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.ActivityOptionsWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.Executors;
@@ -257,7 +256,10 @@
                     new BubbleStashController(this),
                     new BubbleStashedHandleViewController(this, bubbleHandleView),
                     new BubbleDragController(this),
-                    new BubbleDismissController(this, mDragLayer)));
+                    new BubbleDismissController(this, mDragLayer),
+                    new BubbleBarPinController(this, mDragLayer,
+                            () -> getDeviceProfile().getDisplayInfo().currentSize)
+            ));
         }
 
         // Construct controllers.
@@ -663,7 +665,7 @@
 
         LauncherAtom.TaskBarContainer.Builder taskbarBuilder =
                 LauncherAtom.TaskBarContainer.newBuilder();
-        if (mControllers.uiController.isInOverview()) {
+        if (mControllers.uiController.isInOverviewUi()) {
             taskbarBuilder.setTaskSwitcherContainer(
                     LauncherAtom.TaskSwitcherContainer.newBuilder());
         }
@@ -1092,7 +1094,6 @@
         } else if (tag instanceof AppPairInfo api) {
             // Tapping an app pair icon on Taskbar
             if (recents != null && recents.isSplitSelectionActive()) {
-                // TODO (b/274835596): Implement "can't split with this" bounce animation
                 Toast.makeText(this, "Unable to split with an app pair. Select another app.",
                         Toast.LENGTH_SHORT).show();
             } else {
@@ -1119,7 +1120,7 @@
                         } else if (info.isPromise()) {
                             TestLogging.recordEvent(
                                     TestProtocol.SEQUENCE_MAIN, "start: taskbarPromiseIcon");
-                            intent = ApiWrapper.getAppMarketActivityIntent(this,
+                            intent = ApiWrapper.INSTANCE.get(this).getAppMarketActivityIntent(
                                     info.getTargetPackage(), Process.myUserHandle());
                             startActivity(intent);
 
@@ -1216,7 +1217,7 @@
                     .handleAppPairLaunchInApp((AppPairIcon) launchingIconView, itemInfos);
         } else {
             // Tapped a single app, nothing complicated here.
-            startItemInfoActivity(itemInfos.get(0));
+            startItemInfoActivity(itemInfos.get(0), null /*foundTask*/);
         }
     }
 
@@ -1232,13 +1233,13 @@
             return;
         }
 
-        boolean findExactPairMatch = itemInfos.size() == 2;
+        boolean isLaunchingAppPair = itemInfos.size() == 2;
         // Convert the list of ItemInfo instances to a list of ComponentKeys
         List<ComponentKey> componentKeys =
                 itemInfos.stream().map(ItemInfo::getComponentKey).toList();
         recents.getSplitSelectController().findLastActiveTasksAndRunCallback(
                 componentKeys,
-                findExactPairMatch,
+                isLaunchingAppPair,
                 foundTasks -> {
                     @Nullable Task foundTask = foundTasks[0];
                     if (foundTask != null) {
@@ -1252,24 +1253,50 @@
                         }
                     }
 
-                    if (findExactPairMatch) {
-                        // We did not find the app pair we were looking for, so launch one.
-                        recents.getSplitSelectController().getAppPairsController().launchAppPair(
-                                (AppPairIcon) launchingIconView, -1 /*cuj*/);
+                    if (isLaunchingAppPair) {
+                        // Finish recents animation if it's running before launching to ensure
+                        // we get both leashes for the animation
+                        mControllers.uiController.setSkipNextRecentsAnimEnd();
+                        recents.switchToScreenshot(() ->
+                                recents.finishRecentsAnimation(true /*toRecents*/,
+                                        false /*shouldPip*/,
+                                        () -> recents
+                                                .getSplitSelectController()
+                                                .getAppPairsController()
+                                                .launchAppPair((AppPairIcon) launchingIconView,
+                                                        -1 /*cuj*/)));
                     } else {
-                        startItemInfoActivity(itemInfos.get(0));
+                        startItemInfoActivity(itemInfos.get(0), foundTask);
                     }
                 }
         );
     }
 
-    private void startItemInfoActivity(ItemInfo info) {
+    /**
+     * Starts an activity with the information provided by the "info" param. However, if
+     * taskInRecents is present, it will prioritize re-launching an existing instance via
+     * {@link ActivityManagerWrapper#startActivityFromRecents(int, ActivityOptions)}
+     */
+    private void startItemInfoActivity(ItemInfo info, @Nullable Task taskInRecents) {
         Intent intent = new Intent(info.getIntent())
                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         try {
             TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: taskbarAppIcon");
             if (info.user.equals(Process.myUserHandle())) {
                 // TODO(b/216683257): Use startActivityForResult for search results that require it.
+                if (taskInRecents != null) {
+                    // Re launch instance from recents
+                    ActivityOptionsWrapper opts = getActivityLaunchOptions(null, info);
+                    opts.options.setLaunchDisplayId(
+                            getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
+                    if (ActivityManagerWrapper.getInstance()
+                            .startActivityFromRecents(taskInRecents.key, opts.options)) {
+                        mControllers.uiController.getRecentsView()
+                                .addSideTaskLaunchCallback(opts.onEndCallback);
+                        return;
+                    }
+                }
+
                 startActivity(intent);
             } else {
                 getSystemService(LauncherApps.class).startMainActivity(
@@ -1328,8 +1355,12 @@
      * Called when we want to unstash taskbar when user performs swipes up gesture.
      */
     public void onSwipeToUnstashTaskbar() {
-        VibratorWrapper.INSTANCE.get(this).vibrateForTaskbarUnstash();
+        boolean wasStashed = mControllers.taskbarStashController.isStashed();
         mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(/* stash= */ false);
+        boolean isStashed = mControllers.taskbarStashController.isStashed();
+        if (isStashed != wasStashed) {
+            VibratorWrapper.INSTANCE.get(this).vibrateForTaskbarUnstash();
+        }
         mControllers.taskbarEduTooltipController.hide();
     }
 
@@ -1411,23 +1442,6 @@
         });
     }
 
-    public void hideTaskbarWhenFolding() {
-        AnimatedFloat alphaAnim = mControllers.taskbarDragLayerController.getTaskbarAlpha();
-        alphaAnim.cancelAnimation();
-        alphaAnim.updateValue(0);
-        ObjectAnimator animator = alphaAnim.animateToValue(1).setDuration(0);
-        animator.setStartDelay(TASKBAR_REAPPEAR_DELAY_MS);
-        animator.start();
-    }
-
-    public void cancelHideTaskbarWhenFolding() {
-        mControllers.taskbarDragLayerController.getTaskbarAlpha().cancelAnimation();
-    }
-
-    public void resetHideTaskbarWhenUnfolding() {
-        mControllers.taskbarDragLayerController.getTaskbarAlpha().updateValue(1);
-    }
-
     protected boolean isUserSetupComplete() {
         return mIsUserSetupComplete;
     }
@@ -1559,4 +1573,13 @@
     public float getStashedTaskbarScale() {
         return mControllers.stashedHandleViewController.getStashedHandleHintScale().value;
     }
+
+    /** Closes the KeyboardQuickSwitchView without an animation if open. */
+    public void closeKeyboardQuickSwitchView() {
+        mControllers.keyboardQuickSwitchController.closeQuickSwitchView(false);
+    }
+
+    boolean canToggleHomeAllApps() {
+        return mControllers.uiController.canToggleHomeAllApps();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index e48c20d..ff890fb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -44,12 +44,6 @@
     private static final boolean DEBUG = SystemProperties.getBoolean(
             "persist.debug.draw_taskbar_debug_ui", false);
 
-    // Delay to reset the task bar alpha back to 1 after fading it for transition from unfold to
-    // fold. Normally this is not needed since the new task bar is recreated after fading, but in
-    // case something goes wrong this provides a fallback mechanism to make sure the task bar is
-    // visible after the transition finishes.
-    public static final long TASKBAR_REAPPEAR_DELAY_MS = 2000;
-
     private final TaskbarActivityContext mActivity;
     private final TaskbarDragLayer mTaskbarDragLayer;
     private final int mFolderMargin;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
index 7eed955..e53f627 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduTooltipController.kt
@@ -15,7 +15,12 @@
  */
 package com.android.launcher3.taskbar
 
+import android.content.Intent
+import android.net.Uri
 import android.os.Bundle
+import android.text.SpannableString
+import android.text.method.LinkMovementMethod
+import android.text.style.URLSpan
 import android.view.Gravity
 import android.view.View
 import android.view.View.GONE
@@ -24,16 +29,20 @@
 import android.view.ViewGroup.MarginLayoutParams
 import android.view.accessibility.AccessibilityEvent
 import android.view.accessibility.AccessibilityNodeInfo
+import android.widget.TextView
 import androidx.annotation.IntDef
 import androidx.annotation.LayoutRes
+import androidx.core.text.HtmlCompat
 import androidx.core.view.updateLayoutParams
 import com.airbnb.lottie.LottieAnimationView
+import com.android.launcher3.LauncherPrefs
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.launcher3.config.FeatureFlags.enableTaskbarPinning
 import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
 import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
 import com.android.launcher3.util.DisplayController
+import com.android.launcher3.util.OnboardingPrefs.TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN
 import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
 import com.android.launcher3.views.BaseDragLayer
 import com.android.quickstep.util.LottieAnimationColorUtils
@@ -52,6 +61,10 @@
  * This value should match the maximum count for [TASKBAR_EDU_TOOLTIP_STEP].
  */
 const val TOOLTIP_STEP_NONE = 3
+/** The base URL for the Privacy Policy that will later be localized. */
+private const val PRIVACY_POLICY_BASE_URL = "https://policies.google.com/privacy/embedded?hl="
+/** The base URL for the Terms of Service that will later be localized. */
+private const val TOS_BASE_URL = "https://policies.google.com/terms?hl="
 
 /** Current step in the tooltip EDU flow. */
 @Retention(AnnotationRetention.SOURCE)
@@ -70,6 +83,15 @@
         get() = isTooltipEnabled && tooltipStep <= TOOLTIP_STEP_FEATURES
     private lateinit var controllers: TaskbarControllers
 
+    // Keep track of whether the user has seen the Circle to Search Edu
+    private var userHasSeenCircleToSearchEdu: Boolean
+        get() {
+            return TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN.get(activityContext)
+        }
+        private set(seen) {
+            LauncherPrefs.get(activityContext).put(TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN, seen)
+        }
+
     @TaskbarEduTooltipStep
     var tooltipStep: Int
         get() {
@@ -83,6 +105,8 @@
 
     fun init(controllers: TaskbarControllers) {
         this.controllers = controllers
+        // We want to show the Circle To Search Edu right after pinning, so we post it here
+        activityContext.dragLayer.post { maybeShowCircleToSearchEdu() }
     }
 
     /** Shows swipe EDU tooltip if it is the current [tooltipStep]. */
@@ -112,6 +136,7 @@
     fun maybeShowFeaturesEdu() {
         if (!isTooltipEnabled || tooltipStep > TOOLTIP_STEP_FEATURES) {
             maybeShowPinningEdu()
+            maybeShowCircleToSearchEdu()
             return
         }
 
@@ -207,6 +232,96 @@
         }
     }
 
+    /**
+     * Shows standalone Circle To Search EDU tooltip if this EDU has not been seen.
+     *
+     * We show this standalone edu for users to learn to how to trigger Circle To Search from the
+     * pinned taskbar
+     */
+    fun maybeShowCircleToSearchEdu() {
+        if (
+            !enableTaskbarPinning() ||
+                !DisplayController.isPinnedTaskbar(activityContext) ||
+                !isTooltipEnabled ||
+                userHasSeenCircleToSearchEdu
+        ) {
+            return
+        }
+        userHasSeenCircleToSearchEdu = true
+        inflateTooltip(R.layout.taskbar_edu_circle_to_search)
+        tooltip?.run {
+            requireViewById<LottieAnimationView>(R.id.circle_to_search_animation)
+                .supportLightTheme()
+            val eduSubtitle: TextView = requireViewById(R.id.circle_to_search_text)
+            showDisclosureText(eduSubtitle)
+            updateLayoutParams<BaseDragLayer.LayoutParams> {
+                if (DisplayController.isTransientTaskbar(activityContext)) {
+                    bottomMargin += activityContext.deviceProfile.taskbarHeight
+                }
+                // Unlike other tooltips, we want to align with the all apps button rather than
+                // center.
+                gravity = Gravity.BOTTOM
+                marginStart = 0
+                width =
+                    resources.getDimensionPixelSize(
+                        R.dimen.taskbar_edu_features_tooltip_width_with_one_feature
+                    )
+            }
+
+            // Calculate the amount the tooltip must be shifted by to align with the action key
+            val allAppsButtonView = controllers.taskbarViewController.allAppsButtonView
+            if (allAppsButtonView != null) {
+                val allAppsIconLocation = allAppsButtonView.x + allAppsButtonView.width / 2
+                x = allAppsIconLocation - layoutParams.width / 2
+            }
+
+            show()
+        }
+    }
+
+    /**
+     * Set up the provided TextView to display legal disclosures. The method takes locale into
+     * account to show the appropriate links to regional disclosures.
+     */
+    private fun TaskbarEduTooltip.showDisclosureText(
+        textView: TextView,
+        stringId: Int = R.string.taskbar_edu_circle_to_search_disclosure,
+    ) {
+        val locale = resources.configuration.locales[0]
+        val text =
+            SpannableString(
+                HtmlCompat.fromHtml(
+                    resources.getString(
+                        stringId,
+                        PRIVACY_POLICY_BASE_URL + locale.language,
+                        TOS_BASE_URL + locale.language,
+                    ),
+                    HtmlCompat.FROM_HTML_MODE_COMPACT,
+                )
+            )
+        // Directly process URLSpan clicks
+        text.getSpans(0, text.length, URLSpan::class.java).forEach { urlSpan ->
+            val url: URLSpan =
+                object : URLSpan(urlSpan.url) {
+                    override fun onClick(widget: View) {
+                        val uri = Uri.parse(urlSpan.url)
+                        val context = widget.context
+                        val intent =
+                            Intent(Intent.ACTION_VIEW, uri).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                        context.startActivity(intent)
+                    }
+                }
+
+            val spanStart = text.getSpanStart(urlSpan)
+            val spanEnd = text.getSpanEnd(urlSpan)
+            val spanFlags = text.getSpanFlags(urlSpan)
+            text.removeSpan(urlSpan)
+            text.setSpan(url, spanStart, spanEnd, spanFlags)
+        }
+        textView.text = text
+        textView.movementMethod = LinkMovementMethod.getInstance()
+    }
+
     /** Closes the current [tooltip]. */
     fun hide() = tooltip?.close(true)
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 8dc81cf..6163dad 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -375,7 +375,7 @@
         ) {
             // Taskbar has some touchable elements, take over the full taskbar area
             if (
-                controllers.uiController.isInOverview &&
+                controllers.uiController.isInOverviewUi &&
                     DisplayController.isTransientTaskbar(context)
             ) {
                 val region =
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 259af1d..17dcace 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -148,6 +148,7 @@
     private Integer mPrevState;
     private int mState;
     private LauncherState mLauncherState = LauncherState.NORMAL;
+    private boolean mSkipNextRecentsAnimEnd;
 
     // Time when FLAG_TASKBAR_HIDDEN was last cleared, SystemClock.elapsedRealtime (milliseconds).
     private long mLastUnlockTimeMs = 0;
@@ -193,7 +194,7 @@
                     updateStateForFlag(FLAG_LAUNCHER_IN_STATE_TRANSITION, true);
                     if (!mShouldDelayLauncherStateAnim) {
                         if (toState == LauncherState.NORMAL) {
-                            applyState(QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION);
+                            applyState(QuickstepTransitionManager.getTaskbarToHomeDuration());
                         } else {
                             applyState();
                         }
@@ -292,12 +293,12 @@
 
         if (mTaskBarRecentsAnimationListener != null) {
             mTaskBarRecentsAnimationListener.endGestureStateOverride(
-                    !mLauncher.isInState(LauncherState.OVERVIEW));
+                    !mLauncher.isInState(LauncherState.OVERVIEW), false /*canceled*/);
         }
         mTaskBarRecentsAnimationListener = new TaskBarRecentsAnimationListener(callbacks);
         callbacks.addListener(mTaskBarRecentsAnimationListener);
         ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(() ->
-                mTaskBarRecentsAnimationListener.endGestureStateOverride(true));
+                mTaskBarRecentsAnimationListener.endGestureStateOverride(true, false /*canceled*/));
 
         ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchCancelledRunnable(() -> {
             updateStateForUserFinishedToApp(false /* finishedToApp */);
@@ -318,6 +319,11 @@
         mShouldDelayLauncherStateAnim = shouldDelayLauncherStateAnim;
     }
 
+    /** Will make the next onRecentsAnimationFinished() a no-op. */
+    public void setSkipNextRecentsAnimEnd() {
+        mSkipNextRecentsAnimEnd = true;
+    }
+
     /** SysUI flags updated, see QuickStepContract.SYSUI_STATE_* values. */
     public void updateStateForSysuiFlags(int systemUiStateFlags) {
         updateStateForSysuiFlags(systemUiStateFlags, /* applyState */ true);
@@ -656,11 +662,12 @@
      * Returns if the current Launcher state has hotseat on top of other elemnets.
      */
     public boolean isInHotseatOnTopStates() {
-        return mLauncherState != LauncherState.ALL_APPS;
+        return mLauncherState != LauncherState.ALL_APPS
+                && !mLauncher.getWorkspace().isOverlayShown();
     }
 
-    boolean isInOverview() {
-        return mLauncherState == LauncherState.OVERVIEW;
+    boolean isInOverviewUi() {
+        return mLauncherState.overviewUi;
     }
 
     private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
@@ -770,19 +777,33 @@
         @Override
         public void onRecentsAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
             boolean isInOverview = mLauncher.isInState(LauncherState.OVERVIEW);
-            endGestureStateOverride(!isInOverview);
+            endGestureStateOverride(!isInOverview, true /*canceled*/);
         }
 
         @Override
         public void onRecentsAnimationFinished(RecentsAnimationController controller) {
-            endGestureStateOverride(!controller.getFinishTargetIsLauncher());
+            endGestureStateOverride(!controller.getFinishTargetIsLauncher(), false /*canceled*/);
         }
 
-        private void endGestureStateOverride(boolean finishedToApp) {
+        /**
+         * Handles whatever cleanup is needed after the recents animation is completed.
+         * NOTE: If {@link #mSkipNextRecentsAnimEnd} is set and we're coming from a non-cancelled
+         * path, this will not call {@link #updateStateForUserFinishedToApp(boolean)}
+         *
+         * @param finishedToApp {@code true} if the recents animation finished to showing an app and
+         *                      not workspace or overview
+         * @param canceled {@code true} if the recents animation was canceled instead of finishing
+         *                 to completion
+         */
+        private void endGestureStateOverride(boolean finishedToApp, boolean canceled) {
             mCallbacks.removeListener(this);
             mTaskBarRecentsAnimationListener = null;
             ((RecentsView) mLauncher.getOverviewPanel()).setTaskLaunchListener(null);
 
+            if (mSkipNextRecentsAnimEnd && !canceled) {
+                mSkipNextRecentsAnimEnd = false;
+                return;
+            }
             updateStateForUserFinishedToApp(finishedToApp);
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index ff33ca9..e47640b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -23,14 +23,12 @@
 
 import static com.android.launcher3.BaseActivity.EVENT_DESTROYED;
 import static com.android.launcher3.Flags.enableUnfoldStateAnimation;
-import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate;
 import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
 import static com.android.launcher3.util.DisplayController.CHANGE_TASKBAR_PINNING;
 import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange;
 import static com.android.quickstep.util.SystemActionConstants.ACTION_SHOW_TASKBAR;
@@ -44,7 +42,6 @@
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
-import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
 import android.os.Handler;
@@ -61,6 +58,7 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.statemanager.StatefulActivity;
@@ -69,6 +67,7 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.SettingsCache;
 import com.android.launcher3.util.SimpleBroadcastReceiver;
+import com.android.quickstep.AllAppsActionManager;
 import com.android.quickstep.RecentsActivity;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TouchInteractionService;
@@ -111,7 +110,6 @@
 
     private final Context mContext;
     private final @Nullable Context mNavigationBarPanelContext;
-    private final DeviceStateManager mDeviceStateManager;
     private WindowManager mWindowManager;
     private FrameLayout mTaskbarRootLayout;
     private boolean mAddedWindow;
@@ -158,6 +156,8 @@
     private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver =
             new SimpleBroadcastReceiver(this::showTaskbarFromBroadcast);
 
+    private final AllAppsActionManager mAllAppsActionManager;
+
     private final Runnable mActivityOnDestroyCallback = new Runnable() {
         @Override
         public void run() {
@@ -178,8 +178,7 @@
         }
     };
 
-    private final UnfoldTransitionProgressProvider.TransitionProgressListener
-            mUnfoldTransitionProgressListener =
+    UnfoldTransitionProgressProvider.TransitionProgressListener mUnfoldTransitionProgressListener =
             new UnfoldTransitionProgressProvider.TransitionProgressListener() {
                 @Override
                 public void onTransitionStarted() {
@@ -208,16 +207,15 @@
                 }
             };
 
-    private final DeviceStateManager.FoldStateListener mFoldStateListener;
-    private Boolean mFolded;
-
     @SuppressLint("WrongConstant")
-    public TaskbarManager(TouchInteractionService service) {
+    public TaskbarManager(
+            TouchInteractionService service, AllAppsActionManager allAppsActionManager) {
         Display display =
                 service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
         mContext = service.createWindowContext(display,
                 ENABLE_TASKBAR_NAVBAR_UNIFICATION ? TYPE_NAVIGATION_BAR : TYPE_NAVIGATION_BAR_PANEL,
                 null);
+        mAllAppsActionManager = allAppsActionManager;
         mNavigationBarPanelContext = ENABLE_TASKBAR_NAVBAR_UNIFICATION
                 ? service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null)
                 : null;
@@ -236,29 +234,6 @@
                 }
             };
         }
-        // Temporary solution to mitigate the visual jump from folding the device. Currently, the
-        // screen turns on much earlier than we receive the onConfigurationChanged callback or
-        // receiving the correct device profile. While the ideal the solution is to align turning
-        // the screen on after onConfigurationChanged (by either delaying turning on the screen or
-        // figuring out what is causing the delay in getting onConfigurationChanged callback), one
-        // easy temporary mitigation is to dimming the bar so that the visual jump isn't as glaring.
-        mFoldStateListener = new DeviceStateManager.FoldStateListener(mContext, folded -> {
-            boolean firstTime = mFolded == null;
-            if (mTaskbarActivityContext == null) {
-                return;
-            }
-            if (!firstTime && mFolded.booleanValue() != folded) {
-                mTaskbarActivityContext.cancelHideTaskbarWhenFolding();
-            }
-            mFolded = folded;
-            if (folded && !firstTime) {
-                mTaskbarActivityContext.hideTaskbarWhenFolding();
-            } else {
-                mTaskbarActivityContext.resetHideTaskbarWhenUnfolding();
-            }
-        });
-        mDeviceStateManager = mContext.getSystemService(DeviceStateManager.class);
-        mDeviceStateManager.registerCallback(MAIN_EXECUTOR, mFoldStateListener);
         mNavButtonController = new TaskbarNavButtonController(service,
                 SystemUiProxy.INSTANCE.get(mContext), new Handler(),
                 AssistUtils.newInstance(mContext));
@@ -291,10 +266,10 @@
                     recreateTaskbar();
                 } else {
                     // Config change might be handled without re-creating the taskbar
-                    if (dp != null && !isTaskbarPresent(dp)) {
+                    if (dp != null && !isTaskbarEnabled(dp)) {
                         destroyExistingTaskbar();
                     } else {
-                        if (dp != null && isTaskbarPresent(dp)) {
+                        if (dp != null && isTaskbarEnabled(dp)) {
                             if (ENABLE_TASKBAR_NAVBAR_UNIFICATION) {
                                 // Re-initialize for screen size change? Should this be done
                                 // by looking at screen-size change flag in configDiff in the
@@ -349,7 +324,7 @@
         }
         DeviceProfile dp = mUserUnlocked ?
                 LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
-        if (dp == null || !isTaskbarPresent(dp)) {
+        if (dp == null || !isTaskbarEnabled(dp)) {
             removeTaskbarRootViewFromWindow();
         }
     }
@@ -365,24 +340,15 @@
 
     /**
      * Toggles All Apps for Taskbar or Launcher depending on the current state.
-     *
-     * @param homeAllAppsIntent Intent used if Taskbar is not enabled or Launcher is resumed.
      */
-    public void toggleAllApps(Intent homeAllAppsIntent) {
-        if (mTaskbarActivityContext == null) {
-            mContext.startActivity(homeAllAppsIntent);
-            return;
+    public void toggleAllApps() {
+        if (mTaskbarActivityContext == null || mTaskbarActivityContext.canToggleHomeAllApps()) {
+            // Home All Apps should be toggled from this class, because the controllers are not
+            // initialized when Taskbar is disabled (i.e. TaskbarActivityContext is null).
+            if (mActivity instanceof Launcher l) l.toggleAllAppsSearch();
+        } else {
+            mTaskbarActivityContext.toggleAllAppsSearch();
         }
-
-        if (mActivity != null
-                && mActivity.isResumed()
-                && !mActivity.isInState(OVERVIEW)
-                && !(mActivity instanceof QuickstepLauncher l && l.areFreeformTasksVisible())) {
-            mContext.startActivity(homeAllAppsIntent);
-            return;
-        }
-
-        mTaskbarActivityContext.toggleAllAppsSearch();
     }
 
     /**
@@ -477,9 +443,13 @@
             DeviceProfile dp = mUserUnlocked ?
                 LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
 
+            // All Apps action is unrelated to navbar unification, so we only need to check DP.
+            final boolean isLargeScreenTaskbar = dp != null && dp.isTaskbarPresent;
+            mAllAppsActionManager.setTaskbarPresent(isLargeScreenTaskbar);
+
             destroyExistingTaskbar();
 
-            boolean isTaskbarEnabled = dp != null && isTaskbarPresent(dp);
+            boolean isTaskbarEnabled = dp != null && isTaskbarEnabled(dp);
             debugWhyTaskbarNotDestroyed("recreateTaskbar: isTaskbarEnabled=" + isTaskbarEnabled
                 + " [dp != null (i.e. mUserUnlocked)]=" + (dp != null)
                 + " FLAG_HIDE_NAVBAR_WINDOW=" + ENABLE_TASKBAR_NAVBAR_UNIFICATION
@@ -499,6 +469,7 @@
             }
             mSharedState.startTaskbarVariantIsTransient =
                     DisplayController.isTransientTaskbar(mTaskbarActivityContext);
+            mSharedState.allAppsVisible = mSharedState.allAppsVisible && isLargeScreenTaskbar;
             mTaskbarActivityContext.init(mSharedState);
 
             if (mActivity != null) {
@@ -544,7 +515,7 @@
         }
     }
 
-    private static boolean isTaskbarPresent(DeviceProfile deviceProfile) {
+    private static boolean isTaskbarEnabled(DeviceProfile deviceProfile) {
         return ENABLE_TASKBAR_NAVBAR_UNIFICATION || deviceProfile.isTaskbarPresent;
     }
 
@@ -621,7 +592,6 @@
         Log.d(TASKBAR_NOT_DESTROYED_TAG, "unregistering component callbacks from destroy().");
         mContext.unregisterComponentCallbacks(mComponentCallbacks);
         mContext.unregisterReceiver(mShutdownReceiver);
-        mDeviceStateManager.unregisterCallback(mFoldStateListener);
     }
 
     public @Nullable TaskbarActivityContext getCurrentActivityContext() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 19293b5..03f55ca 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -27,7 +27,6 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_IME_SWITCHER_BUTTON_TAP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_LONGPRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_OVERVIEW_BUTTON_TAP;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
@@ -281,12 +280,10 @@
     private void navigateHome() {
         TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
 
-        if (isDesktopModeSupported()) {
-            DesktopVisibilityController desktopVisibilityController =
-                    LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
-            if (desktopVisibilityController != null) {
-                desktopVisibilityController.onHomeActionTriggered();
-            }
+        DesktopVisibilityController desktopVisibilityController =
+                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+        if (desktopVisibilityController != null) {
+            desktopVisibilityController.onHomeActionTriggered();
         }
 
         mService.getOverviewCommandHelper().addCommand(OverviewCommandHelper.TYPE_HOME);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 689a1ec..15be8e7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -598,7 +598,8 @@
                             ? stashTranslation : 0)
                     .setDuration(duration));
             mAnimator.play(mTaskbarImeBgAlpha.animateToValue(
-                    hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
+                    (hasAnyFlag(FLAG_STASHED_IN_APP_IME) && isStashed) ? 0 : 1).setDuration(
+                    duration));
             mAnimator.addListener(AnimatorListeners.forEndCallback(() -> {
                 mAnimator = null;
                 mIsStashed = isStashed;
@@ -984,7 +985,7 @@
         DesktopVisibilityController visibilityController =
                 LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
         if (visibilityController != null && mActivity.isHardwareKeyboard()
-                && mActivity.isThreeButtonNav() && visibilityController.areFreeformTasksVisible()) {
+                && mActivity.isThreeButtonNav() && visibilityController.areDesktopTasksVisible()) {
             return false;
         }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index efe1e39..2e78489 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -193,7 +193,12 @@
     }
 
     /** Returns {@code true} if Taskbar is currently within overview. */
-    protected boolean isInOverview() {
+    protected boolean isInOverviewUi() {
+        return false;
+    }
+
+    /** Returns {@code true} if Home All Apps available instead of Taskbar All Apps. */
+    protected boolean canToggleHomeAllApps() {
         return false;
     }
 
@@ -394,4 +399,12 @@
         mControllers.taskbarStashController.updateStateForFlag(FLAG_IN_APP, !isVisible);
         mControllers.taskbarStashController.applyState();
     }
+
+    /**
+     * Request for UI controller to ignore animations for the next callback for the end of recents
+     * animation
+     */
+    public void setSkipNextRecentsAnimEnd() {
+        // Overridden
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 67b41c6..effef3c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -32,6 +32,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.util.AttributeSet;
+import android.view.DisplayCutout;
 import android.view.InputDevice;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -134,7 +135,7 @@
 
         int actualMargin = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
         int actualIconSize = mActivityContext.getDeviceProfile().taskbarIconSize;
-        if (enableTaskbarPinning()) {
+        if (enableTaskbarPinning() && !mActivityContext.isThreeButtonNav()) {
             DeviceProfile deviceProfile = mActivityContext.getTransientTaskbarDeviceProfile();
             actualIconSize = deviceProfile.taskbarIconSize;
         }
@@ -273,7 +274,7 @@
             mAllAppsButton.setHapticFeedbackEnabled(
                     mControllerCallbacks.isAllAppsButtonHapticFeedbackEnabled());
         }
-        if (mTaskbarDivider != null) {
+        if (mTaskbarDivider != null && !mActivityContext.isThreeButtonNav()) {
             mTaskbarDivider.setOnLongClickListener(
                     mControllerCallbacks.getTaskbarDividerLongClickListener());
             mTaskbarDivider.setOnTouchListener(
@@ -472,6 +473,29 @@
             iconEnd = centerAlignIconEnd + offset;
         }
 
+        // Currently, we support only one device with display cutout and we only are concern about
+        // it when the bottom rect is present and non empty
+        DisplayCutout displayCutout = getDisplay().getCutout();
+        if (displayCutout != null && !displayCutout.getBoundingRectBottom().isEmpty()) {
+            Rect cutoutBottomRect = displayCutout.getBoundingRectBottom();
+            // when cutout present at the bottom of screen align taskbar icons to cutout offset
+            // if taskbar icon overlaps with cutout
+            int taskbarIconLeftBound = iconEnd - spaceNeeded;
+            int taskbarIconRightBound = iconEnd;
+
+            boolean doesTaskbarIconsOverlapWithCutout =
+                    taskbarIconLeftBound <= cutoutBottomRect.centerX()
+                            && cutoutBottomRect.centerX() <= taskbarIconRightBound;
+
+            if (doesTaskbarIconsOverlapWithCutout) {
+                if (!layoutRtl) {
+                    iconEnd = spaceNeeded + cutoutBottomRect.width();
+                } else {
+                    iconEnd = right - cutoutBottomRect.width();
+                }
+            }
+        }
+
         sTmpRect.set(mIconLayoutBounds);
 
         // Layout the children
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 1f7f0a7..5d0eac3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -337,11 +337,6 @@
     private void updateTaskbarIconTranslationXForPinning() {
         View[] iconViews = mTaskbarView.getIconViews();
         float scale = mTaskbarIconTranslationXForPinning.value;
-        float taskbarCenterX =
-                mTaskbarView.getLeft() + (mTaskbarView.getRight() - mTaskbarView.getLeft()) / 2.0f;
-
-        float finalMarginScale = mapRange(scale, 0f, mTransientIconSize - mPersistentIconSize);
-
         float transientTaskbarAllAppsOffset = mActivity.getResources().getDimension(
                 mTaskbarView.getAllAppsButtonTranslationXOffset(true));
         float persistentTaskbarAllAppsOffset = mActivity.getResources().getDimension(
@@ -354,6 +349,17 @@
             allAppIconTranslateRange *= -1;
         }
 
+        if (mActivity.isThreeButtonNav()) {
+            ((IconButtonView) mTaskbarView.getAllAppsButtonView())
+                    .setTranslationXForTaskbarAllAppsIcon(allAppIconTranslateRange);
+            return;
+        }
+
+        float taskbarCenterX =
+                mTaskbarView.getLeft() + (mTaskbarView.getRight() - mTaskbarView.getLeft()) / 2.0f;
+
+        float finalMarginScale = mapRange(scale, 0f, mTransientIconSize - mPersistentIconSize);
+
         float halfIconCount = iconViews.length / 2.0f;
         for (int iconIndex = 0; iconIndex < iconViews.length; iconIndex++) {
             View iconView = iconViews[iconIndex];
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 5424fcf..6ceec3e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -96,7 +96,7 @@
         mAllAppsCallbacks.onAllAppsTransitionStart(true);
         if (!animate) {
             mAllAppsCallbacks.onAllAppsTransitionEnd(true);
-            mTranslationShift = TRANSLATION_SHIFT_OPENED;
+            setTranslationShift(TRANSLATION_SHIFT_OPENED);
             return;
         }
 
@@ -196,15 +196,21 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        mAppsView.drawOnScrimWithScale(canvas, mSlideInViewScale.value);
+        // We should call drawOnScrimWithBottomOffset() rather than drawOnScrimWithScale(). Because
+        // for taskbar all apps, the scrim view is a child view of AbstractSlideInView. Thus scaling
+        // down in AbstractSlideInView#onScaleProgressChanged() with SCALE_PROPERTY has already
+        // done the job - there is no need to re-apply scale effect here. But it also means we need
+        // to pass extra bottom offset to background scrim to fill the bottom gap during predictive
+        // back swipe.
+        mAppsView.drawOnScrimWithBottomOffset(canvas, getBottomOffsetPx());
         super.dispatchDraw(canvas);
     }
 
     @Override
-    protected void onScaleProgressChanged() {
-        super.onScaleProgressChanged();
-        mAppsView.setClipChildren(!mIsBackProgressing);
-        mAppsView.getAppsRecyclerViewContainer().setClipChildren(!mIsBackProgressing);
+    protected void onUserSwipeToDismissProgressChanged() {
+        super.onUserSwipeToDismissProgressChanged();
+        mAppsView.setClipChildren(!mIsDismissInProgress);
+        mAppsView.getAppsRecyclerViewContainer().setClipChildren(!mIsDismissInProgress);
     }
 
     @Override
@@ -255,7 +261,11 @@
 
     @Override
     public void onBackInvoked() {
-        if (!mAllAppsCallbacks.handleSearchBackInvoked()) {
+        if (mAllAppsCallbacks.handleSearchBackInvoked()) {
+            // We need to scale back taskbar all apps if we navigate back within search inside all
+            // apps
+            animateSwipeToDismissProgressToStart();
+        } else {
             super.onBackInvoked();
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
index aa2b29d..8eeb055 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
@@ -15,10 +15,12 @@
  */
 package com.android.launcher3.taskbar.bubbles
 
+import android.content.Context
 import android.graphics.Canvas
 import android.graphics.Color
 import android.graphics.ColorFilter
 import android.graphics.Paint
+import android.graphics.PixelFormat
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.ShapeDrawable
 import com.android.app.animation.Interpolators
@@ -26,12 +28,10 @@
 import com.android.launcher3.Utilities
 import com.android.launcher3.Utilities.mapToRange
 import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
-import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.wm.shell.common.TriangleShape
 
 /** Drawable for the background of the bubble bar. */
-class BubbleBarBackground(context: TaskbarActivityContext, private val backgroundHeight: Float) :
-    Drawable() {
+class BubbleBarBackground(context: Context, private val backgroundHeight: Float) : Drawable() {
 
     private val DARK_THEME_SHADOW_ALPHA = 51f
     private val LIGHT_THEME_SHADOW_ALPHA = 25f
@@ -45,6 +45,7 @@
 
     var arrowPositionX: Float = 0f
         private set
+
     private var showingArrow: Boolean = false
     private var arrowDrawable: ShapeDrawable
 
@@ -122,14 +123,24 @@
 
         // Draw background.
         val radius = backgroundHeight / 2f
-        val left = if (anchorLeft) 0f else canvas.width.toFloat() - width
-        val right = if (anchorLeft) width else canvas.width.toFloat()
-        canvas.drawRoundRect(left, 0f, right, canvas.height.toFloat(), radius, radius, paint)
+        val left = if (anchorLeft) 0f else bounds.width().toFloat() - width
+        val right = if (anchorLeft) width else bounds.width().toFloat()
+        canvas.drawRoundRect(
+            left,
+            pointerSize,
+            right,
+            bounds.height().toFloat(),
+            radius,
+            radius,
+            paint
+        )
 
         if (showingArrow) {
             // Draw arrow.
             val transX = arrowPositionX - pointerSize / 2f
-            canvas.translate(transX, -pointerSize)
+            // Shift arrow down by 1 pixel. Rounded rect has a 1 pixel border which will show up
+            // between background and arrow otherwise.
+            canvas.translate(transX, 1f)
             arrowDrawable.draw(canvas)
         }
 
@@ -137,11 +148,20 @@
     }
 
     override fun getOpacity(): Int {
-        return paint.alpha
+        return when (paint.alpha) {
+            255 -> PixelFormat.OPAQUE
+            0 -> PixelFormat.TRANSPARENT
+            else -> PixelFormat.TRANSLUCENT
+        }
     }
 
     override fun setAlpha(alpha: Int) {
         paint.alpha = alpha
+        arrowDrawable.paint.alpha = alpha
+    }
+
+    override fun getAlpha(): Int {
+        return paint.alpha
     }
 
     override fun setColorFilter(colorFilter: ColorFilter?) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 6dc7db7..a2c1b07 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -73,6 +73,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.wm.shell.Flags;
 import com.android.wm.shell.bubbles.IBubblesListener;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 import com.android.wm.shell.common.bubbles.BubbleBarUpdate;
 import com.android.wm.shell.common.bubbles.BubbleInfo;
 import com.android.wm.shell.common.bubbles.RemovedBubble;
@@ -150,17 +151,22 @@
     private BubbleStashController mBubbleStashController;
     private BubbleStashedHandleViewController mBubbleStashedHandleViewController;
 
+    // Keep track of bubble bar bounds sent to shell to avoid sending duplicate updates
+    private final Rect mLastSentBubbleBarBounds = new Rect();
+
     /**
      * Similar to {@link BubbleBarUpdate} but rather than {@link BubbleInfo}s it uses
      * {@link BubbleBarBubble}s so that it can be used to update the views.
      */
     private static class BubbleBarViewUpdate {
+        final boolean initialState;
         boolean expandedChanged;
         boolean expanded;
         boolean shouldShowEducation;
         String selectedBubbleKey;
         String suppressedBubbleKey;
         String unsuppressedBubbleKey;
+        BubbleBarLocation bubbleBarLocation;
         List<RemovedBubble> removedBubbles;
         List<String> bubbleKeysInOrder;
 
@@ -170,12 +176,14 @@
         List<BubbleBarBubble> currentBubbles;
 
         BubbleBarViewUpdate(BubbleBarUpdate update) {
+            initialState = update.initialState;
             expandedChanged = update.expandedChanged;
             expanded = update.expanded;
             shouldShowEducation = update.shouldShowEducation;
             selectedBubbleKey = update.selectedBubbleKey;
             suppressedBubbleKey = update.suppressedBubbleKey;
             unsuppressedBubbleKey = update.unsupressedBubbleKey;
+            bubbleBarLocation = update.bubbleBarLocation;
             removedBubbles = update.removedBubbles;
             bubbleKeysInOrder = update.bubbleKeysInOrder;
         }
@@ -215,7 +223,8 @@
             mBubbleStashedHandleViewController.setHiddenForBubbles(
                     !sBubbleBarEnabled || mBubbles.isEmpty());
             mBubbleBarViewController.setUpdateSelectedBubbleAfterCollapse(
-                    key -> setSelectedBubble(mBubbles.get(key)));
+                    key -> setSelectedBubbleInternal(mBubbles.get(key)));
+            mBubbleBarViewController.setBoundsChangeListener(this::onBubbleBarBoundsChanged);
         });
     }
 
@@ -232,7 +241,8 @@
                 // we're on the main executor now, so check that the overflow hasn't been created
                 // again to avoid races.
                 if (mOverflowBubble == null) {
-                    mBubbleBarViewController.addBubble(overflow);
+                    mBubbleBarViewController.addBubble(
+                            overflow, /* isExpanding= */ false, /* suppressAnimation= */ true);
                     mOverflowBubble = overflow;
                 }
             });
@@ -301,6 +311,10 @@
     private void applyViewChanges(BubbleBarViewUpdate update) {
         final boolean isCollapsed = (update.expandedChanged && !update.expanded)
                 || (!update.expandedChanged && !mBubbleBarViewController.isExpanded());
+        final boolean isExpanding = update.expandedChanged && update.expanded;
+        // don't animate bubbles if this is the initial state because we may be unfolding or
+        // enabling gesture nav
+        final boolean suppressAnimation = update.initialState;
         BubbleBarItem previouslySelectedBubble = mSelectedBubble;
         BubbleBarBubble bubbleToSelect = null;
         if (!update.removedBubbles.isEmpty()) {
@@ -317,7 +331,7 @@
         }
         if (update.addedBubble != null) {
             mBubbles.put(update.addedBubble.getKey(), update.addedBubble);
-            mBubbleBarViewController.addBubble(update.addedBubble);
+            mBubbleBarViewController.addBubble(update.addedBubble, isExpanding, suppressAnimation);
             if (isCollapsed) {
                 // If we're collapsed, the most recently added bubble will be selected.
                 bubbleToSelect = update.addedBubble;
@@ -330,7 +344,7 @@
                 BubbleBarBubble bubble = update.currentBubbles.get(i);
                 if (bubble != null) {
                     mBubbles.put(bubble.getKey(), bubble);
-                    mBubbleBarViewController.addBubble(bubble);
+                    mBubbleBarViewController.addBubble(bubble, isExpanding, suppressAnimation);
                     if (isCollapsed) {
                         // If we're collapsed, the most recently added bubble will be selected.
                         bubbleToSelect = bubble;
@@ -385,7 +399,7 @@
             }
         }
         if (bubbleToSelect != null) {
-            setSelectedBubble(bubbleToSelect);
+            setSelectedBubbleInternal(bubbleToSelect);
             if (previouslySelectedBubble == null) {
                 mBubbleStashController.animateToInitialState(update.expanded);
             }
@@ -400,6 +414,13 @@
                 Log.w(TAG, "expansion was changed but is the same");
             }
         }
+        if (update.bubbleBarLocation != null) {
+            if (update.bubbleBarLocation != mBubbleBarViewController.getBubbleBarLocation()) {
+                // Animate when receiving updates. Skip it if we received the initial state.
+                boolean animate = !update.initialState;
+                updateBubbleBarLocationInternal(update.bubbleBarLocation, animate);
+            }
+        }
     }
 
     /** Tells WMShell to show the currently selected bubble. */
@@ -414,7 +435,9 @@
                         info.getFlags() | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION);
                 mSelectedBubble.getView().updateDotVisibility(true /* animate */);
             }
-            mSystemUiProxy.showBubble(getSelectedBubbleKey(), getExpandedBubbleBarDisplayBounds());
+            Rect bounds = getExpandedBubbleBarDisplayBounds();
+            mLastSentBubbleBarBounds.set(bounds);
+            mSystemUiProxy.showBubble(getSelectedBubbleKey(), bounds);
         } else {
             Log.w(TAG, "Trying to show the selected bubble but it's null");
         }
@@ -423,7 +446,7 @@
     /** Updates the currently selected bubble for launcher views and tells WMShell to show it. */
     public void showAndSelectBubble(BubbleBarItem b) {
         if (DEBUG) Log.w(TAG, "showingSelectedBubble: " + b.getKey());
-        setSelectedBubble(b);
+        setSelectedBubbleInternal(b);
         showSelectedBubble();
     }
 
@@ -432,7 +455,7 @@
      * WMShell that the selection has changed, that should go through either
      * {@link #showSelectedBubble()} or {@link #showAndSelectBubble(BubbleBarItem)}.
      */
-    private void setSelectedBubble(BubbleBarItem b) {
+    private void setSelectedBubbleInternal(BubbleBarItem b) {
         if (!Objects.equals(b, mSelectedBubble)) {
             if (DEBUG) Log.w(TAG, "selectingBubble: " + b.getKey());
             mSelectedBubble = b;
@@ -451,6 +474,21 @@
         return null;
     }
 
+    /**
+     * Set a new bubble bar location.
+     * <p>
+     * Updates the value locally in Launcher and in WMShell.
+     */
+    public void updateBubbleBarLocation(BubbleBarLocation location) {
+        updateBubbleBarLocationInternal(location, false /* animate */);
+        mSystemUiProxy.setBubbleBarLocation(location);
+    }
+
+    private void updateBubbleBarLocationInternal(BubbleBarLocation location, boolean animate) {
+        mBubbleBarViewController.setBubbleBarLocation(location, animate);
+        mBubbleStashController.setBubbleBarLocation(location);
+    }
+
     //
     // Loading data for the bubbles
     //
@@ -582,27 +620,39 @@
         return mIconFactory.createBadgedIconBitmap(drawable).icon;
     }
 
+    private void onBubbleBarBoundsChanged(Rect newBounds) {
+        Rect displayBounds = convertToDisplayBounds(newBounds);
+        // Only send bounds over if they changed
+        if (!displayBounds.equals(mLastSentBubbleBarBounds)) {
+            mLastSentBubbleBarBounds.set(displayBounds);
+            mSystemUiProxy.setBubbleBarBounds(displayBounds);
+        }
+    }
+
     /**
      * Get bounds of the bubble bar as if it would be expanded.
      * Calculates the bounds instead of retrieving current view location as the view may be
      * animating.
      */
     private Rect getExpandedBubbleBarDisplayBounds() {
+        return convertToDisplayBounds(mBarView.getBubbleBarBounds());
+    }
+
+    private Rect convertToDisplayBounds(Rect currentBarBounds) {
         Point displaySize = DisplayController.INSTANCE.get(mContext).getInfo().currentSize;
-        Rect currentBarBounds = mBarView.getBubbleBarBounds();
-        Rect location = new Rect();
+        Rect displayBounds = new Rect();
         // currentBarBounds is only useful for distance from left or right edge.
         // It contains the current bounds, calculate the expanded bounds.
-        if (mBarView.isOnLeft()) {
-            location.left = currentBarBounds.left;
-            location.right = (int) (currentBarBounds.left + mBarView.expandedWidth());
+        if (mBarView.getBubbleBarLocation().isOnLeft(mBarView.isLayoutRtl())) {
+            displayBounds.left = currentBarBounds.left;
+            displayBounds.right = (int) (currentBarBounds.left + mBarView.expandedWidth());
         } else {
-            location.left = (int) (currentBarBounds.right - mBarView.expandedWidth());
-            location.right = currentBarBounds.right;
+            displayBounds.left = (int) (currentBarBounds.right - mBarView.expandedWidth());
+            displayBounds.right = currentBarBounds.right;
         }
         final int translation = (int) abs(mBubbleStashController.getBubbleBarTranslationY());
-        location.top = displaySize.y - mBarView.getHeight() - translation;
-        location.bottom = displaySize.y - translation;
-        return location;
+        displayBounds.top = displaySize.y - currentBarBounds.height() - translation;
+        displayBounds.bottom = displaySize.y - translation;
+        return displayBounds;
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
new file mode 100644
index 0000000..8ed9949
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarPinController.kt
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Point
+import android.graphics.RectF
+import android.view.Gravity.BOTTOM
+import android.view.Gravity.LEFT
+import android.view.Gravity.RIGHT
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.FrameLayout
+import androidx.core.view.updateLayoutParams
+import com.android.launcher3.R
+import com.android.wm.shell.common.bubbles.BaseBubblePinController
+import com.android.wm.shell.common.bubbles.BubbleBarLocation
+
+/**
+ * Controller to manage pinning bubble bar to left or right when dragging starts from the bubble bar
+ */
+class BubbleBarPinController(
+    private val context: Context,
+    private val container: FrameLayout,
+    private val screenSizeProvider: () -> Point
+) : BaseBubblePinController() {
+
+    private lateinit var bubbleBarViewController: BubbleBarViewController
+    private lateinit var bubbleStashController: BubbleStashController
+    private var dropTargetView: View? = null
+
+    fun init(bubbleControllers: BubbleControllers) {
+        bubbleBarViewController = bubbleControllers.bubbleBarViewController
+        bubbleStashController = bubbleControllers.bubbleStashController
+    }
+
+    override fun getScreenCenterX(): Int {
+        return screenSizeProvider.invoke().x / 2
+    }
+
+    override fun getExclusionRect(): RectF {
+        val rect =
+            RectF(
+                0f,
+                0f,
+                context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_width),
+                context.resources.getDimension(R.dimen.bubblebar_dismiss_zone_height)
+            )
+        val screenSize = screenSizeProvider.invoke()
+        val middleX = screenSize.x / 2
+        // Center it around the bottom center of the screen
+        rect.offsetTo(middleX - rect.width() / 2, screenSize.y - rect.height())
+        return rect
+    }
+
+    override fun createDropTargetView(): View {
+        return LayoutInflater.from(context)
+            .inflate(R.layout.bubble_bar_drop_target, container, false)
+            .also { view ->
+                dropTargetView = view
+                container.addView(view)
+            }
+    }
+
+    override fun getDropTargetView(): View? {
+        return dropTargetView
+    }
+
+    override fun removeDropTargetView(view: View) {
+        container.removeView(view)
+        dropTargetView = null
+    }
+
+    @SuppressLint("RtlHardcoded")
+    override fun updateLocation(location: BubbleBarLocation) {
+        val onLeft = location.isOnLeft(container.isLayoutRtl)
+
+        val bounds = bubbleBarViewController.bubbleBarBounds
+        val horizontalMargin = bubbleBarViewController.horizontalMargin
+        dropTargetView?.updateLayoutParams<FrameLayout.LayoutParams> {
+            width = bounds.width()
+            height = bounds.height()
+            gravity = BOTTOM or (if (onLeft) LEFT else RIGHT)
+            leftMargin = horizontalMargin
+            rightMargin = horizontalMargin
+            bottomMargin = -bubbleStashController.bubbleBarTranslationY.toInt()
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 8f693a6..711ba62 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -15,21 +15,33 @@
  */
 package com.android.launcher3.taskbar.bubbles;
 
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
+
 import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.content.Context;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.LayoutDirection;
 import android.util.Log;
+import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.dynamicanimation.animation.SpringForce;
+
 import com.android.launcher3.R;
-import com.android.launcher3.taskbar.TaskbarActivityContext;
-import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.anim.SpringAnimationBuilder;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 import java.util.List;
 import java.util.function.Consumer;
@@ -70,8 +82,22 @@
     private static final int ARROW_POSITION_ANIMATION_DURATION_MS = 200;
     private static final int WIDTH_ANIMATION_DURATION_MS = 200;
 
+    private static final long FADE_OUT_ANIM_ALPHA_DURATION_MS = 50L;
+    private static final long FADE_OUT_ANIM_ALPHA_DELAY_MS = 50L;
+    private static final long FADE_OUT_ANIM_POSITION_DURATION_MS = 100L;
+    // During fade out animation we shift the bubble bar 1/80th of the screen width
+    private static final float FADE_OUT_ANIM_POSITION_SHIFT = 1 / 80f;
+
+    private static final long FADE_IN_ANIM_ALPHA_DURATION_MS = 100L;
+    // Use STIFFNESS_MEDIUMLOW which is not defined in the API constants
+    private static final float FADE_IN_ANIM_POSITION_SPRING_STIFFNESS = 400f;
+    // During fade in animation we shift the bubble bar 1/60th of the screen width
+    private static final float FADE_IN_ANIM_POSITION_SHIFT = 1 / 60f;
+
     private final BubbleBarBackground mBubbleBarBackground;
 
+    private boolean mIsAnimatingNewBubble = false;
+
     /**
      * The current bounds of all the bubble bar. Note that these bounds may not account for
      * translation. The bounds should be retrieved using {@link #getBubbleBarBounds()} which
@@ -86,11 +112,14 @@
     private final float mIconSize;
     // The elevation of the bubbles within the bar
     private final float mBubbleElevation;
+    private final float mDragElevation;
+    private final int mPointerSize;
 
     // Whether the bar is expanded (i.e. the bubble activity is being displayed).
     private boolean mIsBarExpanded = false;
     // The currently selected bubble view.
     private BubbleView mSelectedBubbleView;
+    private BubbleBarLocation mBubbleBarLocation = BubbleBarLocation.DEFAULT;
     // The click listener when the bubble bar is collapsed.
     private View.OnClickListener mOnClickListener;
 
@@ -102,6 +131,9 @@
     // collapsed state and 1 to the fully expanded state.
     private final ValueAnimator mWidthAnimator = ValueAnimator.ofFloat(0, 1);
 
+    @Nullable
+    private Animator mBubbleBarLocationAnimator = null;
+
     // We don't reorder the bubbles when they are expanded as it could be jarring for the user
     // this runnable will be populated with any reordering of the bubbles that should be applied
     // once they are collapsed.
@@ -111,9 +143,15 @@
     @Nullable
     private Consumer<String> mUpdateSelectedBubbleAfterCollapse;
 
+    private boolean mDragging;
+
     @Nullable
     private BubbleView mDraggedBubbleView;
 
+    private int mPreviousLayoutDirection = LayoutDirection.UNDEFINED;
+
+    private boolean mLocationChangePending;
+
     public BubbleBarView(Context context) {
         this(context, null);
     }
@@ -128,17 +166,18 @@
 
     public BubbleBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        TaskbarActivityContext activityContext = ActivityContext.lookupContext(context);
-
         setAlpha(0);
         setVisibility(INVISIBLE);
         mIconOverlapAmount = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_overlap);
         mIconSpacing = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_spacing);
         mIconSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
         mBubbleElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_elevation);
+        mDragElevation = getResources().getDimensionPixelSize(R.dimen.bubblebar_drag_elevation);
+        mPointerSize = getResources().getDimensionPixelSize(R.dimen.bubblebar_pointer_size);
+
         setClipToPadding(false);
 
-        mBubbleBarBackground = new BubbleBarBackground(activityContext,
+        mBubbleBarBackground = new BubbleBarBackground(context,
                 getResources().getDimensionPixelSize(R.dimen.bubblebar_size));
         setBackgroundDrawable(mBubbleBarBackground);
 
@@ -184,7 +223,7 @@
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         mBubbleBarBounds.left = left;
-        mBubbleBarBounds.top = top;
+        mBubbleBarBounds.top = top + mPointerSize;
         mBubbleBarBounds.right = right;
         mBubbleBarBounds.bottom = bottom;
 
@@ -199,24 +238,195 @@
 
     @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
-        // TODO(b/313661121): set this based on bubble bar position and not LTR or RTL
-        boolean onLeft = layoutDirection == LAYOUT_DIRECTION_RTL;
+        if (mBubbleBarLocation == BubbleBarLocation.DEFAULT
+                && mPreviousLayoutDirection != layoutDirection) {
+            Log.d(TAG, "BubbleBar RTL properties changed, new layoutDirection=" + layoutDirection
+                    + " previous layoutDirection=" + mPreviousLayoutDirection);
+            mPreviousLayoutDirection = layoutDirection;
+            onBubbleBarLocationChanged();
+        }
+    }
+
+    @SuppressLint("RtlHardcoded")
+    private void onBubbleBarLocationChanged() {
+        mLocationChangePending = false;
+        final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
         mBubbleBarBackground.setAnchorLeft(onLeft);
         mRelativePivotX = onLeft ? 0f : 1f;
+        if (getLayoutParams() instanceof LayoutParams lp) {
+            lp.gravity = Gravity.BOTTOM | (onLeft ? Gravity.LEFT : Gravity.RIGHT);
+            setLayoutParams(lp);
+        }
+        invalidate();
     }
 
     /**
-     * @return <code>true</code> when bar is pinned to the left edge of the screen
+     * @return current {@link BubbleBarLocation}
      */
-    public boolean isOnLeft() {
-        return getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+    public BubbleBarLocation getBubbleBarLocation() {
+        return mBubbleBarLocation;
+    }
+
+    /**
+     * Update {@link BubbleBarLocation}
+     */
+    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) {
+        if (animate) {
+            animateToBubbleBarLocation(bubbleBarLocation);
+        } else {
+            setBubbleBarLocationInternal(bubbleBarLocation);
+        }
+    }
+
+    /**
+     * Set whether this view is being currently being dragged
+     */
+    public void setIsDragging(boolean dragging) {
+        if (mDragging == dragging) {
+            return;
+        }
+        mDragging = dragging;
+        setElevation(dragging ? mDragElevation : mBubbleElevation);
+        if (!dragging && mLocationChangePending) {
+            // During drag finish animation we may update the translation x value to shift the
+            // bubble to the new drop target. Clear the translation here.
+            setTranslationX(0f);
+            onBubbleBarLocationChanged();
+        }
+    }
+
+    /**
+     * Adjust resting position for the bubble bar while it is being dragged.
+     * <p>
+     * Bubble bar is laid out on left or right side of the screen. When it is being dragged to
+     * the opposite side, the resting position should be on that side. Calculate any additional
+     * translation that may be required to move the bubble bar to the new side.
+     *
+     * @param restingPosition relative resting position of the bubble bar from the laid out position
+     */
+    @SuppressLint("RtlHardcoded")
+    void adjustRelativeRestingPosition(PointF restingPosition) {
+        final boolean locationOnLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
+        // Bubble bar is placed left or right with gravity. Check where it is currently.
+        final int absoluteGravity = Gravity.getAbsoluteGravity(
+                ((LayoutParams) getLayoutParams()).gravity, getLayoutDirection());
+        final boolean gravityOnLeft =
+                (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.LEFT;
+
+        // Bubble bar is pinned to the same side per gravity and the desired location.
+        // Resting translation does not need to be adjusted.
+        if (locationOnLeft == gravityOnLeft) {
+            return;
+        }
+
+        // Bubble bar is laid out on left or right side of the screen. And the desired new
+        // location is on the other side. Calculate x translation value required to shift the
+        // bubble bar from one side to the other.
+        float x = getDistanceFromOtherSide();
+        if (locationOnLeft) {
+            // New location is on the left, shift left
+            // before -> |......ooo.| after -> |.ooo......|
+            restingPosition.x = -x;
+        } else {
+            // New location is on the right, shift right
+            // before -> |.ooo......| after -> |......ooo.|
+            restingPosition.x = x;
+        }
+    }
+
+    private float getDistanceFromOtherSide() {
+        // Calculate the shift needed to position the bubble bar on the other side
+        int displayWidth = getResources().getDisplayMetrics().widthPixels;
+        int margin = 0;
+        if (getLayoutParams() instanceof MarginLayoutParams lp) {
+            margin += lp.leftMargin;
+            margin += lp.rightMargin;
+        }
+        return (float) (displayWidth - getWidth() - margin);
+    }
+
+    private void setBubbleBarLocationInternal(BubbleBarLocation bubbleBarLocation) {
+        if (bubbleBarLocation != mBubbleBarLocation) {
+            mBubbleBarLocation = bubbleBarLocation;
+            if (mDragging) {
+                mLocationChangePending = true;
+            } else {
+                onBubbleBarLocationChanged();
+                invalidate();
+            }
+        }
+    }
+
+    private void animateToBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        if (bubbleBarLocation == mBubbleBarLocation) {
+            // nothing to do, already at expected location
+            return;
+        }
+        if (mBubbleBarLocationAnimator != null && mBubbleBarLocationAnimator.isRunning()) {
+            mBubbleBarLocationAnimator.cancel();
+        }
+
+        // Location animation uses two separate animators.
+        // First animator hides the bar.
+        // After it completes, location update is sent to layout the bar in the new location.
+        // Second animator is started to show the bar.
+        mBubbleBarLocationAnimator = getLocationUpdateFadeOutAnimator();
+        mBubbleBarLocationAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                // Bubble bar is not visible, update the location
+                setBubbleBarLocationInternal(bubbleBarLocation);
+                // Animate it in
+                mBubbleBarLocationAnimator = getLocationUpdateFadeInAnimator();
+                mBubbleBarLocationAnimator.start();
+            }
+        });
+        mBubbleBarLocationAnimator.start();
+    }
+
+    private AnimatorSet getLocationUpdateFadeOutAnimator() {
+        final float shift =
+                getResources().getDisplayMetrics().widthPixels * FADE_OUT_ANIM_POSITION_SHIFT;
+        final float tx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift;
+
+        ObjectAnimator positionAnim = ObjectAnimator.ofFloat(this, TRANSLATION_X, tx)
+                .setDuration(FADE_OUT_ANIM_POSITION_DURATION_MS);
+        positionAnim.setInterpolator(EMPHASIZED_ACCELERATE);
+
+        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, ALPHA, 0f)
+                .setDuration(FADE_OUT_ANIM_ALPHA_DURATION_MS);
+        alphaAnim.setStartDelay(FADE_OUT_ANIM_ALPHA_DELAY_MS);
+
+        AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.playTogether(positionAnim, alphaAnim);
+        return animatorSet;
+    }
+
+    private Animator getLocationUpdateFadeInAnimator() {
+        final float shift =
+                getResources().getDisplayMetrics().widthPixels * FADE_IN_ANIM_POSITION_SHIFT;
+        final float startTx = mBubbleBarLocation.isOnLeft(isLayoutRtl()) ? shift : -shift;
+
+        ValueAnimator positionAnim = new SpringAnimationBuilder(getContext())
+                .setStartValue(startTx)
+                .setEndValue(0)
+                .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY)
+                .setStiffness(FADE_IN_ANIM_POSITION_SPRING_STIFFNESS)
+                .build(this, VIEW_TRANSLATE_X);
+
+        ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(this, ALPHA, 1f)
+                .setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS);
+
+        AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.playTogether(positionAnim, alphaAnim);
+        return animatorSet;
     }
 
     /**
      * Updates the bounds with translation that may have been applied and returns the result.
      */
     public Rect getBubbleBarBounds() {
-        mBubbleBarBounds.top = getTop() + (int) getTranslationY();
+        mBubbleBarBounds.top = getTop() + (int) getTranslationY() + mPointerSize;
         mBubbleBarBounds.bottom = getBottom() + (int) getTranslationY();
         return mBubbleBarBounds;
     }
@@ -247,6 +457,40 @@
         return mRelativePivotY;
     }
 
+    /** Prepares for animating a bubble while being stashed. */
+    public void prepareForAnimatingBubbleWhileStashed(String bubbleKey) {
+        mIsAnimatingNewBubble = true;
+        // we're about to animate the new bubble in. the new bubble has already been added to this
+        // view, but we're currently stashed, so before we can start the animation we need make
+        // everything else in the bubble bar invisible, except for the bubble that's being animated.
+        setBackground(null);
+        for (int i = 0; i < getChildCount(); i++) {
+            final BubbleView view = (BubbleView) getChildAt(i);
+            final String key = view.getBubble().getKey();
+            if (!bubbleKey.equals(key)) {
+                view.setVisibility(INVISIBLE);
+            }
+        }
+        setVisibility(VISIBLE);
+        setAlpha(1);
+        setTranslationY(0);
+        setScaleX(1);
+        setScaleY(1);
+    }
+
+    /** Resets the state after the bubble animation completed. */
+    public void onAnimatingBubbleCompleted() {
+        mIsAnimatingNewBubble = false;
+        // setting the background triggers relayout so no need to explicitly invalidate after the
+        // animation
+        setBackground(mBubbleBarBackground);
+        for (int i = 0; i < getChildCount(); i++) {
+            final BubbleView view = (BubbleView) getChildAt(i);
+            view.setVisibility(VISIBLE);
+            view.setAlpha(1f);
+        }
+    }
+
     // TODO: (b/280605790) animate it
     @Override
     public void addView(View child, int index, ViewGroup.LayoutParams params) {
@@ -283,6 +527,12 @@
      * on the expanded state.
      */
     private void updateChildrenRenderNodeProperties() {
+        if (mIsAnimatingNewBubble) {
+            // don't update bubbles if a new bubble animation is playing.
+            // the bubble bar will redraw itself via onLayout after the animation.
+            return;
+        }
+
         final float widthState = (float) mWidthAnimator.getAnimatedValue();
         final float currentWidth = getWidth();
         final float expandedWidth = expandedWidth();
@@ -290,7 +540,7 @@
         int bubbleCount = getChildCount();
         final float ty = (mBubbleBarBounds.height() - mIconSize) / 2f;
         final boolean animate = getVisibility() == VISIBLE;
-        final boolean onLeft = isOnLeft();
+        final boolean onLeft = mBubbleBarLocation.isOnLeft(isLayoutRtl());
         for (int i = 0; i < bubbleCount; i++) {
             BubbleView bv = (BubbleView) getChildAt(i);
             bv.setTranslationY(ty);
@@ -453,7 +703,7 @@
     private float arrowPositionForSelectedWhenExpanded() {
         final int index = indexOfChild(mSelectedBubbleView);
         final int bubblePosition;
-        if (isOnLeft()) {
+        if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) {
             // Bubble positions are reversed. First bubble is on the right.
             bubblePosition = getChildCount() - index - 1;
         } else {
@@ -465,7 +715,7 @@
     private float arrowPositionForSelectedWhenCollapsed() {
         final int index = indexOfChild(mSelectedBubbleView);
         final int bubblePosition;
-        if (isOnLeft()) {
+        if (mBubbleBarLocation.isOnLeft(isLayoutRtl())) {
             // Bubble positions are reversed. First bubble may be shifted, if there are more
             // bubbles than the current bubble and overflow.
             bubblePosition = index == 0 && getChildCount() > 2 ? 1 : 0;
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 6bb7b04..aa1b4df 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -27,6 +27,7 @@
 import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatedFloat;
@@ -34,9 +35,11 @@
 import com.android.launcher3.taskbar.TaskbarControllers;
 import com.android.launcher3.taskbar.TaskbarInsetsController;
 import com.android.launcher3.taskbar.TaskbarStashController;
+import com.android.launcher3.taskbar.bubbles.animation.BubbleBarViewAnimator;
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.SystemUiProxy;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 import java.util.List;
 import java.util.Objects;
@@ -54,6 +57,7 @@
     private final TaskbarActivityContext mActivity;
     private final BubbleBarView mBarView;
     private final int mIconSize;
+    private final int mPointerSize;
 
     // Initialized in init.
     private BubbleStashController mBubbleStashController;
@@ -79,6 +83,13 @@
     private boolean mHiddenForNoBubbles = true;
     private boolean mShouldShowEducation;
 
+    private BubbleBarViewAnimator mBubbleBarViewAnimator;
+
+    @Nullable
+    private BubbleBarBoundsChangeListener mBoundsChangeListener;
+
+    private final Rect mPreviousBubbleBarBounds = new Rect();
+
     public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
         mActivity = activity;
         mBarView = barView;
@@ -86,6 +97,8 @@
         mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */);
         mBubbleBarAlpha.setUpdateVisibility(true);
         mIconSize = activity.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
+        mPointerSize = activity.getResources().getDimensionPixelSize(
+                R.dimen.bubblebar_pointer_size);
     }
 
     public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
@@ -96,17 +109,29 @@
         mTaskbarInsetsController = controllers.taskbarInsetsController;
 
         mActivity.addOnDeviceProfileChangeListener(dp ->
-                mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight
+                mBarView.getLayoutParams().height =
+                        mActivity.getDeviceProfile().taskbarHeight + mPointerSize
         );
-        mBarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarHeight;
+        mBarView.getLayoutParams().height =
+                mActivity.getDeviceProfile().taskbarHeight + mPointerSize;
         mBubbleBarScale.updateValue(1f);
         mBubbleClickListener = v -> onBubbleClicked(v);
         mBubbleBarClickListener = v -> onBubbleBarClicked();
         mBubbleDragController.setupBubbleBarView(mBarView);
         mBarView.setOnClickListener(mBubbleBarClickListener);
-        mBarView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
-                mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
-        );
+        mBarView.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    mTaskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+                    Rect bubbleBarBounds = mBarView.getBubbleBarBounds();
+                    if (!bubbleBarBounds.equals(mPreviousBubbleBarBounds)) {
+                        mPreviousBubbleBarBounds.set(bubbleBarBounds);
+                        if (mBoundsChangeListener != null) {
+                            mBoundsChangeListener.onBoundsChanged(bubbleBarBounds);
+                        }
+                    }
+                });
+
+        mBubbleBarViewAnimator = new BubbleBarViewAnimator(mBarView, mBubbleStashController);
     }
 
     private void onBubbleClicked(View v) {
@@ -169,6 +194,20 @@
     }
 
     /**
+     * @return current {@link BubbleBarLocation}
+     */
+    public BubbleBarLocation getBubbleBarLocation() {
+        return mBarView.getBubbleBarLocation();
+    }
+
+    /**
+     * Update bar {@link BubbleBarLocation}
+     */
+    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation, boolean animate) {
+        mBarView.setBubbleBarLocation(bubbleBarLocation, animate);
+    }
+
+    /**
      * The bounds of the bubble bar.
      */
     public Rect getBubbleBarBounds() {
@@ -213,6 +252,10 @@
         if (mHiddenForNoBubbles != hidden) {
             mHiddenForNoBubbles = hidden;
             updateVisibilityForStateChange();
+            if (hidden) {
+                mBarView.setAlpha(0);
+                mBarView.setExpanded(false);
+            }
             mActivity.bubbleBarVisibilityChanged(!hidden);
         }
     }
@@ -239,8 +282,6 @@
             mBarView.setVisibility(VISIBLE);
         } else {
             mBarView.setVisibility(INVISIBLE);
-            mBarView.setAlpha(0);
-            mBarView.setExpanded(false);
         }
     }
 
@@ -288,12 +329,23 @@
     /**
      * Adds the provided bubble to the bubble bar.
      */
-    public void addBubble(BubbleBarItem b) {
+    public void addBubble(BubbleBarItem b, boolean isExpanding, boolean suppressAnimation) {
         if (b != null) {
             mBarView.addView(b.getView(), 0,
                     new FrameLayout.LayoutParams(mIconSize, mIconSize, Gravity.LEFT));
             b.getView().setOnClickListener(mBubbleClickListener);
             mBubbleDragController.setupBubbleView(b.getView());
+
+            if (suppressAnimation) {
+                return;
+            }
+
+            boolean isStashedOrGone =
+                    mBubbleStashController.isStashed() || mBarView.getVisibility() != VISIBLE;
+            // don't animate the new bubble if we're auto expanding from stashed
+            if (b instanceof BubbleBarBubble && isStashedOrGone && !isExpanding) {
+                mBubbleBarViewAnimator.animateBubbleInForStashed((BubbleBarBubble) b);
+            }
         } else {
             Log.w(TAG, "addBubble, bubble was null!");
         }
@@ -393,4 +445,19 @@
     public void onDismissAllBubblesWhileDragging() {
         mSystemUiProxy.removeAllBubbles();
     }
+
+    /**
+     * Set listener to be notified when bubble bar bounds have changed
+     */
+    public void setBoundsChangeListener(@Nullable BubbleBarBoundsChangeListener listener) {
+        mBoundsChangeListener = listener;
+    }
+
+    /**
+     * Listener to receive updates about bubble bar bounds changing
+     */
+    public interface BubbleBarBoundsChangeListener {
+        /** Called when bounds have changed */
+        void onBoundsChanged(Rect newBounds);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
index c47427d..90f1be3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java
@@ -29,6 +29,7 @@
     public final BubbleStashedHandleViewController bubbleStashedHandleViewController;
     public final BubbleDragController bubbleDragController;
     public final BubbleDismissController bubbleDismissController;
+    public final BubbleBarPinController bubbleBarPinController;
 
     private final RunnableList mPostInitRunnables = new RunnableList();
 
@@ -43,13 +44,15 @@
             BubbleStashController bubbleStashController,
             BubbleStashedHandleViewController bubbleStashedHandleViewController,
             BubbleDragController bubbleDragController,
-            BubbleDismissController bubbleDismissController) {
+            BubbleDismissController bubbleDismissController,
+            BubbleBarPinController bubbleBarPinController) {
         this.bubbleBarController = bubbleBarController;
         this.bubbleBarViewController = bubbleBarViewController;
         this.bubbleStashController = bubbleStashController;
         this.bubbleStashedHandleViewController = bubbleStashedHandleViewController;
         this.bubbleDragController = bubbleDragController;
         this.bubbleDismissController = bubbleDismissController;
+        this.bubbleBarPinController = bubbleBarPinController;
     }
 
     /**
@@ -64,6 +67,7 @@
         bubbleStashController.init(taskbarControllers, this);
         bubbleDragController.init(/* bubbleControllers = */ this);
         bubbleDismissController.init(/* bubbleControllers = */ this);
+        bubbleBarPinController.init(this);
 
         mPostInitRunnables.executeAllAndDestroy();
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
index 73c71c8..a40f33c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDismissController.java
@@ -67,6 +67,9 @@
     @Nullable
     private BubbleDragAnimator mAnimator;
 
+    @Nullable
+    private Listener mListener;
+
     public BubbleDismissController(TaskbarActivityContext activity, TaskbarDragLayer dragLayer) {
         mActivity = activity;
         mDragLayer = dragLayer;
@@ -82,6 +85,13 @@
     }
 
     /**
+     * Set listener to be notified of dismiss events
+     */
+    public void setListener(@Nullable Listener listener) {
+        mListener = listener;
+    }
+
+    /**
      * Setup the dismiss view and magnetized object that will be attracted to magnetic target.
      * Should be called before handling events or showing/hiding dismiss view.
      *
@@ -189,6 +199,9 @@
                     @NonNull MagnetizedObject<?> draggedObject) {
                 if (mAnimator == null) return;
                 mAnimator.animateDismissCaptured();
+                if (mListener != null) {
+                    mListener.onStuckToDismissChanged(true /* stuck */);
+                }
             }
 
             @Override
@@ -197,6 +210,9 @@
                     float velX, float velY, boolean wasFlungOut) {
                 if (mAnimator == null) return;
                 mAnimator.animateDismissReleased();
+                if (mListener != null) {
+                    mListener.onStuckToDismissChanged(false /* stuck */);
+                }
             }
 
             @Override
@@ -206,4 +222,10 @@
             }
         });
     }
+
+    /** Interface to receive updates about the dismiss state */
+    public interface Listener {
+        /** Called when view is stuck or unstuck from dismiss target */
+        void onStuckToDismissChanged(boolean stuck);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
index 24dca5e..8b811d9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragAnimator.java
@@ -18,7 +18,6 @@
 
 import static androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY;
 import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_LOW;
-import static androidx.dynamicanimation.animation.SpringForce.STIFFNESS_MEDIUM;
 
 import android.content.res.Resources;
 import android.graphics.PointF;
@@ -30,9 +29,9 @@
 import androidx.dynamicanimation.animation.FloatPropertyCompat;
 
 import com.android.launcher3.R;
-import com.android.wm.shell.animation.PhysicsAnimator;
 import com.android.wm.shell.common.bubbles.DismissCircleView;
 import com.android.wm.shell.common.bubbles.DismissView;
+import com.android.wm.shell.shared.animation.PhysicsAnimator;
 
 /**
  * The animator performs the bubble animations while dragging and coordinates bubble and dismiss
@@ -42,11 +41,14 @@
     private static final float SCALE_BUBBLE_FOCUSED = 1.2f;
     private static final float SCALE_BUBBLE_CAPTURED = 0.9f;
     private static final float SCALE_BUBBLE_BAR_FOCUSED = 1.1f;
+    // 400f matches to MEDIUM_LOW spring stiffness
+    private static final float TRANSLATION_SPRING_STIFFNESS = 400f;
 
     private final PhysicsAnimator.SpringConfig mDefaultConfig =
             new PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY);
     private final PhysicsAnimator.SpringConfig mTranslationConfig =
-            new PhysicsAnimator.SpringConfig(STIFFNESS_MEDIUM, DAMPING_RATIO_LOW_BOUNCY);
+            new PhysicsAnimator.SpringConfig(TRANSLATION_SPRING_STIFFNESS,
+                    DAMPING_RATIO_LOW_BOUNCY);
     @NonNull
     private final View mView;
     @NonNull
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
index 08fd681..5ffc6d8 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleDragController.java
@@ -28,7 +28,7 @@
 import com.android.launcher3.taskbar.TaskbarActivityContext;
 
 /**
- * Controls bubble bar drag to dismiss interaction.
+ * Controls bubble bar drag interactions.
  * Interacts with {@link BubbleDismissController}, used by {@link BubbleBarViewController}.
  * Supported interactions:
  * - Drag a single bubble view into dismiss target to remove it.
@@ -39,6 +39,7 @@
     private final TaskbarActivityContext mActivity;
     private BubbleBarViewController mBubbleBarViewController;
     private BubbleDismissController mBubbleDismissController;
+    private BubbleBarPinController mBubbleBarPinController;
 
     public BubbleDragController(TaskbarActivityContext activity) {
         mActivity = activity;
@@ -52,6 +53,11 @@
     public void init(@NonNull BubbleControllers bubbleControllers) {
         mBubbleBarViewController = bubbleControllers.bubbleBarViewController;
         mBubbleDismissController = bubbleControllers.bubbleDismissController;
+        mBubbleBarPinController = bubbleControllers.bubbleBarPinController;
+        mBubbleBarPinController.setListener(
+                bubbleControllers.bubbleBarController::updateBubbleBarLocation);
+        mBubbleDismissController.setListener(
+                stuck -> mBubbleBarPinController.setDropTargetHidden(stuck));
     }
 
     /**
@@ -89,6 +95,7 @@
     public void setupBubbleBarView(@NonNull BubbleBarView bubbleBarView) {
         PointF initialRelativePivot = new PointF();
         bubbleBarView.setOnTouchListener(new BubbleTouchListener() {
+
             @Override
             protected boolean onTouchDown(@NonNull View view, @NonNull MotionEvent event) {
                 if (bubbleBarView.isExpanded()) return false;
@@ -102,12 +109,38 @@
                 // By default the bubble bar view pivot is in bottom right corner, while dragging
                 // it should be centered in order to align it with the dismiss target view
                 bubbleBarView.setRelativePivot(/* x = */ 0.5f, /* y = */ 0.5f);
+                bubbleBarView.setIsDragging(true);
+                mBubbleBarPinController.onDragStart(
+                        bubbleBarView.getBubbleBarLocation().isOnLeft(bubbleBarView.isLayoutRtl()));
+            }
+
+            @Override
+            protected void onDragUpdate(float x, float y) {
+                mBubbleBarPinController.onDragUpdate(x, y);
+            }
+
+            @Override
+            protected void onDragRelease() {
+                mBubbleBarPinController.onDragEnd();
+            }
+
+            @Override
+            protected void onDragDismiss() {
+                mBubbleBarPinController.onDragEnd();
             }
 
             @Override
             void onDragEnd() {
                 // Restoring the initial pivot for the bubble bar view
                 bubbleBarView.setRelativePivot(initialRelativePivot.x, initialRelativePivot.y);
+                bubbleBarView.setIsDragging(false);
+            }
+
+            @Override
+            protected PointF getRestingPosition() {
+                PointF restingPosition = super.getRestingPosition();
+                bubbleBarView.adjustRelativeRestingPosition(restingPosition);
+                return restingPosition;
             }
         });
     }
@@ -170,6 +203,13 @@
         abstract void onDragStart();
 
         /**
+         * Called when bubble is dragged to new coordinates.
+         * Not called while bubble is stuck to the dismiss target.
+         */
+        protected void onDragUpdate(float x, float y) {
+        }
+
+        /**
          * Called when the dragging interaction has ended and all the animations have completed
          */
         abstract void onDragEnd();
@@ -188,6 +228,13 @@
         protected void onDragDismiss() {
         }
 
+        /**
+         * Get the resting position of the view when drag is released
+         */
+        protected PointF getRestingPosition() {
+            return mViewInitialPosition;
+        }
+
         @Override
         @SuppressLint("ClickableViewAccessibility")
         public boolean onTouch(@NonNull View view, @NonNull MotionEvent event) {
@@ -232,8 +279,10 @@
          * @param event the motion event
          */
         protected void onTouchMove(@NonNull View view, @NonNull MotionEvent event) {
-            final float dx = event.getRawX() - mTouchDownLocation.x;
-            final float dy = event.getRawY() - mTouchDownLocation.y;
+            float rawX = event.getRawX();
+            float rawY = event.getRawY();
+            final float dx = rawX - mTouchDownLocation.x;
+            final float dy = rawY - mTouchDownLocation.y;
             switch (mState) {
                 case TOUCHED:
                     final boolean movedOut = Math.hypot(dx, dy) > mTouchSlop;
@@ -244,7 +293,7 @@
                     }
                     break;
                 case DRAGGING:
-                    drag(view, event, dx, dy);
+                    drag(view, event, dx, dy, rawX, rawY);
                     break;
             }
         }
@@ -293,10 +342,12 @@
             mBubbleDismissController.showDismissView();
         }
 
-        private void drag(@NonNull View view, @NonNull MotionEvent event, float dx, float dy) {
+        private void drag(@NonNull View view, @NonNull MotionEvent event, float dx, float dy,
+                float x, float y) {
             if (mBubbleDismissController.handleTouchEvent(event)) return;
             view.setTranslationX(mViewInitialPosition.x + dx);
             view.setTranslationY(mViewInitialPosition.y + dy);
+            onDragUpdate(x, y);
         }
 
         private void stopDragging(@NonNull View view, @NonNull MotionEvent event) {
@@ -311,7 +362,7 @@
                 mAnimator.animateDismiss(mViewInitialPosition, onComplete);
             } else {
                 onDragRelease();
-                mAnimator.animateToInitialState(mViewInitialPosition, getCurrentVelocity(),
+                mAnimator.animateToInitialState(getRestingPosition(), getCurrentVelocity(),
                         onComplete);
             }
             mBubbleDismissController.hideDismissView();
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index 09021ed..61a2e22 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -31,6 +31,7 @@
 import com.android.launcher3.taskbar.TaskbarInsetsController;
 import com.android.launcher3.taskbar.TaskbarStashController;
 import com.android.launcher3.util.MultiPropertyFactory;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 /**
  * Coordinates between controllers such as BubbleBarView and BubbleHandleViewController to
@@ -50,6 +51,15 @@
      */
     private static final float STASHED_BAR_SCALE = 0.5f;
 
+    /** The duration of hiding and showing the stashed handle as part of a new bubble animation. */
+    private static final long NEW_BUBBLE_HANDLE_ANIMATION_DURATION_MS = 200;
+
+    /** The translation Y value the handle animates to when hiding it for a new bubble. */
+    private static final int NEW_BUBBLE_HIDE_HANDLE_ANIMATION_TRANSLATION_Y = -20;
+
+    /** The alpha value the handle animates to when hiding it for a new bubble. */
+    public static final float NEW_BUBBLE_HIDE_HANDLE_ANIMATION_ALPHA = 0.5f;
+
     protected final TaskbarActivityContext mActivity;
 
     // Initialized in init.
@@ -63,6 +73,7 @@
     private AnimatedFloat mIconScaleForStash;
     private AnimatedFloat mIconTranslationYForStash;
     private MultiPropertyFactory.MultiProperty mBubbleStashedHandleAlpha;
+    private AnimatedFloat mBubbleStashedHandleTranslationY;
 
     private boolean mRequestedStashState;
     private boolean mRequestedExpandedState;
@@ -94,6 +105,7 @@
 
         mBubbleStashedHandleAlpha = mHandleViewController.getStashedHandleAlpha().get(
                 StashedHandleViewController.ALPHA_INDEX_STASHED);
+        mBubbleStashedHandleTranslationY = mHandleViewController.getStashedHandleTranslationY();
 
         mStashedHeight = mHandleViewController.getStashedHeight();
         mUnstashedHeight = mHandleViewController.getUnstashedHeight();
@@ -356,4 +368,40 @@
     public boolean isEventOverStashHandle(MotionEvent ev) {
         return mHandleViewController.isEventOverHandle(ev);
     }
+
+    /** Set a bubble bar location */
+    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        mHandleViewController.setBubbleBarLocation(bubbleBarLocation);
+    }
+
+    /** Returns the x position of the center of the stashed handle. */
+    public float getStashedHandleCenterX() {
+        return mHandleViewController.getStashedHandleCenterX();
+    }
+
+    /** Returns the animation for hiding the handle before a new bubble animates in. */
+    public AnimatorSet buildHideHandleAnimationForNewBubble() {
+        AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.playTogether(
+                mBubbleStashedHandleTranslationY.animateToValue(
+                        NEW_BUBBLE_HIDE_HANDLE_ANIMATION_TRANSLATION_Y),
+                mBubbleStashedHandleAlpha.animateToValue(NEW_BUBBLE_HIDE_HANDLE_ANIMATION_ALPHA));
+        animatorSet.setDuration(NEW_BUBBLE_HANDLE_ANIMATION_DURATION_MS);
+        return animatorSet;
+    }
+
+    /** Sets the alpha value of the stashed handle. */
+    public void setStashAlpha(float alpha) {
+        mBubbleStashedHandleAlpha.setValue(alpha);
+    }
+
+    /** Returns the animation for showing the handle after a new bubble animated in. */
+    public AnimatorSet buildShowHandleAnimationForNewBubble() {
+        AnimatorSet animatorSet = new AnimatorSet();
+        animatorSet.playTogether(
+                mBubbleStashedHandleTranslationY.animateToValue(0),
+                mBubbleStashedHandleAlpha.animateToValue(1));
+        animatorSet.setDuration(NEW_BUBBLE_HANDLE_ANIMATION_DURATION_MS);
+        return animatorSet;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index f88460f..2a5912a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -16,7 +16,6 @@
 package com.android.launcher3.taskbar.bubbles;
 
 import static android.view.View.INVISIBLE;
-import static android.view.View.LAYOUT_DIRECTION_RTL;
 import static android.view.View.VISIBLE;
 
 import android.animation.Animator;
@@ -30,6 +29,7 @@
 import android.view.ViewOutlineProvider;
 
 import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.RevealOutlineAnimation;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.taskbar.StashedHandleView;
@@ -39,6 +39,7 @@
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 
 /**
  * Handles properties/data collection, then passes the results to our stashed handle View to render.
@@ -47,7 +48,7 @@
 
     private final TaskbarActivityContext mActivity;
     private final StashedHandleView mStashedHandleView;
-    private final MultiValueAlpha mTaskbarStashedHandleAlpha;
+    private final MultiValueAlpha mStashedHandleAlpha;
 
     // Initialized in init.
     private BubbleBarViewController mBarViewController;
@@ -58,6 +59,12 @@
     private int mStashedHandleWidth;
     private int mStashedHandleHeight;
 
+    private final AnimatedFloat mStashedHandleTranslationY =
+            new AnimatedFloat(this::updateTranslationY);
+
+    // Modified when swipe up is happening on the stashed handle or task bar.
+    private float mSwipeUpTranslationY;
+
     // The bounds we want to clip to in the settled state when showing the stashed handle.
     private final Rect mStashedHandleBounds = new Rect();
 
@@ -75,7 +82,7 @@
             StashedHandleView stashedHandleView) {
         mActivity = activity;
         mStashedHandleView = stashedHandleView;
-        mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, 1);
+        mStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, 1);
     }
 
     public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
@@ -93,7 +100,7 @@
                 R.dimen.transient_taskbar_bottom_margin);
         mStashedHandleView.getLayoutParams().height = mBarSize + bottomMargin;
 
-        mTaskbarStashedHandleAlpha.get(0).setValue(0);
+        mStashedHandleAlpha.get(0).setValue(0);
 
         mStashedTaskbarHeight = resources.getDimensionPixelSize(
                 R.dimen.bubblebar_stashed_size);
@@ -119,14 +126,14 @@
                 }, Executors.UI_HELPER_EXECUTOR);
 
         mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) ->
-                updateBounds());
+                updateBounds(mBarViewController.getBubbleBarLocation()));
     }
 
-    private void updateBounds() {
+    private void updateBounds(BubbleBarLocation bubbleBarLocation) {
         // As more bubbles get added, the icon bounds become larger. To ensure a consistent
         // handle bar position, we pin it to the edge of the screen.
         final int stashedCenterY = mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2;
-        if (isOnLeft()) {
+        if (bubbleBarLocation.isOnLeft(mStashedHandleView.isLayoutRtl())) {
             final int left = mBarViewController.getHorizontalMargin();
             mStashedHandleBounds.set(
                     left,
@@ -149,11 +156,6 @@
         mStashedHandleView.setPivotY(mStashedHandleView.getHeight() - mStashedTaskbarHeight / 2f);
     }
 
-    private boolean isOnLeft() {
-        // TODO(b/313661121): set this based on bubble bar position and not LTR or RTL
-        return mStashedHandleView.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-    }
-
     public void onDestroy() {
         mRegionSamplingHelper.stopAndDestroy();
         mRegionSamplingHelper = null;
@@ -236,18 +238,33 @@
         }
     }
 
+    /** Returns an animator for translation Y. */
+    public AnimatedFloat getStashedHandleTranslationY() {
+        return mStashedHandleTranslationY;
+    }
+
     /**
      * Sets the translation of the stashed handle during the swipe up gesture.
      */
     public void setTranslationYForSwipe(float transY) {
-        mStashedHandleView.setTranslationY(transY);
+        mSwipeUpTranslationY = transY;
+        updateTranslationY();
+    }
+
+    private void updateTranslationY() {
+        mStashedHandleView.setTranslationY(mStashedHandleTranslationY.value + mSwipeUpTranslationY);
     }
 
     /**
      * Used by {@link BubbleStashController} to animate the handle when stashing or un stashing.
      */
     public MultiPropertyFactory<View> getStashedHandleAlpha() {
-        return mTaskbarStashedHandleAlpha;
+        return mStashedHandleAlpha;
+    }
+
+    /** Returns the x position of the center of the stashed handle. */
+    public float getStashedHandleCenterX() {
+        return mStashedHandleBounds.exactCenterX();
     }
 
     /**
@@ -301,4 +318,9 @@
     public boolean containsX(int x) {
         return x >= mStashedHandleBounds.left && x <= mStashedHandleBounds.right;
     }
+
+    /** Set a bubble bar location */
+    public void setBubbleBarLocation(BubbleBarLocation bubbleBarLocation) {
+        updateBounds(bubbleBarLocation);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index 6549ad6..bcdc718 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -145,7 +145,7 @@
     }
 
     /** Sets the bubble being rendered in this view. */
-    void setBubble(BubbleBarBubble bubble) {
+    public void setBubble(BubbleBarBubble bubble) {
         mBubble = bubble;
         mBubbleIcon.setImageBitmap(bubble.getIcon());
         mAppIcon.setImageBitmap(bubble.getBadge());
@@ -159,7 +159,7 @@
      * the list of bubbles. It doesn't show an app icon because it is part of system UI / doesn't
      * come from an app.
      */
-    void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) {
+    public void setOverflow(BubbleBarOverflow overflow, Bitmap bitmap) {
         mBubble = overflow;
         mBubbleIcon.setImageBitmap(bitmap);
         mAppIcon.setVisibility(GONE); // Overflow doesn't show the app badge
@@ -168,7 +168,7 @@
 
     /** Returns the bubble being rendered in this view. */
     @Nullable
-    BubbleBarItem getBubble() {
+    public BubbleBarItem getBubble() {
         return mBubble;
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
new file mode 100644
index 0000000..1db5103
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.animation
+
+import android.view.View
+import android.view.View.VISIBLE
+import androidx.core.animation.AnimatorSet
+import androidx.core.animation.ObjectAnimator
+import androidx.core.animation.doOnEnd
+import androidx.dynamicanimation.animation.DynamicAnimation
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
+import com.android.launcher3.taskbar.bubbles.BubbleBarView
+import com.android.launcher3.taskbar.bubbles.BubbleStashController
+import com.android.launcher3.taskbar.bubbles.BubbleView
+import com.android.systemui.util.doOnEnd
+import com.android.wm.shell.shared.animation.PhysicsAnimator
+
+/** Handles animations for bubble bar bubbles. */
+class BubbleBarViewAnimator
+@JvmOverloads
+constructor(
+    private val bubbleBarView: BubbleBarView,
+    private val bubbleStashController: BubbleStashController,
+    private val scheduler: Scheduler = HandlerScheduler(bubbleBarView)
+) {
+
+    private companion object {
+        /** The time to show the flyout. */
+        const val FLYOUT_DELAY_MS: Long = 2500
+        /** The translation Y the new bubble will animate to. */
+        const val BUBBLE_ANIMATION_FINAL_TRANSLATION_Y = -50f
+        /** The initial translation Y value the new bubble is set to before the animation starts. */
+        // TODO(liranb): get rid of this and calculate this based on the y-distance between the
+        // bubble and the stash handle.
+        const val BUBBLE_ANIMATION_INITIAL_TRANSLATION_Y = 50f
+        /** The initial scale Y value that the new bubble is set to before the animation starts. */
+        const val BUBBLE_ANIMATION_INITIAL_SCALE_Y = 0.3f
+        /** The initial alpha value that the new bubble is set to before the animation starts. */
+        const val BUBBLE_ANIMATION_INITIAL_ALPHA = 0.5f
+        /** The duration of the hide bubble animation. */
+        const val HIDE_BUBBLE_ANIMATION_DURATION_MS = 250L
+    }
+
+    /** An interface for scheduling jobs. */
+    interface Scheduler {
+
+        /** Schedule the given [block] to run. */
+        fun post(block: () -> Unit)
+
+        /** Schedule the given [block] to start with a delay of [delayMillis]. */
+        fun postDelayed(delayMillis: Long, block: () -> Unit)
+    }
+
+    /** A [Scheduler] that uses a Handler to run jobs. */
+    private class HandlerScheduler(private val view: View) : Scheduler {
+
+        override fun post(block: () -> Unit) {
+            view.post(block)
+        }
+
+        override fun postDelayed(delayMillis: Long, block: () -> Unit) {
+            view.postDelayed(block, delayMillis)
+        }
+    }
+
+    private val springConfig =
+        PhysicsAnimator.SpringConfig(
+            stiffness = SpringForce.STIFFNESS_LOW,
+            dampingRatio = SpringForce.DAMPING_RATIO_MEDIUM_BOUNCY
+        )
+
+    /** Animates a bubble for the state where the bubble bar is stashed. */
+    fun animateBubbleInForStashed(b: BubbleBarBubble) {
+        val bubbleView = b.view
+        val animator = PhysicsAnimator.getInstance(bubbleView)
+        if (animator.isRunning()) animator.cancel()
+        // the animation of a new bubble is divided into 2 parts. The first part shows the bubble
+        // and the second part hides it after a delay.
+        val showAnimation = buildShowAnimation(bubbleView, b.key, animator)
+        val hideAnimation = buildHideAnimation(bubbleView)
+        scheduler.post(showAnimation)
+        scheduler.postDelayed(FLYOUT_DELAY_MS, hideAnimation)
+    }
+
+    /**
+     * Returns a lambda that starts the animation that shows the new bubble.
+     *
+     * The animation is divided into 2 parts. First the stash handle starts animating up and fades
+     * out. When it ends the bubble starts fading in. The bubble and stashed handle are aligned to
+     * give the impression of the stash handle morphing into the bubble.
+     */
+    private fun buildShowAnimation(
+        bubbleView: BubbleView,
+        key: String,
+        bubbleAnimator: PhysicsAnimator<BubbleView>
+    ): () -> Unit = {
+        // calculate the initial translation x the bubble should have in order to align it with the
+        // stash handle.
+        val initialTranslationX =
+            bubbleStashController.stashedHandleCenterX - bubbleView.centerXOnScreen
+        bubbleBarView.prepareForAnimatingBubbleWhileStashed(key)
+        bubbleAnimator.setDefaultSpringConfig(springConfig)
+        bubbleAnimator
+            .spring(DynamicAnimation.ALPHA, 1f)
+            .spring(DynamicAnimation.TRANSLATION_Y, BUBBLE_ANIMATION_FINAL_TRANSLATION_Y)
+            .spring(DynamicAnimation.SCALE_Y, 1f)
+        // prepare the bubble for the animation
+        bubbleView.alpha = 0f
+        bubbleView.translationX = initialTranslationX
+        bubbleView.translationY = BUBBLE_ANIMATION_INITIAL_TRANSLATION_Y
+        bubbleView.scaleY = BUBBLE_ANIMATION_INITIAL_SCALE_Y
+        bubbleView.visibility = VISIBLE
+        // start the stashed handle animation. when it ends, start the bubble animation.
+        val stashedHandleAnimation = bubbleStashController.buildHideHandleAnimationForNewBubble()
+        stashedHandleAnimation.doOnEnd {
+            bubbleView.alpha = BUBBLE_ANIMATION_INITIAL_ALPHA
+            bubbleAnimator.start()
+            bubbleStashController.setStashAlpha(0f)
+        }
+        stashedHandleAnimation.start()
+    }
+
+    /**
+     * Returns a lambda that starts the animation that hides the new bubble.
+     *
+     * Similarly to the show animation, this is divided into 2 parts. We first animate the bubble
+     * out, and then animate the stash handle in. At the end of the animation we reset the values of
+     * the bubble.
+     */
+    private fun buildHideAnimation(bubbleView: BubbleView): () -> Unit = {
+        val stashAnimation = bubbleStashController.buildShowHandleAnimationForNewBubble()
+        val alphaAnimator =
+            ObjectAnimator.ofFloat(bubbleView, View.ALPHA, BUBBLE_ANIMATION_INITIAL_ALPHA)
+        val translationYAnimator =
+            ObjectAnimator.ofFloat(
+                bubbleView,
+                View.TRANSLATION_Y,
+                BUBBLE_ANIMATION_INITIAL_TRANSLATION_Y
+            )
+        val scaleYAnimator =
+            ObjectAnimator.ofFloat(bubbleView, View.SCALE_Y, BUBBLE_ANIMATION_INITIAL_SCALE_Y)
+        val hideBubbleAnimation = AnimatorSet()
+        hideBubbleAnimation.playTogether(alphaAnimator, translationYAnimator, scaleYAnimator)
+        hideBubbleAnimation.duration = HIDE_BUBBLE_ANIMATION_DURATION_MS
+        hideBubbleAnimation.doOnEnd {
+            // the bubble is now hidden, start the stash handle animation and reset bubble
+            // properties
+            bubbleStashController.setStashAlpha(
+                BubbleStashController.NEW_BUBBLE_HIDE_HANDLE_ANIMATION_ALPHA
+            )
+            bubbleView.alpha = 0f
+            stashAnimation.start()
+            bubbleView.translationY = 0f
+            bubbleView.scaleY = 1f
+            if (bubbleStashController.isStashed) {
+                bubbleBarView.alpha = 0f
+            }
+            bubbleBarView.onAnimatingBubbleCompleted()
+        }
+        hideBubbleAnimation.start()
+    }
+}
+
+/** The X position in screen coordinates of the center of the bubble. */
+private val BubbleView.centerXOnScreen: Float
+    get() {
+        val screenCoordinates = IntArray(2)
+        getLocationOnScreen(screenCoordinates)
+        return screenCoordinates[0] + width / 2f
+    }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
index 2b60dc0..5bfdce9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
@@ -20,7 +20,6 @@
 import android.view.Surface.ROTATION_90
 import android.view.Surface.Rotation
 import android.view.ViewGroup
-import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.Space
@@ -56,18 +55,18 @@
          * @param isThreeButtonNav are no-ops when taskbar is present/showing
          */
         fun getUiLayoutter(
-                deviceProfile: DeviceProfile,
-                navButtonsView: NearestTouchFrame,
-                imeSwitcher: ImageView?,
-                rotationButton: RotationButton?,
-                a11yButton: ImageView?,
-                space: Space?,
-                resources: Resources,
-                isKidsMode: Boolean,
-                isInSetup: Boolean,
-                isThreeButtonNav: Boolean,
-                phoneMode: Boolean,
-                @Rotation surfaceRotation: Int
+            deviceProfile: DeviceProfile,
+            navButtonsView: NearestTouchFrame,
+            imeSwitcher: ImageView?,
+            rotationButton: RotationButton?,
+            a11yButton: ImageView?,
+            space: Space?,
+            resources: Resources,
+            isKidsMode: Boolean,
+            isInSetup: Boolean,
+            isThreeButtonNav: Boolean,
+            phoneMode: Boolean,
+            @Rotation surfaceRotation: Int
         ): NavButtonLayoutter {
             val navButtonContainer =
                 navButtonsView.requireViewById<LinearLayout>(ID_END_NAV_BUTTONS)
@@ -82,43 +81,6 @@
                     if (!deviceProfile.isLandscape) {
                         navButtonsView.setIsVertical(false)
                         PhonePortraitNavLayoutter(
-                                resources,
-                                navButtonContainer,
-                                endContextualContainer,
-                                startContextualContainer,
-                                imeSwitcher,
-                                rotationButton,
-                                a11yButton,
-                                space
-                        )
-                    } else if (surfaceRotation == ROTATION_90) {
-                        navButtonsView.setIsVertical(true)
-                        PhoneLandscapeNavLayoutter(
-                                resources,
-                                navButtonContainer,
-                                endContextualContainer,
-                                startContextualContainer,
-                                imeSwitcher,
-                                rotationButton,
-                                a11yButton,
-                                space
-                        )
-                    } else {
-                        navButtonsView.setIsVertical(true)
-                        PhoneSeascapeNavLayoutter(
-                                resources,
-                                navButtonContainer,
-                                endContextualContainer,
-                                startContextualContainer,
-                                imeSwitcher,
-                                rotationButton,
-                                a11yButton,
-                                space
-                        )
-                    }
-                }
-                isPhoneGestureMode ->{
-                    PhoneGestureLayoutter(
                             resources,
                             navButtonContainer,
                             endContextualContainer,
@@ -127,44 +89,82 @@
                             rotationButton,
                             a11yButton,
                             space
+                        )
+                    } else if (surfaceRotation == ROTATION_90) {
+                        navButtonsView.setIsVertical(true)
+                        PhoneLandscapeNavLayoutter(
+                            resources,
+                            navButtonContainer,
+                            endContextualContainer,
+                            startContextualContainer,
+                            imeSwitcher,
+                            rotationButton,
+                            a11yButton,
+                            space
+                        )
+                    } else {
+                        navButtonsView.setIsVertical(true)
+                        PhoneSeascapeNavLayoutter(
+                            resources,
+                            navButtonContainer,
+                            endContextualContainer,
+                            startContextualContainer,
+                            imeSwitcher,
+                            rotationButton,
+                            a11yButton,
+                            space
+                        )
+                    }
+                }
+                isPhoneGestureMode -> {
+                    PhoneGestureLayoutter(
+                        resources,
+                        navButtonContainer,
+                        endContextualContainer,
+                        startContextualContainer,
+                        imeSwitcher,
+                        rotationButton,
+                        a11yButton,
+                        space
                     )
                 }
                 deviceProfile.isTaskbarPresent -> {
                     return when {
                         isInSetup -> {
                             SetupNavLayoutter(
-                                    resources,
-                                    navButtonContainer,
-                                    endContextualContainer,
-                                    startContextualContainer,
-                                    imeSwitcher,
-                                    rotationButton,
-                                    a11yButton,
-                                    space
+                                resources,
+                                navButtonsView,
+                                navButtonContainer,
+                                endContextualContainer,
+                                startContextualContainer,
+                                imeSwitcher,
+                                rotationButton,
+                                a11yButton,
+                                space
                             )
                         }
                         isKidsMode -> {
                             KidsNavLayoutter(
-                                    resources,
-                                    navButtonContainer,
-                                    endContextualContainer,
-                                    startContextualContainer,
-                                    imeSwitcher,
-                                    rotationButton,
-                                    a11yButton,
-                                    space
+                                resources,
+                                navButtonContainer,
+                                endContextualContainer,
+                                startContextualContainer,
+                                imeSwitcher,
+                                rotationButton,
+                                a11yButton,
+                                space
                             )
                         }
                         else ->
                             TaskbarNavLayoutter(
-                                    resources,
-                                    navButtonContainer,
-                                    endContextualContainer,
-                                    startContextualContainer,
-                                    imeSwitcher,
-                                    rotationButton,
-                                    a11yButton,
-                                    space
+                                resources,
+                                navButtonContainer,
+                                endContextualContainer,
+                                startContextualContainer,
+                                imeSwitcher,
+                                rotationButton,
+                                a11yButton,
+                                space
                             )
                     }
                 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
index 181e0ed..8eff95c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
@@ -24,50 +24,89 @@
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.Space
+import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.systemui.shared.rotation.RotationButton
 
+const val SQUARE_ASPECT_RATIO_BOTTOM_BOUND = 0.95
+const val SQUARE_ASPECT_RATIO_UPPER_BOUND = 1.05
+
 class SetupNavLayoutter(
-        resources: Resources,
-        navButtonContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navButtonsView: NearestTouchFrame,
+    navButtonContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    rotationButton: RotationButton?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
     AbstractNavButtonLayoutter(
-            resources,
-            navButtonContainer,
-            endContextualContainer,
-            startContextualContainer,
-            imeSwitcher,
-            rotationButton,
-            a11yButton,
-            space
+        resources,
+        navButtonContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        rotationButton,
+        a11yButton,
+        space
     ) {
+    private val mNavButtonsView = navButtonsView
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
         // Since setup wizard only has back button enabled, it looks strange to be
         // end-aligned, so start-align instead.
         val navButtonsLayoutParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
-        navButtonsLayoutParams.apply {
-            marginStart = navButtonsLayoutParams.marginEnd
-            marginEnd = 0
-            gravity = Gravity.START
+        val navButtonsViewLayoutParams = mNavButtonsView.layoutParams as FrameLayout.LayoutParams
+        val deviceProfile: DeviceProfile = context.deviceProfile
+
+        navButtonsLayoutParams.marginEnd = 0
+        navButtonsLayoutParams.gravity = Gravity.START
+        context.setTaskbarWindowSize(context.setupWindowSize)
+
+        // If SUW is on a large screen device that is landscape (or has a square aspect
+        // ratio) the back button has to be placed accordingly
+        if (
+            deviceProfile.isTablet && deviceProfile.isLandscape ||
+                (deviceProfile.aspectRatio > SQUARE_ASPECT_RATIO_BOTTOM_BOUND &&
+                    deviceProfile.aspectRatio < SQUARE_ASPECT_RATIO_UPPER_BOUND)
+        ) {
+            navButtonsLayoutParams.marginStart =
+                resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_start_margin)
+            navButtonsViewLayoutParams.bottomMargin =
+                resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_bottom_margin)
+            navButtonsLayoutParams.height =
+                resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_height)
+        } else {
+            val phoneOrPortraitSetupMargin =
+                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
+            navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
+            navButtonsLayoutParams.bottomMargin =
+                if (!deviceProfile.isLandscape) 0
+                else
+                    phoneOrPortraitSetupMargin -
+                        resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
+            navButtonsViewLayoutParams.height =
+                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
         }
-        navButtonContainer.requestLayout()
+        mNavButtonsView.layoutParams = navButtonsViewLayoutParams
+        navButtonContainer.layoutParams = navButtonsLayoutParams
 
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
 
-        val contextualMargin = resources.getDimensionPixelSize(
-                R.dimen.taskbar_contextual_button_padding)
+        val contextualMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_padding)
         repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
-        repositionContextualContainer(startContextualContainer, WRAP_CONTENT, contextualMargin,
-                contextualMargin, Gravity.START)
+        repositionContextualContainer(
+            startContextualContainer,
+            WRAP_CONTENT,
+            contextualMargin,
+            contextualMargin,
+            Gravity.START
+        )
 
         if (imeSwitcher != null) {
             startContextualContainer.addView(imeSwitcher)
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
index 5c57a01..34d3fad 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/TaskbarNavLayoutter.kt
@@ -28,35 +28,39 @@
 import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.systemui.shared.rotation.RotationButton
 
-/**
- * Layoutter for rendering task bar in large screen, both in 3-button and gesture nav mode.
- */
+/** Layoutter for rendering task bar in large screen, both in 3-button and gesture nav mode. */
 class TaskbarNavLayoutter(
-        resources: Resources,
-        navBarContainer: LinearLayout,
-        endContextualContainer: ViewGroup,
-        startContextualContainer: ViewGroup,
-        imeSwitcher: ImageView?,
-        rotationButton: RotationButton?,
-        a11yButton: ImageView?,
-        space: Space?
+    resources: Resources,
+    navBarContainer: LinearLayout,
+    endContextualContainer: ViewGroup,
+    startContextualContainer: ViewGroup,
+    imeSwitcher: ImageView?,
+    rotationButton: RotationButton?,
+    a11yButton: ImageView?,
+    space: Space?
 ) :
     AbstractNavButtonLayoutter(
-            resources,
-            navBarContainer,
-            endContextualContainer,
-            startContextualContainer,
-            imeSwitcher,
-            rotationButton,
-            a11yButton,
-            space
+        resources,
+        navBarContainer,
+        endContextualContainer,
+        startContextualContainer,
+        imeSwitcher,
+        rotationButton,
+        a11yButton,
+        space
     ) {
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
         // Add spacing after the end of the last nav button
-        var navMarginEnd = resources
-                .getDimension(context.deviceProfile.inv.inlineNavButtonsEndSpacing)
-                .toInt()
+        var navMarginEnd =
+            resources.getDimension(context.deviceProfile.inv.inlineNavButtonsEndSpacing).toInt()
+
+        val cutout = context.display.cutout
+        val bottomRect = cutout?.boundingRectBottom
+        if (bottomRect != null && !bottomRect.isEmpty) {
+            navMarginEnd = bottomRect.width()
+        }
+
         val contextualWidth = endContextualContainer.width
         // If contextual buttons are showing, we check if the end margin is enough for the
         // contextual button to be showing - if not, move the nav buttons over a smidge
@@ -65,8 +69,11 @@
             navMarginEnd += resources.getDimensionPixelSize(R.dimen.taskbar_hotseat_nav_spacing) / 2
         }
 
-        val navButtonParams = FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT)
+        val navButtonParams =
+            FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.MATCH_PARENT
+            )
         navButtonParams.apply {
             gravity = Gravity.END or Gravity.CENTER_VERTICAL
             marginEnd = navMarginEnd
@@ -98,15 +105,33 @@
         startContextualContainer.removeAllViews()
 
         if (!context.deviceProfile.isGestureMode) {
-            val contextualMargin = resources.getDimensionPixelSize(
-                    R.dimen.taskbar_contextual_button_padding)
+            val contextualMargin =
+                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_padding)
             repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
-            repositionContextualContainer(startContextualContainer, WRAP_CONTENT, contextualMargin,
-                    contextualMargin, Gravity.START)
+            repositionContextualContainer(
+                startContextualContainer,
+                WRAP_CONTENT,
+                contextualMargin,
+                contextualMargin,
+                Gravity.START
+            )
 
             if (imeSwitcher != null) {
+                val imeStartMargin =
+                    resources.getDimensionPixelSize(
+                        R.dimen.taskbar_ime_switcher_button_margin_start
+                    )
                 startContextualContainer.addView(imeSwitcher)
-                imeSwitcher.layoutParams = getParamsToCenterView()
+                val imeSwitcherButtonParams =
+                    FrameLayout.LayoutParams(
+                        FrameLayout.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.MATCH_PARENT
+                    )
+                imeSwitcherButtonParams.apply {
+                    marginStart = imeStartMargin
+                    gravity = Gravity.CENTER_VERTICAL
+                }
+                imeSwitcher.layoutParams = imeSwitcherButtonParams
             }
             if (a11yButton != null) {
                 endContextualContainer.addView(a11yButton)
diff --git a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
deleted file mode 100644
index dcc3b05..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/ApiWrapper.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2017 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.uioverrides;
-
-import android.app.ActivityOptions;
-import android.app.PendingIntent;
-import android.app.Person;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.LauncherActivityInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.LauncherUserInfo;
-import android.content.pm.ShortcutInfo;
-import android.graphics.drawable.ColorDrawable;
-import android.net.Uri;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.ArrayMap;
-import android.window.RemoteTransition;
-
-import com.android.launcher3.Flags;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.proxy.ProxyActivityStarter;
-import com.android.launcher3.util.StartActivityParams;
-import com.android.launcher3.util.UserIconInfo;
-import com.android.quickstep.util.FadeOutRemoteTransition;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A wrapper for the hidden API calls
- */
-public class ApiWrapper {
-
-    public static final boolean TASKBAR_DRAWN_IN_PROCESS = true;
-
-    public static Person[] getPersons(ShortcutInfo si) {
-        Person[] persons = si.getPersons();
-        return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons;
-    }
-
-    public static Map<String, LauncherActivityInfo> getActivityOverrides(Context context) {
-        return context.getSystemService(LauncherApps.class).getActivityOverrides();
-    }
-
-    /**
-     * Creates an ActivityOptions to play fade-out animation on closing targets
-     */
-    public static ActivityOptions createFadeOutAnimOptions(Context context) {
-        ActivityOptions options = ActivityOptions.makeBasic();
-        options.setRemoteTransition(new RemoteTransition(new FadeOutRemoteTransition()));
-        return options;
-    }
-
-    /**
-     * Returns a map of all users on the device to their corresponding UI properties
-     */
-    public static Map<UserHandle, UserIconInfo> queryAllUsers(Context context) {
-        UserManager um = context.getSystemService(UserManager.class);
-        Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
-        List<UserHandle> usersActual = um.getUserProfiles();
-        if (usersActual != null) {
-            for (UserHandle user : usersActual) {
-                if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()) {
-                    LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
-                    LauncherUserInfo launcherUserInfo = launcherApps.getLauncherUserInfo(user);
-                    if (launcherUserInfo == null) {
-                        continue;
-                    }
-                    // UserTypes not supported in Launcher are deemed to be the current
-                    // Foreground User.
-                    int userType = switch (launcherUserInfo.getUserType()) {
-                        case UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK;
-                        case UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED;
-                        case UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE;
-                        default -> UserIconInfo.TYPE_MAIN;
-                    };
-                    long serial = launcherUserInfo.getUserSerialNumber();
-                    users.put(user, new UserIconInfo(user, userType, serial));
-                } else {
-                    long serial = um.getSerialNumberForUser(user);
-
-                    // Simple check to check if the provided user is work profile
-                    // TODO: Migrate to a better platform API
-                    NoopDrawable d = new NoopDrawable();
-                    boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user));
-                    UserIconInfo info = new UserIconInfo(
-                            user,
-                            isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN,
-                            serial);
-                    users.put(user, info);
-                }
-            }
-        }
-        return users;
-    }
-
-    /**
-     * Returns the list of the system packages that are installed at user creation.
-     * An empty list denotes that all system packages are installed for that user at creation.
-     */
-    public static List<String> getPreInstalledSystemPackages(Context context, UserHandle user) {
-        LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
-        if (android.os.Flags.allowPrivateProfile() && Flags.enablePrivateSpace()
-                && Flags.privateSpaceSysAppsSeparation()) {
-            return launcherApps.getPreInstalledSystemPackages(user);
-        } else {
-            return new ArrayList<>();
-        }
-    }
-
-    /**
-     * Returns an intent which can be used to start the App Market activity (Installer
-     * Activity).
-     */
-    public static Intent getAppMarketActivityIntent(Context context, String packageName,
-            UserHandle user) {
-        LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
-        if (android.os.Flags.allowPrivateProfile()
-                && Flags.enablePrivateSpace()
-                && (Flags.privateSpaceAppInstallerButton()
-                        || Flags.enablePrivateSpaceInstallShortcut())) {
-            StartActivityParams params = new StartActivityParams((PendingIntent) null, 0);
-            params.intentSender = launcherApps.getAppMarketActivityIntent(packageName, user);
-            ActivityOptions options = ActivityOptions.makeBasic()
-                    .setPendingIntentBackgroundActivityStartMode(ActivityOptions
-                            .MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
-            params.options = options.toBundle();
-            params.requireActivityResult = false;
-            return ProxyActivityStarter.getLaunchIntent(context, params);
-        } else {
-            return new Intent(Intent.ACTION_VIEW)
-                    .setData(new Uri.Builder()
-                            .scheme("market")
-                            .authority("details")
-                            .appendQueryParameter("id", packageName)
-                            .build())
-                    .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
-                            .authority(context.getPackageName()).build());
-        }
-    }
-
-    /**
-     * Checks if an activity is flagged as non-resizeable.
-     */
-    public static boolean isNonResizeableActivity(LauncherActivityInfo lai) {
-        return lai.getActivityInfo().resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-    }
-
-    private static class NoopDrawable extends ColorDrawable {
-        @Override
-        public int getIntrinsicHeight() {
-            return 1;
-        }
-
-        @Override
-        public int getIntrinsicWidth() {
-            return 1;
-        }
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
deleted file mode 100644
index 8f1d319..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2020 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.uioverrides;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.launcher3.R;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-
-/** A util class that inflates a predicted app icon */
-public class PredictedAppIconInflater {
-    public static View inflate(LayoutInflater inflater, ViewGroup parent, WorkspaceItemInfo info) {
-        PredictedAppIcon icon = (PredictedAppIcon) inflater.inflate(
-                R.layout.predicted_app_icon, parent, false);
-        icon.applyFromWorkspaceItem(info);
-        return icon;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 10a7ff6..6c05bfe 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -40,8 +40,8 @@
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
 import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
 import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
@@ -62,8 +62,8 @@
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.util.AnimUtils.completeRunnableListCallback;
 import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
 
 import android.animation.Animator;
@@ -105,7 +105,7 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Flags;
-import com.android.launcher3.HomeTransitionController;
+import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.LauncherState;
@@ -181,6 +181,7 @@
 import com.android.quickstep.views.FloatingTaskView;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -204,7 +205,7 @@
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
-public class QuickstepLauncher extends Launcher {
+public class QuickstepLauncher extends Launcher implements RecentsViewContainer {
     private static final boolean TRACE_LAYOUTS =
             SystemProperties.getBoolean("persist.debug.trace_layouts", false);
     private static final String TRACE_RELAYOUT_CLASS =
@@ -216,9 +217,10 @@
     private FixedContainerItems mAllAppsPredictions;
     private HotseatPredictionController mHotseatPredictionController;
     private DepthController mDepthController;
-    private DesktopVisibilityController mDesktopVisibilityController;
+    private @Nullable DesktopVisibilityController mDesktopVisibilityController;
     private QuickstepTransitionManager mAppTransitionManager;
-    private OverviewActionsView mActionsView;
+
+    private OverviewActionsView<?> mActionsView;
     private TISBindHelper mTISBindHelper;
     private @Nullable LauncherTaskbarUIController mTaskbarUIController;
     // Will be updated when dragging from taskbar.
@@ -244,21 +246,23 @@
 
     private boolean mIsPredictiveBackToHomeInProgress;
 
-    private HomeTransitionController mHomeTransitionController;
+    public static QuickstepLauncher getLauncher(Context context) {
+        return fromContext(context);
+    }
 
     @Override
     protected void setupViews() {
         super.setupViews();
 
         mActionsView = findViewById(R.id.overview_actions_view);
-        RecentsView overviewPanel = getOverviewPanel();
+        RecentsView<?,?> overviewPanel = getOverviewPanel();
         SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(this);
         mSplitSelectStateController =
                 new SplitSelectStateController(this, mHandler, getStateManager(),
                         getDepthController(), getStatsLogManager(),
                         systemUiProxy, RecentsModel.INSTANCE.get(this),
                         () -> onStateBack());
-        if (isDesktopModeSupported()) {
+        if (enableDesktopWindowingMode()) {
             mDesktopRecentsTransitionController = new DesktopRecentsTransitionController(
                     getStateManager(), systemUiProxy, getIApplicationThread(),
                     getDepthController());
@@ -276,15 +280,10 @@
         mAppTransitionManager.registerRemoteAnimations();
         mAppTransitionManager.registerRemoteTransitions();
 
-        if (FeatureFlags.enableHomeTransitionListener()) {
-            mHomeTransitionController = new HomeTransitionController();
-            mHomeTransitionController.registerHomeTransitionListener(this);
-        }
-
         mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
         mDepthController = new DepthController(this);
-        mDesktopVisibilityController = new DesktopVisibilityController(this);
-        if (isDesktopModeSupported()) {
+        if (enableDesktopWindowingMode()) {
+            mDesktopVisibilityController = new DesktopVisibilityController(this);
             mDesktopVisibilityController.registerSystemUiListener();
             mSplitSelectStateController.initSplitFromDesktopController(this);
         }
@@ -522,10 +521,6 @@
             mLauncherUnfoldAnimationController.onDestroy();
         }
 
-        if (mHomeTransitionController != null) {
-            mHomeTransitionController.unregisterHomeTransitionListener();
-        }
-
         if (mDesktopVisibilityController != null) {
             mDesktopVisibilityController.unregisterSystemUiListener();
         }
@@ -667,6 +662,14 @@
     }
 
     @Override
+    protected boolean initDeviceProfile(InvariantDeviceProfile idp) {
+        final boolean ret = super.initDeviceProfile(idp);
+        mDeviceProfile.isPredictiveBackSwipe =
+                getApplicationInfo().isOnBackInvokedCallbackEnabled();
+        return ret;
+    }
+
+    @Override
     public void startSplitSelection(SplitSelectSource splitSelectSource) {
         RecentsView recentsView = getOverviewPanel();
         // Check if there is already an instance of this app running, if so, initiate the split
@@ -939,15 +942,13 @@
 
     @Override
     public void setResumed() {
-        if (isDesktopModeSupported()) {
-            DesktopVisibilityController controller = mDesktopVisibilityController;
-            if (controller != null && controller.areFreeformTasksVisible()
-                    && !controller.isRecentsGestureInProgress()) {
-                // Return early to skip setting activity to appear as resumed
-                // TODO(b/255649902): shouldn't be needed when we have a separate launcher state
-                //  for desktop that we can use to control other parts of launcher
-                return;
-            }
+        if (mDesktopVisibilityController != null
+                && mDesktopVisibilityController.areDesktopTasksVisible()
+                && !mDesktopVisibilityController.isRecentsGestureInProgress()) {
+            // Return early to skip setting activity to appear as resumed
+            // TODO(b/255649902): shouldn't be needed when we have a separate launcher state
+            //  for desktop that we can use to control other parts of launcher
+            return;
         }
         super.setResumed();
     }
@@ -1060,8 +1061,9 @@
                 .playPlaceholderDismissAnim(this, splitDismissEvent);
     }
 
-    public <T extends OverviewActionsView> T getActionsView() {
-        return (T) mActionsView;
+    @Override
+    public OverviewActionsView<?> getActionsView() {
+        return mActionsView;
     }
 
     @Override
@@ -1081,6 +1083,7 @@
         return mDepthController;
     }
 
+    @Nullable
     public DesktopVisibilityController getDesktopVisibilityController() {
         return mDesktopVisibilityController;
     }
@@ -1288,9 +1291,9 @@
     }
 
     @Override
-    public boolean areFreeformTasksVisible() {
+    public boolean areDesktopTasksVisible() {
         if (mDesktopVisibilityController != null) {
-            return mDesktopVisibilityController.areFreeformTasksVisible();
+            return mDesktopVisibilityController.areDesktopTasksVisible();
         }
         return false;
     }
@@ -1373,25 +1376,25 @@
     }
 
     private static final class LauncherTaskViewController extends
-            TaskViewTouchController<Launcher> {
+            TaskViewTouchController<QuickstepLauncher> {
 
-        LauncherTaskViewController(Launcher activity) {
+        LauncherTaskViewController(QuickstepLauncher activity) {
             super(activity);
         }
 
         @Override
         protected boolean isRecentsInteractive() {
-            return mActivity.isInState(OVERVIEW) || mActivity.isInState(OVERVIEW_MODAL_TASK);
+            return mContainer.isInState(OVERVIEW) || mContainer.isInState(OVERVIEW_MODAL_TASK);
         }
 
         @Override
         protected boolean isRecentsModal() {
-            return mActivity.isInState(OVERVIEW_MODAL_TASK);
+            return mContainer.isInState(OVERVIEW_MODAL_TASK);
         }
 
         @Override
         protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) {
-            mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
+            mContainer.getStateManager().setCurrentUserControlledAnimation(animController);
         }
     }
 
@@ -1414,6 +1417,10 @@
         if (mHotseatPredictionController != null) {
             mHotseatPredictionController.dump(prefix, writer);
         }
+        PredictionRowView<?> predictionRowView =
+                getAppsView().getFloatingHeaderView().findFixedRowByType(
+                        PredictionRowView.class);
+        predictionRowView.dump(prefix, writer);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
index 23e2622..01d5ff0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.uioverrides;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
@@ -32,7 +33,6 @@
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -101,7 +101,7 @@
                                     new ArrayList<>(h.mProviderChangedListeners).forEach(
                                     ProviderChangedListener::notifyWidgetProvidersChanged))),
                     UI_HELPER_EXECUTOR.getLooper());
-            if (!WidgetsModel.GO_DISABLE_WIDGETS) {
+            if (WIDGETS_ENABLED) {
                 sWidgetHost.startListening();
             }
         }
@@ -195,7 +195,7 @@
      */
     @Override
     public void stopListening() {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return;
         }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index e6a115a..6c1d4b1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -133,7 +133,7 @@
         // Create transition animations to split select
         RecentsPagedOrientationHandler orientationHandler =
                 ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
-        Pair<FloatProperty, FloatProperty> taskViewsFloat =
+        Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
                 orientationHandler.getSplitSelectTaskOffset(
                         TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
                         mLauncher.getDeviceProfile());
diff --git a/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
new file mode 100644
index 0000000..535b4c2
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/SystemApiWrapper.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.uioverrides
+
+import android.app.ActivityOptions
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.LauncherActivityInfo
+import android.content.pm.LauncherApps
+import android.content.pm.ShortcutInfo
+import android.os.Flags.allowPrivateProfile
+import android.os.UserHandle
+import android.os.UserManager
+import android.util.ArrayMap
+import android.window.RemoteTransition
+import com.android.launcher3.Flags.enablePrivateSpace
+import com.android.launcher3.Flags.enablePrivateSpaceInstallShortcut
+import com.android.launcher3.Flags.privateSpaceAppInstallerButton
+import com.android.launcher3.Flags.privateSpaceSysAppsSeparation
+import com.android.launcher3.Utilities
+import com.android.launcher3.proxy.ProxyActivityStarter
+import com.android.launcher3.util.ApiWrapper
+import com.android.launcher3.util.StartActivityParams
+import com.android.launcher3.util.UserIconInfo
+import com.android.quickstep.util.FadeOutRemoteTransition
+
+/** A wrapper for the hidden API calls */
+class SystemApiWrapper(context: Context?) : ApiWrapper(context) {
+
+    override fun getPersons(si: ShortcutInfo) = si.persons ?: Utilities.EMPTY_PERSON_ARRAY
+
+    override fun getActivityOverrides(): Map<String, LauncherActivityInfo> =
+        mContext.getSystemService(LauncherApps::class.java)!!.activityOverrides
+
+    override fun createFadeOutAnimOptions(): ActivityOptions =
+        ActivityOptions.makeBasic().apply {
+            remoteTransition = RemoteTransition(FadeOutRemoteTransition())
+        }
+
+    override fun queryAllUsers(): Map<UserHandle, UserIconInfo> {
+        if (!allowPrivateProfile() || !enablePrivateSpace()) {
+            return super.queryAllUsers()
+        }
+        val users = ArrayMap<UserHandle, UserIconInfo>()
+        mContext.getSystemService(UserManager::class.java)!!.userProfiles?.forEach { user ->
+            mContext.getSystemService(LauncherApps::class.java)!!.getLauncherUserInfo(user)?.apply {
+                users[user] =
+                    UserIconInfo(
+                        user,
+                        when (userType) {
+                            UserManager.USER_TYPE_PROFILE_MANAGED -> UserIconInfo.TYPE_WORK
+                            UserManager.USER_TYPE_PROFILE_CLONE -> UserIconInfo.TYPE_CLONED
+                            UserManager.USER_TYPE_PROFILE_PRIVATE -> UserIconInfo.TYPE_PRIVATE
+                            else -> UserIconInfo.TYPE_MAIN
+                        },
+                        userSerialNumber.toLong()
+                    )
+            }
+        }
+        return users
+    }
+
+    override fun getPreInstalledSystemPackages(user: UserHandle): List<String> =
+        if (allowPrivateProfile() && enablePrivateSpace() && privateSpaceSysAppsSeparation())
+            mContext
+                .getSystemService(LauncherApps::class.java)!!
+                .getPreInstalledSystemPackages(user)
+        else ArrayList()
+
+    override fun getAppMarketActivityIntent(packageName: String, user: UserHandle): Intent =
+        if (
+            allowPrivateProfile() &&
+                enablePrivateSpace() &&
+                (privateSpaceAppInstallerButton() || enablePrivateSpaceInstallShortcut())
+        )
+            ProxyActivityStarter.getLaunchIntent(
+                mContext,
+                StartActivityParams(null as PendingIntent?, 0).apply {
+                    intentSender =
+                        mContext
+                            .getSystemService(LauncherApps::class.java)!!
+                            .getAppMarketActivityIntent(packageName, user)
+                    options =
+                        ActivityOptions.makeBasic()
+                            .setPendingIntentBackgroundActivityStartMode(
+                                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+                            )
+                            .toBundle()
+                    requireActivityResult = false
+                }
+            )
+        else super.getAppMarketActivityIntent(packageName, user)
+
+    /** Returns an intent which can be used to open Private Space Settings. */
+    override fun getPrivateSpaceSettingsIntent(): Intent? =
+        if (allowPrivateProfile() && enablePrivateSpace())
+            ProxyActivityStarter.getLaunchIntent(
+                mContext,
+                StartActivityParams(null as PendingIntent?, 0).apply {
+                    intentSender =
+                        mContext
+                            .getSystemService(LauncherApps::class.java)
+                            ?.privateSpaceSettingsIntent
+                            ?: return null
+                    options =
+                        ActivityOptions.makeBasic()
+                            .setPendingIntentBackgroundActivityStartMode(
+                                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
+                            )
+                            .toBundle()
+                    requireActivityResult = false
+                }
+            )
+        else null
+
+    override fun isNonResizeableActivity(lai: LauncherActivityInfo) =
+        lai.activityInfo.resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
deleted file mode 100644
index 630ef39..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.uioverrides.flags;
-
-import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;
-
-import androidx.annotation.NonNull;
-
-import com.android.launcher3.config.FeatureFlags.BooleanFlag;
-import com.android.launcher3.config.FeatureFlags.FlagState;
-
-class DebugFlag extends BooleanFlag {
-
-    public final String key;
-    public final String description;
-
-    @NonNull
-    public final FlagState defaultValue;
-
-    DebugFlag(String key, String description, FlagState defaultValue, boolean currentValue) {
-        super(currentValue);
-        this.key = key;
-        this.defaultValue = defaultValue;
-        this.description = description;
-    }
-
-    /**
-     * Returns {@code true} if this flag's value has been modified from its default.
-     * <p>
-     * This helps to identify which flags have been toggled in log dumps and bug reports to
-     * further help triaging and debugging.
-     */
-    boolean currentValueModified() {
-        switch (defaultValue) {
-            case ENABLED: return !get();
-            case TEAMFOOD: return TEAMFOOD_FLAG.get() != get();
-            case DISABLED: return get();
-            default: return true;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return key + ": defaultValue=" + defaultValue + ", mCurrentValue=" + get();
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
new file mode 100644
index 0000000..6b44ca7
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DevOptionsUiHelper.kt
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.uioverrides.flags
+
+import android.os.Handler
+import android.provider.DeviceConfig
+import android.text.Html
+import android.view.inputmethod.EditorInfo
+import androidx.preference.Preference
+import androidx.preference.PreferenceGroup
+import androidx.preference.PreferenceViewHolder
+import androidx.preference.SwitchPreference
+import com.android.launcher3.ExtendedEditText
+import com.android.launcher3.R
+import com.android.quickstep.util.DeviceConfigHelper
+import com.android.quickstep.util.DeviceConfigHelper.Companion.NAMESPACE_LAUNCHER
+import com.android.quickstep.util.DeviceConfigHelper.DebugInfo
+
+/** Helper class to generate UI for Device Config */
+class DevOptionsUiHelper {
+
+    /** Inflates preferences for all server flags in the provider PreferenceGroup */
+    fun inflateServerFlags(parent: PreferenceGroup) {
+        val prefs = DeviceConfigHelper.prefs
+        // Sort the keys in the order of modified first followed by natural order
+        val allProps =
+            DeviceConfigHelper.allProps.values
+                .toList()
+                .sortedWith(
+                    Comparator.comparingInt { prop: DebugInfo<*> ->
+                            if (prefs.contains(prop.key)) 0 else 1
+                        }
+                        .thenComparing { prop: DebugInfo<*> -> prop.key }
+                )
+
+        // First add boolean flags
+        allProps.forEach {
+            if (it.isInt) return@forEach
+            val info = it as DebugInfo<Boolean>
+
+            val preference =
+                object : SwitchPreference(parent.context) {
+                    override fun onBindViewHolder(holder: PreferenceViewHolder) {
+                        super.onBindViewHolder(holder)
+                        holder.itemView.setOnLongClickListener {
+                            prefs.edit().remove(key).apply()
+                            setChecked(info.getBoolValue())
+                            summary = info.getSummary()
+                            true
+                        }
+                    }
+                }
+            preference.key = info.key
+            preference.isPersistent = false
+            preference.title = info.key
+            preference.summary = info.getSummary()
+            preference.setChecked(prefs.getBoolean(info.key, info.getBoolValue()))
+            preference.setOnPreferenceChangeListener { _, newVal ->
+                DeviceConfigHelper.prefs.edit().putBoolean(info.key, newVal as Boolean).apply()
+                preference.summary = info.getSummary()
+                true
+            }
+            parent.addPreference(preference)
+        }
+
+        // Apply Int flags
+        allProps.forEach {
+            if (!it.isInt) return@forEach
+            val info = it as DebugInfo<Int>
+
+            val preference =
+                object : Preference(parent.context) {
+                    override fun onBindViewHolder(holder: PreferenceViewHolder) {
+                        super.onBindViewHolder(holder)
+                        val textView = holder.findViewById(R.id.pref_edit_text) as ExtendedEditText
+                        textView.setText(info.getIntValueAsString())
+                        textView.setOnEditorActionListener { _, actionId, _ ->
+                            if (actionId == EditorInfo.IME_ACTION_DONE) {
+                                DeviceConfigHelper.prefs
+                                    .edit()
+                                    .putInt(key, textView.text.toString().toInt())
+                                    .apply()
+                                Handler().post { summary = info.getSummary() }
+                                true
+                            }
+                            false
+                        }
+                        textView.setOnBackKeyListener {
+                            textView.setText(info.getIntValueAsString())
+                            true
+                        }
+
+                        holder.itemView.setOnLongClickListener {
+                            prefs.edit().remove(key).apply()
+                            textView.setText(info.getIntValueAsString())
+                            summary = info.getSummary()
+                            true
+                        }
+                    }
+                }
+            preference.key = info.key
+            preference.isPersistent = false
+            preference.title = info.key
+            preference.summary = info.getSummary()
+            preference.widgetLayoutResource = R.layout.develop_options_edit_text
+            parent.addPreference(preference)
+        }
+    }
+
+    /**
+     * Returns the summary to show the description and whether the flag overrides the default value.
+     */
+    private fun DebugInfo<*>.getSummary() =
+        Html.fromHtml(
+            (if (DeviceConfigHelper.prefs.contains(this.key))
+                "<font color='red'><b>[OVERRIDDEN]</b></font><br>"
+            else "") + this.desc
+        )
+
+    private fun DebugInfo<Boolean>.getBoolValue() =
+        DeviceConfigHelper.prefs.getBoolean(
+            this.key,
+            DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, this.key, this.valueInCode)
+        )
+
+    private fun DebugInfo<Int>.getIntValueAsString() =
+        DeviceConfigHelper.prefs
+            .getInt(this.key, DeviceConfig.getInt(NAMESPACE_LAUNCHER, this.key, this.valueInCode))
+            .toString()
+
+    companion object {
+        const val TAG = "DeviceConfigUIHelper"
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java
index 369ff14..3f818ac 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java
@@ -20,18 +20,8 @@
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
-import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
-import static com.android.launcher3.LauncherPrefs.PRIVATE_SPACE_APPS;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_DELAY;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_END_SCALE_PERCENT;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_ITERATIONS;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_SCALE_EXPONENT;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_START_SCALE_PERCENT;
-import static com.android.launcher3.config.FeatureFlags.LPNH_SLOP_PERCENTAGE;
-import static com.android.launcher3.config.FeatureFlags.LPNH_TIMEOUT_MS;
 import static com.android.launcher3.settings.SettingsActivity.EXTRA_FRAGMENT_HIGHLIGHT_KEY;
 import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
-import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;
 import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
 import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_COUNT;
 import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN;
@@ -50,7 +40,6 @@
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -60,21 +49,18 @@
 
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceDataStore;
 import androidx.preference.PreferenceFragmentCompat;
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SeekBarPreference;
 import androidx.preference.SwitchPreference;
 
-import com.android.launcher3.ConstantItem;
-import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.systemui.shared.plugins.PluginEnabler;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -89,19 +75,17 @@
 
     private static final String ACTION_PLUGIN_SETTINGS =
             "com.android.systemui.action.PLUGIN_SETTINGS";
-    private static final String TAG = "DeveloperOptionsUI";
     private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN";
 
     private final PreferenceFragmentCompat mFragment;
     private final PreferenceScreen mPreferenceScreen;
 
-    private final FlagTogglerPrefUi mFlagTogglerPrefUi;
-
     private PreferenceCategory mPluginsCategory;
 
     public DeveloperOptionsUI(PreferenceFragmentCompat fragment, PreferenceCategory flags) {
         mFragment = fragment;
         mPreferenceScreen = fragment.getPreferenceScreen();
+        flags.getParent().removePreference(flags);
 
         // Add search bar
         View listView = mFragment.getListView();
@@ -111,20 +95,12 @@
         parent.addView(topBar, parent.indexOfChild(listView));
         initSearch(topBar.findViewById(R.id.filter_box));
 
-        mFlagTogglerPrefUi = new FlagTogglerPrefUi(mFragment.requireActivity(),
-                topBar.findViewById(R.id.flag_apply_btn));
-        mFlagTogglerPrefUi.applyTo(flags);
+        DevOptionsUiHelper uiHelper = new DevOptionsUiHelper();
+        uiHelper.inflateServerFlags(newCategory("Server flags"));
 
         loadPluginPrefs();
         maybeAddSandboxCategory();
         addOnboardingPrefsCatergory();
-        if (FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()) {
-            addAllAppsFromOverviewCatergory();
-        }
-        addCustomLpnhCategory();
-        if (Flags.enablePrivateSpace()) {
-            addCustomPrivateAppsCategory();
-        }
     }
 
     private void filterPreferences(String query, PreferenceGroup pg) {
@@ -204,7 +180,7 @@
                 new ArrayMap<>();
 
         Set<String> pluginPermissionApps = pm.getPackagesHoldingPermissions(
-                new String[]{PLUGIN_PERMISSION}, MATCH_DISABLED_COMPONENTS)
+                        new String[]{PLUGIN_PERMISSION}, MATCH_DISABLED_COMPONENTS)
                 .stream()
                 .map(pi -> pi.packageName)
                 .collect(Collectors.toSet());
@@ -227,7 +203,7 @@
             }
         }
 
-        PreferenceDataStore enabler = manager.getPluginEnabler();
+        PluginEnabler enabler = manager.getPluginEnabler();
         plugins.forEach((key, si) -> {
             String packageName = key.first;
             List<ComponentName> componentNames = si.stream()
@@ -346,107 +322,10 @@
         return onboardingPref;
     }
 
-    private void addAllAppsFromOverviewCatergory() {
-        PreferenceCategory category = newCategory("All Apps from Overview Config");
-        category.addPreference(createSeekBarPreference("Threshold to open All Apps from Overview",
-                105, 500, 100, ALL_APPS_OVERVIEW_THRESHOLD));
-    }
-
-    private void addCustomLpnhCategory() {
-        PreferenceCategory category = newCategory("Long Press Nav Handle Config");
-        if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
-            category.addPreference(createSeekBarPreference(
-                    "Slop multiplier (applied to edge slop, "
-                            + "which is generally already 50% higher than touch slop)",
-                    25, 200, 100, LPNH_SLOP_PERCENTAGE));
-            category.addPreference(createSeekBarPreference("LPNH timeout",
-                    100, 500, 1, LPNH_TIMEOUT_MS));
-        }
-        if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get()) {
-            category.addPreference(
-                    createSeekBarPreference("Haptic hint start scale",
-                            0, 100, 100, LPNH_HAPTIC_HINT_START_SCALE_PERCENT));
-            category.addPreference(createSeekBarPreference("Haptic hint end scale",
-                    0, 100, 100, LPNH_HAPTIC_HINT_END_SCALE_PERCENT));
-            category.addPreference(
-                    createSeekBarPreference("Haptic hint scale exponent",
-                            1, 5, 1, LPNH_HAPTIC_HINT_SCALE_EXPONENT));
-            category.addPreference(
-                    createSeekBarPreference("Haptic hint iterations (12 ms each)",
-                            0, 200, 1, LPNH_HAPTIC_HINT_ITERATIONS));
-            category.addPreference(createSeekBarPreference("Haptic hint delay (ms)",
-                    0, 400, 1, LPNH_HAPTIC_HINT_DELAY));
-        }
-    }
-
-    private void addCustomPrivateAppsCategory() {
-        PreferenceCategory category = newCategory("Apps in Private Space Config");
-        category.addPreference(createSeekBarPreference(
-                "Number of Apps to put in private region", 0, 100, 1, PRIVATE_SPACE_APPS));
-    }
-
-    private SeekBarPreference createSeekBarPreference(String title, int min,
-            int max, int scale, FeatureFlags.IntFlag flag) {
-        if (!(flag instanceof IntDebugFlag)) {
-            Log.e(TAG, "Cannot create seekbar preference with IntFlag. Use a launcher preference "
-                    + "flag or pref-backed IntDebugFlag instead");
-            return null;
-        }
-        IntDebugFlag debugflag = (IntDebugFlag) flag;
-        if (debugflag.launcherPrefFlag == null) {
-            Log.e(TAG, "Cannot create seekbar preference with IntDebugFlag. Use a launcher "
-                    + "preference flag or pref-backed IntDebugFlag instead");
-            return null;
-        }
-        SeekBarPreference seekBarPref = createSeekBarPreference(title, min, max, scale,
-                debugflag.launcherPrefFlag);
-        int value = flag.get();
-        seekBarPref.setValue(value);
-        // For some reason the initial value is not triggering the summary update, so call manually.
-        seekBarPref.setSummary(String.valueOf(scale == 1 ? value
-                : value / (float) scale));
-        return seekBarPref;
-    }
-
-    /**
-     * Create a preference with text and a seek bar. Should be added to a PreferenceCategory.
-     *
-     * @param title text to show for this seek bar
-     * @param min min value for the seek bar
-     * @param max max value for the seek bar
-     * @param scale how much to divide the value to convert int to float
-     * @param launcherPref used to store the current value
-     */
-    private SeekBarPreference createSeekBarPreference(String title, int min, int max, int scale,
-            ConstantItem<Integer> launcherPref) {
-        SeekBarPreference seekBarPref = new SeekBarPreference(getContext());
-        seekBarPref.setTitle(title);
-        seekBarPref.setSingleLineTitle(false);
-
-        seekBarPref.setMax(max);
-        seekBarPref.setMin(min);
-        seekBarPref.setUpdatesContinuously(true);
-        seekBarPref.setIconSpaceReserved(false);
-        // Don't directly save to shared prefs, use LauncherPrefs instead.
-        seekBarPref.setPersistent(false);
-        seekBarPref.setOnPreferenceChangeListener((preference, newValue) -> {
-            LauncherPrefs.get(getContext()).put(launcherPref, newValue);
-            preference.setSummary(String.valueOf(scale == 1 ? newValue
-                    : (int) newValue / (float) scale));
-            mFlagTogglerPrefUi.updateMenu();
-            return true;
-        });
-        int value = LauncherPrefs.get(getContext()).get(launcherPref);
-        seekBarPref.setValue(value);
-        // For some reason the initial value is not triggering the summary update, so call manually.
-        seekBarPref.setSummary(String.valueOf(scale == 1 ? value
-                : value / (float) scale));
-        return seekBarPref;
-    }
-
     private String toName(String action) {
         String str = action.replace("com.android.systemui.action.PLUGIN_", "")
                 .replace("com.android.launcher3.action.PLUGIN_", "");
+
         StringBuilder b = new StringBuilder();
         for (String s : str.split("_")) {
             if (b.length() != 0) {
@@ -461,11 +340,11 @@
     private static class PluginPreference extends SwitchPreference {
         private final String mPackageName;
         private final ResolveInfo mSettingsInfo;
-        private final PreferenceDataStore mPluginEnabler;
+        private final PluginEnabler mPluginEnabler;
         private final List<ComponentName> mComponentNames;
 
         PluginPreference(Context prefContext, ResolveInfo pluginInfo,
-                PreferenceDataStore pluginEnabler, List<ComponentName> componentNames) {
+                PluginEnabler pluginEnabler, List<ComponentName> componentNames) {
             super(prefContext);
             PackageManager pm = prefContext.getPackageManager();
             mPackageName = pluginInfo.serviceInfo.applicationInfo.packageName;
@@ -490,14 +369,9 @@
             setWidgetLayoutResource(R.layout.switch_preference_with_settings);
         }
 
-        private boolean isEnabled(ComponentName cn) {
-            return mPluginEnabler.getBoolean(pluginEnabledKey(cn), true);
-
-        }
-
         private boolean isPluginEnabled() {
             for (ComponentName componentName : mComponentNames) {
-                if (!isEnabled(componentName)) {
+                if (!mPluginEnabler.isEnabled(componentName)) {
                     return false;
                 }
             }
@@ -508,8 +382,9 @@
         protected boolean persistBoolean(boolean isEnabled) {
             boolean shouldSendBroadcast = false;
             for (ComponentName componentName : mComponentNames) {
-                if (isEnabled(componentName) != isEnabled) {
-                    mPluginEnabler.putBoolean(pluginEnabledKey(componentName), isEnabled);
+                if (mPluginEnabler.isEnabled(componentName) != isEnabled) {
+                    mPluginEnabler.setDisabled(componentName,
+                            isEnabled ? PluginEnabler.ENABLED : PluginEnabler.DISABLED_MANUALLY);
                     shouldSendBroadcast = true;
                 }
             }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
deleted file mode 100644
index 915f4ae..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeviceFlag.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 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.uioverrides.flags;
-
-import com.android.launcher3.config.FeatureFlags.FlagState;
-
-class DeviceFlag extends DebugFlag {
-
-    private final boolean mDefaultValueInCode;
-
-    DeviceFlag(String key, String description, FlagState defaultValue,
-            boolean currentValue, boolean defaultValueInCode) {
-        super(key, description, defaultValue, currentValue);
-        mDefaultValueInCode = defaultValueInCode;
-    }
-
-    @Override
-    boolean currentValueModified() {
-        return super.currentValueModified() || mDefaultValueInCode != get();
-    }
-
-    @Override
-    public String toString() {
-        return super.toString() + ", mDefaultValueInCode=" + mDefaultValueInCode;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
deleted file mode 100644
index 4326c67..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2018 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.uioverrides.flags;
-
-import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
-import static com.android.launcher3.uioverrides.flags.FlagsFactory.TEAMFOOD_FLAG;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Handler;
-import android.os.Process;
-import android.text.Html;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.widget.Toast;
-
-import androidx.preference.PreferenceDataStore;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceViewHolder;
-import androidx.preference.SwitchPreference;
-
-import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}.
- */
-public final class FlagTogglerPrefUi implements ActivityLifecycleCallbacksAdapter {
-
-    private static final String TAG = "FlagTogglerPrefFrag";
-
-    private final View mFlagsApplyButton;
-    private final Context mContext;
-
-    private final PreferenceDataStore mDataStore = new PreferenceDataStore() {
-
-        @Override
-        public void putBoolean(String key, boolean value) {
-            FlagsFactory.getSharedPreferences().edit().putBoolean(key, value).apply();
-            updateMenu();
-        }
-
-        @Override
-        public boolean getBoolean(String key, boolean defaultValue) {
-            return FlagsFactory.getSharedPreferences().getBoolean(key, defaultValue);
-        }
-    };
-
-    public FlagTogglerPrefUi(Activity activity, View flagsApplyButton) {
-        mFlagsApplyButton = flagsApplyButton;
-        mContext = mFlagsApplyButton.getContext();
-        activity.registerActivityLifecycleCallbacks(this);
-
-        mFlagsApplyButton.setOnClickListener(v -> {
-            FlagsFactory.getSharedPreferences().edit().commit();
-            Log.e(TAG,
-                    "Killing launcher process " + Process.myPid() + " to apply new flag values");
-            System.exit(0);
-        });
-    }
-
-    public void applyTo(PreferenceGroup parent) {
-        Set<String> modifiedPrefs = FlagsFactory.getSharedPreferences().getAll().keySet();
-        List<DebugFlag> flags = FlagsFactory.getDebugFlags();
-        flags.sort((f1, f2) -> {
-            // Sort first by any prefs that the user has changed, then alphabetically.
-            int changeComparison = Boolean.compare(
-                    modifiedPrefs.contains(f2.key), modifiedPrefs.contains(f1.key));
-            return changeComparison != 0
-                    ? changeComparison
-                    : f1.key.compareToIgnoreCase(f2.key);
-        });
-
-        // Ensure that teamfood flag comes on the top
-        if (flags.remove(TEAMFOOD_FLAG)) {
-            flags.add(0, (DebugFlag) TEAMFOOD_FLAG);
-        }
-
-        // For flag overrides we only want to store when the engineer chose to override the
-        // flag with a different value than the default. That way, when we flip flags in
-        // future, engineers will pick up the new value immediately. To accomplish this, we use a
-        // custom preference data store.
-        for (DebugFlag flag : flags) {
-            SwitchPreference switchPreference = new SwitchPreference(mContext) {
-                @Override
-                public void onBindViewHolder(PreferenceViewHolder holder) {
-                    super.onBindViewHolder(holder);
-                    holder.itemView.setOnLongClickListener(v -> {
-                        FlagsFactory.getSharedPreferences().edit().remove(flag.key).apply();
-                        setChecked(getFlagStateFromSharedPrefs(flag));
-                        updateSummary(this, flag);
-                        updateMenu();
-                        return true;
-                    });
-                }
-            };
-            switchPreference.setKey(flag.key);
-            switchPreference.setDefaultValue(FlagsFactory.getEnabledValue(flag.defaultValue));
-            switchPreference.setChecked(getFlagStateFromSharedPrefs(flag));
-            switchPreference.setTitle(flag.key);
-            updateSummary(switchPreference, flag);
-            switchPreference.setPreferenceDataStore(mDataStore);
-            switchPreference.setOnPreferenceChangeListener((p, v) -> {
-                new Handler().post(() -> updateSummary(switchPreference, flag));
-                return true;
-            });
-
-
-            parent.addPreference(switchPreference);
-        }
-        updateMenu();
-    }
-
-    /**
-     * Updates the summary to show the description and whether the flag overrides the default value.
-     */
-    private void updateSummary(SwitchPreference switchPreference, DebugFlag flag) {
-        String summary = flag.defaultValue == TEAMFOOD
-                ? "<font color='blue'><b>[TEAMFOOD]</b> </font>" : "";
-        if (FlagsFactory.getSharedPreferences().contains(flag.key)) {
-            summary += "<font color='red'><b>[OVERRIDDEN]</b> </font>";
-        }
-        if (!TextUtils.isEmpty(summary)) {
-            summary += "<br>";
-        }
-        switchPreference.setSummary(Html.fromHtml(summary + flag.description));
-    }
-
-    public void updateMenu() {
-        mFlagsApplyButton.setVisibility(anyChanged() ? View.VISIBLE : View.INVISIBLE);
-    }
-
-    @Override
-    public void onActivityStopped(Activity activity) {
-        if (anyChanged()) {
-            Toast.makeText(mContext, "Flag won't be applied until you restart launcher",
-                    Toast.LENGTH_LONG).show();
-        }
-    }
-
-    private boolean getFlagStateFromSharedPrefs(DebugFlag flag) {
-        boolean defaultValue = FlagsFactory.getEnabledValue(flag.defaultValue);
-        return mDataStore.getBoolean(flag.key, defaultValue);
-    }
-
-    private int getIntFlagStateFromSharedPrefs(IntDebugFlag flag) {
-        LauncherPrefs prefs = LauncherPrefs.get(mContext);
-        return flag.launcherPrefFlag == null ? flag.get() : prefs.get(flag.launcherPrefFlag);
-    }
-
-    private boolean anyChanged() {
-        for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
-            if (getFlagStateFromSharedPrefs(flag) != flag.get()) {
-                return true;
-            }
-        }
-        for (IntDebugFlag flag : FlagsFactory.getIntDebugFlags()) {
-            if (getIntFlagStateFromSharedPrefs(flag) != flag.get()) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
deleted file mode 100644
index 686ed64..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides.flags;
-
-import static android.app.ActivityThread.currentApplication;
-
-import static com.android.launcher3.BuildConfig.IS_DEBUG_DEVICE;
-import static com.android.launcher3.config.FeatureFlags.FlagState.DISABLED;
-import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
-import static java.util.Collections.unmodifiableList;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.provider.DeviceConfig;
-import android.provider.DeviceConfig.Properties;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.ConstantItem;
-import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.config.FeatureFlags.BooleanFlag;
-import com.android.launcher3.config.FeatureFlags.FlagState;
-import com.android.launcher3.config.FeatureFlags.IntFlag;
-import com.android.launcher3.util.ScreenOnTracker;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Helper class to create various flags for system build
- */
-public class FlagsFactory {
-
-    private static final String TAG = "FlagsFactory";
-
-    private static final FlagsFactory INSTANCE = new FlagsFactory();
-    private static final boolean FLAG_AUTO_APPLY_ENABLED = true;
-
-    private static final String FLAGS_PREF_NAME = "featureFlags";
-    public static final String NAMESPACE_LAUNCHER = "launcher";
-
-    private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
-    private static final List<IntDebugFlag> sIntDebugFlags = new ArrayList<>();
-    private static SharedPreferences sSharedPreferences;
-
-    static final BooleanFlag TEAMFOOD_FLAG = getReleaseFlag(
-            0, "LAUNCHER_TEAMFOOD", DISABLED, "Enable this flag to opt-in all team food flags");
-
-    private final Set<String> mKeySet = new HashSet<>();
-    private boolean mRestartRequested = false;
-
-    private FlagsFactory() {
-        if (!FLAG_AUTO_APPLY_ENABLED) {
-            return;
-        }
-        DeviceConfig.addOnPropertiesChangedListener(
-                NAMESPACE_LAUNCHER, UI_HELPER_EXECUTOR, this::onPropertiesChanged);
-    }
-
-    static boolean getEnabledValue(FlagState flagState) {
-        if (IS_DEBUG_DEVICE) {
-            switch (flagState) {
-                case ENABLED:
-                    return true;
-                case TEAMFOOD:
-                    return TEAMFOOD_FLAG.get();
-                default:
-                    return false;
-            }
-        } else {
-            return flagState == ENABLED;
-        }
-    }
-
-    /**
-     * Creates a new debug flag. Debug flags always take their default value in release builds. On
-     * dogfood builds, they can be manually turned on using the flag toggle UI.
-     */
-    public static BooleanFlag getDebugFlag(
-            int bugId, String key, FlagState flagState, String description) {
-        if (IS_DEBUG_DEVICE) {
-            boolean defaultValue = getEnabledValue(flagState);
-            boolean currentValue = getSharedPreferences().getBoolean(key, defaultValue);
-            DebugFlag flag = new DebugFlag(key, description, flagState, currentValue);
-            sDebugFlags.add(flag);
-            return flag;
-        } else {
-            return new BooleanFlag(getEnabledValue(flagState));
-        }
-    }
-
-    /**
-     * Creates a new release flag. Release flags can be rolled out using server configurations and
-     * also allow manual overrides on debug builds.
-     */
-    public static BooleanFlag getReleaseFlag(
-            int bugId, String key, FlagState flagState, String description) {
-        INSTANCE.mKeySet.add(key);
-        boolean defaultValueInCode = getEnabledValue(flagState);
-        boolean defaultValue = DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, defaultValueInCode);
-        if (IS_DEBUG_DEVICE) {
-            boolean currentValue = getSharedPreferences().getBoolean(key, defaultValue);
-            DebugFlag flag = new DeviceFlag(key, description,
-                    (defaultValue == defaultValueInCode) ? flagState
-                            : defaultValue ? ENABLED : DISABLED, currentValue, defaultValueInCode);
-            sDebugFlags.add(flag);
-            return flag;
-        } else {
-            return new BooleanFlag(defaultValue);
-        }
-    }
-
-    /**
-     * Creates a new integer flag. Integer flags are always release flags
-     */
-    public static IntFlag getIntFlag(
-            int bugId, String key, int defaultValueInCode, String description) {
-        return getIntFlag(bugId, key, defaultValueInCode, description, null);
-    }
-
-    /**
-     * Creates a new integer flag.
-     *
-     * @param launcherPrefFlag Set launcherPrefFlag to non-null if you want
-     * to modify the int flag in Launcher Developer Options and IntDebugFlag
-     * will be backed up by LauncherPrefs. Modified int value will be saved
-     * in LauncherPrefs.
-     */
-    public static IntFlag getIntFlag(
-            int bugId, String key, int defaultValueInCode, String description,
-            @Nullable ConstantItem<Integer> launcherPrefFlag) {
-        INSTANCE.mKeySet.add(key);
-        int defaultValue = DeviceConfig.getInt(NAMESPACE_LAUNCHER, key, defaultValueInCode);
-        if (IS_DEBUG_DEVICE) {
-            int currentValue;
-            if (launcherPrefFlag == null) {
-                currentValue = defaultValue;
-            } else {
-                currentValue = LauncherPrefs.get(currentApplication()).get(launcherPrefFlag);
-            }
-            IntDebugFlag flag = new IntDebugFlag(key, currentValue, defaultValueInCode,
-                    launcherPrefFlag);
-            sIntDebugFlags.add(flag);
-            return flag;
-        } else {
-            return new IntFlag(defaultValue);
-        }
-    }
-
-    static List<DebugFlag> getDebugFlags() {
-        if (!IS_DEBUG_DEVICE) {
-            return Collections.emptyList();
-        }
-        synchronized (sDebugFlags) {
-            return new ArrayList<>(sDebugFlags);
-        }
-    }
-
-    static List<IntDebugFlag> getIntDebugFlags() {
-        if (!IS_DEBUG_DEVICE) {
-            return unmodifiableList(Collections.emptyList());
-        }
-        synchronized (sIntDebugFlags) {
-            return unmodifiableList(sIntDebugFlags);
-        }
-    }
-
-    /** Returns the SharedPreferences instance backing Debug FeatureFlags. */
-    @NonNull
-    static SharedPreferences getSharedPreferences() {
-        if (sSharedPreferences == null) {
-            sSharedPreferences = currentApplication()
-                    .createDeviceProtectedStorageContext()
-                    .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
-        }
-        return sSharedPreferences;
-    }
-
-    /**
-     * Dumps the current flags state to the print writer
-     */
-    public static void dump(PrintWriter pw) {
-        if (!IS_DEBUG_DEVICE) {
-            return;
-        }
-        pw.println("DeviceFlags:");
-        pw.println("  BooleanFlags:");
-        synchronized (sDebugFlags) {
-            for (DebugFlag flag : sDebugFlags) {
-                if (flag instanceof DeviceFlag) {
-                    pw.println((flag.currentValueModified() ? "  ->" : "    ") + flag);
-                }
-            }
-        }
-        pw.println("  IntFlags:");
-        synchronized (sIntDebugFlags) {
-            for (IntFlag flag : sIntDebugFlags) {
-                pw.println("    " + flag);
-            }
-        }
-        pw.println("  DebugFlags:");
-        synchronized (sDebugFlags) {
-            for (DebugFlag flag : sDebugFlags) {
-                if (!(flag instanceof DeviceFlag)) {
-                    pw.println((flag.currentValueModified() ? "  ->" : "    ") + flag);
-                }
-            }
-        }
-    }
-
-    private void onPropertiesChanged(Properties properties) {
-        if (!Collections.disjoint(properties.getKeyset(), mKeySet)) {
-            // Schedule a restart
-            if (mRestartRequested) {
-                return;
-            }
-            Log.e(TAG, "Flag changed, scheduling restart");
-            mRestartRequested = true;
-            ScreenOnTracker sot = ScreenOnTracker.INSTANCE.get(currentApplication());
-            if (sot.isScreenOn()) {
-                sot.addListener(this::onScreenOnChanged);
-            } else {
-                onScreenOnChanged(false);
-            }
-        }
-    }
-
-    private void onScreenOnChanged(boolean isOn) {
-        if (mRestartRequested && !isOn) {
-            Log.e(TAG, "Restart requested, killing process");
-            System.exit(0);
-        }
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/IntDebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/IntDebugFlag.java
deleted file mode 100644
index 1350aa8..0000000
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/IntDebugFlag.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.uioverrides.flags;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.ConstantItem;
-import com.android.launcher3.config.FeatureFlags.IntFlag;
-
-public class IntDebugFlag extends IntFlag {
-    public final String key;
-    private final int mDefaultValueInCode;
-    @Nullable
-    public final ConstantItem<Integer> launcherPrefFlag;
-
-    public IntDebugFlag(String key, int currentValue, int defaultValueInCode,
-            @Nullable ConstantItem<Integer> launcherPrefFlag) {
-        super(currentValue);
-        this.key = key;
-        mDefaultValueInCode = defaultValueInCode;
-        this.launcherPrefFlag = launcherPrefFlag;
-    }
-
-    @Override
-    public String toString() {
-        return key + ": mCurrentValue=" + get() + ", defaultValueInCode=" + mDefaultValueInCode;
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
index faa900b..4e09f1f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginEnablerImpl.java
@@ -18,12 +18,10 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 
-import androidx.preference.PreferenceDataStore;
-
 import com.android.launcher3.LauncherPrefs;
 import com.android.systemui.shared.plugins.PluginEnabler;
 
-public class PluginEnablerImpl extends PreferenceDataStore implements PluginEnabler {
+public class PluginEnablerImpl implements PluginEnabler {
 
     private static final String PREFIX_PLUGIN_ENABLED = "PLUGIN_ENABLED_";
 
@@ -44,12 +42,12 @@
     }
 
     private void setState(ComponentName component, boolean enabled) {
-        putBoolean(pluginEnabledKey(component), enabled);
+        mSharedPrefs.edit().putBoolean(pluginEnabledKey(component), enabled).apply();
     }
 
     @Override
     public boolean isEnabled(ComponentName component) {
-        return getBoolean(pluginEnabledKey(component), true);
+        return mSharedPrefs.getBoolean(pluginEnabledKey(component), true);
     }
 
     @Override
@@ -57,17 +55,7 @@
         return isEnabled(componentName) ? ENABLED : DISABLED_MANUALLY;
     }
 
-    @Override
-    public void putBoolean(String key, boolean value) {
-        mSharedPrefs.edit().putBoolean(key, value).apply();
-    }
-
-    @Override
-    public boolean getBoolean(String key, boolean defValue) {
-        return mSharedPrefs.getBoolean(key, defValue);
-    }
-
-    static String pluginEnabledKey(ComponentName cn) {
+    private static String pluginEnabledKey(ComponentName cn) {
         return PREFIX_PLUGIN_ENABLED + cn.flattenToString();
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
index 7f78713..a09d0a1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
@@ -98,13 +98,6 @@
         return new PluginPrefs(mContext).getPluginList();
     }
 
-    /**
-     * Returns the string key used to store plugin enabled/disabled setting
-     */
-    public static String pluginEnabledKey(ComponentName cn) {
-        return PluginEnablerImpl.pluginEnabledKey(cn);
-    }
-
     public static boolean hasPlugins(Context context) {
         return PluginPrefs.hasPlugins(context);
     }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 577eba6..2625919 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.uioverrides.states;
 
 import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
 
 import android.content.Context;
@@ -28,8 +29,11 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ActivityContext;
+import com.android.quickstep.util.BaseDepthController;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Definition for AllApps state
  */
@@ -37,6 +41,8 @@
 
     private static final int STATE_FLAGS =
             FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS | FLAG_HOTSEAT_INACCESSIBLE;
+    private static final long BACK_CUJ_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5);
+
 
     public AllAppsState(int id) {
         super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
@@ -51,14 +57,36 @@
     }
 
     @Override
-    public void onBackPressed(Launcher launcher) {
+    public void onBackStarted(Launcher launcher) {
+        // Because the back gesture can take longer time depending on when user release the finger,
+        // we pass BACK_CUJ_TIMEOUT_MS as timeout to the jank monitor.
         InteractionJankMonitorWrapper.begin(launcher.getAppsView(),
-                Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK);
-        super.onBackPressed(launcher);
+                Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK, BACK_CUJ_TIMEOUT_MS);
+        super.onBackStarted(launcher);
     }
 
     @Override
-    protected void onBackPressCompleted(boolean success) {
+    public void onBackInvoked(Launcher launcher) {
+        // In predictive back swipe, onBackInvoked() will be called after onBackStarted().
+        // In 3 button mode, onBackStarted() is not called but onBackInvoked() will be called.
+        // Thus In onBackInvoked(), we should only begin instrumenting if we didn't call
+        // onBackStarted() to start instrumenting CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK.
+        if (!InteractionJankMonitorWrapper.isInstrumenting(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK)) {
+            InteractionJankMonitorWrapper.begin(
+                    launcher.getAppsView(), Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK);
+        }
+        super.onBackInvoked(launcher);
+    }
+
+    /** Called when predictive back swipe is cancelled. */
+    @Override
+    public void onBackCancelled(Launcher launcher) {
+        super.onBackCancelled(launcher);
+        InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK);
+    }
+
+    @Override
+    protected void onBackAnimationCompleted(boolean success) {
         if (success) {
             // Animation was successful.
             InteractionJankMonitorWrapper.end(Cuj.CUJ_LAUNCHER_CLOSE_ALL_APPS_BACK);
@@ -105,8 +133,14 @@
             return context.getDeviceProfile().bottomSheetDepth;
         } else {
             // The scrim fades in at approximately 50% of the swipe gesture.
-            // This means that the depth should be greater than 1, in order to fully zoom out.
-            return 2f;
+            if (enableScalingRevealHomeAnimation()) {
+                // This means that the depth should be twice of what we want, in order to fully zoom
+                // out during the visible portion of the animation.
+                return BaseDepthController.DEPTH_60_PERCENT;
+            } else {
+                // This means that the depth should be greater than 1, in order to fully zoom out.
+                return 2f;
+            }
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
index d11a08b..7fa121d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
@@ -15,17 +15,17 @@
  */
 package com.android.launcher3.uioverrides.states;
 
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.content.Context;
 import android.graphics.Color;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.quickstep.util.BaseDepthController;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
 
@@ -62,7 +62,7 @@
 
     @Override
     public float[] getOverviewScaleAndOffset(Launcher launcher) {
-        return getOverviewScaleAndOffsetForBackgroundState(launcher);
+        return getOverviewScaleAndOffsetForBackgroundState(launcher.getOverviewPanel());
     }
 
     @Override
@@ -90,13 +90,14 @@
 
     @Override
     protected float getDepthUnchecked(Context context) {
-        if (isDesktopModeSupported()) {
-            if (Launcher.getLauncher(context).areFreeformTasksVisible()) {
-                // Don't blur the background while freeform tasks are visible
-                return 0;
-            }
+        if (Launcher.getLauncher(context).areDesktopTasksVisible()) {
+            // Don't blur the background while desktop tasks are visible
+            return BaseDepthController.DEPTH_0_PERCENT;
+        } else if (enableScalingRevealHomeAnimation()) {
+            return BaseDepthController.DEPTH_70_PERCENT;
+        } else {
+            return 1f;
         }
-        return 1;
     }
 
     @Override
@@ -123,9 +124,7 @@
     }
 
     public static float[] getOverviewScaleAndOffsetForBackgroundState(
-            BaseDraggingActivity activity) {
-        return new float[] {
-                ((RecentsView) activity.getOverviewPanel()).getMaxScaleForFullScreen(),
-                NO_OFFSET};
+            RecentsView recentsView) {
+        return new float[] {recentsView.getMaxScaleForFullScreen(), NO_OFFSET};
     }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
index 856b519..3c291e6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.graphics.Rect;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.Flags;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
@@ -51,7 +50,7 @@
 
     @Override
     public float[] getOverviewScaleAndOffset(Launcher launcher) {
-        return getOverviewScaleAndOffsetForModalState(launcher);
+        return getOverviewScaleAndOffsetForModalState(launcher.getOverviewPanel());
     }
 
     @Override
@@ -60,7 +59,7 @@
     }
 
     @Override
-    public void onBackPressed(Launcher launcher) {
+    public void onBackInvoked(Launcher launcher) {
         launcher.getStateManager().goToState(LauncherState.OVERVIEW);
     }
 
@@ -72,8 +71,7 @@
         return super.isTaskbarStashed(launcher);
     }
 
-    public static float[] getOverviewScaleAndOffsetForModalState(BaseDraggingActivity activity) {
-        RecentsView recentsView = activity.<RecentsView>getOverviewPanel();
+    public static float[] getOverviewScaleAndOffsetForModalState(RecentsView recentsView) {
         Rect taskSize = recentsView.getSelectedTaskBounds();
         Rect modalTaskSize = new Rect();
         recentsView.getModalTaskSize(modalTaskSize);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 7650235..d0eef8e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.uioverrides.states;
 
 import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
 import static com.android.wm.shell.Flags.enableSplitContextual;
 
@@ -29,6 +30,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.Themes;
+import com.android.quickstep.util.BaseDepthController;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
@@ -186,12 +188,18 @@
 
     @Override
     protected float getDepthUnchecked(Context context) {
-        //TODO revert when b/178661709 is fixed
-        return SystemProperties.getBoolean("ro.launcher.depth.overview", true) ? 1 : 0;
+        // TODO(178661709): revert to always scaled
+        if (enableScalingRevealHomeAnimation()) {
+            return SystemProperties.getBoolean("ro.launcher.depth.overview", true)
+                    ? BaseDepthController.DEPTH_70_PERCENT
+                    : BaseDepthController.DEPTH_0_PERCENT;
+        } else {
+            return SystemProperties.getBoolean("ro.launcher.depth.overview", true) ? 1 : 0;
+        }
     }
 
     @Override
-    public void onBackPressed(Launcher launcher) {
+    public void onBackInvoked(Launcher launcher) {
         RecentsView recentsView = launcher.getOverviewPanel();
         TaskView taskView = recentsView.getRunningTaskView();
         if (taskView != null) {
@@ -201,7 +209,7 @@
                 recentsView.snapToPage(recentsView.indexOfChild(taskView));
             }
         } else {
-            super.onBackPressed(launcher);
+            super.onBackInvoked(launcher);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
index ba44d6a..dfad409 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
@@ -16,7 +16,6 @@
 package com.android.launcher3.uioverrides.states;
 
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.graphics.Color;
 
@@ -46,11 +45,9 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
-        if (isDesktopModeSupported()) {
-            if (launcher.areFreeformTasksVisible()) {
-                // No scrim while freeform tasks are visible
-                return Color.TRANSPARENT;
-            }
+        if (launcher.areDesktopTasksVisible()) {
+            // No scrim while desktop tasks are visible
+            return Color.TRANSPARENT;
         }
         DeviceProfile dp = launcher.getDeviceProfile();
         if (dp.isTaskbarPresentInApps) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index 8c92c7d..0368f3a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -37,7 +37,6 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
-import static com.android.launcher3.QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION;
 import static com.android.launcher3.WorkspaceStateTransitionAnimation.getWorkspaceSpringScaleAnimator;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
@@ -59,6 +58,7 @@
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.QuickstepTransitionManager;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.touch.AllAppsSwipeController;
@@ -94,7 +94,7 @@
     @Override
     public void prepareForAtomicAnimation(LauncherState fromState, LauncherState toState,
             StateAnimationConfig config) {
-        RecentsView overview = mActivity.getOverviewPanel();
+        RecentsView overview = mContainer.getOverviewPanel();
         if ((fromState == OVERVIEW || fromState == OVERVIEW_SPLIT_SELECT) && toState == NORMAL) {
             overview.switchToScreenshot(() ->
                     overview.finishRecentsAnimation(true /* toRecents */, null));
@@ -108,7 +108,8 @@
 
             // We sync the scrim fade with the taskbar animation duration to avoid any flickers for
             // taskbar icons disappearing before hotseat icons show up.
-            float scrimUpperBoundFromSplit = TASKBAR_TO_HOME_DURATION / (float) config.duration;
+            float scrimUpperBoundFromSplit =
+                    QuickstepTransitionManager.getTaskbarToHomeDuration() / (float) config.duration;
             config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, 0, 0.25f));
             config.setInterpolator(ANIM_SCRIM_FADE,
                     fromState == OVERVIEW_SPLIT_SELECT
@@ -117,7 +118,7 @@
             config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATE);
             config.setInterpolator(ANIM_WORKSPACE_FADE, ACCELERATE);
 
-            if (DisplayController.getNavigationMode(mActivity).hasGestures
+            if (DisplayController.getNavigationMode(mContainer).hasGestures
                     && overview.getTaskViewCount() > 0) {
                 // Overview is going offscreen, so keep it at its current scale and opacity.
                 config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
@@ -135,8 +136,9 @@
                 config.duration = Math.max(config.duration, scrollDuration);
 
                 // Sync scroll so that it ends before or at the same time as the taskbar animation.
-                if (mActivity.getDeviceProfile().isTaskbarPresent) {
-                    config.duration = Math.min(config.duration, TASKBAR_TO_HOME_DURATION);
+                if (mContainer.getDeviceProfile().isTaskbarPresent) {
+                    config.duration = Math.min(
+                            config.duration, QuickstepTransitionManager.getTaskbarToHomeDuration());
                 }
                 overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration));
             } else {
@@ -145,7 +147,7 @@
                 config.setInterpolator(ANIM_OVERVIEW_FADE, DECELERATE_1_7);
             }
 
-            Workspace<?> workspace = mActivity.getWorkspace();
+            Workspace<?> workspace = mContainer.getWorkspace();
             // Start from a higher workspace scale, but only if we're invisible so we don't jump.
             boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
             if (isWorkspaceVisible) {
@@ -158,7 +160,7 @@
                 workspace.setScaleX(WORKSPACE_PREPARE_SCALE);
                 workspace.setScaleY(WORKSPACE_PREPARE_SCALE);
             }
-            Hotseat hotseat = mActivity.getHotseat();
+            Hotseat hotseat = mContainer.getHotseat();
             boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
             if (!isHotseatVisible) {
                 hotseat.setScaleX(WORKSPACE_PREPARE_SCALE);
@@ -166,7 +168,7 @@
             }
         } else if ((fromState == NORMAL || fromState == HINT_STATE
                 || fromState == HINT_STATE_TWO_BUTTON) && toState == OVERVIEW) {
-            if (DisplayController.getNavigationMode(mActivity).hasGestures) {
+            if (DisplayController.getNavigationMode(mContainer).hasGestures) {
                 config.setInterpolator(ANIM_WORKSPACE_SCALE,
                         fromState == NORMAL ? ACCELERATE : OVERSHOOT_1_2);
                 config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCELERATE);
@@ -199,18 +201,18 @@
         } else if (fromState == HINT_STATE && toState == NORMAL) {
             config.setInterpolator(ANIM_DEPTH, DECELERATE_3);
             if (mHintToNormalDuration == -1) {
-                ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity,
-                        mActivity.getWorkspace(),
-                        toState.getWorkspaceScaleAndTranslation(mActivity).scale);
+                ValueAnimator va = getWorkspaceSpringScaleAnimator(mContainer,
+                        mContainer.getWorkspace(),
+                        toState.getWorkspaceScaleAndTranslation(mContainer).scale);
                 mHintToNormalDuration = (int) va.getDuration();
             }
             config.duration = Math.max(config.duration, mHintToNormalDuration);
         } else if (fromState == ALL_APPS && toState == NORMAL) {
-            AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config);
+            AllAppsSwipeController.applyAllAppsToNormalConfig(mContainer, config);
         } else if (fromState == NORMAL && toState == ALL_APPS) {
-            AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
+            AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mContainer, config);
         } else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) {
-            SplitAnimationTimings timings = mActivity.getDeviceProfile().isTablet
+            SplitAnimationTimings timings = mContainer.getDeviceProfile().isTablet
                     ? SplitAnimationTimings.TABLET_OVERVIEW_TO_SPLIT
                     : SplitAnimationTimings.PHONE_OVERVIEW_TO_SPLIT;
             config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR,
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index e8b5081..615e3e3 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -47,6 +47,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.TouchController;
 import com.android.quickstep.TaskUtils;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 3a1c42d..5a19ed4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -49,7 +49,6 @@
 import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
 import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
 import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
@@ -85,7 +84,6 @@
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.util.MotionPauseDetector;
 import com.android.quickstep.util.WorkspaceRevealAnim;
-import com.android.quickstep.views.LauncherRecentsView;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 
@@ -109,7 +107,7 @@
     private final float mMaxYProgress;
     private final MotionPauseDetector mMotionPauseDetector;
     private final float mMotionPauseMinDisplacement;
-    private final LauncherRecentsView mRecentsView;
+    private final RecentsView mRecentsView;
     protected final AnimatorListener mClearStateOnCancelListener =
             newCancelListener(this::clearState);
 
@@ -178,10 +176,6 @@
         if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
             return false;
         }
-        if (isDesktopModeSupported()) {
-            // TODO(b/268075592): add support for quickswitch to/from desktop
-            return false;
-        }
         if (isTrackpadMultiFingerSwipe(ev)) {
             return isTrackpadFourFingerSwipe(ev);
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index ff142fe..05a55d0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -30,7 +30,6 @@
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
 import static com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
@@ -39,12 +38,12 @@
 
 import android.view.MotionEvent;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.touch.AbstractStateChangeTouchController;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.NavigationMode;
 import com.android.quickstep.SystemUiProxy;
@@ -59,11 +58,12 @@
 
     protected final RecentsView mOverviewPanel;
 
-    public QuickSwitchTouchController(Launcher launcher) {
+    public QuickSwitchTouchController(QuickstepLauncher launcher) {
         this(launcher, SingleAxisSwipeDetector.HORIZONTAL);
     }
 
-    protected QuickSwitchTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) {
+    protected QuickSwitchTouchController(QuickstepLauncher l,
+            SingleAxisSwipeDetector.Direction dir) {
         super(l, dir);
         mOverviewPanel = l.getOverviewPanel();
     }
@@ -79,10 +79,6 @@
         if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
             return false;
         }
-        if (isDesktopModeSupported()) {
-            // TODO(b/268075592): add support for quickswitch to/from desktop
-            return false;
-        }
         return true;
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index e9f2d4f..300d697 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -21,6 +21,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
 import android.os.VibrationEffect;
 import android.view.MotionEvent;
 import android.view.View;
@@ -28,7 +29,6 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
@@ -44,12 +44,13 @@
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.util.VibrationConstants;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
 
 /**
  * Touch controller for handling task view card swipes
  */
-public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
+public abstract class TaskViewTouchController<CONTAINER extends Context & RecentsViewContainer>
         extends AnimatorListenerAdapter implements TouchController,
         SingleAxisSwipeDetector.Listener {
 
@@ -63,7 +64,7 @@
     public static final VibrationEffect TASK_DISMISS_VIBRATION_FALLBACK =
             VibrationConstants.EFFECT_TEXTURE_TICK;
 
-    protected final T mActivity;
+    protected final CONTAINER mContainer;
     private final SingleAxisSwipeDetector mDetector;
     private final RecentsView mRecentsView;
     private final int[] mTempCords = new int[2];
@@ -87,13 +88,13 @@
 
     private boolean mIsDismissHapticRunning = false;
 
-    public TaskViewTouchController(T activity) {
-        mActivity = activity;
-        mRecentsView = activity.getOverviewPanel();
-        mIsRtl = Utilities.isRtl(activity.getResources());
+    public TaskViewTouchController(CONTAINER container) {
+        mContainer = container;
+        mRecentsView = container.getOverviewPanel();
+        mIsRtl = Utilities.isRtl(container.getResources());
         SingleAxisSwipeDetector.Direction dir =
                 mRecentsView.getPagedOrientationHandler().getUpDownSwipeDirection();
-        mDetector = new SingleAxisSwipeDetector(activity, this, dir);
+        mDetector = new SingleAxisSwipeDetector(container, this, dir);
     }
 
     private boolean canInterceptTouch(MotionEvent ev) {
@@ -113,7 +114,7 @@
             return true;
         }
         if (AbstractFloatingView.getTopOpenViewWithType(
-                mActivity, TYPE_TOUCH_CONTROLLER_NO_INTERCEPT) != null) {
+                mContainer, TYPE_TOUCH_CONTROLLER_NO_INTERCEPT) != null) {
             return false;
         }
         return isRecentsInteractive();
@@ -159,7 +160,7 @@
                 for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) {
                     TaskView view = mRecentsView.getTaskViewAt(i);
 
-                    if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer()
+                    if (mRecentsView.isTaskViewVisible(view) && mContainer.getDragLayer()
                             .isEventOverView(view, ev)) {
                         // Disable swiping up and down if the task overlay is modal.
                         if (isRecentsModal()) {
@@ -179,7 +180,7 @@
                         // - It's the focused task if in grid view
                         // - The task is snapped
                         mAllowGoingDown = i == mRecentsView.getCurrentPage()
-                                && DisplayController.getNavigationMode(mActivity).hasGestures
+                                && DisplayController.getNavigationMode(mContainer).hasGestures
                                 && (!mRecentsView.showAsGrid() || mTaskBeingDragged.isFocusedTask())
                                 && mRecentsView.isTaskInExpectedScrollPosition(i);
 
@@ -228,7 +229,7 @@
         RecentsPagedOrientationHandler orientationHandler =
                 mRecentsView.getPagedOrientationHandler();
         mCurrentAnimationIsGoingUp = goingUp;
-        BaseDragLayer dl = mActivity.getDragLayer();
+        BaseDragLayer dl = mContainer.getDragLayer();
         final int secondaryLayerDimension = orientationHandler.getSecondaryDimension(dl);
         long maxDuration = 2 * secondaryLayerDimension;
         int verticalFactor = orientationHandler.getTaskDragDisplacementFactor(mIsRtl);
@@ -372,10 +373,10 @@
                 MIN_TASK_DISMISS_ANIMATION_DURATION, MAX_TASK_DISMISS_ANIMATION_DURATION);
 
         mCurrentAnimation.setEndAction(this::clearState);
-        mCurrentAnimation.startWithVelocity(mActivity, goingToEnd, Math.abs(velocity),
+        mCurrentAnimation.startWithVelocity(mContainer, goingToEnd, Math.abs(velocity),
                 mEndDisplacement, animationDuration);
         if (goingUp && goingToEnd && !mIsDismissHapticRunning) {
-            VibratorWrapper.INSTANCE.get(mActivity).vibrate(TASK_DISMISS_VIBRATION_PRIMITIVE,
+            VibratorWrapper.INSTANCE.get(mContainer).vibrate(TASK_DISMISS_VIBRATION_PRIMITIVE,
                     TASK_DISMISS_VIBRATION_PRIMITIVE_SCALE, TASK_DISMISS_VIBRATION_FALLBACK);
             mIsDismissHapticRunning = true;
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
index 8f9c014..b70cabe 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
@@ -15,13 +15,13 @@
  */
 package com.android.launcher3.uioverrides.touchcontrollers;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 
 public class TransposedQuickSwitchTouchController extends QuickSwitchTouchController {
 
-    public TransposedQuickSwitchTouchController(Launcher launcher) {
+    public TransposedQuickSwitchTouchController(QuickstepLauncher launcher) {
         super(launcher, SingleAxisSwipeDetector.VERTICAL);
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
index 9f2c1d4..31c9b3e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TwoButtonNavbarTouchController.java
@@ -27,10 +27,10 @@
 import android.view.MotionEvent;
 
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.touch.AbstractStateChangeTouchController;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.LayoutUtils;
 import com.android.quickstep.views.AllAppsEduView;
@@ -51,7 +51,7 @@
 
     private int mContinuousTouchCount = 0;
 
-    public TwoButtonNavbarTouchController(Launcher l) {
+    public TwoButtonNavbarTouchController(QuickstepLauncher l) {
         super(l, l.getDeviceProfile().isVerticalBarLayout()
                 ? SingleAxisSwipeDetector.HORIZONTAL : SingleAxisSwipeDetector.VERTICAL);
         mIsTransposed = l.getDeviceProfile().isVerticalBarLayout();
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 4752225..cceaf27 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -22,8 +22,8 @@
 import static android.widget.Toast.LENGTH_SHORT;
 
 import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
-import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.app.animation.Interpolators.OVERSHOOT_1_2;
 import static com.android.launcher3.BaseActivity.EVENT_DESTROYED;
@@ -31,7 +31,6 @@
 import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
 import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
-import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
 import static com.android.launcher3.PagedView.INVALID_PAGE;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
@@ -59,7 +58,6 @@
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.INVALID_VELOCITY_ON_SWIPE_UP;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.LAUNCHER_DESTROYED;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
@@ -101,7 +99,6 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimationSuccessListener;
@@ -111,7 +108,6 @@
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.statemanager.BaseState;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.taskbar.TaskbarThresholdUtils;
 import com.android.launcher3.taskbar.TaskbarUIController;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
@@ -139,6 +135,7 @@
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
 import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
 import com.android.systemui.shared.recents.model.Task;
@@ -163,7 +160,7 @@
 /**
  * Handles the navigation gestures when Launcher is the default home activity.
  */
-public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
+public abstract class AbsSwipeUpHandler<T extends RecentsViewContainer,
         Q extends RecentsView, S extends BaseState<S>>
         extends SwipeUpAnimationLogic implements OnApplyWindowInsetsListener,
         RecentsAnimationCallbacks.RecentsAnimationListener {
@@ -174,7 +171,7 @@
     // Fraction of the scroll and transform animation in which the current task fades out
     private static final float KQS_TASK_FADE_ANIMATION_FRACTION = 0.4f;
 
-    protected final BaseActivityInterface<S, T> mActivityInterface;
+    protected final BaseContainerInterface<S, T> mContainerInterface;
     protected final InputConsumerProxy mInputConsumerProxy;
     protected final ActivityInitListener mActivityInitListener;
     // Callbacks to be made once the recents animation starts
@@ -185,7 +182,7 @@
     protected @Nullable RecentsAnimationController mRecentsAnimationController;
     protected @Nullable RecentsAnimationController mDeferredCleanupRecentsAnimationController;
     protected RecentsAnimationTargets mRecentsAnimationTargets;
-    protected @Nullable T mActivity;
+    protected @Nullable T mContainer;
     protected @Nullable Q mRecentsView;
     protected Runnable mGestureEndCallback;
     protected MultiStateCallback mStateCallback;
@@ -195,7 +192,7 @@
     private final Runnable mLauncherOnDestroyCallback = () -> {
         ActiveGestureLog.INSTANCE.addLog("Launcher destroyed", LAUNCHER_DESTROYED);
         mRecentsView = null;
-        mActivity = null;
+        mContainer = null;
         mStateCallback.clearState(STATE_LAUNCHER_PRESENT);
     };
 
@@ -350,8 +347,9 @@
             long touchTimeMs, boolean continuingLastGesture,
             InputConsumerController inputConsumer) {
         super(context, deviceState, gestureState);
-        mActivityInterface = gestureState.getActivityInterface();
-        mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
+        mContainerInterface = gestureState.getContainerInterface();
+        mActivityInitListener =
+                mContainerInterface.createActivityInitListener(this::onActivityInit);
         mInputConsumerProxy =
                 new InputConsumerProxy(context, /* rotationSupplier = */ () -> {
                     if (mRecentsView == null) {
@@ -361,7 +359,7 @@
                 }, inputConsumer, /* onTouchDownCallback = */ () -> {
                     endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
                     endLauncherTransitionController();
-                }, new InputProxyHandlerFactory(mActivityInterface, mGestureState));
+                }, new InputProxyHandlerFactory(mContainerInterface, mGestureState));
         mTaskAnimationManager = taskAnimationManager;
         mTouchTimeMs = touchTimeMs;
         mContinuingLastGesture = continuingLastGesture;
@@ -378,8 +376,8 @@
         initStateCallbacks();
 
         mIsTransientTaskbar = mDp.isTaskbarPresent
-                && DisplayController.isTransientTaskbar(mActivity);
-        TaskbarUIController controller = mActivityInterface.getTaskbarController();
+                && DisplayController.isTransientTaskbar(context);
+        TaskbarUIController controller = mContainerInterface.getTaskbarController();
         mTaskbarAlreadyOpen = controller != null && !controller.isTaskbarStashed();
         mIsTaskbarAllAppsOpen = controller != null && controller.isTaskbarAllAppsOpen();
         mTaskbarAppWindowThreshold =
@@ -476,16 +474,16 @@
             return false;
         }
 
-        T createdActivity = mActivityInterface.getCreatedActivity();
-        if (createdActivity != null) {
-            initTransitionEndpoints(createdActivity.getDeviceProfile());
+        T createdContainer = (T) mContainerInterface.getCreatedContainer();
+        if (createdContainer != null) {
+            initTransitionEndpoints(createdContainer.getDeviceProfile());
         }
-        final T activity = mActivityInterface.getCreatedActivity();
-        if (mActivity == activity) {
+        final T container = (T) mContainerInterface.getCreatedContainer();
+        if (mContainer == container) {
             return true;
         }
 
-        if (mActivity != null) {
+        if (mContainer != null) {
             if (mStateCallback.hasStates(STATE_GESTURE_COMPLETED)) {
                 // If the activity has restarted between setting the page scroll settling callback
                 // and actually receiving the callback, just mark the gesture completed
@@ -500,23 +498,23 @@
             mStateCallback.setState(oldState);
         }
         mWasLauncherAlreadyVisible = alreadyOnHome;
-        mActivity = activity;
+        mContainer = container;
         // Override the visibility of the activity until the gesture actually starts and we swipe
         // up, or until we transition home and the home animation is composed
         if (alreadyOnHome) {
-            mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
+            mContainer.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
         } else {
-            mActivity.addForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
+            mContainer.addForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
         }
 
-        mRecentsView = activity.getOverviewPanel();
+        mRecentsView = container.getOverviewPanel();
         mRecentsView.setOnPageTransitionEndCallback(null);
 
         mStateCallback.setState(STATE_LAUNCHER_PRESENT);
         if (alreadyOnHome) {
             onLauncherStart();
         } else {
-            activity.addEventCallback(EVENT_STARTED, mLauncherOnStartCallback);
+            container.addEventCallback(EVENT_STARTED, mLauncherOnStartCallback);
         }
 
         // Set up a entire animation lifecycle callback to notify the current recents view when
@@ -541,8 +539,8 @@
 
         setupRecentsViewUi();
         mRecentsView.runOnPageScrollsInitialized(this::linkRecentsViewScroll);
-        mActivity.runOnBindToTouchInteractionService(this::onLauncherBindToService);
-        mActivity.addEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback);
+        mContainer.runOnBindToTouchInteractionService(this::onLauncherBindToService);
+        mContainer.addEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback);
         return true;
     }
 
@@ -554,8 +552,8 @@
     }
 
     private void onLauncherStart() {
-        final T activity = mActivityInterface.getCreatedActivity();
-        if (activity == null || mActivity != activity) {
+        final T container = (T) mContainerInterface.getCreatedContainer();
+        if (container == null || mContainer != container) {
             return;
         }
         if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) {
@@ -571,7 +569,7 @@
         // as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
         if (mGestureState.getEndTarget() != HOME) {
             Runnable initAnimFactory = () -> {
-                mAnimationFactory = mActivityInterface.prepareRecentsUI(mDeviceState,
+                mAnimationFactory = mContainerInterface.prepareRecentsUI(mDeviceState,
                         mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated);
                 maybeUpdateRecentsAttachedState(false /* animate */);
                 if (mGestureState.getEndTarget() != null) {
@@ -588,14 +586,14 @@
                 initAnimFactory.run();
             }
         }
-        AbstractFloatingView.closeAllOpenViewsExcept(activity, mWasLauncherAlreadyVisible,
+        AbstractFloatingView.closeAllOpenViewsExcept(container, mWasLauncherAlreadyVisible,
                 AbstractFloatingView.TYPE_LISTENER);
 
         if (mWasLauncherAlreadyVisible) {
             mStateCallback.setState(STATE_LAUNCHER_DRAWN);
         } else {
             SafeCloseable traceToken = TraceHelper.INSTANCE.beginAsyncSection("WTS-init");
-            View dragLayer = activity.getDragLayer();
+            View dragLayer = container.getDragLayer();
             dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() {
                 boolean mHandled = false;
 
@@ -609,7 +607,7 @@
                     traceToken.close();
                     dragLayer.post(() ->
                             dragLayer.getViewTreeObserver().removeOnDrawListener(this));
-                    if (activity != mActivity) {
+                    if (container != mContainer) {
                         return;
                     }
 
@@ -618,7 +616,7 @@
             });
         }
 
-        activity.getRootView().setOnApplyWindowInsetsListener(this);
+        container.getRootView().setOnApplyWindowInsetsListener(this);
         mStateCallback.setState(STATE_LAUNCHER_STARTED);
     }
 
@@ -634,21 +632,21 @@
 
         // For the duration of the gesture, in cases where an activity is launched while the
         // activity is not yet resumed, finish the animation to ensure we get resumed
-        mGestureState.getActivityInterface().setOnDeferredActivityLaunchCallback(
+        mGestureState.getContainerInterface().setOnDeferredActivityLaunchCallback(
                 mOnDeferredActivityLaunch);
 
         mGestureState.runOnceAtState(STATE_END_TARGET_SET,
                 () -> {
                     mDeviceState.getRotationTouchHelper()
                             .onEndTargetCalculated(mGestureState.getEndTarget(),
-                                    mActivityInterface);
+                                    mContainerInterface);
                 });
 
         notifyGestureStarted();
     }
 
     private void onDeferredActivityLaunch() {
-        mActivityInterface.switchRunningTaskViewToScreenshot(
+        mContainerInterface.switchRunningTaskViewToScreenshot(
                 null, () -> {
                     mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
                 });
@@ -709,7 +707,7 @@
             public void onMotionPauseDetected() {
                 mHasMotionEverBeenPaused = true;
                 maybeUpdateRecentsAttachedState(true/* animate */, true/* moveRunningTask */);
-                Optional.ofNullable(mActivityInterface.getTaskbarController())
+                Optional.ofNullable(mContainerInterface.getTaskbarController())
                         .ifPresent(TaskbarUIController::startTranslationSpring);
                 if (!mIsInAllAppsRegion) {
                     performHapticFeedback();
@@ -815,7 +813,7 @@
      */
     private void setIsInAllAppsRegion(boolean isInAllAppsRegion) {
         if (mIsInAllAppsRegion == isInAllAppsRegion
-                || !mActivityInterface.allowAllAppsFromOverview()) {
+                || !mContainerInterface.allowAllAppsFromOverview()) {
             return;
         }
         mIsInAllAppsRegion = isInAllAppsRegion;
@@ -824,8 +822,9 @@
         VibratorWrapper.INSTANCE.get(mContext).vibrate(OVERVIEW_HAPTIC);
         maybeUpdateRecentsAttachedState(true);
 
-        if (mActivity != null) {
-            mActivity.getAppsView().getSearchUiManager().prepareToFocusEditText(mIsInAllAppsRegion);
+        if (mContainer != null) {
+            mContainer.getAppsView().getSearchUiManager()
+                    .prepareToFocusEditText(mIsInAllAppsRegion);
         }
 
         // Draw active task below Launcher so that All Apps can appear over it.
@@ -838,7 +837,7 @@
         if (!canCreateNewOrUpdateExistingLauncherTransitionController()) {
             return;
         }
-        initTransitionEndpoints(mActivity.getDeviceProfile());
+        initTransitionEndpoints(mContainer.getDeviceProfile());
         mAnimationFactory.createActivityInterface(mTransitionDragLength);
     }
 
@@ -849,7 +848,7 @@
      */
     private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
         return mGestureState.getEndTarget() != HOME
-                && !mHasEndedLauncherTransition && mActivity != null;
+                && !mHasEndedLauncherTransition && mContainer != null;
     }
 
     @Override
@@ -893,7 +892,7 @@
     @UiThread
     @Override
     public void onCurrentShiftUpdated() {
-        float threshold = LauncherPrefs.get(mContext).get(ALL_APPS_OVERVIEW_THRESHOLD) / 100f;
+        float threshold = DeviceConfigWrapper.get().getAllAppsOverviewThreshold() / 100f;
         setIsInAllAppsRegion(mCurrentShift.value >= threshold);
         updateSysUiFlags(mCurrentShift.value);
         applyScrollAndTransform();
@@ -933,11 +932,11 @@
             // needs to be canceled
             mRecentsAnimationController.setWillFinishToHome(swipeUpThresholdPassed);
 
-            if (mActivity == null) return;
+            if (mContainer == null) return;
             if (swipeUpThresholdPassed) {
-                mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
+                mContainer.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
             } else {
-                mActivity.getSystemUiController().updateUiState(
+                mContainer.getSystemUiController().updateUiState(
                         UI_STATE_FULLSCREEN_TASK, centermostTaskFlags);
             }
         }
@@ -947,7 +946,7 @@
     public void onRecentsAnimationStart(RecentsAnimationController controller,
             RecentsAnimationTargets targets) {
         super.onRecentsAnimationStart(controller, targets);
-        if (isDesktopModeSupported() && targets.hasDesktopTasks()) {
+        if (targets.hasDesktopTasks()) {
             mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets);
         } else {
             int untrimmedAppCount = mRemoteTargetHandles.length;
@@ -965,7 +964,7 @@
 
         // Only initialize the device profile, if it has not been initialized before, as in some
         // configurations targets.homeContentInsets may not be correct.
-        if (mActivity == null) {
+        if (mContainer == null) {
             RemoteAnimationTarget primaryTaskTarget = targets.apps[0];
             // orientation state is independent of which remote target handle we use since both
             // should be pointing to the same one. Just choose index 0 for now since that works for
@@ -974,7 +973,7 @@
                     .getOrientationState();
             DeviceProfile dp = orientationState.getLauncherDeviceProfile();
             if (targets.minimizedHomeBounds != null && primaryTaskTarget != null) {
-                Rect overviewStackBounds = mActivityInterface
+                Rect overviewStackBounds = mContainerInterface
                         .getOverviewWindowBounds(targets.minimizedHomeBounds, primaryTaskTarget);
                 dp = dp.getMultiWindowProfile(mContext,
                         new WindowBounds(overviewStackBounds, targets.homeContentInsets));
@@ -1002,7 +1001,7 @@
         ActiveGestureLog.INSTANCE.addLog(
                 /* event= */ "cancelRecentsAnimation",
                 /* gestureEvent= */ CANCEL_RECENTS_ANIMATION);
-        mActivityInitListener.unregister();
+        mActivityInitListener.unregister("AbsSwipeUpHandler.onRecentsAnimationCanceled");
         // Cache the recents animation controller so we can defer its cleanup to after having
         // properly cleaned up the screenshot without accidentally using it.
         mDeferredCleanupRecentsAnimationController = mRecentsAnimationController;
@@ -1017,7 +1016,7 @@
 
     @UiThread
     public void onGestureStarted(boolean isLikelyToStartNewTask) {
-        mActivityInterface.closeOverlay();
+        mContainerInterface.closeOverlay();
         TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
 
         if (mRecentsView != null) {
@@ -1077,11 +1076,11 @@
      */
     @UiThread
     private void notifyGestureStarted() {
-        final T curActivity = mActivity;
+        final T curActivity = mContainer;
         if (curActivity != null) {
             // Once the gesture starts, we can no longer transition home through the button, so
             // reset the force override of the activity visibility
-            mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
+            mContainer.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
         }
     }
 
@@ -1150,7 +1149,7 @@
         maybeUpdateRecentsAttachedState(false);
         final GestureEndTarget endTarget = mGestureState.getEndTarget();
         // Wait until the given View (if supplied) draws before resuming the last task.
-        View postResumeLastTask = mActivityInterface.onSettledOnEndTarget(endTarget);
+        View postResumeLastTask = mContainerInterface.onSettledOnEndTarget(endTarget);
 
         if (endTarget != NEW_TASK) {
             InteractionJankMonitorWrapper.cancel(Cuj.CUJ_LAUNCHER_QUICK_SWITCH);
@@ -1170,13 +1169,11 @@
                 mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
                 // Notify the SysUI to use fade-in animation when entering PiP
                 SystemUiProxy.INSTANCE.get(mContext).setPipAnimationTypeToAlpha();
-                if (isDesktopModeSupported()) {
+                DesktopVisibilityController desktopVisibilityController =
+                        mContainerInterface.getDesktopVisibilityController();
+                if (desktopVisibilityController != null) {
                     // Notify the SysUI to stash desktop apps if they are visible
-                    DesktopVisibilityController desktopVisibilityController =
-                            mActivityInterface.getDesktopVisibilityController();
-                    if (desktopVisibilityController != null) {
-                        desktopVisibilityController.onHomeActionTriggered();
-                    }
+                    desktopVisibilityController.onHomeActionTriggered();
                 }
                 break;
             case RECENTS:
@@ -1255,7 +1252,11 @@
             return LAST_TASK;
         }
 
-        if (isDesktopModeSupported() && endTarget == NEW_TASK) {
+        if (((mRecentsView.getNextPageTaskView() != null
+                && mRecentsView.getNextPageTaskView().isDesktopTask())
+                || (mRecentsView.getCurrentPageTaskView() != null
+                && mRecentsView.getCurrentPageTaskView().isDesktopTask()))
+                && endTarget == NEW_TASK) {
             // TODO(b/268075592): add support for quickswitch to/from desktop
             return LAST_TASK;
         }
@@ -1358,7 +1359,7 @@
             }
         }
         Interpolator interpolator;
-        S state = mActivityInterface.stateFromGestureEndTarget(endTarget);
+        S state = mContainerInterface.stateFromGestureEndTarget(endTarget);
         if (isKeyboardTaskFocusPending()) {
             interpolator = EMPHASIZED;
         } else if (state.displayOverviewTasksAsGrid(mDp)) {
@@ -1373,7 +1374,7 @@
             mInputConsumerProxy.enable();
         }
         if (endTarget == HOME) {
-            duration = mActivity != null && mActivity.getDeviceProfile().isTaskbarPresent
+            duration = mContainer != null && mContainer.getDeviceProfile().isTaskbarPresent
                     ? StaggeredWorkspaceAnim.DURATION_TASKBAR_MS
                     : StaggeredWorkspaceAnim.DURATION_MS;
             // Early detach the nav bar once the endTarget is determined as HOME
@@ -1416,9 +1417,11 @@
             mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED);
             setClampScrollOffset(false);
         };
-        if (mRecentsView != null) {
+        if (mRecentsView != null && (mRecentsView.getCurrentPageTaskView() != null
+                && !mRecentsView.getCurrentPageTaskView().isDesktopTask())) {
             ActiveGestureLog.INSTANCE.trackEvent(ActiveGestureErrorDetector.GestureEvent
                     .SET_ON_PAGE_TRANSITION_END_CALLBACK);
+            // TODO(b/268075592): add support for quickswitch to/from desktop
             mRecentsView.setOnPageTransitionEndCallback(onPageTransitionEnd);
         } else {
             onPageTransitionEnd.run();
@@ -1508,14 +1511,14 @@
         if (mGestureState.getEndTarget().isLauncher) {
             // This is also called when the launcher is resumed, in order to clear the pending
             // widgets that have yet to be configured.
-            if (mActivity != null) {
-                DragView.removeAllViews(mActivity);
+            if (mContainer != null) {
+                DragView.removeAllViews(mContainer);
             }
 
             TaskStackChangeListeners.getInstance().registerTaskStackListener(
                     mActivityRestartListener);
 
-            mParallelRunningAnim = mActivityInterface.getParallelAnimationToLauncher(
+            mParallelRunningAnim = mContainerInterface.getParallelAnimationToLauncher(
                     mGestureState.getEndTarget(), duration,
                     mTaskAnimationManager.getCurrentCallbacks());
             if (mParallelRunningAnim != null) {
@@ -1613,7 +1616,7 @@
                 if (windowAnimation == null) {
                     continue;
                 }
-                DeviceProfile dp = mActivity == null ? null : mActivity.getDeviceProfile();
+                DeviceProfile dp = mContainer == null ? null : mContainer.getDeviceProfile();
                 windowAnimation.start(mContext, dp, velocityPxPerMs);
                 mRunningWindowAnim[i] = RunningWindowAnim.wrap(windowAnimation);
             }
@@ -1866,7 +1869,7 @@
                 }
                 // Make sure recents is in its final state
                 maybeUpdateRecentsAttachedState(false);
-                mActivityInterface.onSwipeUpToHomeComplete(mDeviceState);
+                mContainerInterface.onSwipeUpToHomeComplete(mDeviceState);
             }
         });
         if (mRecentsAnimationTargets != null) {
@@ -1940,8 +1943,8 @@
 
     private void reset() {
         mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
-        if (mActivity != null) {
-            mActivity.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback);
+        if (mContainer != null) {
+            mContainer.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback);
         }
     }
 
@@ -1958,14 +1961,14 @@
 
         // Cleanup when switching handlers
         mInputConsumerProxy.unregisterOnTouchDownCallback();
-        mActivityInitListener.unregister();
+        mActivityInitListener.unregister("AbsSwipeUpHandler.cancelCurrentAnimation");
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
                 mActivityRestartListener);
         mTaskSnapshotCache.clear();
     }
 
     private void invalidateHandler() {
-        if (!mActivityInterface.isInLiveTileMode() || mGestureState.getEndTarget() != RECENTS) {
+        if (!mContainerInterface.isInLiveTileMode() || mGestureState.getEndTarget() != RECENTS) {
             mInputConsumerProxy.destroy();
             mTaskAnimationManager.setLiveTileCleanUpHandler(null);
         }
@@ -1976,7 +1979,7 @@
             mGestureEndCallback.run();
         }
 
-        mActivityInitListener.unregister();
+        mActivityInitListener.unregister("AbsSwipeUpHandler.invalidateHandler");
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
                 mActivityRestartListener);
         mTaskSnapshotCache.clear();
@@ -2012,11 +2015,11 @@
      * continued quick switch gesture, which cancels the previous handler but doesn't invalidate it.
      */
     private void resetLauncherListeners() {
-        if (mActivity != null) {
-            mActivity.removeEventCallback(EVENT_STARTED, mLauncherOnStartCallback);
-            mActivity.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback);
+        if (mContainer != null) {
+            mContainer.removeEventCallback(EVENT_STARTED, mLauncherOnStartCallback);
+            mContainer.removeEventCallback(EVENT_DESTROYED, mLauncherOnDestroyCallback);
 
-            mActivity.getRootView().setOnApplyWindowInsetsListener(null);
+            mContainer.getRootView().setOnApplyWindowInsetsListener(null);
         }
         if (mRecentsView != null) {
             mRecentsView.removeOnScrollChangedListener(mOnRecentsScrollListener);
@@ -2025,11 +2028,11 @@
 
     private void resetStateForAnimationCancel() {
         boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted;
-        mActivityInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
+        mContainerInterface.onTransitionCancelled(wasVisible, mGestureState.getEndTarget());
 
         // Leave the pending invisible flag, as it may be used by wallpaper open animation.
-        if (mActivity != null) {
-            mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
+        if (mContainer != null) {
+            mContainer.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER);
         }
     }
 
@@ -2232,6 +2235,15 @@
                     mRecentsAnimationController, mRecentsAnimationTargets);
         });
 
+        if ((mRecentsView.getNextPageTaskView() != null
+                && mRecentsView.getNextPageTaskView().isDesktopTask())
+                || (mRecentsView.getCurrentPageTaskView() != null
+                && mRecentsView.getCurrentPageTaskView().isDesktopTask())) {
+            // TODO(b/268075592): add support for quickswitch to/from desktop
+            mRecentsViewScrollLinked = false;
+            return;
+        }
+
         // Disable scrolling in RecentsView for trackpad 3-finger swipe up gesture.
         if (!mGestureState.isThreeFingerTrackpadGesture()) {
             mRecentsViewScrollLinked = true;
@@ -2286,14 +2298,14 @@
                             onRestartPreviouslyAppearedTask();
                         }
                     } else {
-                        mActivityInterface.onLaunchTaskFailed();
+                        mContainerInterface.onLaunchTaskFailed();
                         if (mRecentsAnimationController != null) {
                             mRecentsAnimationController.finish(true /* toRecents */, null);
                         }
                     }
                 }, true /* freezeTaskList */);
             } else {
-                mActivityInterface.onLaunchTaskFailed();
+                mContainerInterface.onLaunchTaskFailed();
                 Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show();
                 if (mRecentsAnimationController != null) {
                     mRecentsAnimationController.finish(true /* toRecents */, null);
@@ -2385,12 +2397,12 @@
             finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
             return;
         }
-        if (mActivity == null) {
+        if (mContainer == null) {
             ActiveGestureLog.INSTANCE.addLog("Activity destroyed");
             finishRecentsAnimationOnTasksAppeared(null /* onFinishComplete */);
             return;
         }
-        animateSplashScreenExit(mActivity, appearedTaskTargets, taskTarget.leash);
+        animateSplashScreenExit(mContainer, appearedTaskTargets, taskTarget.leash);
     }
 
     private void animateSplashScreenExit(
@@ -2471,11 +2483,11 @@
     /**
      * Registers a callback to run when the activity is ready.
      */
-    public void initWhenReady() {
+    public void initWhenReady(String reasonString) {
         // Preload the plan
         RecentsModel.INSTANCE.get(mContext).getTasks(null);
 
-        mActivityInitListener.register();
+        mActivityInitListener.register(reasonString);
     }
 
     private boolean shouldFadeOutTargetsForKeyboardQuickSwitch(
@@ -2505,7 +2517,7 @@
             transaction.setAlpha(app.leash, 1f - fadeProgress);
             transaction.setPosition(app.leash,
                     /* x= */ app.startBounds.left
-                            + (mActivity.getDeviceProfile().overviewPageSpacing
+                            + (mContainer.getDeviceProfile().overviewPageSpacing
                             * (mRecentsView.isRtl() ? fadeProgress : -fadeProgress)),
                     /* y= */ 0f);
             transaction.setScale(app.leash, 1f, 1f);
@@ -2556,7 +2568,7 @@
 
     // Scaling of RecentsView during quick switch based on amount of recents scroll
     private float getScaleProgressDueToScroll() {
-        if (mActivity == null || !mActivity.getDeviceProfile().isTablet || mRecentsView == null
+        if (mContainer == null || !mContainer.getDeviceProfile().isTablet || mRecentsView == null
                 || !shouldLinkRecentsViewScroll()) {
             return 0;
         }
diff --git a/quickstep/src/com/android/quickstep/AllAppsActionManager.kt b/quickstep/src/com/android/quickstep/AllAppsActionManager.kt
new file mode 100644
index 0000000..6fd68d5
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/AllAppsActionManager.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import android.accessibilityservice.AccessibilityService.GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS
+import android.app.PendingIntent
+import android.app.RemoteAction
+import android.content.Context
+import android.graphics.drawable.Icon
+import android.view.accessibility.AccessibilityManager
+import com.android.launcher3.R
+import java.util.concurrent.Executor
+
+/**
+ * Registers a [RemoteAction] for toggling All Apps if needed.
+ *
+ * We need this action when either [isHomeAndOverviewSame] or [isTaskbarPresent] is `true`. When
+ * home and overview are the same, we can control Launcher's or Taskbar's All Apps tray. If they are
+ * not the same, but Taskbar is present, we can only control Taskbar's tray.
+ */
+class AllAppsActionManager(
+    private val context: Context,
+    private val bgExecutor: Executor,
+    private val createAllAppsPendingIntent: () -> PendingIntent,
+) {
+
+    /** `true` if home and overview are the same Activity. */
+    var isHomeAndOverviewSame = false
+        set(value) {
+            field = value
+            updateSystemAction()
+        }
+
+    /** `true` if Taskbar is enabled. */
+    var isTaskbarPresent = false
+        set(value) {
+            field = value
+            updateSystemAction()
+        }
+
+    /** `true` if the action should be registered. */
+    var isActionRegistered = false
+        private set
+
+    private fun updateSystemAction() {
+        val shouldRegisterAction = isHomeAndOverviewSame || isTaskbarPresent
+        if (isActionRegistered == shouldRegisterAction) return
+        isActionRegistered = shouldRegisterAction
+
+        bgExecutor.execute {
+            val accessibilityManager =
+                context.getSystemService(AccessibilityManager::class.java) ?: return@execute
+            if (shouldRegisterAction) {
+                accessibilityManager.registerSystemAction(
+                    RemoteAction(
+                        Icon.createWithResource(context, R.drawable.ic_apps),
+                        context.getString(R.string.all_apps_label),
+                        context.getString(R.string.all_apps_label),
+                        createAllAppsPendingIntent(),
+                    ),
+                    GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
+                )
+            } else {
+                accessibilityManager.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
+            }
+        }
+    }
+
+    fun onDestroy() {
+        isActionRegistered = false
+        context
+            .getSystemService(AccessibilityManager::class.java)
+            ?.unregisterSystemAction(
+                GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
+            )
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 2341e4c..00cd60b 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -18,14 +18,11 @@
 import static com.android.app.animation.Interpolators.ACCELERATE_2;
 import static com.android.app.animation.Interpolators.INSTANT;
 import static com.android.app.animation.Interpolators.LINEAR;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
 import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
 import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
-import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
 import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
 import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
@@ -34,23 +31,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Color;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.view.Gravity;
 import android.view.MotionEvent;
-import android.view.RemoteAnimationTarget;
-import android.view.View;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
 
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Flags;
-import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.statehandlers.DepthController;
@@ -58,29 +44,23 @@
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.taskbar.TaskbarUIController;
-import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.NavigationMode;
-import com.android.launcher3.views.ScrimView;
-import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
-import com.android.quickstep.util.ActivityInitListener;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
 import java.util.HashMap;
 import java.util.Optional;
 import java.util.function.Consumer;
-import java.util.function.Predicate;
 
 /**
  * Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
  */
 public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_TYPE>,
-        ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>> {
-
-    public final boolean rotationSupportedByActivity;
-
+        ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE> & RecentsViewContainer> extends
+        BaseContainerInterface<STATE_TYPE, ACTIVITY_TYPE> {
     private final STATE_TYPE mBackgroundState;
 
     private STATE_TYPE mTargetState;
@@ -101,7 +81,7 @@
      */
     public void onTransitionCancelled(boolean activityVisible,
             @Nullable GestureState.GestureEndTarget endTarget) {
-        ACTIVITY_TYPE activity = getCreatedActivity();
+        ACTIVITY_TYPE activity = getCreatedContainer();
         if (activity == null) {
             return;
         }
@@ -109,67 +89,37 @@
         if (endTarget != null) {
             // We were on our way to this state when we got canceled, end there instead.
             startState = stateFromGestureEndTarget(endTarget);
-            if (isDesktopModeSupported()) {
-                DesktopVisibilityController controller = getDesktopVisibilityController();
-                if (controller != null && controller.areFreeformTasksVisible()
-                        && endTarget == LAST_TASK) {
-                    // When we are cancelling the transition and going back to last task, move to
-                    // rest state instead when desktop tasks are visible.
-                    // If a fullscreen task is visible, launcher goes to normal state when the
-                    // activity is stopped. This does not happen when freeform tasks are visible
-                    // on top of launcher. Force the launcher state to rest state here.
-                    startState = activity.getStateManager().getRestState();
-                    // Do not animate the transition
-                    activityVisible = false;
-                }
+            DesktopVisibilityController controller = getDesktopVisibilityController();
+            if (controller != null && controller.areDesktopTasksVisible()
+                    && endTarget == LAST_TASK) {
+                // When we are cancelling the transition and going back to last task, move to
+                // rest state instead when desktop tasks are visible.
+                // If a fullscreen task is visible, launcher goes to normal state when the
+                // activity is stopped. This does not happen when desktop tasks are visible
+                // on top of launcher. Force the launcher state to rest state here.
+                startState = activity.getStateManager().getRestState();
+                // Do not animate the transition
+                activityVisible = false;
             }
         }
         activity.getStateManager().goToState(startState, activityVisible);
     }
 
-    public abstract int getSwipeUpDestinationAndLength(
-            DeviceProfile dp, Context context, Rect outRect,
-            RecentsPagedOrientationHandler orientationHandler);
-
-    /** Called when the animation to home has fully settled. */
-    public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) {}
-
-    public abstract void onAssistantVisibilityChanged(float visibility);
-
-    public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
-            boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
-
-    public abstract ActivityInitListener createActivityInitListener(
-            Predicate<Boolean> onInitListener);
-
-    /**
-     * Sets a callback to be run when an activity launch happens while launcher is not yet resumed.
-     */
-    public void setOnDeferredActivityLaunchCallback(Runnable r) {}
-
     @Nullable
-    public abstract ACTIVITY_TYPE getCreatedActivity();
+    public abstract ACTIVITY_TYPE getCreatedContainer();
 
     @Nullable
     public DepthController getDepthController() {
         return null;
     }
 
-    @Nullable
-    public DesktopVisibilityController getDesktopVisibilityController() {
-        return null;
-    }
-
-    @Nullable
-    public abstract TaskbarUIController getTaskbarController();
-
     public final boolean isResumed() {
-        ACTIVITY_TYPE activity = getCreatedActivity();
+        ACTIVITY_TYPE activity = getCreatedContainer();
         return activity != null && activity.hasBeenResumed();
     }
 
     public final boolean isStarted() {
-        ACTIVITY_TYPE activity = getCreatedActivity();
+        ACTIVITY_TYPE activity = getCreatedContainer();
         return activity != null && activity.isStarted();
     }
 
@@ -180,14 +130,6 @@
     @UiThread
     public abstract boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener);
 
-    public abstract Rect getOverviewWindowBounds(
-            Rect homeBounds, RemoteAnimationTarget target);
-
-    public abstract boolean allowMinimizeSplitScreen();
-
-    /** @return whether to allow going to All Apps from Overview. */
-    public abstract boolean allowAllAppsFromOverview();
-
     public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
         TaskbarUIController controller = getTaskbarController();
         boolean isEventOverBubbleBarStashHandle =
@@ -197,20 +139,6 @@
     }
 
     /**
-     * @return Whether the gesture in progress should be cancelled.
-     */
-    public boolean shouldCancelCurrentGesture() {
-        return false;
-    }
-
-    public abstract void onExitOverview(RotationTouchHelper deviceState,
-            Runnable exitRunnable);
-
-    public abstract boolean isInLiveTileMode();
-
-    public abstract void onLaunchTaskFailed();
-
-    /**
      * Closes any overlays.
      */
     public void closeOverlay() {
@@ -220,7 +148,7 @@
 
     public void switchRunningTaskViewToScreenshot(HashMap<Integer, ThumbnailData> thumbnailDatas,
             Runnable runnable) {
-        ACTIVITY_TYPE activity = getCreatedActivity();
+        ACTIVITY_TYPE activity = getCreatedContainer();
         if (activity == null) {
             return;
         }
@@ -234,237 +162,9 @@
         recentsView.switchToScreenshot(thumbnailDatas, runnable);
     }
 
-    /**
-     * Calculates the taskView size for the provided device configuration.
-     */
-    public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
-            PagedOrientationHandler orientedState) {
-        if (dp.isTablet) {
-            if (Flags.enableGridOnlyOverview()) {
-                calculateGridTaskSize(context, dp, outRect, orientedState);
-            } else {
-                calculateFocusTaskSize(context, dp, outRect);
-            }
-        } else {
-            Resources res = context.getResources();
-            float maxScale = res.getFloat(R.dimen.overview_max_scale);
-            int taskMargin = dp.overviewTaskMarginPx;
-            calculateTaskSizeInternal(
-                    context,
-                    dp,
-                    dp.overviewTaskThumbnailTopMarginPx,
-                    dp.getOverviewActionsClaimedSpace(),
-                    res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
-                    maxScale,
-                    Gravity.CENTER,
-                    outRect);
-        }
-    }
-
-    /**
-     * Calculates the taskView size for carousel during app to overview animation on tablets.
-     */
-    public final void calculateCarouselTaskSize(Context context, DeviceProfile dp, Rect outRect,
-            PagedOrientationHandler orientedState) {
-        if (dp.isTablet && dp.isGestureMode) {
-            Resources res = context.getResources();
-            float minScale = res.getFloat(R.dimen.overview_carousel_min_scale);
-            Rect gridRect = new Rect();
-            calculateGridSize(dp, context, gridRect);
-            calculateTaskSizeInternal(context, dp, gridRect, minScale, Gravity.CENTER | Gravity.TOP,
-                    outRect);
-        } else {
-            calculateTaskSize(context, dp, outRect, orientedState);
-        }
-    }
-
-    private void calculateFocusTaskSize(Context context, DeviceProfile dp, Rect outRect) {
-        Resources res = context.getResources();
-        float maxScale = res.getFloat(R.dimen.overview_max_scale);
-        Rect gridRect = new Rect();
-        calculateGridSize(dp, context, gridRect);
-        calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
-    }
-
-    private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
-            int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
-            Rect outRect) {
-        Rect insets = dp.getInsets();
-
-        Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
-        potentialTaskRect.inset(insets.left, insets.top, insets.right, insets.bottom);
-        potentialTaskRect.inset(
-                minimumHorizontalPadding,
-                claimedSpaceAbove,
-                minimumHorizontalPadding,
-                claimedSpaceBelow);
-
-        calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
-    }
-
-    private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
-            Rect potentialTaskRect, float targetScale, int gravity, Rect outRect) {
-        PointF taskDimension = getTaskDimension(context, dp);
-
-        float scale = Math.min(
-                potentialTaskRect.width() / taskDimension.x,
-                potentialTaskRect.height() / taskDimension.y);
-        scale = Math.min(scale, targetScale);
-        int outWidth = Math.round(scale * taskDimension.x);
-        int outHeight = Math.round(scale * taskDimension.y);
-
-        Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
-    }
-
-    private static PointF getTaskDimension(Context context, DeviceProfile dp) {
-        PointF dimension = new PointF();
-        getTaskDimension(context, dp, dimension);
-        return dimension;
-    }
-
-    /**
-     * Gets the dimension of the task in the current system state.
-     */
-    public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) {
-        out.x = dp.widthPx;
-        out.y = dp.heightPx;
-        if (dp.isTablet && !DisplayController.isTransientTaskbar(context)) {
-            out.y -= dp.taskbarHeight;
-        }
-    }
-
-    /**
-     * Calculates the overview grid size for the provided device configuration.
-     */
-    public final void calculateGridSize(DeviceProfile dp, Context context, Rect outRect) {
-        Rect insets = dp.getInsets();
-        int topMargin = dp.overviewTaskThumbnailTopMarginPx;
-        int bottomMargin = dp.getOverviewActionsClaimedSpace();
-        if (dp.isTaskbarPresent && Flags.enableGridOnlyOverview()) {
-            topMargin += context.getResources().getDimensionPixelSize(
-                    R.dimen.overview_top_margin_grid_only);
-            bottomMargin += context.getResources().getDimensionPixelSize(
-                    R.dimen.overview_bottom_margin_grid_only);
-        }
-        int sideMargin = dp.overviewGridSideMargin;
-
-        outRect.set(0, 0, dp.widthPx, dp.heightPx);
-        outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin,
-                Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin));
-    }
-
-    /**
-     * Calculates the overview grid non-focused task size for the provided device configuration.
-     */
-    public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect,
-            PagedOrientationHandler orientedState) {
-        Resources res = context.getResources();
-        Rect potentialTaskRect = new Rect();
-        if (Flags.enableGridOnlyOverview()) {
-            calculateGridSize(dp, context, potentialTaskRect);
-        } else {
-            calculateFocusTaskSize(context, dp, potentialTaskRect);
-        }
-
-        float rowHeight = (potentialTaskRect.height() + dp.overviewTaskThumbnailTopMarginPx
-                - dp.overviewRowSpacing) / 2f;
-
-        PointF taskDimension = getTaskDimension(context, dp);
-        float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y;
-        int outWidth = Math.round(scale * taskDimension.x);
-        int outHeight = Math.round(scale * taskDimension.y);
-
-        int gravity = Gravity.TOP;
-        gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
-        Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
-    }
-
-    /**
-     * Calculates the task size for the desktop task
-     */
-    public final void calculateDesktopTaskSize(Context context, DeviceProfile dp, Rect outRect) {
-        calculateFocusTaskSize(context, dp, outRect);
-    }
-
-    /**
-     * Calculates the modal taskView size for the provided device configuration
-     */
-    public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect,
-            PagedOrientationHandler orientedState) {
-        calculateTaskSize(context, dp, outRect, orientedState);
-        boolean isGridOnlyOverview = dp.isTablet && Flags.enableGridOnlyOverview();
-        int claimedSpaceBelow = isGridOnlyOverview
-                ? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarHeight
-                : (dp.heightPx - outRect.bottom - dp.getInsets().bottom);
-        int minimumHorizontalPadding = 0;
-        if (!isGridOnlyOverview) {
-            float maxScale = context.getResources().getFloat(R.dimen.overview_modal_max_scale);
-            minimumHorizontalPadding =
-                    Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2);
-        }
-        calculateTaskSizeInternal(
-                context,
-                dp,
-                dp.overviewTaskMarginPx,
-                claimedSpaceBelow,
-                minimumHorizontalPadding,
-                1f /*maxScale*/,
-                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
-                outRect);
-    }
-
-    /**
-     * Called when the gesture ends and the animation starts towards the given target. Used to add
-     * an optional additional animation with the same duration.
-     */
-    public @Nullable Animator getParallelAnimationToLauncher(
-            GestureState.GestureEndTarget endTarget, long duration,
-            RecentsAnimationCallbacks callbacks) {
-        if (endTarget == RECENTS) {
-            ACTIVITY_TYPE activity = getCreatedActivity();
-            if (activity == null) {
-                return null;
-            }
-            RecentsView recentsView = activity.getOverviewPanel();
-            STATE_TYPE state = stateFromGestureEndTarget(endTarget);
-            ScrimView scrimView = activity.getScrimView();
-            ObjectAnimator anim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR,
-                    getOverviewScrimColorForState(activity, state));
-            anim.setDuration(duration);
-            anim.setInterpolator(recentsView == null || !recentsView.isKeyboardTaskFocusPending()
-                    ? LINEAR : INSTANT);
-            return anim;
-        }
-        return null;
-    }
-
-    /**
-     * Returns the color of the scrim behind overview when at rest in this state.
-     * Return {@link Color#TRANSPARENT} for no scrim.
-     */
-    protected abstract int getOverviewScrimColorForState(ACTIVITY_TYPE activity, STATE_TYPE state);
-
-    /**
-     * Returns the expected STATE_TYPE from the provided GestureEndTarget.
-     */
-    public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget);
-
-    /**
-     * Called when the animation to the target has finished, but right before updating the state.
-     * @return A View that needs to draw before ending the recents animation to LAST_TASK.
-     * (This is a hack to ensure Taskbar draws its background first to avoid flickering.)
-     */
-    public @Nullable View onSettledOnEndTarget(GestureState.GestureEndTarget endTarget) {
-        TaskbarUIController taskbarUIController = getTaskbarController();
-        if (taskbarUIController != null) {
-            taskbarUIController.setSystemGestureInProgress(false);
-            return taskbarUIController.getRootView();
-        }
-        return null;
-    }
 
     protected void runOnInitBackgroundStateUI(Runnable callback) {
-        ACTIVITY_TYPE activity = getCreatedActivity();
+        ACTIVITY_TYPE activity = getCreatedContainer();
         if (activity != null && activity.getStateManager().getState() == mBackgroundState) {
             callback.run();
             onInitBackgroundStateUI();
@@ -515,7 +215,7 @@
         DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
             mCallback = callback;
 
-            mActivity = getCreatedActivity();
+            mActivity = getCreatedContainer();
             mStartState = mActivity.getStateManager().getState();
         }
 
diff --git a/quickstep/src/com/android/quickstep/BaseContainerInterface.java b/quickstep/src/com/android/quickstep/BaseContainerInterface.java
new file mode 100644
index 0000000..9955183
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/BaseContainerInterface.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
+import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
+import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.RemoteAnimationTarget;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
+import com.android.launcher3.R;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
+import com.android.launcher3.statemanager.BaseState;
+import com.android.launcher3.taskbar.TaskbarUIController;
+import com.android.launcher3.touch.PagedOrientationHandler;
+import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.views.ScrimView;
+import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.util.ActivityInitListener;
+import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+import java.util.HashMap;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public abstract class BaseContainerInterface<STATE_TYPE extends BaseState<STATE_TYPE>,
+        CONTAINER_TYPE extends RecentsViewContainer> {
+
+    public boolean rotationSupportedByActivity = false;
+
+    @Nullable
+    public abstract CONTAINER_TYPE getCreatedContainer();
+
+    public abstract boolean isInLiveTileMode();
+
+    public abstract void onAssistantVisibilityChanged(float assistantVisibility);
+
+    public abstract boolean allowMinimizeSplitScreen();
+
+    public abstract boolean isResumed();
+
+    public abstract boolean isStarted();
+    public abstract boolean deferStartingActivity(RecentsAnimationDeviceState deviceState,
+            MotionEvent ev);
+
+    /** @return whether to allow going to All Apps from Overview. */
+    public abstract boolean allowAllAppsFromOverview();
+
+    /**
+     * Returns the color of the scrim behind overview when at rest in this state.
+     * Return {@link Color#TRANSPARENT} for no scrim.
+     */
+    protected abstract int getOverviewScrimColorForState(CONTAINER_TYPE container,
+            STATE_TYPE state);
+
+    public abstract int getSwipeUpDestinationAndLength(
+            DeviceProfile dp, Context context, Rect outRect,
+            RecentsPagedOrientationHandler orientationHandler);
+
+    @Nullable
+    public abstract TaskbarUIController getTaskbarController();
+
+    public abstract BaseActivityInterface.AnimationFactory prepareRecentsUI(
+            RecentsAnimationDeviceState deviceState, boolean activityVisible,
+            Consumer<AnimatorControllerWithResistance> callback);
+
+    public abstract ActivityInitListener createActivityInitListener(
+            Predicate<Boolean> onInitListener);
+    /**
+     * Returns the expected STATE_TYPE from the provided GestureEndTarget.
+     */
+    public abstract STATE_TYPE stateFromGestureEndTarget(GestureState.GestureEndTarget endTarget);
+
+    public abstract void switchRunningTaskViewToScreenshot(HashMap<Integer,
+            ThumbnailData> thumbnailDatas, Runnable runnable);
+
+    public abstract void closeOverlay();
+
+    public abstract Rect getOverviewWindowBounds(
+            Rect homeBounds, RemoteAnimationTarget target);
+
+    public abstract void onLaunchTaskFailed();
+
+    public abstract void onExitOverview(RotationTouchHelper deviceState,
+            Runnable exitRunnable);
+
+    /** Called when the animation to home has fully settled. */
+    public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) {}
+
+    /**
+     * Sets a callback to be run when an activity launch happens while launcher is not yet resumed.
+     */
+    public void setOnDeferredActivityLaunchCallback(Runnable r) {}
+    /**
+     * @return Whether the gesture in progress should be cancelled.
+     */
+    public boolean shouldCancelCurrentGesture() {
+        return false;
+    }
+
+    @Nullable
+    public DesktopVisibilityController getDesktopVisibilityController() {
+        return null;
+    }
+
+    /**
+     * Called when the gesture ends and the animation starts towards the given target. Used to add
+     * an optional additional animation with the same duration.
+     */
+    public @Nullable Animator getParallelAnimationToLauncher(
+            GestureState.GestureEndTarget endTarget, long duration,
+            RecentsAnimationCallbacks callbacks) {
+        if (endTarget == RECENTS) {
+            CONTAINER_TYPE container = getCreatedContainer();
+            if (container == null) {
+                return null;
+            }
+            RecentsView recentsView = container.getOverviewPanel();
+            STATE_TYPE state = stateFromGestureEndTarget(endTarget);
+            ScrimView scrimView = container.getScrimView();
+            ObjectAnimator anim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR,
+                    getOverviewScrimColorForState(container, state));
+            anim.setDuration(duration);
+            anim.setInterpolator(recentsView == null || !recentsView.isKeyboardTaskFocusPending()
+                    ? LINEAR : INSTANT);
+            return anim;
+        }
+        return null;
+    }
+
+    /**
+     * Called when the animation to the target has finished, but right before updating the state.
+     * @return A View that needs to draw before ending the recents animation to LAST_TASK.
+     * (This is a hack to ensure Taskbar draws its background first to avoid flickering.)
+     */
+    public @Nullable View onSettledOnEndTarget(GestureState.GestureEndTarget endTarget) {
+        TaskbarUIController taskbarUIController = getTaskbarController();
+        if (taskbarUIController != null) {
+            taskbarUIController.setSystemGestureInProgress(false);
+            return taskbarUIController.getRootView();
+        }
+        return null;
+    }
+
+    /**
+     * Called when the current gesture transition is cancelled.
+     * @param activityVisible Whether the user can see the changes we make here, so try to animate.
+     * @param endTarget If the gesture ended before we got cancelled, where we were headed.
+     */
+    public void onTransitionCancelled(boolean activityVisible,
+            @Nullable GestureState.GestureEndTarget endTarget) {
+        RecentsViewContainer container = getCreatedContainer();
+        if (container == null) {
+            return;
+        }
+        RecentsView recentsView = container.getOverviewPanel();
+        BaseState startState = recentsView.getStateManager().getRestState();
+        if (endTarget != null) {
+            // We were on our way to this state when we got canceled, end there instead.
+            startState = stateFromGestureEndTarget(endTarget);
+            DesktopVisibilityController controller = getDesktopVisibilityController();
+            if (controller != null && controller.areDesktopTasksVisible()
+                    && endTarget == LAST_TASK) {
+                // When we are cancelling the transition and going back to last task, move to
+                // rest state instead when desktop tasks are visible.
+                // If a fullscreen task is visible, launcher goes to normal state when the
+                // activity is stopped. This does not happen when desktop tasks are visible
+                // on top of launcher. Force the launcher state to rest state here.
+                startState = recentsView.getStateManager().getRestState();
+                // Do not animate the transition
+                activityVisible = false;
+            }
+        }
+        recentsView.getStateManager().goToState(startState, activityVisible);
+    }
+
+    public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
+            PagedOrientationHandler orientedState) {
+        if (dp.isTablet) {
+            if (Flags.enableGridOnlyOverview()) {
+                calculateGridTaskSize(context, dp, outRect, orientedState);
+            } else {
+                calculateFocusTaskSize(context, dp, outRect);
+            }
+        } else {
+            Resources res = context.getResources();
+            float maxScale = res.getFloat(R.dimen.overview_max_scale);
+            int taskMargin = dp.overviewTaskMarginPx;
+            calculateTaskSizeInternal(
+                    context,
+                    dp,
+                    dp.overviewTaskThumbnailTopMarginPx,
+                    dp.getOverviewActionsClaimedSpace(),
+                    res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
+                    maxScale,
+                    Gravity.CENTER,
+                    outRect);
+        }
+    }
+
+    /**
+     * Calculates the taskView size for carousel during app to overview animation on tablets.
+     */
+    public final void calculateCarouselTaskSize(Context context, DeviceProfile dp, Rect outRect,
+            PagedOrientationHandler orientedState) {
+        if (dp.isTablet && dp.isGestureMode) {
+            Resources res = context.getResources();
+            float minScale = res.getFloat(R.dimen.overview_carousel_min_scale);
+            Rect gridRect = new Rect();
+            calculateGridSize(dp, context, gridRect);
+            calculateTaskSizeInternal(context, dp, gridRect, minScale, Gravity.CENTER | Gravity.TOP,
+                    outRect);
+        } else {
+            calculateTaskSize(context, dp, outRect, orientedState);
+        }
+    }
+
+    private void calculateFocusTaskSize(Context context, DeviceProfile dp, Rect outRect) {
+        Resources res = context.getResources();
+        float maxScale = res.getFloat(R.dimen.overview_max_scale);
+        Rect gridRect = new Rect();
+        calculateGridSize(dp, context, gridRect);
+        calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
+    }
+
+    private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
+            int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
+            Rect outRect) {
+        Rect insets = dp.getInsets();
+
+        Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
+        potentialTaskRect.inset(insets.left, insets.top, insets.right, insets.bottom);
+        potentialTaskRect.inset(
+                minimumHorizontalPadding,
+                claimedSpaceAbove,
+                minimumHorizontalPadding,
+                claimedSpaceBelow);
+
+        calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
+    }
+
+    private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
+            Rect potentialTaskRect, float targetScale, int gravity, Rect outRect) {
+        PointF taskDimension = getTaskDimension(context, dp);
+
+        float scale = Math.min(
+                potentialTaskRect.width() / taskDimension.x,
+                potentialTaskRect.height() / taskDimension.y);
+        scale = Math.min(scale, targetScale);
+        int outWidth = Math.round(scale * taskDimension.x);
+        int outHeight = Math.round(scale * taskDimension.y);
+
+        Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
+    }
+
+    private static PointF getTaskDimension(Context context, DeviceProfile dp) {
+        PointF dimension = new PointF();
+        getTaskDimension(context, dp, dimension);
+        return dimension;
+    }
+
+    /**
+     * Gets the dimension of the task in the current system state.
+     */
+    public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) {
+        out.x = dp.widthPx;
+        out.y = dp.heightPx;
+        if (dp.isTablet && !DisplayController.isTransientTaskbar(context)) {
+            out.y -= dp.taskbarHeight;
+        }
+    }
+
+    /**
+     * Calculates the overview grid size for the provided device configuration.
+     */
+    public final void calculateGridSize(DeviceProfile dp, Context context, Rect outRect) {
+        Rect insets = dp.getInsets();
+        int topMargin = dp.overviewTaskThumbnailTopMarginPx;
+        int bottomMargin = dp.getOverviewActionsClaimedSpace();
+        if (dp.isTaskbarPresent && Flags.enableGridOnlyOverview()) {
+            topMargin += context.getResources().getDimensionPixelSize(
+                    R.dimen.overview_top_margin_grid_only);
+            bottomMargin += context.getResources().getDimensionPixelSize(
+                    R.dimen.overview_bottom_margin_grid_only);
+        }
+        int sideMargin = dp.overviewGridSideMargin;
+
+        outRect.set(0, 0, dp.widthPx, dp.heightPx);
+        outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin,
+                Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin));
+    }
+
+    /**
+     * Calculates the overview grid non-focused task size for the provided device configuration.
+     */
+    public final void calculateGridTaskSize(Context context, DeviceProfile dp, Rect outRect,
+            PagedOrientationHandler orientedState) {
+        Resources res = context.getResources();
+        Rect potentialTaskRect = new Rect();
+        if (Flags.enableGridOnlyOverview()) {
+            calculateGridSize(dp, context, potentialTaskRect);
+        } else {
+            calculateFocusTaskSize(context, dp, potentialTaskRect);
+        }
+
+        float rowHeight = (potentialTaskRect.height() + dp.overviewTaskThumbnailTopMarginPx
+                - dp.overviewRowSpacing) / 2f;
+
+        PointF taskDimension = getTaskDimension(context, dp);
+        float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y;
+        int outWidth = Math.round(scale * taskDimension.x);
+        int outHeight = Math.round(scale * taskDimension.y);
+
+        int gravity = Gravity.TOP;
+        gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
+        Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
+    }
+
+    /**
+     * Calculates the modal taskView size for the provided device configuration
+     */
+    public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect,
+            PagedOrientationHandler orientedState) {
+        calculateTaskSize(context, dp, outRect, orientedState);
+        boolean isGridOnlyOverview = dp.isTablet && Flags.enableGridOnlyOverview();
+        int claimedSpaceBelow = isGridOnlyOverview
+                ? dp.overviewActionsTopMarginPx + dp.overviewActionsHeight + dp.stashedTaskbarHeight
+                : (dp.heightPx - outRect.bottom - dp.getInsets().bottom);
+        int minimumHorizontalPadding = 0;
+        if (!isGridOnlyOverview) {
+            float maxScale = context.getResources().getFloat(R.dimen.overview_modal_max_scale);
+            minimumHorizontalPadding =
+                    Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2);
+        }
+        calculateTaskSizeInternal(
+                context,
+                dp,
+                dp.overviewTaskMarginPx,
+                claimedSpaceBelow,
+                minimumHorizontalPadding,
+                1f /*maxScale*/,
+                Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
+                outRect);
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
new file mode 100644
index 0000000..aa0f728
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/DesktopSystemShortcut.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import android.view.View
+import com.android.launcher3.AbstractFloatingViewHelper
+import com.android.launcher3.R
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent
+import com.android.launcher3.popup.SystemShortcut
+import com.android.quickstep.views.RecentsView
+import com.android.quickstep.views.RecentsViewContainer
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
+import com.android.window.flags.Flags
+
+/** A menu item, "Desktop", that allows the user to bring the current app into Desktop Windowing. */
+class DesktopSystemShortcut(
+    container: RecentsViewContainer,
+    private val mTaskContainer: TaskIdAttributeContainer,
+    abstractFloatingViewHelper: AbstractFloatingViewHelper
+) :
+    SystemShortcut<RecentsViewContainer>(
+        R.drawable.ic_caption_desktop_button_foreground,
+        R.string.recent_task_option_desktop,
+        container,
+        mTaskContainer.itemInfo,
+        mTaskContainer.taskView,
+        abstractFloatingViewHelper
+    ) {
+    override fun onClick(view: View) {
+        dismissTaskMenuView()
+        val recentsView = mTarget!!.getOverviewPanel<RecentsView<*, *>>()
+        recentsView.moveTaskToDesktop(mTaskContainer) {
+            mTarget.statsLogManager
+                .logger()
+                .withItemInfo(mTaskContainer.itemInfo)
+                .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP)
+        }
+    }
+
+    companion object {
+        /** Creates a factory for creating Desktop system shorcuts. */
+        @JvmOverloads
+        fun createFactory(
+            abstractFloatingViewHelper: AbstractFloatingViewHelper = AbstractFloatingViewHelper()
+        ): TaskShortcutFactory {
+            return object : TaskShortcutFactory {
+                override fun getShortcuts(
+                    container: RecentsViewContainer,
+                    taskContainer: TaskIdAttributeContainer
+                ): List<DesktopSystemShortcut>? {
+                    return if (!Flags.enableDesktopWindowingMode()) null
+                    else if (!taskContainer.task.isDockable) null
+                    else
+                        listOf(
+                            DesktopSystemShortcut(
+                                container,
+                                taskContainer,
+                                abstractFloatingViewHelper
+                            )
+                        )
+                }
+
+                override fun showForSplitscreen() = true
+            }
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
new file mode 100644
index 0000000..1cc54d8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/DeviceConfigWrapper.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import com.android.quickstep.util.DeviceConfigHelper
+import com.android.quickstep.util.DeviceConfigHelper.PropReader
+import java.io.PrintWriter
+
+/** Various configurations specific to nav-bar functionalities */
+class DeviceConfigWrapper private constructor(propReader: PropReader) {
+
+    val customLpnhThresholds =
+        propReader.get(
+            "CUSTOM_LPNH_THRESHOLDS",
+            true,
+            "Add dev options and server side control to customize the LPNH trigger slop and milliseconds"
+        )
+
+    val customLphThresholds =
+        propReader.get(
+            "CUSTOM_LPH_THRESHOLDS",
+            false,
+            "Server side control to customize LPH timeout and touch slop"
+        )
+
+    val overrideLpnhLphThresholds =
+        propReader.get(
+            "OVERRIDE_LPNH_LPH_THRESHOLDS",
+            false,
+            "Enable AGSA override for LPNH and LPH timeout and touch slop"
+        )
+
+    val lpnhTimeoutMs =
+        propReader.get("LPNH_TIMEOUT_MS", 450, "Controls lpnh timeout in milliseconds")
+
+    val lpnhSlopPercentage =
+        propReader.get("LPNH_SLOP_PERCENTAGE", 100, "Controls touch slop percentage for lpnh")
+
+    val enableLpnhTwoStages =
+        propReader.get(
+            "ENABLE_LPNH_TWO_STAGES",
+            false,
+            "Enable two stage for LPNH duration and touch slop"
+        )
+
+    val twoStageMultiplier =
+        propReader.get(
+            "TWO_STAGE_MULTIPLIER",
+            2,
+            "Extends the duration and touch slop if the initial slop is passed"
+        )
+
+    val animateLpnh = propReader.get("ANIMATE_LPNH", false, "Animates navbar when long pressing")
+
+    val shrinkNavHandleOnPress =
+        propReader.get(
+            "SHRINK_NAV_HANDLE_ON_PRESS",
+            false,
+            "Shrinks navbar when long pressing if ANIMATE_LPNH is enabled"
+        )
+
+    val enableLongPressNavHandle =
+        propReader.get(
+            "ENABLE_LONG_PRESS_NAV_HANDLE",
+            true,
+            "Enables long pressing on the bottom bar nav handle to trigger events."
+        )
+
+    val enableSearchHapticHint =
+        propReader.get(
+            "ENABLE_SEARCH_HAPTIC_HINT",
+            true,
+            "Enables haptic hint while long pressing on the bottom bar nav handle."
+        )
+
+    val enableSearchHapticCommit =
+        propReader.get(
+            "ENABLE_SEARCH_HAPTIC_COMMIT",
+            true,
+            "Enables haptic hint at end of long pressing on the bottom bar nav handle."
+        )
+
+    val lpnhHapticHintStartScalePercent =
+        propReader.get("LPNH_HAPTIC_HINT_START_SCALE_PERCENT", 0, "Haptic hint start scale.")
+
+    val lpnhHapticHintEndScalePercent =
+        propReader.get("LPNH_HAPTIC_HINT_END_SCALE_PERCENT", 100, "Haptic hint end scale.")
+
+    val lpnhHapticHintScaleExponent =
+        propReader.get("LPNH_HAPTIC_HINT_SCALE_EXPONENT", 1, "Haptic hint scale exponent.")
+
+    val lpnhHapticHintIterations =
+        propReader.get("LPNH_HAPTIC_HINT_ITERATIONS", 50, "Haptic hint number of iterations.")
+
+    val enableLpnhDeepPress =
+        propReader.get(
+            "ENABLE_LPNH_DEEP_PRESS",
+            true,
+            "Long press of nav handle is instantly triggered if deep press is detected."
+        )
+
+    val lpnhHapticHintDelay =
+        propReader.get("LPNH_HAPTIC_HINT_DELAY", 0, "Delay before haptic hint starts.")
+
+    val lpnhExtraTouchWidthDp =
+        propReader.get(
+            "LPNH_EXTRA_TOUCH_WIDTH_DP",
+            0,
+            "Controls extra dp on the nav bar sides to trigger LPNH. Can be negative for a smaller touch region."
+        )
+
+    val allAppsOverviewThreshold =
+        propReader.get(
+            "ALL_APPS_OVERVIEW_THRESHOLD",
+            180,
+            "Threshold to open All Apps from Overview"
+        )
+
+    /** Dump config values. */
+    fun dump(prefix: String, writer: PrintWriter) {
+        writer.println("$prefix DeviceConfigWrapper:")
+        writer.println("$prefix\tcustomLpnhThresholds=$customLpnhThresholds")
+        writer.println("$prefix\tcustomLphThresholds=$customLphThresholds")
+        writer.println("$prefix\toverrideLpnhLphThresholds=$overrideLpnhLphThresholds")
+        writer.println("$prefix\tlpnhSlopPercentage=$lpnhSlopPercentage")
+        writer.println("$prefix\tanimateLpnh=$animateLpnh")
+        writer.println("$prefix\tshrinkNavHandleOnPress=$shrinkNavHandleOnPress")
+        writer.println("$prefix\tlpnhTimeoutMs=$lpnhTimeoutMs")
+        writer.println("$prefix\tenableLongPressNavHandle=$enableLongPressNavHandle")
+        writer.println("$prefix\tenableSearchHapticHint=$enableSearchHapticHint")
+        writer.println("$prefix\tenableSearchHapticCommit=$enableSearchHapticCommit")
+        writer.println("$prefix\tlpnhHapticHintStartScalePercent=$lpnhHapticHintStartScalePercent")
+        writer.println("$prefix\tlpnhHapticHintEndScalePercent=$lpnhHapticHintEndScalePercent")
+        writer.println("$prefix\tlpnhHapticHintScaleExponent=$lpnhHapticHintScaleExponent")
+        writer.println("$prefix\tlpnhHapticHintIterations=$lpnhHapticHintIterations")
+        writer.println("$prefix\tenableLpnhDeepPress=$enableLpnhDeepPress")
+        writer.println("$prefix\tlpnhHapticHintDelay=$lpnhHapticHintDelay")
+        writer.println("$prefix\tlpnhExtraTouchWidthDp=$lpnhExtraTouchWidthDp")
+        writer.println("$prefix\tallAppsOverviewThreshold=$allAppsOverviewThreshold")
+    }
+
+    companion object {
+        val configHelper by lazy { DeviceConfigHelper(::DeviceConfigWrapper) }
+
+        @JvmStatic fun get() = configHelper.config
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
index 27e8726..9e896fd 100644
--- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
@@ -96,13 +96,13 @@
 
     @Nullable
     @Override
-    public RecentsActivity getCreatedActivity() {
+    public RecentsActivity getCreatedContainer() {
         return RecentsActivity.ACTIVITY_TRACKER.getCreatedActivity();
     }
 
     @Override
     public FallbackTaskbarUIController getTaskbarController() {
-        RecentsActivity activity = getCreatedActivity();
+        RecentsActivity activity = getCreatedContainer();
         if (activity == null) {
             return null;
         }
@@ -112,7 +112,7 @@
     @Nullable
     @Override
     public RecentsView getVisibleRecentsView() {
-        RecentsActivity activity = getCreatedActivity();
+        RecentsActivity activity = getCreatedContainer();
         if (activity != null) {
             if (activity.hasBeenResumed() || isInLiveTileMode()) {
                 return activity.getOverviewPanel();
@@ -154,7 +154,7 @@
 
     @Override
     public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) {
-        final StateManager<RecentsState> stateManager = getCreatedActivity().getStateManager();
+        final StateManager<RecentsState> stateManager = getCreatedContainer().getStateManager();
         if (stateManager.getState() == HOME) {
             exitRunnable.run();
             notifyRecentsOfOrientation(deviceState);
@@ -177,7 +177,7 @@
 
     @Override
     public boolean isInLiveTileMode() {
-        RecentsActivity activity = getCreatedActivity();
+        RecentsActivity activity = getCreatedContainer();
         return activity != null && activity.getStateManager().getState() == DEFAULT &&
                 activity.isStarted();
     }
@@ -185,7 +185,7 @@
     @Override
     public void onLaunchTaskFailed() {
         // TODO: probably go back to overview instead.
-        RecentsActivity activity = getCreatedActivity();
+        RecentsActivity activity = getCreatedContainer();
         if (activity == null) {
             return;
         }
@@ -209,7 +209,7 @@
 
     private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) {
         // reset layout on swipe to home
-        RecentsView recentsView = getCreatedActivity().getOverviewPanel();
+        RecentsView recentsView = getCreatedContainer().getOverviewPanel();
         recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
                 rotationTouchHelper.getDisplayRotation());
     }
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index b42eb06..92cdf72 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -223,7 +223,7 @@
         public AnimatorPlaybackController createActivityAnimationToHome() {
             // copied from {@link LauncherSwipeHandlerV2.LauncherHomeAnimationFactory}
             long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
-            return mActivity.getStateManager().createAnimationToNewWorkspace(
+            return mContainer.getStateManager().createAnimationToNewWorkspace(
                     RecentsState.HOME, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS);
         }
     }
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index d02909c..6b33c0a 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -37,10 +37,10 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.statemanager.BaseState;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
 import com.android.quickstep.util.ActiveGestureErrorDetector;
 import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
 import java.io.PrintWriter;
@@ -151,7 +151,7 @@
     // Needed to interact with the current activity
     private final Intent mHomeIntent;
     private final Intent mOverviewIntent;
-    private final BaseActivityInterface mActivityInterface;
+    private final BaseContainerInterface mContainerInterface;
     private final MultiStateCallback mStateCallback;
     private final int mGestureId;
 
@@ -189,7 +189,7 @@
     public GestureState(OverviewComponentObserver componentObserver, int gestureId) {
         mHomeIntent = componentObserver.getHomeIntent();
         mOverviewIntent = componentObserver.getOverviewIntent();
-        mActivityInterface = componentObserver.getActivityInterface();
+        mContainerInterface = componentObserver.getActivityInterface();
         mStateCallback = new MultiStateCallback(
                 STATE_NAMES.toArray(new String[0]), GestureState::getTrackedEventForState);
         mGestureId = gestureId;
@@ -198,7 +198,7 @@
     public GestureState(GestureState other) {
         mHomeIntent = other.mHomeIntent;
         mOverviewIntent = other.mOverviewIntent;
-        mActivityInterface = other.mActivityInterface;
+        mContainerInterface = other.mContainerInterface;
         mStateCallback = other.mStateCallback;
         mGestureId = other.mGestureId;
         mRunningTask = other.mRunningTask;
@@ -212,7 +212,7 @@
         // Do nothing, only used for initializing the gesture state prior to user unlock
         mHomeIntent = new Intent();
         mOverviewIntent = new Intent();
-        mActivityInterface = null;
+        mContainerInterface = null;
         mStateCallback = new MultiStateCallback(
                 STATE_NAMES.toArray(new String[0]), GestureState::getTrackedEventForState);
         mGestureId = -1;
@@ -268,9 +268,9 @@
     /**
      * @return the interface to the activity handing the UI updates for this gesture.
      */
-    public <S extends BaseState<S>,
-            T extends StatefulActivity<S>> BaseActivityInterface<S, T> getActivityInterface() {
-        return mActivityInterface;
+    public <S extends BaseState<S>, T extends RecentsViewContainer>
+            BaseContainerInterface<S, T> getContainerInterface() {
+        return mContainerInterface;
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/HomeVisibilityState.kt b/quickstep/src/com/android/quickstep/HomeVisibilityState.kt
new file mode 100644
index 0000000..241e16d
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/HomeVisibilityState.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import android.os.RemoteException
+import android.util.Log
+import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.util.Executors
+import com.android.wm.shell.shared.IHomeTransitionListener.Stub
+import com.android.wm.shell.shared.IShellTransitions
+
+/** Class to track visibility state of Launcher */
+class HomeVisibilityState {
+
+    var isHomeVisible = true
+        private set
+
+    private var listeners = mutableSetOf<VisibilityChangeListener>()
+
+    fun addListener(l: VisibilityChangeListener) = listeners.add(l)
+
+    fun removeListener(l: VisibilityChangeListener) = listeners.remove(l)
+
+    fun init(transitions: IShellTransitions?) {
+        if (!FeatureFlags.enableHomeTransitionListener()) return
+        try {
+            transitions?.setHomeTransitionListener(
+                object : Stub() {
+                    override fun onHomeVisibilityChanged(isVisible: Boolean) {
+                        Executors.MAIN_EXECUTOR.execute {
+                            isHomeVisible = isVisible
+                            listeners.forEach { it.onHomeVisibilityChanged(isVisible) }
+                        }
+                    }
+                }
+            )
+        } catch (e: RemoteException) {
+            Log.w(TAG, "Failed call setHomeTransitionListener", e)
+        }
+    }
+
+    interface VisibilityChangeListener {
+        fun onHomeVisibilityChanged(isVisible: Boolean)
+    }
+
+    override fun toString() = "{HomeVisibilityState isHomeVisible=$isHomeVisible}"
+
+    companion object {
+
+        private const val TAG = "HomeVisibilityState"
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 97c48e6..7655c59 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -35,7 +35,7 @@
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.Flags;
 import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.LauncherInitListener;
 import com.android.launcher3.LauncherState;
@@ -85,7 +85,7 @@
 
     @Override
     public void onSwipeUpToHomeComplete(RecentsAnimationDeviceState deviceState) {
-        Launcher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return;
         }
@@ -102,7 +102,7 @@
 
     @Override
     public void onAssistantVisibilityChanged(float visibility) {
-        Launcher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return;
         }
@@ -144,7 +144,7 @@
 
     @Override
     public void setOnDeferredActivityLaunchCallback(Runnable r) {
-        Launcher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return;
         }
@@ -153,14 +153,14 @@
 
     @Nullable
     @Override
-    public QuickstepLauncher getCreatedActivity() {
+    public QuickstepLauncher getCreatedContainer() {
         return QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
     }
 
     @Nullable
     @Override
     public DepthController getDepthController() {
-        QuickstepLauncher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return null;
         }
@@ -170,7 +170,7 @@
     @Nullable
     @Override
     public DesktopVisibilityController getDesktopVisibilityController() {
-        QuickstepLauncher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return null;
         }
@@ -180,7 +180,7 @@
     @Nullable
     @Override
     public LauncherTaskbarUIController getTaskbarController() {
-        QuickstepLauncher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return null;
         }
@@ -190,7 +190,7 @@
     @Nullable
     @Override
     public RecentsView getVisibleRecentsView() {
-        Launcher launcher = getVisibleLauncher();
+        QuickstepLauncher launcher = getVisibleLauncher();
         RecentsView recentsView =
                 launcher != null && launcher.getStateManager().getState().overviewUi
                         ? launcher.getOverviewPanel() : null;
@@ -204,15 +204,24 @@
 
     @Nullable
     @UiThread
-    private Launcher getVisibleLauncher() {
-        Launcher launcher = getCreatedActivity();
-        return (launcher != null) && launcher.isStarted()
-                && (isInLiveTileMode() || launcher.hasBeenResumed()) ? launcher : null;
+    private QuickstepLauncher getVisibleLauncher() {
+        QuickstepLauncher launcher = getCreatedContainer();
+        if (launcher == null) {
+            return null;
+        }
+        if (launcher.isStarted() && (isInLiveTileMode() || launcher.hasBeenResumed())) {
+            return launcher;
+        }
+        if (Flags.useActivityOverlay()
+                && SystemUiProxy.INSTANCE.get(launcher).getHomeVisibilityState().isHomeVisible()) {
+            return launcher;
+        }
+        return null;
     }
 
     @Override
     public boolean switchToRecentsIfVisible(Animator.AnimatorListener animatorListener) {
-        Launcher launcher = getVisibleLauncher();
+        QuickstepLauncher launcher = getVisibleLauncher();
         if (launcher == null) {
             return false;
         }
@@ -233,7 +242,7 @@
 
     @Override
     public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) {
-        final StateManager<LauncherState> stateManager = getCreatedActivity().getStateManager();
+        final StateManager<LauncherState> stateManager = getCreatedContainer().getStateManager();
         stateManager.addStateListener(
                 new StateManager.StateListener<LauncherState>() {
                     @Override
@@ -250,7 +259,7 @@
 
     private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) {
         // reset layout on swipe to home
-        RecentsView recentsView = getCreatedActivity().getOverviewPanel();
+        RecentsView recentsView = getCreatedContainer().getOverviewPanel();
         recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(),
                 rotationTouchHelper.getDisplayRotation());
     }
@@ -269,12 +278,12 @@
     public boolean allowAllAppsFromOverview() {
         return FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()
                 // If floating search bar would not show in overview, don't allow all apps gesture.
-                && OVERVIEW.areElementsVisible(getCreatedActivity(), FLOATING_SEARCH_BAR);
+                && OVERVIEW.areElementsVisible(getCreatedContainer(), FLOATING_SEARCH_BAR);
     }
 
     @Override
     public boolean isInLiveTileMode() {
-        Launcher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
 
         return launcher != null
                 && launcher.getStateManager().getState() == OVERVIEW
@@ -284,7 +293,7 @@
 
     @Override
     public void onLaunchTaskFailed() {
-        Launcher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return;
         }
@@ -294,7 +303,7 @@
     @Override
     public void closeOverlay() {
         super.closeOverlay();
-        Launcher launcher = getCreatedActivity();
+        QuickstepLauncher launcher = getCreatedContainer();
         if (launcher == null) {
             return;
         }
@@ -327,9 +336,8 @@
     }
 
     @Override
-    protected int getOverviewScrimColorForState(QuickstepLauncher launcher,
-            LauncherState state) {
-        return state.getWorkspaceScrimColor(launcher);
+    protected int getOverviewScrimColorForState(QuickstepLauncher activity, LauncherState state) {
+        return state.getWorkspaceScrimColor(activity);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
index cc5a923..79b09fd 100644
--- a/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
+++ b/quickstep/src/com/android/quickstep/LauncherBackAnimationController.java
@@ -39,12 +39,12 @@
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.Pair;
+import android.view.Choreographer;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.view.IRemoteAnimationRunner;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
 import android.view.View;
-import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.window.BackEvent;
@@ -84,7 +84,6 @@
  *
  */
 public class LauncherBackAnimationController {
-    private static final int CANCEL_TRANSITION_DURATION = 233;
     private static final int SCRIM_FADE_DURATION = 233;
     private static final float MIN_WINDOW_SCALE = 0.85f;
     private static final float MAX_SCRIM_ALPHA_DARK = 0.8f;
@@ -95,16 +94,13 @@
     private final Matrix mTransformMatrix = new Matrix();
     /** The window position at the beginning of the back animation. */
     private final Rect mStartRect = new Rect();
-    /** The window position when the back gesture is cancelled. */
-    private final RectF mCancelRect = new RectF();
     /** The current window position. */
     private final RectF mCurrentRect = new RectF();
     private final QuickstepLauncher mLauncher;
     private final int mWindowScaleMarginX;
     private float mWindowScaleEndCornerRadius;
     private float mWindowScaleStartCornerRadius;
-    private final Interpolator mCancelInterpolator;
-    private final Interpolator mProgressInterpolator = Interpolators.STANDARD_DECELERATE;
+    private final Interpolator mProgressInterpolator = Interpolators.BACK_GESTURE;
     private final Interpolator mVerticalMoveInterpolator = new DecelerateInterpolator();
     private final PointF mInitialTouchPos = new PointF();
 
@@ -142,8 +138,6 @@
         loadCornerRadius();
         mWindowScaleMarginX = mLauncher.getResources().getDimensionPixelSize(
                 R.dimen.swipe_back_window_scale_x_margin);
-        mCancelInterpolator =
-                AnimationUtils.loadInterpolator(mLauncher, R.interpolator.standard_interpolator);
     }
 
     /**
@@ -181,8 +175,7 @@
             mHandler.post(() -> {
                 LauncherBackAnimationController controller = mControllerRef.get();
                 if (controller != null) {
-                    mProgressAnimator.onBackCancelled(
-                            controller::resetPositionAnimated);
+                    mProgressAnimator.onBackCancelled(controller::onCancelFinished);
                 }
             });
         }
@@ -262,24 +255,9 @@
         public void onAnimationCancelled() {}
     }
 
-    private void resetPositionAnimated() {
-        ValueAnimator cancelAnimator = ValueAnimator.ofFloat(0, 1);
-        mCancelRect.set(mCurrentRect);
-        cancelAnimator.setDuration(CANCEL_TRANSITION_DURATION);
-        cancelAnimator.setInterpolator(mCancelInterpolator);
-        cancelAnimator.addUpdateListener(
-                animation -> {
-                    updateCancelProgress((float) animation.getAnimatedValue());
-                });
-        cancelAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                // Refresh the status bar appearance to the original one.
-                customizeStatusBarAppearance(false);
-                finishAnimation();
-            }
-        });
-        cancelAnimator.start();
+    private void onCancelFinished() {
+        customizeStatusBarAppearance(false);
+        finishAnimation();
     }
 
     /** Unregisters the back to launcher callback in shell. */
@@ -292,6 +270,14 @@
     }
 
     private void startBack(BackMotionEvent backEvent) {
+        // in case we're still animating an onBackCancelled event, let's remove the finish-
+        // callback from the progress animator to prevent calling finishAnimation() before
+        // restarting a new animation
+        // Side note: startBack is never called during the post-commit phase if the back gesture
+        // was committed (not cancelled). BackAnimationController prevents that. Therefore we
+        // don't have to handle that case.
+        mProgressAnimator.removeOnBackCancelledFinishCallback();
+
         mBackInProgress = true;
         RemoteAnimationTarget appTarget = backEvent.getDepartingAnimationTarget();
 
@@ -314,8 +300,10 @@
                 new RemoteAnimationTarget[]{ mBackTarget });
         setLauncherTargetViewVisible(false);
         mCurrentRect.set(mStartRect);
-        addScrimLayer();
-        mTransaction.apply();
+        if (mScrimLayer == null) {
+            addScrimLayer();
+        }
+        applyTransaction();
     }
 
     private void setLauncherTargetViewVisible(boolean isVisible) {
@@ -355,7 +343,8 @@
             return;
         }
         if (mScrimLayer.isValid()) {
-            mTransaction.remove(mScrimLayer).apply();
+            mTransaction.remove(mScrimLayer);
+            applyTransaction();
         }
         mScrimLayer = null;
     }
@@ -397,23 +386,6 @@
         customizeStatusBarAppearance(progress > UPDATE_SYSUI_FLAGS_THRESHOLD);
     }
 
-    private void updateCancelProgress(float progress) {
-        if (mBackTarget == null) {
-            return;
-        }
-        mCurrentRect.set(
-                Utilities.mapRange(progress, mCancelRect.left, mStartRect.left),
-                Utilities.mapRange(progress, mCancelRect.top, mStartRect.top),
-                Utilities.mapRange(progress, mCancelRect.right, mStartRect.right),
-                Utilities.mapRange(progress, mCancelRect.bottom, mStartRect.bottom));
-
-        float endCornerRadius = Utilities.mapRange(
-                mBackProgress, mWindowScaleStartCornerRadius, mWindowScaleEndCornerRadius);
-        float cornerRadius = Utilities.mapRange(
-                progress, endCornerRadius, mWindowScaleStartCornerRadius);
-        applyTransform(mCurrentRect, cornerRadius);
-    }
-
     /** Transform the target window to match the target rect. */
     private void applyTransform(RectF targetRect, float cornerRadius) {
         final float scale = targetRect.width() / mStartRect.width();
@@ -426,7 +398,11 @@
             mTransaction.setWindowCrop(mBackTarget.leash, mStartRect);
             mTransaction.setCornerRadius(mBackTarget.leash, cornerRadius);
         }
+        applyTransaction();
+    }
 
+    private void applyTransaction() {
+        mTransaction.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
         mTransaction.apply();
     }
 
@@ -484,7 +460,6 @@
         mBackInProgress = false;
         mBackProgress = 0;
         mTransformMatrix.reset();
-        mCancelRect.setEmpty();
         mCurrentRect.setEmpty();
         mStartRect.setEmpty();
         mInitialTouchPos.set(0, 0);
@@ -542,7 +517,7 @@
             float value = (Float) animation.getAnimatedValue();
             if (mScrimLayer != null && mScrimLayer.isValid()) {
                 mTransaction.setAlpha(mScrimLayer, value * mScrimAlpha);
-                mTransaction.apply();
+                applyTransaction();
             }
         });
         mScrimAlphaAnimator.addListener(new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index a9d8afc..6647057 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -17,6 +17,7 @@
 
 import static com.android.app.animation.Interpolators.EXAGGERATED_EASE;
 import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.Utilities.mapBoundToRange;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
@@ -46,6 +47,7 @@
 import com.android.launcher3.views.FloatingView;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
 import com.android.quickstep.util.RectFSpringAnim;
+import com.android.quickstep.util.ScalingWorkspaceRevealAnim;
 import com.android.quickstep.util.StaggeredWorkspaceAnim;
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.views.FloatingWidgetView;
@@ -73,7 +75,7 @@
     protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
             long duration, boolean isTargetTranslucent, boolean appCanEnterPip,
             RemoteAnimationTarget runningTaskTarget) {
-        if (mActivity == null) {
+        if (mContainer == null) {
             mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
                     isPresent -> mRecentsView.startHome());
             return new HomeAnimationFactory() {
@@ -89,9 +91,9 @@
         boolean canUseWorkspaceView = workspaceView != null && workspaceView.isAttachedToWindow()
                 && workspaceView.getHeight() > 0;
 
-        mActivity.getRootView().setForceHideBackArrow(true);
+        mContainer.getRootView().setForceHideBackArrow(true);
         if (!TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
-            mActivity.setHintUserWillBeActive();
+            mContainer.setHintUserWillBeActive();
         }
 
         if (!canUseWorkspaceView || appCanEnterPip || mIsSwipeForSplit) {
@@ -106,10 +108,10 @@
 
     private HomeAnimationFactory createIconHomeAnimationFactory(View workspaceView) {
         RectF iconLocation = new RectF();
-        FloatingIconView floatingIconView = getFloatingIconView(mActivity, workspaceView, null,
-                mActivity.getTaskbarUIController() == null
+        FloatingIconView floatingIconView = getFloatingIconView(mContainer, workspaceView, null,
+                mContainer.getTaskbarUIController() == null
                         ? null
-                        : mActivity.getTaskbarUIController().findMatchingView(workspaceView),
+                        : mContainer.getTaskbarUIController().findMatchingView(workspaceView),
                 true /* hideOriginal */, iconLocation, false /* isOpening */);
 
         // We want the window alpha to be 0 once this threshold is met, so that the
@@ -169,7 +171,7 @@
         Size windowSize = new Size(crop.width(), crop.height());
         int fallbackBackgroundColor =
                 FloatingWidgetView.getDefaultBackgroundColor(mContext, runningTaskTarget);
-        FloatingWidgetView floatingWidgetView = FloatingWidgetView.getFloatingWidgetView(mActivity,
+        FloatingWidgetView floatingWidgetView = FloatingWidgetView.getFloatingWidgetView(mContainer,
                 hostView, backgroundLocation, windowSize, tvs.getCurrentCornerRadius(),
                 isTargetTranslucent, fallbackBackgroundColor);
 
@@ -246,7 +248,7 @@
             }
         }
 
-        return mActivity.getFirstMatchForAppClose(launchCookieItemId,
+        return mContainer.getFirstMatchForAppClose(launchCookieItemId,
                 runningTaskView.getTask().key.getComponent().getPackageName(),
                 UserHandle.of(runningTaskView.getTask().key.userId),
                 false /* supportsAllAppsState */);
@@ -290,15 +292,21 @@
             // Return an empty APC here since we have an non-user controlled animation
             // to home.
             long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
-            return mActivity.getStateManager().createAnimationToNewWorkspace(
+            return mContainer.getStateManager().createAnimationToNewWorkspace(
                     NORMAL, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS);
         }
 
         @Override
         public void playAtomicAnimation(float velocity) {
-            new StaggeredWorkspaceAnim(mActivity, velocity, true /* animateOverviewScrim */,
-                    getViewIgnoredInWorkspaceRevealAnimation())
-                    .start();
+            if (enableScalingRevealHomeAnimation()) {
+                if (mContainer != null) {
+                    new ScalingWorkspaceRevealAnim(mContainer).start();
+                }
+            } else {
+                new StaggeredWorkspaceAnim(mContainer, velocity, true /* animateOverviewScrim */,
+                        getViewIgnoredInWorkspaceRevealAnimation())
+                        .start();
+            }
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 65b5397..68923ee 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -40,6 +40,7 @@
 import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
 import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -191,7 +192,8 @@
      * Executes the task and returns true if next task can be executed. If false, then the next
      * task is deferred until {@link #scheduleNextTask} is called
      */
-    private <T extends StatefulActivity<?>> boolean executeCommand(CommandInfo cmd) {
+    private <T extends StatefulActivity<?> & RecentsViewContainer> boolean executeCommand(
+            CommandInfo cmd) {
         if (mWaitForToggleCommandComplete && cmd.type == TYPE_TOGGLE) {
             return true;
         }
@@ -200,7 +202,7 @@
         RecentsView visibleRecentsView = activityInterface.getVisibleRecentsView();
         RecentsView createdRecentsView;
         if (visibleRecentsView == null) {
-            T activity = activityInterface.getCreatedActivity();
+            T activity = activityInterface.getCreatedContainer();
             createdRecentsView = activity == null ? null : activity.getOverviewPanel();
             DeviceProfile dp = activity == null ? null : activity.getDeviceProfile();
             TaskbarUIController uiController = activityInterface.getTaskbarController();
@@ -248,7 +250,15 @@
                 case TYPE_SHOW:
                     // already visible
                     return true;
+                case TYPE_KEYBOARD_INPUT: {
+                    if (visibleRecentsView.isHandlingTouch()) {
+                        return true;
+                    }
+                }
                 case TYPE_HIDE: {
+                    if (visibleRecentsView.isHandlingTouch()) {
+                        return true;
+                    }
                     mKeyboardTaskFocusIndex = INVALID_PAGE;
                     int currentPage = visibleRecentsView.getNextPage();
                     TaskView tv = (currentPage >= 0
@@ -288,7 +298,7 @@
             return false;
         }
 
-        final T activity = activityInterface.getCreatedActivity();
+        final T activity = activityInterface.getCreatedContainer();
         if (activity != null) {
             InteractionJankMonitorWrapper.begin(
                     activity.getRootView(),
@@ -302,7 +312,7 @@
                 .newHandler(gestureState, cmd.createTime);
         interactionHandler.setGestureEndCallback(
                 () -> onTransitionComplete(cmd, interactionHandler));
-        interactionHandler.initWhenReady();
+        interactionHandler.initWhenReady("OverviewCommandHelper: cmd.type=" + cmd.type);
 
         RecentsAnimationListener recentAnimListener = new RecentsAnimationListener() {
             @Override
@@ -319,7 +329,7 @@
                 interactionHandler.onGestureCancelled();
                 cmd.removeListener(this);
 
-                T createdActivity = activityInterface.getCreatedActivity();
+                T createdActivity = activityInterface.getCreatedContainer();
                 if (createdActivity == null) {
                     return;
                 }
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index c3a4351..dfbae65 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -208,7 +208,7 @@
         RecentsAnimationDeviceState rads = new RecentsAnimationDeviceState(mContext);
         OverviewComponentObserver observer = new OverviewComponentObserver(mContext, rads);
         try {
-            return observer.getActivityInterface().getCreatedActivity();
+            return observer.getActivityInterface().getCreatedContainer();
         } finally {
             observer.onDestroy();
             rads.destroy();
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index f3704e09..879fccb 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -20,7 +20,7 @@
 
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.quickstep.util.SplitScreenUtils.convertShellSplitBoundsToLauncher;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 import static com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM;
 
 import android.app.ActivityManager;
@@ -270,9 +270,13 @@
 
         int numVisibleTasks = 0;
         for (GroupedRecentTaskInfo rawTask : rawTasks) {
-            if (isDesktopModeSupported() && rawTask.getType() == TYPE_FREEFORM) {
-                GroupTask desktopTask = createDesktopTask(rawTask);
-                allTasks.add(desktopTask);
+            if (rawTask.getType() == TYPE_FREEFORM) {
+                // TYPE_FREEFORM tasks is only created when enableDesktopWindowingMode() is true,
+                // leftover TYPE_FREEFORM tasks created when flag was on should be ignored.
+                if (enableDesktopWindowingMode()) {
+                    GroupTask desktopTask = createDesktopTask(rawTask);
+                    allTasks.add(desktopTask);
+                }
                 continue;
             }
             ActivityManager.RecentTaskInfo taskInfo1 = rawTask.getTaskInfo1();
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 02f9a69..f57f4c8 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -27,12 +27,13 @@
 import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
 import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
 import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.app.ActivityOptions;
+import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.os.Bundle;
@@ -85,6 +86,7 @@
 import com.android.quickstep.util.TISBindHelper;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskView;
 
 import java.io.FileDescriptor;
@@ -95,7 +97,8 @@
  * A recents activity that shows the recently launched tasks as swipable task cards.
  * See {@link com.android.quickstep.views.RecentsView}.
  */
-public final class RecentsActivity extends StatefulActivity<RecentsState> {
+public final class RecentsActivity extends StatefulActivity<RecentsState> implements
+        RecentsViewContainer {
     private static final String TAG = "RecentsActivity";
 
     public static final ActivityTracker<RecentsActivity> ACTIVITY_TRACKER =
@@ -109,7 +112,7 @@
     private RecentsDragLayer mDragLayer;
     private ScrimView mScrimView;
     private FallbackRecentsView mFallbackRecentsView;
-    private OverviewActionsView mActionsView;
+    private OverviewActionsView<?> mActionsView;
     private TISBindHelper mTISBindHelper;
     private @Nullable FallbackTaskbarUIController mTaskbarUIController;
 
@@ -144,7 +147,7 @@
                         systemUiProxy, RecentsModel.INSTANCE.get(this),
                         null /*activityBackCallback*/);
         mDragLayer.recreateControllers();
-        if (isDesktopModeSupported()) {
+        if (enableDesktopWindowingMode()) {
             mDesktopRecentsTransitionController = new DesktopRecentsTransitionController(
                     getStateManager(), systemUiProxy, getIApplicationThread(),
                     null /* depthController */
@@ -224,11 +227,12 @@
     }
 
     @Override
-    public <T extends View> T getOverviewPanel() {
-        return (T) mFallbackRecentsView;
+    public FallbackRecentsView getOverviewPanel() {
+        return mFallbackRecentsView;
     }
 
-    public OverviewActionsView getActionsView() {
+    @Override
+    public OverviewActionsView<?> getActionsView() {
         return mActionsView;
     }
 
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index c56a621..4b4f914 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -60,7 +60,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
 import com.android.launcher3.util.DisplayController.Info;
@@ -68,6 +67,7 @@
 import com.android.launcher3.util.SettingsCache;
 import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
 import com.android.quickstep.util.ActiveGestureLog;
+import com.android.quickstep.util.AssistStateManager;
 import com.android.quickstep.util.GestureExclusionManager;
 import com.android.quickstep.util.GestureExclusionManager.ExclusionListener;
 import com.android.quickstep.util.NavBarPosition;
@@ -97,7 +97,7 @@
     private final DisplayController mDisplayController;
 
     private final GestureExclusionManager mExclusionManager;
-
+    private final AssistStateManager mAssistStateManager;
 
     private final RotationTouchHelper mRotationTouchHelper;
     private final TaskStackChangeListener mPipListener;
@@ -148,6 +148,7 @@
         mContext = context;
         mDisplayController = DisplayController.INSTANCE.get(context);
         mExclusionManager = exclusionManager;
+        mAssistStateManager = AssistStateManager.INSTANCE.get(context);
         mIsOneHandedModeSupported = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
         mRotationTouchHelper = RotationTouchHelper.INSTANCE.get(context);
         if (isInstanceForTouches) {
@@ -588,9 +589,8 @@
                 : QUICKSTEP_TOUCH_SLOP_RATIO_TWO_BUTTON;
         float touchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
 
-        if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
-            float customSlopMultiplier =
-                    FeatureFlags.LPNH_SLOP_PERCENTAGE.get() / 100f;
+        if (mAssistStateManager.getLPNHCustomSlopMultiplier().isPresent()) {
+            float customSlopMultiplier = mAssistStateManager.getLPNHCustomSlopMultiplier().get();
             return customSlopMultiplier * slopMultiplier * touchSlop;
         } else {
             return slopMultiplier * touchSlop;
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
index 556dd7e..f936882 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java
@@ -17,7 +17,8 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
+
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 
 import android.app.WindowConfiguration;
 import android.graphics.Rect;
@@ -52,7 +53,7 @@
      * @return {@code true} if at least one target app is a desktop task
      */
     public boolean hasDesktopTasks() {
-        if (!isDesktopModeSupported()) {
+        if (!enableDesktopWindowingMode()) {
             return false;
         }
         for (RemoteAnimationTarget target : apps) {
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 6a9caf7..7f2aded 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -17,7 +17,6 @@
 package com.android.quickstep;
 
 import static com.android.quickstep.util.SplitScreenUtils.convertShellSplitBoundsToLauncher;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
 
 import android.app.WindowConfiguration;
@@ -58,7 +57,7 @@
     /**
      * Use this constructor if remote targets are split-screen independent
      */
-    public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy,
+    public RemoteTargetGluer(Context context, BaseContainerInterface sizingStrategy,
             RemoteAnimationTargets targets, boolean forDesktop) {
         init(context, sizingStrategy, targets.apps.length, forDesktop);
     }
@@ -67,18 +66,16 @@
      * Use this constructor if you want the number of handles created to match the number of active
      * running tasks
      */
-    public RemoteTargetGluer(Context context, BaseActivityInterface sizingStrategy) {
-        if (isDesktopModeSupported()) {
-            DesktopVisibilityController desktopVisibilityController =
-                    LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
-            if (desktopVisibilityController != null) {
-                int visibleTasksCount = desktopVisibilityController.getVisibleFreeformTasksCount();
-                if (visibleTasksCount > 0) {
-                    // Allocate +1 to account for a new task added to the desktop mode
-                    int numHandles = visibleTasksCount + 1;
-                    init(context, sizingStrategy, numHandles, true /* forDesktop */);
-                    return;
-                }
+    public RemoteTargetGluer(Context context, BaseContainerInterface sizingStrategy) {
+        DesktopVisibilityController desktopVisibilityController =
+                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+        if (desktopVisibilityController != null) {
+            int visibleTasksCount = desktopVisibilityController.getVisibleDesktopTasksCount();
+            if (visibleTasksCount > 0) {
+                // Allocate +1 to account for a new task added to the desktop mode
+                int numHandles = visibleTasksCount + 1;
+                init(context, sizingStrategy, numHandles, true /* forDesktop */);
+                return;
             }
         }
 
@@ -87,13 +84,13 @@
         init(context, sizingStrategy, DEFAULT_NUM_HANDLES, false /* forDesktop */);
     }
 
-    private void init(Context context, BaseActivityInterface sizingStrategy, int numHandles,
+    private void init(Context context, BaseContainerInterface sizingStrategy, int numHandles,
             boolean forDesktop) {
         mRemoteTargetHandles = createHandles(context, sizingStrategy, numHandles, forDesktop);
     }
 
     private RemoteTargetHandle[] createHandles(Context context,
-            BaseActivityInterface sizingStrategy, int numHandles, boolean forDesktop) {
+            BaseContainerInterface sizingStrategy, int numHandles, boolean forDesktop) {
         RemoteTargetHandle[] handles = new RemoteTargetHandle[numHandles];
         for (int i = 0; i < numHandles; i++) {
             TaskViewSimulator tvs = new TaskViewSimulator(context, sizingStrategy);
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 2d47097..bf50d70 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -345,14 +345,14 @@
     }
 
     void onEndTargetCalculated(GestureState.GestureEndTarget endTarget,
-            BaseActivityInterface activityInterface) {
+            BaseContainerInterface containerInterface) {
         if (endTarget == GestureState.GestureEndTarget.RECENTS) {
             mInOverview = true;
             if (!mTaskListFrozen) {
                 // If we're in landscape w/o ever quickswitching, show the navbar in landscape
                 enableMultipleRegions(true);
             }
-            activityInterface.onExitOverview(this, mExitOverviewRunnable);
+            containerInterface.onExitOverview(this, mExitOverviewRunnable);
         } else if (endTarget == GestureState.GestureEndTarget.HOME
                 || endTarget == GestureState.GestureEndTarget.ALL_APPS) {
             enableMultipleRegions(false);
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index b920c10..5ff9787 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -86,7 +86,7 @@
         updateIsGestureForSplit(TopTaskTracker.INSTANCE.get(context)
                 .getRunningSplitTaskIds().length);
 
-        mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getActivityInterface());
+        mTargetGluer = new RemoteTargetGluer(mContext, mGestureState.getContainerInterface());
         mRemoteTargetHandles = mTargetGluer.getRemoteTargetHandles();
         runActionOnRemoteHandles(remoteTargetHandle ->
                 remoteTargetHandle.getTaskViewSimulator().getOrientationState().update(
@@ -97,9 +97,10 @@
 
     protected void initTransitionEndpoints(DeviceProfile dp) {
         mDp = dp;
-        mTransitionDragLength = mGestureState.getActivityInterface().getSwipeUpDestinationAndLength(
-                dp, mContext, TEMP_RECT, mRemoteTargetHandles[0].getTaskViewSimulator()
-                        .getOrientationState().getOrientationHandler());
+        mTransitionDragLength = mGestureState.getContainerInterface()
+                .getSwipeUpDestinationAndLength(dp, mContext, TEMP_RECT,
+                        mRemoteTargetHandles[0].getTaskViewSimulator().getOrientationState()
+                                .getOrientationHandler());
         mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
 
         for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) {
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 72f67fc..30bb863 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -63,7 +63,6 @@
 import com.android.internal.logging.InstanceId;
 import com.android.internal.util.ScreenshotRequest;
 import com.android.internal.view.AppearanceRegion;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.Preconditions;
 import com.android.quickstep.util.ActiveGestureLog;
@@ -82,6 +81,7 @@
 import com.android.wm.shell.back.IBackAnimation;
 import com.android.wm.shell.bubbles.IBubbles;
 import com.android.wm.shell.bubbles.IBubblesListener;
+import com.android.wm.shell.common.bubbles.BubbleBarLocation;
 import com.android.wm.shell.common.pip.IPip;
 import com.android.wm.shell.common.pip.IPipAnimationListener;
 import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
@@ -91,13 +91,12 @@
 import com.android.wm.shell.onehanded.IOneHanded;
 import com.android.wm.shell.recents.IRecentTasks;
 import com.android.wm.shell.recents.IRecentTasksListener;
+import com.android.wm.shell.shared.IShellTransitions;
 import com.android.wm.shell.splitscreen.ISplitScreen;
 import com.android.wm.shell.splitscreen.ISplitScreenListener;
 import com.android.wm.shell.splitscreen.ISplitSelectListener;
 import com.android.wm.shell.startingsurface.IStartingWindow;
 import com.android.wm.shell.startingsurface.IStartingWindowListener;
-import com.android.wm.shell.transition.IHomeTransitionListener;
-import com.android.wm.shell.transition.IShellTransitions;
 import com.android.wm.shell.util.GroupedRecentTaskInfo;
 
 import java.io.PrintWriter;
@@ -157,7 +156,7 @@
     private IOnBackInvokedCallback mBackToLauncherCallback;
     private IRemoteAnimationRunner mBackToLauncherRunner;
     private IDragAndDrop mDragAndDrop;
-    private IHomeTransitionListener mHomeTransitionListener;
+    private final HomeVisibilityState mHomeVisibilityState = new HomeVisibilityState();
 
     // Used to dedupe calls to SystemUI
     private int mLastShelfHeight;
@@ -269,7 +268,7 @@
         setBubblesListener(mBubblesListener);
         registerSplitScreenListener(mSplitScreenListener);
         registerSplitSelectListener(mSplitSelectListener);
-        setHomeTransitionListener(mHomeTransitionListener);
+        mHomeVisibilityState.init(mShellTransitions);
         setStartingWindowListener(mStartingWindowListener);
         setLauncherUnlockAnimationController(
                 mLauncherActivityClass, mLauncherUnlockAnimationController);
@@ -455,6 +454,17 @@
     }
 
     @Override
+    public void setOverrideHomeButtonLongPress(long duration, float slopMultiplier) {
+        if (mSystemUiProxy != null) {
+            try {
+                mSystemUiProxy.setOverrideHomeButtonLongPress(duration, slopMultiplier);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call setOverrideHomeButtonLongPress", e);
+            }
+        }
+    }
+
+    @Override
     public void notifyAccessibilityButtonClicked(int displayId) {
         if (mSystemUiProxy != null) {
             try {
@@ -808,6 +818,32 @@
         }
     }
 
+    /**
+     * Tells SysUI to update the bubble bar location to the new location.
+     * @param location new location for the bubble bar
+     */
+    public void setBubbleBarLocation(BubbleBarLocation location) {
+        try {
+            mBubbles.setBubbleBarLocation(location);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed call setBubbleBarLocation");
+        }
+    }
+
+    /**
+     * Tells SysUI the bounds for the bubble bar
+     * @param bubbleBarBounds bounds of the bubble bar in display coordinates
+     */
+    public void setBubbleBarBounds(Rect bubbleBarBounds) {
+        try {
+            if (mBubbles != null) {
+                mBubbles.setBubbleBarBounds(bubbleBarBounds);
+            }
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed call setBubbleBarBounds");
+        }
+    }
+
     //
     // Splitscreen
     //
@@ -1102,22 +1138,8 @@
         mRemoteTransitions.remove(remoteTransition);
     }
 
-    public void setHomeTransitionListener(IHomeTransitionListener listener) {
-        if (!FeatureFlags.enableHomeTransitionListener()) {
-            return;
-        }
-
-        mHomeTransitionListener = listener;
-
-        if (mShellTransitions != null) {
-            try {
-                mShellTransitions.setHomeTransitionListener(listener);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed call setHomeTransitionListener", e);
-            }
-        } else  {
-            Log.w(TAG, "Unable to call setHomeTransitionListener because ShellTransitions is null");
-        }
+    public HomeVisibilityState getHomeVisibilityState() {
+        return mHomeVisibilityState;
     }
 
     /**
@@ -1453,6 +1475,17 @@
         }
     }
 
+    /** Call shell to move a task with given `taskId` to desktop  */
+    public void moveToDesktop(int taskId) {
+        if (mDesktopMode != null) {
+            try {
+                mDesktopMode.moveToDesktop(taskId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call moveToDesktop", e);
+            }
+        }
+    }
+
     //
     // Unfold transition
     //
@@ -1558,7 +1591,7 @@
         pw.println("\tmSplitSelectListener=" + mSplitSelectListener);
         pw.println("\tmOneHanded=" + mOneHanded);
         pw.println("\tmShellTransitions=" + mShellTransitions);
-        pw.println("\tmHomeTransitionListener=" + mHomeTransitionListener);
+        pw.println("\tmHomeVisibilityState=" + mHomeVisibilityState);
         pw.println("\tmStartingWindow=" + mStartingWindow);
         pw.println("\tmStartingWindowListener=" + mStartingWindowListener);
         pw.println("\tmSysuiUnlockAnimationController=" + mSysuiUnlockAnimationController);
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 4e62d60..3b1ed46 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -77,10 +77,11 @@
                         mLiveTileRestartListener);
                 return;
             }
-            BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
-            if (activityInterface.isInLiveTileMode()
-                    && activityInterface.getCreatedActivity() != null) {
-                RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
+            BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface();
+            if (containerInterface.isInLiveTileMode()
+                    && containerInterface.getCreatedContainer() != null) {
+                RecentsView recentsView = containerInterface.getCreatedContainer()
+                        .getOverviewPanel();
                 if (recentsView != null) {
                     recentsView.launchSideTaskInLiveTileModeForRestartedApp(task.taskId);
                     TaskStackChangeListeners.getInstance().unregisterTaskStackListener(
@@ -135,10 +136,10 @@
             cleanUpRecentsAnimation(mCallbacks);
         }
 
-        final BaseActivityInterface activityInterface = gestureState.getActivityInterface();
+        final BaseContainerInterface containerInterface = gestureState.getContainerInterface();
         mLastGestureState = gestureState;
         RecentsAnimationCallbacks newCallbacks = new RecentsAnimationCallbacks(
-                SystemUiProxy.INSTANCE.get(mCtx), activityInterface.allowMinimizeSplitScreen());
+                SystemUiProxy.INSTANCE.get(mCtx), containerInterface.allowMinimizeSplitScreen());
         mCallbacks = newCallbacks;
         mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() {
             @Override
@@ -208,17 +209,18 @@
             @Override
             public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) {
                 RemoteAnimationTarget appearedTaskTarget = appearedTaskTargets[0];
-                BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
+                BaseContainerInterface containerInterface =
+                        mLastGestureState.getContainerInterface();
 
                 for (RemoteAnimationTarget compat : appearedTaskTargets) {
                     if (compat.windowConfiguration.getActivityType() == ACTIVITY_TYPE_HOME
-                            && activityInterface.getCreatedActivity() instanceof RecentsActivity
+                            && containerInterface.getCreatedContainer() instanceof RecentsActivity
                             && DisplayController.getNavigationMode(mCtx) != NO_BUTTON) {
                         // The only time we get onTasksAppeared() in button navigation with a
                         // 3p launcher is if the user goes to overview first, and in this case we
                         // can immediately finish the transition
                         RecentsView recentsView =
-                                activityInterface.getCreatedActivity().getOverviewPanel();
+                                containerInterface.getCreatedContainer().getOverviewPanel();
                         if (recentsView != null) {
                             recentsView.finishRecentsAnimation(true, null);
                         }
@@ -232,12 +234,12 @@
                 if (nonAppTargets == null) {
                     nonAppTargets = new RemoteAnimationTarget[0];
                 }
-                if ((activityInterface.isInLiveTileMode()
+                if ((containerInterface.isInLiveTileMode()
                             || mLastGestureState.getEndTarget() == RECENTS
                             || isNonRecentsStartedTasksAppeared(appearedTaskTargets))
-                        && activityInterface.getCreatedActivity() != null) {
+                        && containerInterface.getCreatedContainer() != null) {
                     RecentsView recentsView =
-                            activityInterface.getCreatedActivity().getOverviewPanel();
+                            containerInterface.getCreatedContainer().getOverviewPanel();
                     if (recentsView != null) {
                         ActiveGestureLog.INSTANCE.addLog(
                                 new ActiveGestureLog.CompoundString("Launching side task id=")
@@ -272,13 +274,13 @@
 
             @Override
             public boolean onSwitchToScreenshot(Runnable onFinished) {
-                if (!activityInterface.isInLiveTileMode()
-                        || activityInterface.getCreatedActivity() == null) {
+                if (!containerInterface.isInLiveTileMode()
+                        || containerInterface.getCreatedContainer() == null) {
                     // No need to switch since tile is already a screenshot.
                     onFinished.run();
                 } else {
                     final RecentsView recentsView =
-                            activityInterface.getCreatedActivity().getOverviewPanel();
+                            containerInterface.getCreatedContainer().getOverviewPanel();
                     if (recentsView != null) {
                         recentsView.switchToScreenshot(onFinished);
                     } else {
@@ -295,7 +297,7 @@
         if (ENABLE_SHELL_TRANSITIONS) {
             final ActivityOptions options = ActivityOptions.makeBasic();
             // Use regular (non-transient) launch for all apps page to control IME.
-            if (!activityInterface.allowAllAppsFromOverview()) {
+            if (!containerInterface.allowAllAppsFromOverview()) {
                 options.setTransientLaunch();
             }
             options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
@@ -332,10 +334,10 @@
         if (mLastGestureState == null) {
             return;
         }
-        BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
-        if (activityInterface.isInLiveTileMode()
-                && activityInterface.getCreatedActivity() != null) {
-            RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
+        BaseContainerInterface containerInterface = mLastGestureState.getContainerInterface();
+        if (containerInterface.isInLiveTileMode()
+                && containerInterface.getCreatedContainer() != null) {
+            RecentsView recentsView = containerInterface.getCreatedContainer().getOverviewPanel();
             if (recentsView != null) {
                 recentsView.switchToScreenshot(null,
                         () -> recentsView.finishRecentsAnimation(true /* toRecents */,
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index cc582d1..18b8e3e 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -33,7 +33,6 @@
 import androidx.annotation.RequiresApi;
 
 import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 import com.android.launcher3.model.data.ItemInfo;
@@ -46,6 +45,7 @@
 import com.android.quickstep.views.GroupedTaskView;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskThumbnailView;
 import com.android.quickstep.views.TaskView;
 import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
@@ -63,14 +63,15 @@
     public static List<SystemShortcut> getEnabledShortcuts(TaskView taskView,
             TaskIdAttributeContainer taskContainer) {
         final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
-        final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
+        final RecentsViewContainer container =
+                RecentsViewContainer.containerFromContext(taskView.getContext());
         boolean hasMultipleTasks = taskView.getTaskIds()[1] != -1;
         for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
             if (hasMultipleTasks && !menuOption.showForSplitscreen()) {
                 continue;
             }
 
-            List<SystemShortcut> menuShortcuts = menuOption.getShortcuts(activity, taskContainer);
+            List<SystemShortcut> menuShortcuts = menuOption.getShortcuts(container, taskContainer);
             if (menuShortcuts == null) {
                 continue;
             }
@@ -79,15 +80,16 @@
         RecentsOrientedState orientedState = taskView.getRecentsView().getPagedViewOrientedState();
         boolean canLauncherRotate = orientedState.isRecentsActivityRotationAllowed();
         boolean isInLandscape = orientedState.getTouchRotation() != ROTATION_0;
-        boolean isTablet = activity.getDeviceProfile().isTablet;
+        boolean isTablet = container.getDeviceProfile().isTablet;
 
         boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
-        // Add overview actions to the menu when in in-place rotate landscape mode, or in
-        // grid-only overview.
-        if ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview) {
+        // Add overview actions to the menu when:
+        // - single task is showing
+        // - in in-place rotate landscape mode, or in grid-only overview.
+        if (!hasMultipleTasks && ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview)) {
             // Add screenshot action to task menu.
             List<SystemShortcut> screenshotShortcuts = TaskShortcutFactory.SCREENSHOT
-                    .getShortcuts(activity, taskContainer);
+                    .getShortcuts(container, taskContainer);
             if (screenshotShortcuts != null) {
                 shortcuts.addAll(screenshotShortcuts);
             }
@@ -96,7 +98,7 @@
             // or in grid-only overview.
             if (orientedState.getDisplayRotation() == ROTATION_0 || isGridOnlyOverview) {
                 List<SystemShortcut> modalShortcuts = TaskShortcutFactory.MODAL
-                        .getShortcuts(activity, taskContainer);
+                        .getShortcuts(container, taskContainer);
                 if (modalShortcuts != null) {
                     shortcuts.addAll(modalShortcuts);
                 }
@@ -136,6 +138,7 @@
             TaskShortcutFactory.PIN,
             TaskShortcutFactory.INSTALL,
             TaskShortcutFactory.FREE_FORM,
+            DesktopSystemShortcut.Companion.createFactory(),
             TaskShortcutFactory.WELLBEING,
             TaskShortcutFactory.SAVE_APP_PAIR
     };
@@ -253,9 +256,9 @@
         /**
          * Gets the system shortcut for the screenshot that will be added to the task menu.
          */
-        public SystemShortcut getScreenshotShortcut(BaseDraggingActivity activity,
+        public SystemShortcut getScreenshotShortcut(RecentsViewContainer container,
                 ItemInfo iteminfo, View originalView) {
-            return new ScreenshotSystemShortcut(activity, iteminfo, originalView);
+            return new ScreenshotSystemShortcut(container, iteminfo, originalView);
         }
 
         /**
@@ -303,19 +306,19 @@
 
         private class ScreenshotSystemShortcut extends SystemShortcut {
 
-            private final BaseDraggingActivity mActivity;
+            private final RecentsViewContainer mContainer;
 
-            ScreenshotSystemShortcut(BaseDraggingActivity activity, ItemInfo itemInfo,
+            ScreenshotSystemShortcut(RecentsViewContainer container, ItemInfo itemInfo,
                     View originalView) {
-                super(R.drawable.ic_screenshot, R.string.action_screenshot, activity, itemInfo,
+                super(R.drawable.ic_screenshot, R.string.action_screenshot, container, itemInfo,
                         originalView);
-                mActivity = activity;
+                mContainer = container;
             }
 
             @Override
             public void onClick(View view) {
                 saveScreenshot(mThumbnailView.getTaskView().getTask());
-                dismissTaskMenuView(mActivity);
+                dismissTaskMenuView();
             }
         }
 
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index daa6168..9d10ac1 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -20,9 +20,8 @@
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 
-import android.app.Activity;
 import android.app.ActivityOptions;
 import android.graphics.Bitmap;
 import android.graphics.Color;
@@ -39,19 +38,21 @@
 
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
 import com.android.launcher3.model.WellbeingModel;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
 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.SplitPositionOption;
+import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.views.GroupedTaskView;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.TaskThumbnailView;
 import com.android.quickstep.views.TaskView;
 import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
@@ -61,6 +62,7 @@
 import com.android.systemui.shared.recents.view.RecentsTransition;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.function.Function;
@@ -72,7 +74,7 @@
  */
 public interface TaskShortcutFactory {
     @Nullable
-    default List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+    default List<SystemShortcut> getShortcuts(RecentsViewContainer container,
             TaskIdAttributeContainer taskContainer) {
         return null;
     }
@@ -92,7 +94,7 @@
 
     TaskShortcutFactory APP_INFO = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
             TaskView taskView = taskContainer.getTaskView();
             AppInfo.SplitAccessibilityInfo accessibilityInfo =
@@ -100,7 +102,7 @@
                             TaskUtils.getTitle(taskView.getContext(), taskContainer.getTask()),
                             taskContainer.getA11yNodeId()
                     );
-            return Collections.singletonList(new AppInfo(activity, taskContainer.getItemInfo(),
+            return Collections.singletonList(new AppInfo(container, taskContainer.getItemInfo(),
                     taskView, accessibilityInfo));
         }
 
@@ -114,9 +116,9 @@
         private final TaskView mTaskView;
         private final SplitPositionOption mSplitPositionOption;
 
-        public SplitSelectSystemShortcut(BaseDraggingActivity target, TaskView taskView,
+        public SplitSelectSystemShortcut(RecentsViewContainer container, TaskView taskView,
                 SplitPositionOption option) {
-            super(option.iconResId, option.textResId, target, taskView.getItemInfo(), taskView);
+            super(option.iconResId, option.textResId, container, taskView.getItemInfo(), taskView);
             mTaskView = taskView;
             mSplitPositionOption = option;
         }
@@ -131,25 +133,26 @@
      * A menu item, "Save app pair", that allows the user to preserve the current app combination as
      * one persistent icon on the Home screen, allowing for quick split screen launching.
      */
-    class SaveAppPairSystemShortcut extends SystemShortcut<BaseDraggingActivity> {
+    class SaveAppPairSystemShortcut extends SystemShortcut<RecentsViewContainer> {
         private final GroupedTaskView mTaskView;
 
-        public SaveAppPairSystemShortcut(BaseDraggingActivity activity, GroupedTaskView taskView,
-                int iconResId) {
-            super(iconResId, R.string.save_app_pair, activity,
+
+        public SaveAppPairSystemShortcut(RecentsViewContainer container, GroupedTaskView taskView,
+            int iconResId) {
+                super(iconResId, R.string.save_app_pair, container,
                     taskView.getItemInfo(), taskView);
             mTaskView = taskView;
         }
 
         @Override
         public void onClick(View view) {
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             ((RecentsView) mTarget.getOverviewPanel())
                     .getSplitSelectController().getAppPairsController().saveAppPair(mTaskView);
         }
     }
 
-    class FreeformSystemShortcut extends SystemShortcut<BaseDraggingActivity> {
+    class FreeformSystemShortcut extends SystemShortcut<RecentsViewContainer> {
         private static final String TAG = "FreeformSystemShortcut";
 
         private Handler mHandler;
@@ -159,20 +162,20 @@
         private final TaskView mTaskView;
         private final LauncherEvent mLauncherEvent;
 
-        public FreeformSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity,
+        public FreeformSystemShortcut(int iconRes, int textRes, RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer, LauncherEvent launcherEvent) {
-            super(iconRes, textRes, activity, taskContainer.getItemInfo(),
+            super(iconRes, textRes, container, taskContainer.getItemInfo(),
                     taskContainer.getTaskView());
             mLauncherEvent = launcherEvent;
             mHandler = new Handler(Looper.getMainLooper());
             mTaskView = taskContainer.getTaskView();
-            mRecentsView = activity.getOverviewPanel();
+            mRecentsView = container.getOverviewPanel();
             mThumbnailView = taskContainer.getThumbnailView();
         }
 
         @Override
         public void onClick(View view) {
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             RecentsView rv = mTarget.getOverviewPanel();
             rv.switchToScreenshot(() -> {
                 rv.finishRecentsAnimation(true /* toRecents */, false /* shouldPip */, () -> {
@@ -250,11 +253,11 @@
             }
         }
 
-        private ActivityOptions makeLaunchOptions(Activity activity) {
+        private ActivityOptions makeLaunchOptions(RecentsViewContainer container) {
             ActivityOptions activityOptions = ActivityOptions.makeBasic();
             activityOptions.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM);
             // Arbitrary bounds only because freeform is in dev mode right now
-            final View decorView = activity.getWindow().getDecorView();
+            final View decorView = container.getWindow().getDecorView();
             final WindowInsets insets = decorView.getRootWindowInsets();
             final Rect r = new Rect(0, 0, decorView.getWidth() / 2, decorView.getHeight() / 2);
             r.offsetTo(insets.getSystemWindowInsetLeft() + 50,
@@ -275,9 +278,9 @@
      */
     TaskShortcutFactory SPLIT_SELECT = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
-            DeviceProfile deviceProfile = activity.getDeviceProfile();
+            DeviceProfile deviceProfile = container.getDeviceProfile();
             final Task task = taskContainer.getTask();
             final int intentFlags = task.key.baseIntent.getFlags();
             final TaskView taskView = taskContainer.getTaskView();
@@ -289,7 +292,7 @@
                     !deviceProfile.isTaskbarPresent && recentsView.getTaskViewCount() < 2;
             boolean isTaskSplitNotSupported = !task.isDockable ||
                     (intentFlags & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
-            boolean hideForExistingMultiWindow = activity.getDeviceProfile().isMultiWindowMode;
+            boolean hideForExistingMultiWindow = container.getDeviceProfile().isMultiWindowMode;
             boolean isFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
             boolean isTaskInExpectedScrollPosition =
                     recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
@@ -302,7 +305,7 @@
             return orientationHandler.getSplitPositionOptions(deviceProfile)
                     .stream()
                     .map((Function<SplitPositionOption, SystemShortcut>) option ->
-                            new SplitSelectSystemShortcut(activity, taskView, option))
+                            new SplitSelectSystemShortcut(container, taskView, option))
                     .collect(Collectors.toList());
         }
     };
@@ -310,9 +313,9 @@
     TaskShortcutFactory SAVE_APP_PAIR = new TaskShortcutFactory() {
         @Nullable
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
-            DeviceProfile deviceProfile = activity.getDeviceProfile();
+            DeviceProfile deviceProfile = container.getDeviceProfile();
             final TaskView taskView = taskContainer.getTaskView();
             final RecentsView recentsView = taskView.getRecentsView();
             boolean isLargeTileFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
@@ -320,16 +323,24 @@
                     recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
             boolean shouldShowActionsButtonInstead =
                     isLargeTileFocusedTask && isInExpectedScrollPosition;
+            boolean hasUnpinnableApp = Arrays.stream(taskView.getTaskIdAttributeContainers())
+                    .anyMatch(att -> att != null && att.getItemInfo() != null
+                            && ((att.getItemInfo().runtimeStatusFlags
+                                & ItemInfoWithIcon.FLAG_NOT_PINNABLE) != 0));
 
             // No "save app pair" menu item if:
             // - app pairs feature is not enabled
             // - we are in 3p launcher
             // - the task in question is a single task
+            // - at least one app in app pair is unpinnable
             // - the Overview Actions Button should be visible
+            // - the task is not a GroupedTaskView
             if (!FeatureFlags.enableAppPairs()
                     || !recentsView.supportsAppPairs()
                     || !taskView.containsMultipleTasks()
-                    || shouldShowActionsButtonInstead) {
+                    || hasUnpinnableApp
+                    || shouldShowActionsButtonInstead
+                    || !(taskView instanceof GroupedTaskView)) {
                 return null;
             }
 
@@ -338,7 +349,8 @@
                     : R.drawable.ic_save_app_pair_up_down;
 
             return Collections.singletonList(
-                    new SaveAppPairSystemShortcut(activity, (GroupedTaskView) taskView, iconResId));
+                    new SaveAppPairSystemShortcut(container,
+                            (GroupedTaskView) taskView, iconResId));
         }
 
         @Override
@@ -349,35 +361,35 @@
 
     TaskShortcutFactory FREE_FORM = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
             final Task task = taskContainer.getTask();
             if (!task.isDockable) {
                 return null;
             }
-            if (!isAvailable(activity, task.key.displayId)) {
+            if (!isAvailable(container)) {
                 return null;
             }
 
             return Collections.singletonList(new FreeformSystemShortcut(
                     R.drawable.ic_caption_desktop_button_foreground,
-                    R.string.recent_task_option_freeform, activity, taskContainer,
+                    R.string.recent_task_option_freeform, container, taskContainer,
                     LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP));
         }
 
-        private boolean isAvailable(BaseDraggingActivity activity, int displayId) {
+        private boolean isAvailable(RecentsViewContainer container) {
             return Settings.Global.getInt(
-                    activity.getContentResolver(),
+                    container.asContext().getContentResolver(),
                     Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0
-                    && !isDesktopModeSupported();
+                    && !enableDesktopWindowingMode();
         }
     };
 
     TaskShortcutFactory PIN = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
-            if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
+            if (!SystemUiProxy.INSTANCE.get(container.asContext()).isActive()) {
                 return null;
             }
             if (!ActivityManagerWrapper.getInstance().isScreenPinningEnabled()) {
@@ -387,17 +399,17 @@
                 // We shouldn't be able to pin while an app is locked.
                 return null;
             }
-            return Collections.singletonList(new PinSystemShortcut(activity, taskContainer));
+            return Collections.singletonList(new PinSystemShortcut(container, taskContainer));
         }
     };
 
-    class PinSystemShortcut extends SystemShortcut<BaseDraggingActivity> {
+    class PinSystemShortcut extends SystemShortcut<RecentsViewContainer> {
 
         private static final String TAG = "PinSystemShortcut";
 
         private final TaskView mTaskView;
 
-        public PinSystemShortcut(BaseDraggingActivity target,
+        public PinSystemShortcut(RecentsViewContainer target,
                 TaskIdAttributeContainer taskContainer) {
             super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
                     taskContainer.getItemInfo(), taskContainer.getTaskView());
@@ -407,10 +419,10 @@
         @Override
         public void onClick(View view) {
             if (mTaskView.launchTaskAnimated() != null) {
-                SystemUiProxy.INSTANCE.get(mTarget).startScreenPinning(
+                SystemUiProxy.INSTANCE.get(mTarget.asContext()).startScreenPinning(
                         mTaskView.getTask().key.id);
             }
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             mTarget.getStatsLogManager().logger().withItemInfo(mTaskView.getItemInfo())
                     .log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_PIN_TAP);
         }
@@ -418,12 +430,12 @@
 
     TaskShortcutFactory INSTALL = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
             Task t = taskContainer.getTask();
-            return InstantAppResolver.newInstance(activity).isInstantApp(
+            return InstantAppResolver.newInstance(container.asContext()).isInstantApp(
                     t.getTopComponent().getPackageName(), t.getKey().userId)
-                    ? Collections.singletonList(new SystemShortcut.Install(activity,
+                    ? Collections.singletonList(new SystemShortcut.Install(container,
                     taskContainer.getItemInfo(), taskContainer.getTaskView()))
                     : null;
         }
@@ -431,10 +443,10 @@
 
     TaskShortcutFactory WELLBEING = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
-            SystemShortcut<BaseDraggingActivity> wellbeingShortcut =
-                    WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity,
+            SystemShortcut<ActivityContext> wellbeingShortcut =
+                    WellbeingModel.SHORTCUT_FACTORY.getShortcut(container,
                             taskContainer.getItemInfo(), taskContainer.getTaskView());
             return createSingletonShortcutList(wellbeingShortcut);
         }
@@ -442,11 +454,11 @@
 
     TaskShortcutFactory SCREENSHOT = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
             SystemShortcut screenshotShortcut =
                     taskContainer.getThumbnailView().getTaskOverlay()
-                            .getScreenshotShortcut(activity, taskContainer.getItemInfo(),
+                            .getScreenshotShortcut(container, taskContainer.getItemInfo(),
                                     taskContainer.getTaskView());
             return createSingletonShortcutList(screenshotShortcut);
         }
@@ -454,7 +466,7 @@
 
     TaskShortcutFactory MODAL = new TaskShortcutFactory() {
         @Override
-        public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
+        public List<SystemShortcut> getShortcuts(RecentsViewContainer container,
                 TaskIdAttributeContainer taskContainer) {
             SystemShortcut modalStateSystemShortcut =
                     taskContainer.getThumbnailView().getTaskOverlay()
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 8d4255c..450e960 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -38,7 +38,6 @@
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.quickstep.util.AnimUtils.clampToDuration;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -183,7 +182,7 @@
             // Re-use existing handles
             remoteTargetHandles = recentsViewHandles;
         } else {
-            boolean forDesktop = isDesktopModeSupported() && v instanceof DesktopTaskView;
+            boolean forDesktop = v instanceof DesktopTaskView;
             RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(),
                     recentsView.getSizeStrategy(), targets, forDesktop);
             if (forDesktop) {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 7880124..7035d6e 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -31,6 +31,7 @@
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TRACKPAD_GESTURE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.OnboardingPrefs.HOME_BOUNCE_SEEN;
 import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH;
 import static com.android.quickstep.GestureState.DEFAULT_STATE;
@@ -59,14 +60,12 @@
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW;
 
 import android.app.PendingIntent;
-import android.app.RemoteAction;
 import android.app.Service;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Region;
-import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
@@ -77,7 +76,6 @@
 import android.view.InputDevice;
 import android.view.InputEvent;
 import android.view.MotionEvent;
-import android.view.accessibility.AccessibilityManager;
 
 import androidx.annotation.BinderThread;
 import androidx.annotation.NonNull;
@@ -88,7 +86,6 @@
 import com.android.launcher3.ConstantItem;
 import com.android.launcher3.EncryptionType;
 import com.android.launcher3.LauncherPrefs;
-import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.provider.RestoreDbTask;
@@ -98,10 +95,8 @@
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.ResourceUtils;
 import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.uioverrides.flags.FlagsFactory;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 import com.android.launcher3.util.DisplayController;
-import com.android.launcher3.util.Executors;
 import com.android.launcher3.util.LockedUserState;
 import com.android.launcher3.util.SafeCloseable;
 import com.android.launcher3.util.ScreenOnTracker;
@@ -124,6 +119,7 @@
 import com.android.quickstep.util.ActiveGestureLog.CompoundString;
 import com.android.quickstep.util.AssistStateManager;
 import com.android.quickstep.util.AssistUtils;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -139,9 +135,9 @@
 import com.android.wm.shell.draganddrop.IDragAndDrop;
 import com.android.wm.shell.onehanded.IOneHanded;
 import com.android.wm.shell.recents.IRecentTasks;
+import com.android.wm.shell.shared.IShellTransitions;
 import com.android.wm.shell.splitscreen.ISplitScreen;
 import com.android.wm.shell.startingsurface.IStartingWindow;
-import com.android.wm.shell.transition.IShellTransitions;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -321,7 +317,7 @@
         public void enterStageSplitFromRunningApp(boolean leftOrTop) {
             executeForTouchInteractionService(tis -> {
                 StatefulActivity activity =
-                        tis.mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
+                        tis.mOverviewComponentObserver.getActivityInterface().getCreatedContainer();
                 if (activity != null) {
                     activity.enterStageSplitFromRunningApp(leftOrTop);
                 }
@@ -446,8 +442,10 @@
 
         /** Refreshes the current overview target. */
         public void refreshOverviewTarget() {
-            executeForTouchInteractionService(tis -> tis.onOverviewTargetChange(
-                    tis.mOverviewComponentObserver.isHomeAndOverviewSame()));
+            executeForTouchInteractionService(tis -> {
+                tis.mAllAppsActionManager.onDestroy();
+                tis.onOverviewTargetChange(tis.mOverviewComponentObserver.isHomeAndOverviewSame());
+            });
         }
     }
 
@@ -488,6 +486,7 @@
 
     private TaskbarManager mTaskbarManager;
     private Function<GestureState, AnimatedFloat> mSwipeUpProxyProvider = i -> null;
+    private AllAppsActionManager mAllAppsActionManager;
 
     @Override
     public void onCreate() {
@@ -497,7 +496,9 @@
         mMainChoreographer = Choreographer.getInstance();
         mAM = ActivityManagerWrapper.getInstance();
         mDeviceState = new RecentsAnimationDeviceState(this, true);
-        mTaskbarManager = new TaskbarManager(this);
+        mAllAppsActionManager = new AllAppsActionManager(
+                this, UI_HELPER_EXECUTOR, this::createAllAppsPendingIntent);
+        mTaskbarManager = new TaskbarManager(this, mAllAppsActionManager);
         mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
         mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
         BootAwarePreloader.start(this);
@@ -590,52 +591,34 @@
     }
 
     private void onOverviewTargetChange(boolean isHomeAndOverviewSame) {
-        Executors.UI_HELPER_EXECUTOR.execute(() -> {
-            AccessibilityManager am = getSystemService(AccessibilityManager.class);
-
-            if (isHomeAndOverviewSame) {
-                am.registerSystemAction(
-                        createAllAppsAction(), GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
-            } else {
-                am.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
-            }
-        });
+        mAllAppsActionManager.setHomeAndOverviewSame(isHomeAndOverviewSame);
 
         StatefulActivity newOverviewActivity = mOverviewComponentObserver.getActivityInterface()
-                .getCreatedActivity();
+                .getCreatedContainer();
         if (newOverviewActivity != null) {
             mTaskbarManager.setActivity(newOverviewActivity);
         }
         mTISBinder.onOverviewTargetChange();
     }
 
-    private RemoteAction createAllAppsAction() {
-        final Intent homeIntent = new Intent(mOverviewComponentObserver.getHomeIntent())
-                .setAction(INTENT_ACTION_ALL_APPS_TOGGLE);
-        final PendingIntent actionPendingIntent;
-
+    private PendingIntent createAllAppsPendingIntent() {
         if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
-            actionPendingIntent = new PendingIntent(new IIntentSender.Stub() {
+            return new PendingIntent(new IIntentSender.Stub() {
                 @Override
                 public void send(int code, Intent intent, String resolvedType,
                         IBinder allowlistToken, IIntentReceiver finishedReceiver,
                         String requiredPermission, Bundle options) {
-                    MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps(homeIntent));
+                    MAIN_EXECUTOR.execute(() -> mTaskbarManager.toggleAllApps());
                 }
             });
         } else {
-            actionPendingIntent = PendingIntent.getActivity(
+            return PendingIntent.getActivity(
                     this,
                     GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
-                    homeIntent,
+                    new Intent(mOverviewComponentObserver.getHomeIntent())
+                            .setAction(INTENT_ACTION_ALL_APPS_TOGGLE),
                     PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
         }
-
-        return new RemoteAction(
-                Icon.createWithResource(this, R.drawable.ic_apps),
-                getString(R.string.all_apps_label),
-                getString(R.string.all_apps_label),
-                actionPendingIntent);
     }
 
     @UiThread
@@ -678,8 +661,7 @@
         mDeviceState.destroy();
         SystemUiProxy.INSTANCE.get(this).clearProxy();
 
-        getSystemService(AccessibilityManager.class)
-                .unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
+        mAllAppsActionManager.onDestroy();
 
         mTaskbarManager.destroy();
         sConnected = false;
@@ -754,6 +736,10 @@
 
             boolean isOneHandedModeActive = mDeviceState.isOneHandedModeActive();
             boolean isInSwipeUpTouchRegion = mRotationTouchHelper.isInSwipeUpTouchRegion(event);
+            TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
+            if (isInSwipeUpTouchRegion && tac != null) {
+                tac.closeKeyboardQuickSwitchView();
+            }
             if ((!isOneHandedModeActive && isInSwipeUpTouchRegion)
                     || isHoverActionWithoutConsumer) {
                 reasonString.append(!isOneHandedModeActive && isInSwipeUpTouchRegion
@@ -842,8 +828,8 @@
             }
         }
 
-        boolean cancelGesture = mGestureState.getActivityInterface() != null
-                && mGestureState.getActivityInterface().shouldCancelCurrentGesture();
+        boolean cancelGesture = mGestureState.getContainerInterface() != null
+                && mGestureState.getContainerInterface().shouldCancelCurrentGesture();
         boolean cleanUpConsumer = (action == ACTION_UP || action == ACTION_CANCEL || cancelGesture)
                 && mConsumer != null
                 && !mConsumer.getActiveConsumerInHierarchy().isConsumerDetachedFromGesture();
@@ -1160,7 +1146,7 @@
 
         TopTaskTracker.CachedTaskInfo runningTask = gestureState.getRunningTask();
         // Use overview input consumer for sharesheets on top of home.
-        boolean forceOverviewInputConsumer = gestureState.getActivityInterface().isStarted()
+        boolean forceOverviewInputConsumer = gestureState.getContainerInterface().isStarted()
                 && runningTask != null
                 && runningTask.isRootChooseActivity();
 
@@ -1184,7 +1170,7 @@
         // with shell-transitions, home is resumed during recents animation, so
         // explicitly check against recents animation too.
         boolean launcherResumedThroughShellTransition =
-                gestureState.getActivityInterface().isResumed()
+                gestureState.getContainerInterface().isResumed()
                         && !previousGestureState.isRecentsAnimationRunning();
         // If a task fragment within Launcher is resumed
         boolean launcherChildActivityResumed = useActivityOverlay()
@@ -1194,7 +1180,7 @@
                 && !launcherResumedThroughShellTransition
                 && !previousGestureState.isRecentsAnimationRunning();
 
-        if (gestureState.getActivityInterface().isInLiveTileMode()) {
+        if (gestureState.getContainerInterface().isInLiveTileMode()) {
             return createOverviewInputConsumer(
                     previousGestureState,
                     gestureState,
@@ -1242,7 +1228,7 @@
 
         final AbsSwipeUpHandler.Factory factory = getSwipeUpHandlerFactory();
         final boolean shouldDefer = !mOverviewComponentObserver.isHomeAndOverviewSame()
-                || gestureState.getActivityInterface().deferStartingActivity(mDeviceState, event);
+                || gestureState.getContainerInterface().deferStartingActivity(mDeviceState, event);
         final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
         return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
                 gestureState, shouldDefer, this::onConsumerInactive,
@@ -1276,18 +1262,19 @@
             MotionEvent event,
             boolean forceOverviewInputConsumer,
             CompoundString reasonString) {
-        StatefulActivity activity = gestureState.getActivityInterface().getCreatedActivity();
-        if (activity == null) {
+        RecentsViewContainer container = gestureState.getContainerInterface().getCreatedContainer();
+        if (container == null) {
             return getDefaultInputConsumer(
                     reasonString.append(SUBSTRING_PREFIX)
                             .append("activity == null, trying to use default input consumer"));
         }
 
-        boolean hasWindowFocus = activity.getRootView().hasWindowFocus();
+        boolean hasWindowFocus = container.getRootView().hasWindowFocus();
         boolean isPreviousGestureAnimatingToLauncher =
                 previousGestureState.isRunningAnimationToLauncher()
                         || mDeviceState.isPredictiveBackToHomeInProgress();
-        boolean isInLiveTileMode = gestureState.getActivityInterface().isInLiveTileMode();
+        boolean isInLiveTileMode = gestureState.getContainerInterface().isInLiveTileMode();
+
         reasonString.append(SUBSTRING_PREFIX)
                 .append(hasWindowFocus
                         ? "activity has window focus"
@@ -1301,14 +1288,14 @@
                 || isInLiveTileMode) {
             reasonString.append(SUBSTRING_PREFIX)
                     .append("overview should have focus, using OverviewInputConsumer");
-            return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
+            return new OverviewInputConsumer(gestureState, container, mInputMonitorCompat,
                     false /* startingInActivityBounds */);
         } else {
             reasonString.append(SUBSTRING_PREFIX).append(
                     "overview shouldn't have focus, using OverviewWithoutFocusInputConsumer");
             final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
-            return new OverviewWithoutFocusInputConsumer(activity, mDeviceState, gestureState,
-                    mInputMonitorCompat, disableHorizontalSwipe);
+            return new OverviewWithoutFocusInputConsumer(container.asContext(), mDeviceState,
+                    gestureState, mInputMonitorCompat, disableHorizontalSwipe);
         }
     }
 
@@ -1381,7 +1368,7 @@
                 mOverviewComponentObserver.getActivityInterface();
         final Intent overviewIntent = new Intent(
                 mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState());
-        if (activityInterface.getCreatedActivity() != null && fromInit) {
+        if (activityInterface.getCreatedContainer() != null && fromInit) {
             // The activity has been created before the initialization of overview service. It is
             // usually happens when booting or launcher is the top activity, so we should already
             // have the latest state.
@@ -1403,7 +1390,7 @@
         }
         final BaseActivityInterface activityInterface =
                 mOverviewComponentObserver.getActivityInterface();
-        final BaseDraggingActivity activity = activityInterface.getCreatedActivity();
+        final BaseDraggingActivity activity = activityInterface.getCreatedContainer();
         if (activity == null || activity.isStarted()) {
             // We only care about the existing background activity.
             return;
@@ -1433,7 +1420,6 @@
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] rawArgs) {
         // Dump everything
-        FlagsFactory.dump(pw);
         if (LockedUserState.get(this).isUserUnlocked()) {
             PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
         }
@@ -1453,7 +1439,7 @@
         DisplayController.INSTANCE.get(this).dump(pw);
         pw.println("TouchState:");
         BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
-                : mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
+                : mOverviewComponentObserver.getActivityInterface().getCreatedContainer();
         boolean resumed = mOverviewComponentObserver != null
                 && mOverviewComponentObserver.getActivityInterface().isResumed();
         pw.println("  createdOverviewActivity=" + createdOverviewActivity);
@@ -1468,6 +1454,7 @@
         pw.println("AssistStateManager:");
         AssistStateManager.INSTANCE.get(this).dump("  ", pw);
         SystemUiProxy.INSTANCE.get(this).dump(pw);
+        DeviceConfigWrapper.get().dump("   ", pw);
     }
 
     private AbsSwipeUpHandler createLauncherSwipeHandler(
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
index 8a87f63..ec531d8 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
@@ -24,9 +24,9 @@
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.util.TouchController;
-import com.android.quickstep.RecentsActivity;
 import com.android.quickstep.util.NavBarPosition;
 import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
+import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * In 0-button mode, intercepts swipe up from the nav bar on FallbackRecentsView to go home.
@@ -34,19 +34,19 @@
 public class FallbackNavBarTouchController implements TouchController,
         TriggerSwipeUpTouchTracker.OnSwipeUpListener {
 
-    private final RecentsActivity mActivity;
+    private final RecentsViewContainer mContainer;
     @Nullable
     private final TriggerSwipeUpTouchTracker mTriggerSwipeUpTracker;
 
-    public FallbackNavBarTouchController(RecentsActivity activity) {
-        mActivity = activity;
-        NavigationMode sysUINavigationMode = DisplayController.getNavigationMode(mActivity);
+    public FallbackNavBarTouchController(RecentsViewContainer container) {
+        mContainer = container;
+        NavigationMode sysUINavigationMode =
+                DisplayController.getNavigationMode(mContainer.asContext());
         if (sysUINavigationMode == NavigationMode.NO_BUTTON) {
             NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode,
-                    DisplayController.INSTANCE.get(mActivity).getInfo());
-            mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity,
-                    true /* disableHorizontalSwipe */, navBarPosition,
-                    null /* onInterceptTouch */, this);
+                    DisplayController.INSTANCE.get(mContainer.asContext()).getInfo());
+            mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mContainer.asContext(),
+                    true /* disableHorizontalSwipe */, navBarPosition, this);
         } else {
             mTriggerSwipeUpTracker = null;
         }
@@ -76,9 +76,6 @@
 
     @Override
     public void onSwipeUp(boolean wasFling, PointF finalVelocity) {
-        mActivity.<FallbackRecentsView>getOverviewPanel().startHome();
+        mContainer.<FallbackRecentsView>getOverviewPanel().startHome();
     }
-
-    @Override
-    public void onSwipeUpCancelled() {}
 }
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 3e731e5..2e76356 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -49,6 +49,9 @@
 import com.android.launcher3.util.MultiPropertyFactory;
 import com.android.quickstep.RecentsActivity;
 import com.android.quickstep.views.ClearAllButton;
+import com.android.quickstep.views.OverviewActionsView;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * State controller for fallback recents activity
@@ -125,7 +128,7 @@
             setter.add(pa.buildAnim());
         }
 
-        Pair<FloatProperty, FloatProperty> taskViewsFloat =
+        Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
                 mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset(
                         TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
                         mActivity.getDeviceProfile());
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 32d8be9..d881a1f 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -36,6 +36,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.desktop.DesktopRecentsTransitionController;
 import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.statemanager.StateManager.StateListener;
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
@@ -67,7 +68,7 @@
 
     public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr, FallbackActivityInterface.INSTANCE);
-        mActivity.getStateManager().addStateListener(this);
+        mContainer.getStateManager().addStateListener(this);
     }
 
     @Override
@@ -80,13 +81,18 @@
 
     @Override
     protected void handleStartHome(boolean animated) {
-        mActivity.startHome();
-        AbstractFloatingView.closeAllOpenViews(mActivity, mActivity.isStarted());
+        mContainer.startHome();
+        AbstractFloatingView.closeAllOpenViews(mContainer, mContainer.isStarted());
     }
 
     @Override
     protected boolean canStartHomeSafely() {
-        return mActivity.canStartHomeSafely();
+        return mContainer.canStartHomeSafely();
+    }
+
+    @Override
+    public StateManager<RecentsState> getStateManager() {
+        return mContainer.getStateManager();
     }
 
     /**
@@ -210,10 +216,10 @@
     public void setModalStateEnabled(int taskId, boolean animate) {
         if (taskId != INVALID_TASK_ID) {
             setSelectedTask(taskId);
-            mActivity.getStateManager().goToState(RecentsState.MODAL_TASK, animate);
+            mContainer.getStateManager().goToState(RecentsState.MODAL_TASK, animate);
         } else {
-            if (mActivity.isInState(RecentsState.MODAL_TASK)) {
-                mActivity.getStateManager().goToState(DEFAULT, animate);
+            if (mContainer.isInState(RecentsState.MODAL_TASK)) {
+                mContainer.getStateManager().goToState(DEFAULT, animate);
             }
         }
     }
@@ -223,13 +229,13 @@
             @SplitConfigurationOptions.StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
         super.initiateSplitSelect(taskView, stagePosition, splitEvent);
-        mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
+        mContainer.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
     }
 
     @Override
     public void onStateTransitionStart(RecentsState toState) {
         setOverviewStateEnabled(true);
-        setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
+        setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
         setOverviewFullscreenEnabled(toState.isFullScreen());
         if (toState == MODAL_TASK) {
             setOverviewSelectEnabled(true);
@@ -280,7 +286,7 @@
     public void setOverviewStateEnabled(boolean enabled) {
         super.setOverviewStateEnabled(enabled);
         if (enabled) {
-            RecentsState state = mActivity.getStateManager().getState();
+            RecentsState state = mContainer.getStateManager().getState();
             setDisallowScrollToClearAll(!state.hasClearAllButton());
         }
     }
@@ -289,18 +295,18 @@
     public boolean onTouchEvent(MotionEvent ev) {
         boolean result = super.onTouchEvent(ev);
         // Do not let touch escape to siblings below this view.
-        return result || mActivity.getStateManager().getState().overviewUi();
+        return result || mContainer.getStateManager().getState().overviewUi();
     }
 
     @Override
     public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
         super.initiateSplitSelect(splitSelectSource);
-        mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
+        mContainer.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
     }
 
     @Override
     protected boolean canLaunchFullscreenTask() {
-        return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+        return !mContainer.isInState(OVERVIEW_SPLIT_SELECT);
     }
 
     /** Returns if app pairs are supported in this launcher. */
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index 8b5f091..84937a2 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -26,7 +26,8 @@
 import com.android.launcher3.R;
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.util.Themes;
-import com.android.quickstep.RecentsActivity;
+import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * State definition for Fallback recents
@@ -126,12 +127,13 @@
     /**
      * For this state, what color scrim should be drawn behind overview.
      */
-    public int getScrimColor(RecentsActivity activity) {
-        return hasFlag(FLAG_SCRIM) ? Themes.getAttrColor(activity, R.attr.overviewScrimColor)
+    public int getScrimColor(Context context) {
+        return hasFlag(FLAG_SCRIM)
+                ? Themes.getAttrColor(context, R.attr.overviewScrimColor)
                 : Color.TRANSPARENT;
     }
 
-    public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
+    public float[] getOverviewScaleAndOffset(RecentsViewContainer container) {
         return new float[] { NO_SCALE, NO_OFFSET };
     }
 
@@ -161,8 +163,8 @@
         }
 
         @Override
-        public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
-            return getOverviewScaleAndOffsetForModalState(activity);
+        public float[] getOverviewScaleAndOffset(RecentsViewContainer container) {
+            return getOverviewScaleAndOffsetForModalState(container.getOverviewPanel());
         }
     }
 
@@ -172,8 +174,8 @@
         }
 
         @Override
-        public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
-            return getOverviewScaleAndOffsetForBackgroundState(activity);
+        public float[] getOverviewScaleAndOffset(RecentsViewContainer container) {
+            return getOverviewScaleAndOffsetForBackgroundState(container.getOverviewPanel());
         }
     }
 
@@ -183,7 +185,7 @@
         }
 
         @Override
-        public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
+        public float[] getOverviewScaleAndOffset(RecentsViewContainer container) {
             return new float[] { NO_SCALE, 1 };
         }
     }
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
index db4927a..2cb398c 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
@@ -26,7 +26,7 @@
 
     @Override
     protected boolean isRecentsInteractive() {
-        return mActivity.hasWindowFocus() || mActivity.getStateManager().getState().hasLiveTile();
+        return mContainer.hasWindowFocus() || mContainer.getStateManager().getState().hasLiveTile();
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
index ba012c9..222ccd3 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
@@ -43,13 +43,13 @@
 import android.view.ViewConfiguration;
 
 import com.android.app.animation.Interpolators;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
-import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.BaseContainerInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
 import java.util.function.Consumer;
@@ -78,7 +78,7 @@
     private float mTimeFraction;
     private long mDragTime;
     private float mLastProgress;
-    private BaseActivityInterface mActivityInterface;
+    private BaseContainerInterface mContainerInterface;
 
     private final float mDragDistThreshold;
     private final float mFlingDistThreshold;
@@ -106,7 +106,7 @@
         float slop = ViewConfiguration.get(context).getScaledTouchSlop();
 
         mSquaredSlop = slop * slop;
-        mActivityInterface = gestureState.getActivityInterface();
+        mContainerInterface = gestureState.getContainerInterface();
 
         boolean flingDisabled = deviceState.isAssistantGestureIsConstrained()
                 || deviceState.isInDeferredGestureRegion(startEvent);
@@ -237,9 +237,9 @@
     }
 
     private void startAssistantInternal() {
-        BaseDraggingActivity launcherActivity = mActivityInterface.getCreatedActivity();
-        if (launcherActivity != null) {
-            launcherActivity.getRootView().performHapticFeedback(
+        RecentsViewContainer container = mContainerInterface.getCreatedContainer();
+        if (container != null) {
+            container.getRootView().performHapticFeedback(
                 13, // HapticFeedbackConstants.GESTURE_END
                 HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
         }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
index cf8750f..075e539 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -20,18 +20,22 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LONG_PRESS_NAVBAR;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LONG_PRESS_STASHED_TASKBAR;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.LogConfig.NAV_HANDLE_LONG_PRESS;
 
 import android.content.Context;
+import android.util.Log;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
-import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.util.DisplayController;
+import com.android.quickstep.DeviceConfigWrapper;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.NavHandle;
 import com.android.quickstep.RecentsAnimationDeviceState;
 import com.android.quickstep.TopTaskTracker;
+import com.android.quickstep.util.AssistStateManager;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
 /**
@@ -39,13 +43,20 @@
  */
 public class NavHandleLongPressInputConsumer extends DelegateInputConsumer {
 
+    private static final String TAG = "NavHandleLongPressIC";
+    private static final boolean DEBUG_NAV_HANDLE = Utilities.isPropertyEnabled(
+            NAV_HANDLE_LONG_PRESS);
+
     private final NavHandleLongPressHandler mNavHandleLongPressHandler;
     private final float mNavHandleWidth;
     private final float mScreenWidth;
 
     private final Runnable mTriggerLongPress = this::triggerLongPress;
-    private final float mTouchSlopSquared;
+    private final float mTouchSlopSquaredOriginal;
+    private float mTouchSlopSquared;
+    private final float mOuterTouchSlopSquared;
     private final int mLongPressTimeout;
+    private final int mOuterLongPressTimeout;
     private final boolean mDeepPressEnabled;
     private final NavHandle mNavHandle;
     private final StatsLogManager mStatsLogManager;
@@ -59,13 +70,24 @@
             NavHandle navHandle) {
         super(delegate, inputMonitor);
         mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
-        mDeepPressEnabled = FeatureFlags.ENABLE_LPNH_DEEP_PRESS.get();
-        if (FeatureFlags.CUSTOM_LPNH_THRESHOLDS.get()) {
-            mLongPressTimeout = FeatureFlags.LPNH_TIMEOUT_MS.get();
+        mDeepPressEnabled = DeviceConfigWrapper.get().getEnableLpnhDeepPress();
+        int twoStageMultiplier = DeviceConfigWrapper.get().getTwoStageMultiplier();
+        AssistStateManager assistStateManager = AssistStateManager.INSTANCE.get(context);
+        if (assistStateManager.getLPNHDurationMillis().isPresent()) {
+            mLongPressTimeout = assistStateManager.getLPNHDurationMillis().get().intValue();
         } else {
             mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
         }
-        mTouchSlopSquared = deviceState.getSquaredTouchSlop();
+        mOuterLongPressTimeout = mLongPressTimeout * twoStageMultiplier;
+        mTouchSlopSquaredOriginal = deviceState.getSquaredTouchSlop();
+        mTouchSlopSquared = mTouchSlopSquaredOriginal;
+        mOuterTouchSlopSquared = mTouchSlopSquared * (twoStageMultiplier * twoStageMultiplier);
+        if (DEBUG_NAV_HANDLE) {
+            Log.d(TAG, "mLongPressTimeout=" + mLongPressTimeout);
+            Log.d(TAG, "mOuterLongPressTimeout=" + mOuterLongPressTimeout);
+            Log.d(TAG, "mTouchSlopSquared=" + mTouchSlopSquared);
+            Log.d(TAG, "mOuterTouchSlopSquared=" + mOuterTouchSlopSquared);
+        }
         mNavHandle = navHandle;
         mNavHandleWidth = navHandle.getNavHandleWidth(context);
         mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context);
@@ -103,22 +125,44 @@
                     mCurrentDownEvent.recycle();
                 }
                 mCurrentDownEvent = MotionEvent.obtain(ev);
+                mTouchSlopSquared = mTouchSlopSquaredOriginal;
                 mDeepPressLogged = false;
                 if (isInNavBarHorizontalArea(ev.getRawX())) {
                     mNavHandleLongPressHandler.onTouchStarted(mNavHandle);
                     MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress, mLongPressTimeout);
                 }
+                if (DEBUG_NAV_HANDLE) {
+                    Log.d(TAG, "ACTION_DOWN");
+                }
             }
             case MotionEvent.ACTION_MOVE -> {
                 if (!MAIN_EXECUTOR.getHandler().hasCallbacks(mTriggerLongPress)) {
                     break;
                 }
 
-                float touchSlopSquared = mTouchSlopSquared;
                 float dx = ev.getX() - mCurrentDownEvent.getX();
                 float dy = ev.getY() - mCurrentDownEvent.getY();
                 double distanceSquared = (dx * dx) + (dy * dy);
-                if (distanceSquared > touchSlopSquared) {
+                if (DEBUG_NAV_HANDLE) {
+                    Log.d(TAG, "ACTION_MOVE distanceSquared=" + distanceSquared);
+                }
+                if (DeviceConfigWrapper.get().getEnableLpnhTwoStages()) {
+                    if (mTouchSlopSquared < distanceSquared
+                            && distanceSquared <= mOuterTouchSlopSquared) {
+                        MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress);
+                        int delay = mOuterLongPressTimeout
+                                - (int) (ev.getEventTime() - ev.getDownTime());
+                        MAIN_EXECUTOR.getHandler().postDelayed(mTriggerLongPress, delay);
+                        mTouchSlopSquared = mOuterTouchSlopSquared;
+                        if (DEBUG_NAV_HANDLE) {
+                            Log.d(TAG, "Touch in middle region!");
+                        }
+                    }
+                }
+                if (distanceSquared > mTouchSlopSquared) {
+                    if (DEBUG_NAV_HANDLE) {
+                        Log.d(TAG, "Touch slop out. mTouchSlopSquared=" + mTouchSlopSquared);
+                    }
                     cancelLongPress("touch slop passed");
                 }
             }
@@ -147,6 +191,9 @@
     }
 
     private void triggerLongPress() {
+        if (DEBUG_NAV_HANDLE) {
+            Log.d(TAG, "triggerLongPress");
+        }
         String runningPackage = mTopTaskTracker.getCachedTopTask(
                 /* filterOnlyVisibleRecents */ true).getPackageName();
         mStatsLogManager.logger().withPackageName(runningPackage).log(
@@ -169,12 +216,24 @@
     }
 
     private void cancelLongPress(String reason) {
+        if (DEBUG_NAV_HANDLE) {
+            Log.d(TAG, "cancelLongPress");
+        }
         MAIN_EXECUTOR.getHandler().removeCallbacks(mTriggerLongPress);
         mNavHandleLongPressHandler.onTouchFinished(mNavHandle, reason);
     }
 
     private boolean isInNavBarHorizontalArea(float x) {
         float areaFromMiddle = mNavHandleWidth / 2.0f;
+        if (DeviceConfigWrapper.get().getCustomLpnhThresholds()) {
+            areaFromMiddle += Utilities.dpToPx(
+                    DeviceConfigWrapper.get().getLpnhExtraTouchWidthDp());
+        }
+        int minAccessibleSize = Utilities.dpToPx(24);  // Half of 48dp because this is per side.
+        if (areaFromMiddle < minAccessibleSize) {
+            Log.w(TAG, "Custom nav handle region is too small - resetting to 48dp");
+            areaFromMiddle = minAccessibleSize;
+        }
         float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
 
         return distFromMiddle < areaFromMiddle;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
index 0f8ceba..9f39476 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -49,7 +49,6 @@
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.AbsSwipeUpHandler;
 import com.android.quickstep.AbsSwipeUpHandler.Factory;
-import com.android.quickstep.BaseActivityInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.RecentsAnimationCallbacks;
@@ -86,8 +85,6 @@
     private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
     private final InputMonitorCompat mInputMonitorCompat;
     private final InputEventReceiver mInputEventReceiver;
-    private final BaseActivityInterface mActivityInterface;
-
     private final AbsSwipeUpHandler.Factory mHandlerFactory;
 
     private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
@@ -135,7 +132,6 @@
         mTaskAnimationManager = taskAnimationManager;
         mGestureState = gestureState;
         mHandlerFactory = handlerFactory;
-        mActivityInterface = mGestureState.getActivityInterface();
 
         mMotionPauseDetector = new MotionPauseDetector(base, false,
                 mNavBarPosition.isLeftEdge() || mNavBarPosition.isRightEdge()
@@ -394,7 +390,8 @@
         mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs);
         mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
         mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler.getMotionPauseListener());
-        mInteractionHandler.initWhenReady();
+        mInteractionHandler.initWhenReady(
+                "OtherActivityInputConsumer.startTouchTrackingForWindowAnimation");
 
         if (mTaskAnimationManager.isRecentsAnimationRunning()) {
             mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(mGestureState);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
index 7d3a860..bb8d1d7 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
@@ -28,24 +28,24 @@
 
 import com.android.launcher3.Utilities;
 import com.android.launcher3.statemanager.BaseState;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.BaseContainerInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.TaskUtils;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
 /**
  * Input consumer for handling touch on the recents/Launcher activity.
  */
-public class OverviewInputConsumer<S extends BaseState<S>, T extends StatefulActivity<S>>
+public class OverviewInputConsumer<S extends BaseState<S>, T extends RecentsViewContainer>
         implements InputConsumer {
 
-    private final T mActivity;
-    private final BaseActivityInterface<?, T> mActivityInterface;
+    private final T mContainer;
+    private final BaseContainerInterface<?, T> mContainerInterface;
     private final BaseDragLayer mTarget;
     private final InputMonitorCompat mInputMonitor;
 
@@ -56,14 +56,14 @@
     private boolean mHasSetTouchModeForFirstDPadEvent;
     private boolean mIsWaitingForAttachToWindow;
 
-    public OverviewInputConsumer(GestureState gestureState, T activity,
+    public OverviewInputConsumer(GestureState gestureState, T container,
             @Nullable InputMonitorCompat inputMonitor, boolean startingInActivityBounds) {
-        mActivity = activity;
+        mContainer = container;
         mInputMonitor = inputMonitor;
         mStartingInActivityBounds = startingInActivityBounds;
-        mActivityInterface = gestureState.getActivityInterface();
+        mContainerInterface = gestureState.getContainerInterface();
 
-        mTarget = activity.getDragLayer();
+        mTarget = container.getDragLayer();
         mTarget.getLocationOnScreen(mLocationOnScreen);
     }
 
@@ -91,7 +91,7 @@
         if (!mTargetHandledTouch && handled) {
             mTargetHandledTouch = true;
             if (!mStartingInActivityBounds) {
-                mActivityInterface.closeOverlay();
+                mContainerInterface.closeOverlay();
                 TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
             }
             if (mInputMonitor != null) {
@@ -100,13 +100,13 @@
             }
         }
         if (mHasSetTouchModeForFirstDPadEvent) {
-            mActivity.getRootView().clearFocus();
+            mContainer.getRootView().clearFocus();
         }
     }
 
     @Override
     public void onHoverEvent(MotionEvent ev) {
-        mActivity.dispatchGenericMotionEvent(ev);
+        mContainer.dispatchGenericMotionEvent(ev);
     }
 
     @Override
@@ -115,7 +115,8 @@
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_UP:
             case KeyEvent.KEYCODE_VOLUME_MUTE:
-                MediaSessionManager mgr = mActivity.getSystemService(MediaSessionManager.class);
+                MediaSessionManager mgr = mContainer.asContext()
+                        .getSystemService(MediaSessionManager.class);
                 mgr.dispatchVolumeKeyEventAsSystemService(ev,
                         AudioManager.USE_DEFAULT_STREAM_TYPE);
                 break;
@@ -124,7 +125,7 @@
                 if (mHasSetTouchModeForFirstDPadEvent) {
                     break;
                 }
-                View viewRoot = mActivity.getRootView();
+                View viewRoot = mContainer.getRootView();
                 if (viewRoot.isAttachedToWindow()) {
                     setTouchModeChanged(viewRoot);
                     break;
@@ -150,7 +151,7 @@
             default:
                 break;
         }
-        mActivity.dispatchKeyEvent(ev);
+        mContainer.dispatchKeyEvent(ev);
     }
 
     private void setTouchModeChanged(@NonNull View viewRoot) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
index 41730bb..42e8694 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
@@ -51,7 +51,7 @@
         mGestureState = gestureState;
         mInputMonitor = inputMonitor;
         mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(context, disableHorizontalSwipe,
-                deviceState.getNavBarPosition(), this::onInterceptTouch, this);
+                deviceState.getNavBarPosition(), this);
     }
 
     @Override
@@ -69,7 +69,8 @@
         mTriggerSwipeUpTracker.onMotionEvent(ev);
     }
 
-    private void onInterceptTouch() {
+    @Override
+    public void onSwipeUpTouchIntercepted() {
         if (mInputMonitor != null) {
             TestLogging.recordEvent(TestProtocol.SEQUENCE_PILFER, "pilferPointers");
             mInputMonitor.pilferPointers();
@@ -93,7 +94,4 @@
                         .build())
                 .log(LAUNCHER_HOME_GESTURE);
     }
-
-    @Override
-    public void onSwipeUpCancelled() {}
 }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
index a8bf333..d73c23f 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
@@ -19,12 +19,12 @@
 import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.MotionPauseDetector;
+import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * An input consumer that detects swipe up and hold to exit screen pinning mode.
@@ -44,10 +44,10 @@
         mMotionPauseDetector = new MotionPauseDetector(context, true /* makePauseHarderToTrigger*/);
         mMotionPauseDetector.setOnMotionPauseListener(() -> {
             SystemUiProxy.INSTANCE.get(context).stopScreenPinning();
-            BaseDraggingActivity launcherActivity = gestureState.getActivityInterface()
-                    .getCreatedActivity();
-            if (launcherActivity != null) {
-                launcherActivity.getRootView().performHapticFeedback(
+            RecentsViewContainer container = gestureState.getContainerInterface()
+                    .getCreatedContainer();
+            if (container != null) {
+                container.getRootView().performHapticFeedback(
                         HapticFeedbackConstants.LONG_PRESS,
                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
             }
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
index 4806ac1..871d075 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
@@ -54,7 +54,7 @@
         mContext = context;
         mInputMonitor = inputMonitor;
         mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(context, true,
-                deviceState.getNavBarPosition(), this::onInterceptTouch, this);
+                deviceState.getNavBarPosition(), this);
     }
 
     @Override
@@ -72,7 +72,8 @@
         mTriggerSwipeUpTracker.onMotionEvent(ev);
     }
 
-    private void onInterceptTouch() {
+    @Override
+    public void onSwipeUpTouchIntercepted() {
         if (mInputMonitor != null) {
             TestLogging.recordEvent(TestProtocol.SEQUENCE_PILFER, "pilferPointers");
             mInputMonitor.pilferPointers();
@@ -88,9 +89,4 @@
             Log.e(TAG, "Exception calling closeSystemDialogs " + e.getMessage());
         }
     }
-
-    @Override
-    public void onSwipeUpCancelled() {
-
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
index 4198e2d..4f1dbbe 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java
@@ -59,7 +59,6 @@
 
     @Nullable private TutorialType[] mTutorialSteps;
     private GestureSandboxFragment mCurrentFragment;
-    private GestureSandboxFragment mPendingFragment;
 
     private int mCurrentStep;
     private int mNumSteps;
@@ -177,22 +176,16 @@
                     && getResources().getConfiguration().orientation
                     == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 
-            GestureSandboxFragment recreatedFragment =
-                    showRotationPrompt || mPendingFragment == null
-                            ? null : mPendingFragment.recreateFragment();
             showFragment(showRotationPrompt
                     ? new RotationPromptFragment()
-                    : recreatedFragment == null
-                            ? mCurrentFragment : recreatedFragment);
+                    : mCurrentFragment.canRecreateFragment()
+                            ? mCurrentFragment.recreateFragment() : mCurrentFragment);
         } else {
             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
         }
     }
 
     private void showFragment(@NonNull GestureSandboxFragment fragment) {
-        if (mCurrentFragment.recreateFragment() != null) {
-            mPendingFragment = mCurrentFragment;
-        }
         mCurrentFragment = fragment;
         getSupportFragmentManager().beginTransaction()
                 .replace(R.id.gesture_tutorial_fragment_container, mCurrentFragment)
diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java
index 08f2989..03bdd5d 100644
--- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxFragment.java
@@ -28,6 +28,10 @@
 
     void onDetachedFromWindow() {}
 
+    boolean canRecreateFragment() {
+        return false;
+    }
+
     @Nullable
     GestureSandboxFragment recreateFragment() {
         return null;
diff --git a/quickstep/src/com/android/quickstep/interaction/MenuFragment.java b/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
index dbf141b..8ead3dd 100644
--- a/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/MenuFragment.java
@@ -39,6 +39,11 @@
     }
 
     @Override
+    boolean canRecreateFragment() {
+        return true;
+    }
+
+    @Override
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
             @Nullable Bundle savedInstanceState) {
         final View root = inflater.inflate(
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index c4a2216..c00f508 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -65,7 +65,7 @@
         mSwipeUpTouchTracker =
                 new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
                         new NavBarPosition(NavigationMode.NO_BUTTON, displayInfo),
-                        null /*onInterceptTouch*/, this);
+                        this);
         mMotionPauseDetector = new MotionPauseDetector(context);
 
         final Resources resources = context.getResources();
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 545a94d..f89888a 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -41,6 +41,7 @@
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.Button;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -87,7 +88,7 @@
     private static final int FEEDBACK_ANIMATION_MS = 133;
     private static final int RIPPLE_VISIBLE_MS = 300;
     private static final int GESTURE_ANIMATION_DELAY_MS = 1500;
-    private static final int ADVANCE_TUTORIAL_TIMEOUT_MS = 2000;
+    private static final int ADVANCE_TUTORIAL_TIMEOUT_MS = 3000;
     private static final long GESTURE_ANIMATION_PAUSE_DURATION_MILLIS = 1000;
     protected float mExitingAppEndingCornerRadius;
     protected float mExitingAppStartingCornerRadius;
@@ -209,8 +210,12 @@
                                 mFeedbackView.removeCallbacks(mFeedbackViewCallback);
                             }
                             mFeedbackViewCallback = mTutorialFragment::continueTutorial;
-                            mFeedbackView.postDelayed(mFeedbackViewCallback,
-                                    ADVANCE_TUTORIAL_TIMEOUT_MS);
+                            mFeedbackView.postDelayed(
+                                    mFeedbackViewCallback,
+                                    AccessibilityManager.getInstance(mContext)
+                                            .getRecommendedTimeoutMillis(
+                                                    ADVANCE_TUTORIAL_TIMEOUT_MS,
+                                                    AccessibilityManager.FLAG_CONTENT_TEXT));
                         }
                     })
                     .start();
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index c91ee81..0fafb94 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -114,6 +114,11 @@
         return newInstance(tutorialType, isGestureComplete(), mFromTutorialMenu);
     }
 
+    @Override
+    boolean canRecreateFragment() {
+        return true;
+    }
+
     @NonNull
     abstract TutorialType getDefaultTutorialType();
 
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index e078a49..a09e027 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -113,7 +113,7 @@
             new CopyOnWriteArrayList<>();
 
     public StatsLogCompatManager(Context context) {
-        mContext = context;
+        super(context);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java
deleted file mode 100644
index f345aeb..0000000
--- a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.java
+++ /dev/null
@@ -1,704 +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.orientation;
-
-import static android.view.Gravity.BOTTOM;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.view.Gravity.END;
-import static android.view.Gravity.LEFT;
-import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
-import static android.view.View.LAYOUT_DIRECTION_RTL;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
-import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
-
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.ShapeDrawable;
-import android.util.FloatProperty;
-import android.util.Pair;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.touch.SingleAxisSwipeDetector;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
-import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
-import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.views.IconAppChipView;
-
-import java.util.Collections;
-import java.util.List;
-
-public class LandscapePagedViewHandler implements RecentsPagedOrientationHandler {
-
-    @Override
-    public <T> T getPrimaryValue(T x, T y) {
-        return y;
-    }
-
-    @Override
-    public <T> T getSecondaryValue(T x, T y) {
-        return x;
-    }
-
-    @Override
-    public int getPrimaryValue(int x, int y) {
-        return y;
-    }
-
-    @Override
-    public int getSecondaryValue(int x, int y) {
-        return x;
-    }
-
-    @Override
-    public float getPrimaryValue(float x, float y) {
-        return y;
-    }
-
-    @Override
-    public float getSecondaryValue(float x, float y) {
-        return x;
-    }
-
-    @Override
-    public boolean isLayoutNaturalToLauncher() {
-        return false;
-    }
-
-    @Override
-    public void adjustFloatingIconStartVelocity(PointF velocity) {
-        float oldX = velocity.x;
-        float oldY = velocity.y;
-        velocity.set(-oldY, oldX);
-    }
-
-    @Override
-    public void fixBoundsForHomeAnimStartRect(RectF outStartRect, DeviceProfile deviceProfile) {
-        // We don't need to check the "top" value here because the startRect is in the orientation
-        // of the app, not of the fixed portrait launcher.
-        if (outStartRect.left > deviceProfile.heightPx) {
-            outStartRect.offsetTo(0, outStartRect.top);
-        } else if (outStartRect.left < -deviceProfile.heightPx) {
-            outStartRect.offsetTo(0, outStartRect.top);
-        }
-    }
-
-    @Override
-    public <T> void setPrimary(T target, Int2DAction<T> action, int param) {
-        action.call(target, 0, param);
-    }
-
-    @Override
-    public <T> void setPrimary(T target, Float2DAction<T> action, float param) {
-        action.call(target, 0, param);
-    }
-
-    @Override
-    public <T> void setSecondary(T target, Float2DAction<T> action, float param) {
-        action.call(target, param, 0);
-    }
-
-    @Override
-    public <T> void set(T target, Int2DAction<T> action, int primaryParam,
-            int secondaryParam) {
-        action.call(target, secondaryParam, primaryParam);
-    }
-
-    @Override
-    public float getPrimaryDirection(MotionEvent event, int pointerIndex) {
-        return event.getY(pointerIndex);
-    }
-
-    @Override
-    public float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId) {
-        return velocityTracker.getYVelocity(pointerId);
-    }
-
-    @Override
-    public int getMeasuredSize(View view) {
-        return view.getMeasuredHeight();
-    }
-
-    @Override
-    public int getPrimarySize(View view) {
-        return view.getHeight();
-    }
-
-    @Override
-    public float getPrimarySize(RectF rect) {
-        return rect.height();
-    }
-
-    @Override
-    public float getStart(RectF rect) {
-        return rect.top;
-    }
-
-    @Override
-    public float getEnd(RectF rect) {
-        return rect.bottom;
-    }
-
-    @Override
-    public int getClearAllSidePadding(View view, boolean isRtl) {
-        return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2;
-    }
-
-    @Override
-    public int getSecondaryDimension(View view) {
-        return view.getWidth();
-    }
-
-    @Override
-    public FloatProperty<View> getPrimaryViewTranslate() {
-        return VIEW_TRANSLATE_Y;
-    }
-
-    @Override
-    public FloatProperty<View> getSecondaryViewTranslate() {
-        return VIEW_TRANSLATE_X;
-    }
-
-    @Override
-    public int getPrimaryScroll(View view) {
-        return view.getScrollY();
-    }
-
-    @Override
-    public float getPrimaryScale(View view) {
-        return view.getScaleY();
-    }
-
-    @Override
-    public void setMaxScroll(AccessibilityEvent event, int maxScroll) {
-        event.setMaxScrollY(maxScroll);
-    }
-
-    @Override
-    public boolean getRecentsRtlSetting(Resources resources) {
-        return !Utilities.isRtl(resources);
-    }
-
-    @Override
-    public float getDegreesRotated() {
-        return 90;
-    }
-
-    @Override
-    public int getRotation() {
-        return Surface.ROTATION_90;
-    }
-
-    @Override
-    public void setPrimaryScale(View view, float scale) {
-        view.setScaleY(scale);
-    }
-
-    @Override
-    public void setSecondaryScale(View view, float scale) {
-        view.setScaleX(scale);
-    }
-
-    @Override
-    public int getChildStart(View view) {
-        return view.getTop();
-    }
-
-    @Override
-    public int getCenterForPage(View view, Rect insets) {
-        return (view.getPaddingLeft() + view.getMeasuredWidth() + insets.left
-            - insets.right - view.getPaddingRight()) / 2;
-    }
-
-    @Override
-    public int getScrollOffsetStart(View view, Rect insets) {
-        return insets.top + view.getPaddingTop();
-    }
-
-    @Override
-    public int getScrollOffsetEnd(View view, Rect insets) {
-        return view.getHeight() - view.getPaddingBottom() - insets.bottom;
-    }
-
-    public int getSecondaryTranslationDirectionFactor() {
-        return 1;
-    }
-
-    @Override
-    public int getSplitTranslationDirectionFactor(int stagePosition, DeviceProfile deviceProfile) {
-        if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
-            return -1;
-        } else {
-            return 1;
-        }
-    }
-
-    @Override
-    public float getTaskMenuX(float x, View thumbnailView,
-            DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) {
-        return thumbnailView.getMeasuredWidth() + x - taskInsetMargin;
-    }
-
-    @Override
-    public float getTaskMenuY(float y, View thumbnailView, int stagePosition,
-            View taskMenuView, float taskInsetMargin, View taskViewIcon) {
-        BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams();
-        int taskMenuWidth = lp.width;
-        if (stagePosition == STAGE_POSITION_UNDEFINED) {
-            return y + taskInsetMargin
-                    + (thumbnailView.getMeasuredHeight() - taskMenuWidth) / 2f;
-        } else {
-            return y + taskInsetMargin;
-        }
-    }
-
-    @Override
-    public int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile,
-            @StagePosition int stagePosition) {
-        if (enableOverviewIconMenu()) {
-            return thumbnailView.getResources().getDimensionPixelSize(
-                    R.dimen.task_thumbnail_icon_menu_expanded_width);
-        }
-        if (stagePosition == SplitConfigurationOptions.STAGE_POSITION_UNDEFINED) {
-            return thumbnailView.getMeasuredWidth();
-        } else {
-            return thumbnailView.getMeasuredHeight();
-        }
-    }
-
-    @Override
-    public int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile,
-            float taskMenuX, float taskMenuY) {
-        return (int) (taskMenuX - taskInsetMargin);
-    }
-
-    @Override
-    public void setTaskOptionsMenuLayoutOrientation(DeviceProfile deviceProfile,
-            LinearLayout taskMenuLayout, int dividerSpacing,
-            ShapeDrawable dividerDrawable) {
-        taskMenuLayout.setOrientation(LinearLayout.VERTICAL);
-        dividerDrawable.setIntrinsicHeight(dividerSpacing);
-        taskMenuLayout.setDividerDrawable(dividerDrawable);
-    }
-
-    @Override
-    public void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp,
-            LinearLayout viewGroup, DeviceProfile deviceProfile) {
-        // Phone fake landscape
-        viewGroup.setOrientation(LinearLayout.HORIZONTAL);
-        lp.width = MATCH_PARENT;
-        lp.height = WRAP_CONTENT;
-    }
-
-    @Override
-    public Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
-            int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile,
-            View[] thumbnailViews, int desiredTaskId, View banner) {
-        boolean isRtl = banner.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        float translationX = 0;
-        float translationY = 0;
-        FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams();
-        banner.setPivotX(0);
-        banner.setPivotY(0);
-        banner.setRotation(getDegreesRotated());
-        translationX = banner.getHeight();
-        FrameLayout.LayoutParams snapshotParams =
-                (FrameLayout.LayoutParams) thumbnailViews[0]
-                        .getLayoutParams();
-        bannerParams.gravity = TOP | (isRtl ? END : START);
-        if (splitBounds == null) {
-            // Single, fullscreen case
-            bannerParams.width = taskViewHeight - snapshotParams.topMargin;
-            return new Pair<>(translationX, Integer.valueOf(snapshotParams.topMargin).floatValue());
-        }
-
-        // Set correct width
-        if (desiredTaskId == splitBounds.leftTopTaskId) {
-            bannerParams.width = thumbnailViews[0].getMeasuredHeight();
-        } else {
-            bannerParams.width = thumbnailViews[1].getMeasuredHeight();
-        }
-
-        // Set translations
-        if (desiredTaskId == splitBounds.rightBottomTaskId) {
-            float topLeftTaskPlusDividerPercent = splitBounds.appsStackedVertically
-                    ? (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent)
-                    : (splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent);
-            translationY = snapshotParams.topMargin
-                    + ((taskViewHeight - snapshotParams.topMargin) * topLeftTaskPlusDividerPercent);
-        }
-        if (desiredTaskId == splitBounds.leftTopTaskId) {
-            translationY = snapshotParams.topMargin;
-        }
-        return new Pair<>(translationX, translationY);
-    }
-
-    /* ---------- The following are only used by TaskViewTouchHandler. ---------- */
-
-    @Override
-    public SingleAxisSwipeDetector.Direction getUpDownSwipeDirection() {
-        return HORIZONTAL;
-    }
-
-    @Override
-    public int getUpDirection(boolean isRtl) {
-        return isRtl ? SingleAxisSwipeDetector.DIRECTION_NEGATIVE
-                : SingleAxisSwipeDetector.DIRECTION_POSITIVE;
-    }
-
-    @Override
-    public boolean isGoingUp(float displacement, boolean isRtl) {
-        return isRtl ? displacement < 0 : displacement > 0;
-    }
-
-    @Override
-    public int getTaskDragDisplacementFactor(boolean isRtl) {
-        return isRtl ? 1 : -1;
-    }
-
-    /* -------------------- */
-
-    @Override
-    public ChildBounds getChildBounds(View child, int childStart, int pageCenter,
-            boolean layoutChild) {
-        final int childHeight = child.getMeasuredHeight();
-        final int childBottom = childStart + childHeight;
-        final int childWidth = child.getMeasuredWidth();
-        final int childLeft = pageCenter - childWidth/ 2;
-        if (layoutChild) {
-            child.layout(childLeft, childStart, childLeft + childWidth, childBottom);
-        }
-        return new ChildBounds(childHeight, childWidth, childBottom, childLeft);
-    }
-
-    @SuppressWarnings("SuspiciousNameCombination")
-    @Override
-    public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) {
-        return rect.left;
-    }
-
-    @Override
-    public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
-        // Add "left" side of phone which is actually the top
-        return Collections.singletonList(new SplitPositionOption(
-                R.drawable.ic_split_horizontal, R.string.recent_task_option_split_screen,
-                STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
-    }
-
-    @Override
-    public void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
-            DeviceProfile dp, @StagePosition int stagePosition, Rect out) {
-        // In fake land/seascape, the placeholder always needs to go to the "top" of the device,
-        // which is the same bounds as 0 rotation.
-        int width = dp.widthPx;
-        int insetSizeAdjustment = getPlaceholderSizeAdjustment(dp);
-        out.set(0, 0, width, placeholderHeight + insetSizeAdjustment);
-        out.inset(placeholderInset, 0);
-
-        // Adjust the top to account for content off screen. This will help to animate the view in
-        // with rounded corners.
-        int screenWidth = dp.widthPx;
-        int screenHeight = dp.heightPx;
-        int totalHeight = (int) (1.0f * screenHeight / 2 * (screenWidth - 2 * placeholderInset)
-                / screenWidth);
-        out.top -= (totalHeight - placeholderHeight);
-    }
-
-    @Override
-    public void updateSplitIconParams(View out, float onScreenRectCenterX,
-            float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY,
-            int drawableWidth, int drawableHeight, DeviceProfile dp,
-            @StagePosition int stagePosition) {
-        float insetAdjustment = getPlaceholderSizeAdjustment(dp) / 2f;
-        out.setX(onScreenRectCenterX / fullscreenScaleX
-                - 1.0f * drawableWidth / 2);
-        out.setY((onScreenRectCenterY + insetAdjustment) / fullscreenScaleY
-                - 1.0f * drawableHeight / 2);
-    }
-
-    /**
-     * The split placeholder comes with a default inset to buffer the icon from the top of the
-     * screen. But if the device already has a large inset (from cutouts etc), use that instead.
-     */
-    private int getPlaceholderSizeAdjustment(DeviceProfile dp) {
-        return Math.max(dp.getInsets().top - dp.splitPlaceholderInset, 0);
-    }
-
-    @Override
-    public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
-            int splitInstructionsWidth) {
-        out.setPivotX(0);
-        out.setPivotY(splitInstructionsHeight);
-        out.setRotation(getDegreesRotated());
-        int distanceToEdge = out.getResources().getDimensionPixelSize(
-                R.dimen.split_instructions_bottom_margin_phone_landscape);
-        // Adjust for any insets on the left edge
-        int insetCorrectionX = dp.getInsets().left;
-        // Center the view in case of unbalanced insets on top or bottom of screen
-        int insetCorrectionY = (dp.getInsets().bottom - dp.getInsets().top) / 2;
-        out.setTranslationX(distanceToEdge - insetCorrectionX);
-        out.setTranslationY(((-splitInstructionsHeight - splitInstructionsWidth) / 2f)
-                + insetCorrectionY);
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) out.getLayoutParams();
-        // Setting gravity to LEFT instead of the lint-recommended START because we always want this
-        // view to be screen-left when phone is in landscape, regardless of the RtL setting.
-        lp.gravity = LEFT | CENTER_VERTICAL;
-        out.setLayoutParams(lp);
-    }
-
-    @Override
-    public void getFinalSplitPlaceholderBounds(int splitDividerSize, DeviceProfile dp,
-            @StagePosition int stagePosition, Rect out1, Rect out2) {
-        // In fake land/seascape, the window bounds are always top and bottom half
-        int screenHeight = dp.heightPx;
-        int screenWidth = dp.widthPx;
-        out1.set(0, 0, screenWidth, screenHeight / 2  - splitDividerSize);
-        out2.set(0, screenHeight / 2  + splitDividerSize, screenWidth, screenHeight);
-    }
-
-    @Override
-    public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
-            SplitBounds splitInfo, int desiredStagePosition) {
-        float topLeftTaskPercent = splitInfo.appsStackedVertically
-                ? splitInfo.topTaskPercent
-                : splitInfo.leftTaskPercent;
-        float dividerBarPercent = splitInfo.appsStackedVertically
-                ? splitInfo.dividerHeightPercent
-                : splitInfo.dividerWidthPercent;
-
-        if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
-            outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
-        } else {
-            outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
-        }
-    }
-
-    @Override
-    public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
-            int parentWidth, int parentHeight, SplitBounds splitBoundsConfig, DeviceProfile dp,
-            boolean isRtl) {
-        FrameLayout.LayoutParams primaryParams =
-                (FrameLayout.LayoutParams) primarySnapshot.getLayoutParams();
-        FrameLayout.LayoutParams secondaryParams =
-                (FrameLayout.LayoutParams) secondarySnapshot.getLayoutParams();
-
-        // Swap the margins that are set in TaskView#setRecentsOrientedState()
-        secondaryParams.topMargin = dp.overviewTaskThumbnailTopMarginPx;
-        primaryParams.topMargin = 0;
-
-        // Measure and layout the thumbnails bottom up, since the primary is on the visual left
-        // (portrait bottom) and secondary is on the right (portrait top)
-        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
-        int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
-        int dividerBar = Math.round(totalThumbnailHeight * (splitBoundsConfig.appsStackedVertically
-                ? splitBoundsConfig.dividerHeightPercent
-                : splitBoundsConfig.dividerWidthPercent));
-
-        Pair<Point, Point> taskViewSizes =
-                getGroupedTaskViewSizes(dp, splitBoundsConfig, parentWidth, parentHeight);
-
-        int translationY = taskViewSizes.first.y + spaceAboveSnapshot + dividerBar;
-        primarySnapshot.setTranslationY(spaceAboveSnapshot);
-        secondarySnapshot.setTranslationY(translationY - spaceAboveSnapshot);
-
-        primarySnapshot.measure(
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.first.x, View.MeasureSpec.EXACTLY),
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.first.y, View.MeasureSpec.EXACTLY)
-        );
-        secondarySnapshot.measure(
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.second.x, View.MeasureSpec.EXACTLY),
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.second.y, View.MeasureSpec.EXACTLY)
-        );
-    }
-
-    @Override
-    public Pair<Point, Point> getGroupedTaskViewSizes(
-            DeviceProfile dp,
-            SplitBounds splitBoundsConfig,
-            int parentWidth,
-            int parentHeight) {
-        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
-        int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
-        int dividerBar = Math.round(totalThumbnailHeight * (splitBoundsConfig.appsStackedVertically
-                ? splitBoundsConfig.dividerHeightPercent
-                : splitBoundsConfig.dividerWidthPercent));
-        float taskPercent = splitBoundsConfig.appsStackedVertically
-                ? splitBoundsConfig.topTaskPercent
-                : splitBoundsConfig.leftTaskPercent;
-
-        Point firstTaskViewSize = new Point(
-                parentWidth,
-                (int) (totalThumbnailHeight * taskPercent)
-        );
-        Point secondTaskViewSize = new Point(
-                parentWidth,
-                totalThumbnailHeight - firstTaskViewSize.y - dividerBar
-        );
-
-        return new Pair<>(firstTaskViewSize, secondTaskViewSize);
-    }
-
-    @Override
-    public void setTaskIconParams(FrameLayout.LayoutParams iconParams, int taskIconMargin,
-            int taskIconHeight, int thumbnailTopMargin, boolean isRtl) {
-        iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
-        iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
-        iconParams.leftMargin = 0;
-        iconParams.topMargin = thumbnailTopMargin / 2;
-        iconParams.bottomMargin = 0;
-    }
-
-    @Override
-    public void setIconAppChipChildrenParams(FrameLayout.LayoutParams iconParams,
-            int chipChildMarginStart) {
-        iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL;
-        iconParams.setMarginStart(chipChildMarginStart);
-        iconParams.topMargin = 0;
-    }
-
-    @Override
-    public void setIconAppChipMenuParams(IconAppChipView iconAppChipView,
-            FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) {
-        boolean isRtl = iconAppChipView.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        iconMenuParams.gravity = (isRtl ? START : END) | (isRtl ? BOTTOM : TOP);
-        iconMenuParams.setMarginStart(isRtl ? iconMenuMargin : 0);
-        iconMenuParams.topMargin = iconMenuMargin;
-        iconMenuParams.bottomMargin = isRtl ? iconMenuMargin : 0;
-        iconMenuParams.setMarginEnd(iconMenuMargin);
-
-        iconAppChipView.setPivotX(isRtl ? iconMenuParams.width - (iconMenuParams.height / 2f)
-                : iconMenuParams.width / 2f);
-        iconAppChipView.setPivotY(
-                isRtl ? (iconMenuParams.height / 2f) : iconMenuParams.width / 2f);
-        iconAppChipView.setSplitTranslationY(0);
-        iconAppChipView.setRotation(getDegreesRotated());
-    }
-
-    @Override
-    public void setSplitIconParams(View primaryIconView, View secondaryIconView,
-            int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
-            DeviceProfile deviceProfile, SplitBounds splitConfig) {
-        FrameLayout.LayoutParams primaryIconParams =
-                (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
-        FrameLayout.LayoutParams secondaryIconParams = enableOverviewIconMenu()
-                ? (FrameLayout.LayoutParams) secondaryIconView.getLayoutParams()
-                : new FrameLayout.LayoutParams(primaryIconParams);
-
-        // We calculate the "midpoint" of the thumbnail area, and place the icons there.
-        // This is the place where the thumbnail area splits by default, in a near-50/50 split.
-        // It is usually not exactly 50/50, due to insets/screen cutouts.
-        int fullscreenInsetThickness = deviceProfile.getInsets().top
-                - deviceProfile.getInsets().bottom;
-        int fullscreenMidpointFromBottom = ((deviceProfile.heightPx - fullscreenInsetThickness)
-                / 2);
-        float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
-        float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
-        int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
-        int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
-        int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
-        int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
-
-        if (enableOverviewIconMenu()) {
-            primaryIconParams.gravity = isRtl ? BOTTOM | START : TOP | END;
-            secondaryIconParams.gravity = isRtl ? BOTTOM | START : TOP | END;
-        } else {
-            primaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
-            secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
-        }
-        primaryIconView.setTranslationX(0);
-        secondaryIconView.setTranslationX(0);
-        if (enableOverviewIconMenu()) {
-            IconAppChipView primaryAppChipView = (IconAppChipView) primaryIconView;
-            IconAppChipView secondaryAppChipView = (IconAppChipView) secondaryIconView;
-            if (primaryIconView.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                secondaryAppChipView.setSplitTranslationY(-primarySnapshotHeight);
-                primaryAppChipView.setSplitTranslationY(0);
-            } else {
-                int secondarySnapshotHeight = groupedTaskViewHeight - primarySnapshotHeight;
-                primaryAppChipView.setSplitTranslationY(secondarySnapshotHeight);
-            }
-        } else if (splitConfig.initiatedFromSeascape) {
-            // if the split was initiated from seascape,
-            // the task on the right (secondary) is slightly larger
-            primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
-            secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
-                    + taskIconHeight);
-        } else {
-            // if not,
-            // the task on the left (primary) is slightly larger
-            primaryIconView.setTranslationY(-bottomToMidpointOffset);
-            secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
-        }
-
-        primaryIconView.setLayoutParams(primaryIconParams);
-        secondaryIconView.setLayoutParams(secondaryIconParams);
-    }
-
-    @Override
-    public int getDefaultSplitPosition(DeviceProfile deviceProfile) {
-        throw new IllegalStateException("Default position not available in fake landscape");
-    }
-
-    @Override
-    public Pair<FloatProperty, FloatProperty> getSplitSelectTaskOffset(FloatProperty primary,
-            FloatProperty secondary, DeviceProfile deviceProfile) {
-        return new Pair<>(primary, secondary);
-    }
-
-    @Override
-    public float getFloatingTaskOffscreenTranslationTarget(View floatingTask, RectF onScreenRect,
-            @StagePosition int stagePosition, DeviceProfile dp) {
-        float currentTranslationY = floatingTask.getTranslationY();
-        return currentTranslationY - onScreenRect.height();
-    }
-
-    @Override
-    public void setFloatingTaskPrimaryTranslation(View floatingTask, float translation,
-            DeviceProfile dp) {
-        floatingTask.setTranslationY(translation);
-    }
-
-    @Override
-    public Float getFloatingTaskPrimaryTranslation(View floatingTask, DeviceProfile dp) {
-        return floatingTask.getTranslationY();
-    }
-}
diff --git a/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
new file mode 100644
index 0000000..1640104
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/orientation/LandscapePagedViewHandler.kt
@@ -0,0 +1,700 @@
+/*
+ * 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.orientation
+
+import android.annotation.SuppressLint
+import android.content.res.Resources
+import android.graphics.Point
+import android.graphics.PointF
+import android.graphics.Rect
+import android.graphics.RectF
+import android.graphics.drawable.ShapeDrawable
+import android.util.FloatProperty
+import android.util.Pair
+import android.view.Gravity
+import android.view.MotionEvent
+import android.view.Surface
+import android.view.VelocityTracker
+import android.view.View
+import android.view.View.MeasureSpec
+import android.view.ViewGroup
+import android.view.accessibility.AccessibilityEvent
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import androidx.annotation.VisibleForTesting
+import androidx.core.util.component1
+import androidx.core.util.component2
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.Flags
+import com.android.launcher3.LauncherAnimUtils
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.touch.PagedOrientationHandler.ChildBounds
+import com.android.launcher3.touch.PagedOrientationHandler.Float2DAction
+import com.android.launcher3.touch.PagedOrientationHandler.Int2DAction
+import com.android.launcher3.touch.SingleAxisSwipeDetector
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN
+import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
+import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
+import com.android.launcher3.views.BaseDragLayer
+import com.android.quickstep.views.IconAppChipView
+import kotlin.math.max
+
+open class LandscapePagedViewHandler : RecentsPagedOrientationHandler {
+    override fun <T> getPrimaryValue(x: T, y: T): T = y
+
+    override fun <T> getSecondaryValue(x: T, y: T): T = x
+
+    override fun getPrimaryValue(x: Int, y: Int): Int = y
+
+    override fun getSecondaryValue(x: Int, y: Int): Int = x
+
+    override fun getPrimaryValue(x: Float, y: Float): Float = y
+
+    override fun getSecondaryValue(x: Float, y: Float): Float = x
+
+    override val isLayoutNaturalToLauncher: Boolean = false
+
+    override fun adjustFloatingIconStartVelocity(velocity: PointF) {
+        val oldX = velocity.x
+        val oldY = velocity.y
+        velocity.set(-oldY, oldX)
+    }
+
+    override fun fixBoundsForHomeAnimStartRect(outStartRect: RectF, deviceProfile: DeviceProfile) {
+        // We don't need to check the "top" value here because the startRect is in the orientation
+        // of the app, not of the fixed portrait launcher.
+        if (outStartRect.left > deviceProfile.heightPx) {
+            outStartRect.offsetTo(0f, outStartRect.top)
+        } else if (outStartRect.left < -deviceProfile.heightPx) {
+            outStartRect.offsetTo(0f, outStartRect.top)
+        }
+    }
+
+    override fun <T> setPrimary(target: T, action: Int2DAction<T>, param: Int) =
+        action.call(target, 0, param)
+
+    override fun <T> setPrimary(target: T, action: Float2DAction<T>, param: Float) =
+        action.call(target, 0f, param)
+
+    override fun <T> setSecondary(target: T, action: Float2DAction<T>, param: Float) =
+        action.call(target, param, 0f)
+
+    override fun <T> set(
+        target: T,
+        action: Int2DAction<T>,
+        primaryParam: Int,
+        secondaryParam: Int
+    ) = action.call(target, secondaryParam, primaryParam)
+
+    override fun getPrimaryDirection(event: MotionEvent, pointerIndex: Int): Float =
+        event.getY(pointerIndex)
+
+    override fun getPrimaryVelocity(velocityTracker: VelocityTracker, pointerId: Int): Float =
+        velocityTracker.getYVelocity(pointerId)
+
+    override fun getMeasuredSize(view: View): Int = view.measuredHeight
+
+    override fun getPrimarySize(view: View): Int = view.height
+
+    override fun getPrimarySize(rect: RectF): Float = rect.height()
+
+    override fun getStart(rect: RectF): Float = rect.top
+
+    override fun getEnd(rect: RectF): Float = rect.bottom
+
+    override fun getClearAllSidePadding(view: View, isRtl: Boolean): Int =
+        if (isRtl) view.paddingBottom / 2 else -view.paddingTop / 2
+
+    override fun getSecondaryDimension(view: View): Int = view.width
+
+    override val primaryViewTranslate: FloatProperty<View> = LauncherAnimUtils.VIEW_TRANSLATE_Y
+
+    override val secondaryViewTranslate: FloatProperty<View> = LauncherAnimUtils.VIEW_TRANSLATE_X
+
+    override fun getPrimaryScroll(view: View): Int = view.scrollY
+
+    override fun getPrimaryScale(view: View): Float = view.scaleY
+
+    override fun setMaxScroll(event: AccessibilityEvent, maxScroll: Int) {
+        event.maxScrollY = maxScroll
+    }
+
+    override fun getRecentsRtlSetting(resources: Resources): Boolean = !Utilities.isRtl(resources)
+
+    override val degreesRotated: Float = 90f
+
+    override val rotation: Int = Surface.ROTATION_90
+
+    override fun setPrimaryScale(view: View, scale: Float) {
+        view.scaleY = scale
+    }
+
+    override fun setSecondaryScale(view: View, scale: Float) {
+        view.scaleX = scale
+    }
+
+    override fun getChildStart(view: View): Int = view.top
+
+    override fun getCenterForPage(view: View, insets: Rect): Int =
+        (view.paddingLeft + view.measuredWidth + insets.left - insets.right - view.paddingRight) / 2
+
+    override fun getScrollOffsetStart(view: View, insets: Rect): Int = insets.top + view.paddingTop
+
+    override fun getScrollOffsetEnd(view: View, insets: Rect): Int =
+        view.height - view.paddingBottom - insets.bottom
+
+    override val secondaryTranslationDirectionFactor: Int = 1
+
+    override fun getSplitTranslationDirectionFactor(
+        stagePosition: Int,
+        deviceProfile: DeviceProfile
+    ): Int = if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) -1 else 1
+
+    override fun getTaskMenuX(
+        x: Float,
+        thumbnailView: View,
+        deviceProfile: DeviceProfile,
+        taskInsetMargin: Float,
+        taskViewIcon: View
+    ): Float = thumbnailView.measuredWidth + x - taskInsetMargin
+
+    override fun getTaskMenuY(
+        y: Float,
+        thumbnailView: View,
+        stagePosition: Int,
+        taskMenuView: View,
+        taskInsetMargin: Float,
+        taskViewIcon: View
+    ): Float {
+        val layoutParams = taskMenuView.layoutParams as BaseDragLayer.LayoutParams
+        var taskMenuY = y + taskInsetMargin
+
+        if (stagePosition == STAGE_POSITION_UNDEFINED) {
+            taskMenuY += (thumbnailView.measuredHeight - layoutParams.width) / 2f
+        }
+
+        return taskMenuY
+    }
+
+    override fun getTaskMenuWidth(
+        thumbnailView: View,
+        deviceProfile: DeviceProfile,
+        @StagePosition stagePosition: Int
+    ): Int =
+        when {
+            Flags.enableOverviewIconMenu() ->
+                thumbnailView.resources.getDimensionPixelSize(
+                    R.dimen.task_thumbnail_icon_menu_expanded_width
+                )
+            stagePosition == STAGE_POSITION_UNDEFINED -> thumbnailView.measuredWidth
+            else -> thumbnailView.measuredHeight
+        }
+
+    override fun getTaskMenuHeight(
+        taskInsetMargin: Float,
+        deviceProfile: DeviceProfile,
+        taskMenuX: Float,
+        taskMenuY: Float
+    ): Int = (taskMenuX - taskInsetMargin).toInt()
+
+    override fun setTaskOptionsMenuLayoutOrientation(
+        deviceProfile: DeviceProfile,
+        taskMenuLayout: LinearLayout,
+        dividerSpacing: Int,
+        dividerDrawable: ShapeDrawable
+    ) {
+        taskMenuLayout.orientation = LinearLayout.VERTICAL
+        dividerDrawable.intrinsicHeight = dividerSpacing
+        taskMenuLayout.dividerDrawable = dividerDrawable
+    }
+
+    override fun setLayoutParamsForTaskMenuOptionItem(
+        lp: LinearLayout.LayoutParams,
+        viewGroup: LinearLayout,
+        deviceProfile: DeviceProfile
+    ) {
+        // Phone fake landscape
+        viewGroup.orientation = LinearLayout.HORIZONTAL
+        lp.width = ViewGroup.LayoutParams.MATCH_PARENT
+        lp.height = ViewGroup.LayoutParams.WRAP_CONTENT
+    }
+
+    override fun getDwbLayoutTranslations(
+        taskViewWidth: Int,
+        taskViewHeight: Int,
+        splitBounds: SplitBounds?,
+        deviceProfile: DeviceProfile,
+        thumbnailViews: Array<View>,
+        desiredTaskId: Int,
+        banner: View
+    ): Pair<Float, Float> {
+        val snapshotParams = thumbnailViews[0].layoutParams as FrameLayout.LayoutParams
+        val isRtl = banner.layoutDirection == View.LAYOUT_DIRECTION_RTL
+        val translationX = banner.height.toFloat()
+
+        val bannerParams = banner.layoutParams as FrameLayout.LayoutParams
+        bannerParams.gravity = Gravity.TOP or if (isRtl) Gravity.END else Gravity.START
+        banner.pivotX = 0f
+        banner.pivotY = 0f
+        banner.rotation = degreesRotated
+
+        if (splitBounds == null) {
+            // Single, fullscreen case
+            bannerParams.width = taskViewHeight - snapshotParams.topMargin
+            return Pair(translationX, snapshotParams.topMargin.toFloat())
+        }
+
+        // Set correct width and translations
+        val translationY: Float
+        if (desiredTaskId == splitBounds.leftTopTaskId) {
+            bannerParams.width = thumbnailViews[0].measuredHeight
+            translationY = snapshotParams.topMargin.toFloat()
+        } else {
+            bannerParams.width = thumbnailViews[1].measuredHeight
+            val topLeftTaskPlusDividerPercent =
+                if (splitBounds.appsStackedVertically) {
+                    splitBounds.topTaskPercent + splitBounds.dividerHeightPercent
+                } else {
+                    splitBounds.leftTaskPercent + splitBounds.dividerWidthPercent
+                }
+            translationY =
+                snapshotParams.topMargin +
+                    (taskViewHeight - snapshotParams.topMargin) * topLeftTaskPlusDividerPercent
+        }
+
+        return Pair(translationX, translationY)
+    }
+
+    /* ---------- The following are only used by TaskViewTouchHandler. ---------- */
+    override val upDownSwipeDirection: SingleAxisSwipeDetector.Direction =
+        SingleAxisSwipeDetector.HORIZONTAL
+
+    override fun getUpDirection(isRtl: Boolean): Int =
+        if (isRtl) SingleAxisSwipeDetector.DIRECTION_NEGATIVE
+        else SingleAxisSwipeDetector.DIRECTION_POSITIVE
+
+    override fun isGoingUp(displacement: Float, isRtl: Boolean): Boolean =
+        if (isRtl) displacement < 0 else displacement > 0
+
+    override fun getTaskDragDisplacementFactor(isRtl: Boolean): Int = if (isRtl) 1 else -1
+    /* -------------------- */
+
+    override fun getChildBounds(
+        child: View,
+        childStart: Int,
+        pageCenter: Int,
+        layoutChild: Boolean
+    ): ChildBounds {
+        val childHeight = child.measuredHeight
+        val childWidth = child.measuredWidth
+        val childBottom = childStart + childHeight
+        val childLeft = pageCenter - childWidth / 2
+        if (layoutChild) {
+            child.layout(childLeft, childStart, childLeft + childWidth, childBottom)
+        }
+        return ChildBounds(childHeight, childWidth, childBottom, childLeft)
+    }
+
+    override fun getDistanceToBottomOfRect(dp: DeviceProfile, rect: Rect): Int = rect.left
+
+    override fun getSplitPositionOptions(dp: DeviceProfile): List<SplitPositionOption> =
+        // Add "left" side of phone which is actually the top
+        listOf(
+            SplitPositionOption(
+                R.drawable.ic_split_horizontal,
+                R.string.recent_task_option_split_screen,
+                STAGE_POSITION_TOP_OR_LEFT,
+                STAGE_TYPE_MAIN
+            )
+        )
+
+    override fun getInitialSplitPlaceholderBounds(
+        placeholderHeight: Int,
+        placeholderInset: Int,
+        dp: DeviceProfile,
+        @StagePosition stagePosition: Int,
+        out: Rect
+    ) {
+        // In fake land/seascape, the placeholder always needs to go to the "top" of the device,
+        // which is the same bounds as 0 rotation.
+        val width = dp.widthPx
+        val insetSizeAdjustment = getPlaceholderSizeAdjustment(dp)
+        out.set(0, 0, width, placeholderHeight + insetSizeAdjustment)
+        out.inset(placeholderInset, 0)
+
+        // Adjust the top to account for content off screen. This will help to animate the view in
+        // with rounded corners.
+        val screenWidth = dp.widthPx
+        val screenHeight = dp.heightPx
+        val totalHeight =
+            (1.0f * screenHeight / 2 * (screenWidth - 2 * placeholderInset) / screenWidth).toInt()
+        out.top -= totalHeight - placeholderHeight
+    }
+
+    override fun updateSplitIconParams(
+        out: View,
+        onScreenRectCenterX: Float,
+        onScreenRectCenterY: Float,
+        fullscreenScaleX: Float,
+        fullscreenScaleY: Float,
+        drawableWidth: Int,
+        drawableHeight: Int,
+        dp: DeviceProfile,
+        @StagePosition stagePosition: Int
+    ) {
+        val insetAdjustment = getPlaceholderSizeAdjustment(dp) / 2f
+        out.x = (onScreenRectCenterX / fullscreenScaleX - 1.0f * drawableWidth / 2)
+        out.y =
+            ((onScreenRectCenterY + insetAdjustment) / fullscreenScaleY - 1.0f * drawableHeight / 2)
+    }
+
+    /**
+     * The split placeholder comes with a default inset to buffer the icon from the top of the
+     * screen. But if the device already has a large inset (from cutouts etc), use that instead.
+     */
+    private fun getPlaceholderSizeAdjustment(dp: DeviceProfile?): Int =
+        max((dp!!.insets.top - dp.splitPlaceholderInset).toDouble(), 0.0).toInt()
+
+    override fun setSplitInstructionsParams(
+        out: View,
+        dp: DeviceProfile,
+        splitInstructionsHeight: Int,
+        splitInstructionsWidth: Int
+    ) {
+        out.pivotX = 0f
+        out.pivotY = splitInstructionsHeight.toFloat()
+        out.rotation = degreesRotated
+        val distanceToEdge =
+            out.resources.getDimensionPixelSize(
+                R.dimen.split_instructions_bottom_margin_phone_landscape
+            )
+        // Adjust for any insets on the left edge
+        val insetCorrectionX = dp.insets.left
+        // Center the view in case of unbalanced insets on top or bottom of screen
+        val insetCorrectionY = (dp.insets.bottom - dp.insets.top) / 2
+        out.translationX = (distanceToEdge - insetCorrectionX).toFloat()
+        out.translationY =
+            (-splitInstructionsHeight - splitInstructionsWidth) / 2f + insetCorrectionY
+        // Setting gravity to LEFT instead of the lint-recommended START because we always want this
+        // view to be screen-left when phone is in landscape, regardless of the RtL setting.
+        val lp = out.layoutParams as FrameLayout.LayoutParams
+        lp.gravity = Gravity.LEFT or Gravity.CENTER_VERTICAL
+        out.layoutParams = lp
+    }
+
+    override fun getFinalSplitPlaceholderBounds(
+        splitDividerSize: Int,
+        dp: DeviceProfile,
+        @StagePosition stagePosition: Int,
+        out1: Rect,
+        out2: Rect
+    ) {
+        // In fake land/seascape, the window bounds are always top and bottom half
+        val screenHeight = dp.heightPx
+        val screenWidth = dp.widthPx
+        out1.set(0, 0, screenWidth, screenHeight / 2 - splitDividerSize)
+        out2.set(0, screenHeight / 2 + splitDividerSize, screenWidth, screenHeight)
+    }
+
+    override fun setSplitTaskSwipeRect(
+        dp: DeviceProfile,
+        outRect: Rect,
+        splitInfo: SplitBounds,
+        desiredStagePosition: Int
+    ) {
+        val topLeftTaskPercent: Float
+        val dividerBarPercent: Float
+        if (splitInfo.appsStackedVertically) {
+            topLeftTaskPercent = splitInfo.topTaskPercent
+            dividerBarPercent = splitInfo.dividerHeightPercent
+        } else {
+            topLeftTaskPercent = splitInfo.leftTaskPercent
+            dividerBarPercent = splitInfo.dividerWidthPercent
+        }
+
+        if (desiredStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+            outRect.bottom = outRect.top + (outRect.height() * topLeftTaskPercent).toInt()
+        } else {
+            outRect.top += (outRect.height() * (topLeftTaskPercent + dividerBarPercent)).toInt()
+        }
+    }
+
+    override fun measureGroupedTaskViewThumbnailBounds(
+        primarySnapshot: View,
+        secondarySnapshot: View,
+        parentWidth: Int,
+        parentHeight: Int,
+        splitBoundsConfig: SplitBounds,
+        dp: DeviceProfile,
+        isRtl: Boolean
+    ) {
+        val primaryParams = primarySnapshot.layoutParams as FrameLayout.LayoutParams
+        val secondaryParams = secondarySnapshot.layoutParams as FrameLayout.LayoutParams
+
+        // Swap the margins that are set in TaskView#setRecentsOrientedState()
+        secondaryParams.topMargin = dp.overviewTaskThumbnailTopMarginPx
+        primaryParams.topMargin = 0
+
+        // Measure and layout the thumbnails bottom up, since the primary is on the visual left
+        // (portrait bottom) and secondary is on the right (portrait top)
+        val spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx
+        val totalThumbnailHeight = parentHeight - spaceAboveSnapshot
+        val dividerBar = getDividerBarSize(totalThumbnailHeight, splitBoundsConfig)
+
+        val (taskViewFirst, taskViewSecond) =
+            getGroupedTaskViewSizes(dp, splitBoundsConfig, parentWidth, parentHeight)
+
+        primarySnapshot.translationY = spaceAboveSnapshot.toFloat()
+        primarySnapshot.measure(
+            MeasureSpec.makeMeasureSpec(taskViewFirst.x, MeasureSpec.EXACTLY),
+            MeasureSpec.makeMeasureSpec(taskViewFirst.y, MeasureSpec.EXACTLY)
+        )
+        val translationY = taskViewFirst.y + spaceAboveSnapshot + dividerBar
+        secondarySnapshot.translationY = (translationY - spaceAboveSnapshot).toFloat()
+        secondarySnapshot.measure(
+            MeasureSpec.makeMeasureSpec(taskViewSecond.x, MeasureSpec.EXACTLY),
+            MeasureSpec.makeMeasureSpec(taskViewSecond.y, MeasureSpec.EXACTLY)
+        )
+    }
+
+    override fun getGroupedTaskViewSizes(
+        dp: DeviceProfile,
+        splitBoundsConfig: SplitBounds,
+        parentWidth: Int,
+        parentHeight: Int
+    ): Pair<Point, Point> {
+        val spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx
+        val totalThumbnailHeight = parentHeight - spaceAboveSnapshot
+        val dividerBar = getDividerBarSize(totalThumbnailHeight, splitBoundsConfig)
+
+        val taskPercent =
+            if (splitBoundsConfig.appsStackedVertically) {
+                splitBoundsConfig.topTaskPercent
+            } else {
+                splitBoundsConfig.leftTaskPercent
+            }
+        val firstTaskViewSize = Point(parentWidth, (totalThumbnailHeight * taskPercent).toInt())
+        val secondTaskViewSize =
+            Point(parentWidth, totalThumbnailHeight - firstTaskViewSize.y - dividerBar)
+        return Pair(firstTaskViewSize, secondTaskViewSize)
+    }
+
+    override fun setTaskIconParams(
+        iconParams: FrameLayout.LayoutParams,
+        taskIconMargin: Int,
+        taskIconHeight: Int,
+        thumbnailTopMargin: Int,
+        isRtl: Boolean
+    ) {
+        iconParams.gravity =
+            if (isRtl) {
+                Gravity.START or Gravity.CENTER_VERTICAL
+            } else {
+                Gravity.END or Gravity.CENTER_VERTICAL
+            }
+        iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2
+        iconParams.leftMargin = 0
+        iconParams.topMargin = thumbnailTopMargin / 2
+        iconParams.bottomMargin = 0
+    }
+
+    override fun setIconAppChipChildrenParams(
+        iconParams: FrameLayout.LayoutParams,
+        chipChildMarginStart: Int
+    ) {
+        iconParams.gravity = Gravity.START or Gravity.CENTER_VERTICAL
+        iconParams.marginStart = chipChildMarginStart
+        iconParams.topMargin = 0
+    }
+
+    override fun setIconAppChipMenuParams(
+        iconAppChipView: IconAppChipView,
+        iconMenuParams: FrameLayout.LayoutParams,
+        iconMenuMargin: Int,
+        thumbnailTopMargin: Int
+    ) {
+        val isRtl = iconAppChipView.layoutDirection == View.LAYOUT_DIRECTION_RTL
+
+        if (isRtl) {
+            iconMenuParams.gravity = Gravity.START or Gravity.BOTTOM
+            iconMenuParams.marginStart = iconMenuMargin
+            iconMenuParams.bottomMargin = iconMenuMargin
+            iconAppChipView.pivotX = iconMenuParams.width - iconMenuParams.height / 2f
+            iconAppChipView.pivotY = iconMenuParams.height / 2f
+        } else {
+            iconMenuParams.gravity = Gravity.END or Gravity.TOP
+            iconMenuParams.marginStart = 0
+            iconMenuParams.bottomMargin = 0
+            iconAppChipView.pivotX = iconMenuParams.width / 2f
+            iconAppChipView.pivotY = iconMenuParams.width / 2f
+        }
+
+        iconMenuParams.topMargin = iconMenuMargin
+        iconMenuParams.marginEnd = iconMenuMargin
+        iconAppChipView.setSplitTranslationY(0f)
+        iconAppChipView.setRotation(degreesRotated)
+    }
+
+    override fun setSplitIconParams(
+        primaryIconView: View,
+        secondaryIconView: View,
+        taskIconHeight: Int,
+        primarySnapshotWidth: Int,
+        primarySnapshotHeight: Int,
+        groupedTaskViewHeight: Int,
+        groupedTaskViewWidth: Int,
+        isRtl: Boolean,
+        deviceProfile: DeviceProfile,
+        splitConfig: SplitBounds
+    ) {
+        val spaceAboveSnapshot = deviceProfile.overviewTaskThumbnailTopMarginPx
+        val totalThumbnailHeight = groupedTaskViewHeight - spaceAboveSnapshot
+        val dividerBar: Int = getDividerBarSize(totalThumbnailHeight, splitConfig)
+
+        val (topLeftY, bottomRightY) =
+            getSplitIconsPosition(
+                taskIconHeight,
+                primarySnapshotHeight,
+                totalThumbnailHeight,
+                isRtl,
+                deviceProfile.overviewTaskMarginPx,
+                dividerBar
+            )
+
+        updateSplitIconsPosition(primaryIconView, topLeftY, isRtl)
+        updateSplitIconsPosition(secondaryIconView, bottomRightY, isRtl)
+    }
+
+    override fun getDefaultSplitPosition(deviceProfile: DeviceProfile): Int {
+        throw IllegalStateException("Default position not available in fake landscape")
+    }
+
+    override fun <T> getSplitSelectTaskOffset(
+        primary: FloatProperty<T>,
+        secondary: FloatProperty<T>,
+        deviceProfile: DeviceProfile
+    ): Pair<FloatProperty<T>, FloatProperty<T>> = Pair(primary, secondary)
+
+    override fun getFloatingTaskOffscreenTranslationTarget(
+        floatingTask: View,
+        onScreenRect: RectF,
+        @StagePosition stagePosition: Int,
+        dp: DeviceProfile
+    ): Float = floatingTask.translationY - onScreenRect.height()
+
+    override fun setFloatingTaskPrimaryTranslation(
+        floatingTask: View,
+        translation: Float,
+        dp: DeviceProfile
+    ) {
+        floatingTask.translationY = translation
+    }
+
+    override fun getFloatingTaskPrimaryTranslation(floatingTask: View, dp: DeviceProfile): Float =
+        floatingTask.translationY
+
+    /**
+     * Retrieves split icons position
+     *
+     * @param taskIconHeight The height of the task icon.
+     * @param primarySnapshotHeight The height for the primary snapshot (i.e., top-left snapshot).
+     * @param totalThumbnailHeight The total height for the group task view.
+     * @param isRtl Whether the layout direction is RTL (or false for LTR).
+     * @param overviewTaskMarginPx The space under the focused task icon provided by Device Profile.
+     * @param dividerSize The size of the divider for the group task view.
+     * @return The top-left and right-bottom positions for the icon views.
+     */
+    @VisibleForTesting
+    open fun getSplitIconsPosition(
+        taskIconHeight: Int,
+        primarySnapshotHeight: Int,
+        totalThumbnailHeight: Int,
+        isRtl: Boolean,
+        overviewTaskMarginPx: Int,
+        dividerSize: Int,
+    ): SplitIconPositions {
+        return if (Flags.enableOverviewIconMenu()) {
+            if (isRtl) {
+                SplitIconPositions(0, -(totalThumbnailHeight - primarySnapshotHeight))
+            } else {
+                SplitIconPositions(0, primarySnapshotHeight + dividerSize)
+            }
+        } else {
+            val topLeftY = primarySnapshotHeight + overviewTaskMarginPx
+            SplitIconPositions(
+                topLeftY = topLeftY,
+                bottomRightY = topLeftY + dividerSize + taskIconHeight
+            )
+        }
+    }
+
+    /**
+     * Updates icon view gravity and translation for split tasks
+     *
+     * @param iconView View to be updated
+     * @param translationY the translationY that should be applied
+     * @param isRtl Whether the layout direction is RTL (or false for LTR).
+     */
+    @SuppressLint("RtlHardcoded")
+    @VisibleForTesting
+    open fun updateSplitIconsPosition(iconView: View, translationY: Int, isRtl: Boolean) {
+        val layoutParams = iconView.layoutParams as FrameLayout.LayoutParams
+
+        if (Flags.enableOverviewIconMenu()) {
+            val appChipView = iconView as IconAppChipView
+            layoutParams.gravity =
+                if (isRtl) Gravity.BOTTOM or Gravity.START else Gravity.TOP or Gravity.END
+            appChipView.layoutParams = layoutParams
+            appChipView.setSplitTranslationX(0f)
+            appChipView.setSplitTranslationY(translationY.toFloat())
+        } else {
+            layoutParams.gravity = Gravity.TOP or Gravity.RIGHT
+            layoutParams.topMargin = translationY
+            iconView.translationX = 0f
+            iconView.translationY = 0f
+            iconView.layoutParams = layoutParams
+        }
+    }
+
+    /**
+     * It calculates the divider's size in the group task view.
+     *
+     * @param totalThumbnailHeight The total height for the group task view
+     * @param splitConfig Contains information about sizes and proportions for split task.
+     * @return The divider size for the group task view.
+     */
+    protected fun getDividerBarSize(totalThumbnailHeight: Int, splitConfig: SplitBounds): Int {
+        return Math.round(
+            totalThumbnailHeight *
+                if (splitConfig.appsStackedVertically) splitConfig.dividerHeightPercent
+                else splitConfig.dividerWidthPercent
+        )
+    }
+
+    /**
+     * Data structure to keep the y position to be used for the split task icon views translation.
+     *
+     * @param topLeftY The y-axis position for the task view position on the Top or Left side.
+     * @param bottomRightY The y-axis position for the task view position on the Bottom or Right
+     *   side.
+     */
+    data class SplitIconPositions(val topLeftY: Int, val bottomRightY: Int)
+}
diff --git a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
index 5cd9776..1be908b 100644
--- a/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
+++ b/quickstep/src/com/android/quickstep/orientation/PortraitPagedViewHandler.java
@@ -75,6 +75,7 @@
     public <T> T getSecondaryValue(T x, T y) {
         return y;
     }
+
     @Override
     public boolean isLayoutNaturalToLauncher() {
         return true;
@@ -212,7 +213,8 @@
     @Override
     public int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile,
             float taskMenuX, float taskMenuY) {
-        return (int) (deviceProfile.availableHeightPx - taskInsetMargin - taskMenuY);
+        return (int) (deviceProfile.heightPx - deviceProfile.getInsets().top - taskMenuY
+                    - deviceProfile.getOverviewActionsClaimedSpaceBelow());
     }
 
     @Override
@@ -795,7 +797,7 @@
     }
 
     @Override
-    public Float getFloatingTaskPrimaryTranslation(View floatingTask, DeviceProfile dp) {
+    public float getFloatingTaskPrimaryTranslation(View floatingTask, DeviceProfile dp) {
         return dp.isLeftRightSplit
                 ? floatingTask.getTranslationX()
                 : floatingTask.getTranslationY();
diff --git a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java
deleted file mode 100644
index 4b65d53..0000000
--- a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.java
+++ /dev/null
@@ -1,261 +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.orientation;
-
-
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.ShapeDrawable;
-import android.util.FloatProperty;
-import android.util.Pair;
-import android.view.View;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.touch.SingleAxisSwipeDetector;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
-import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
-import com.android.quickstep.views.IconAppChipView;
-
-import java.util.List;
-
-/**
- * Abstraction layer to separate horizontal and vertical specific implementations
- * for {@link com.android.quickstep.views.RecentsView}. Majority of these implementations are
- * (should be) as simple as choosing the correct X and Y analogous methods.
- */
-public interface RecentsPagedOrientationHandler extends PagedOrientationHandler {
-
-    RecentsPagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler();
-    RecentsPagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler();
-    RecentsPagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler();
-
-    <T> void setSecondary(T target, Float2DAction<T> action, float param);
-    <T> void set(T target, Int2DAction<T> action, int primaryParam, int secondaryParam);
-    int getPrimarySize(View view);
-    float getPrimarySize(RectF rect);
-    int getSecondaryTranslationDirectionFactor();
-    float getDegreesRotated();
-    int getRotation();
-    boolean isLayoutNaturalToLauncher();
-
-    <T> T getPrimaryValue(T x, T y);
-    <T> T getSecondaryValue(T x, T y);
-    void setPrimaryScale(View view, float scale);
-    void setSecondaryScale(View view, float scale);
-    float getStart(RectF rect);
-    float getEnd(RectF rect);
-    int getClearAllSidePadding(View view, boolean isRtl);
-    int getSecondaryDimension(View view);
-    FloatProperty<View> getPrimaryViewTranslate();
-    FloatProperty<View> getSecondaryViewTranslate();
-    int getSplitTranslationDirectionFactor(@StagePosition int stagePosition,
-            DeviceProfile deviceProfile);
-    Pair<FloatProperty, FloatProperty> getSplitSelectTaskOffset(FloatProperty primary,
-            FloatProperty secondary, DeviceProfile deviceProfile);
-    int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect);
-    List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp);
-    /**
-     * @param placeholderHeight height of placeholder view in portrait, width in landscape
-     */
-    void getInitialSplitPlaceholderBounds(int placeholderHeight, int placeholderInset,
-            DeviceProfile dp, @StagePosition int stagePosition, Rect out);
-
-    /**
-     * Centers an icon in the split staging area, accounting for insets.
-     * @param out The icon that needs to be centered.
-     * @param onScreenRectCenterX The x-center of the on-screen staging area (most of the Rect is
-     *                        offscreen).
-     * @param onScreenRectCenterY The y-center of the on-screen staging area (most of the Rect is
-     *                        offscreen).
-     * @param fullscreenScaleX A x-scaling factor used to convert coordinates back into pixels.
-     * @param fullscreenScaleY A y-scaling factor used to convert coordinates back into pixels.
-     * @param drawableWidth The icon's drawable (final) width.
-     * @param drawableHeight The icon's drawable (final) height.
-     * @param dp The device profile, used to report rotation and hardware insets.
-     * @param stagePosition 0 if the staging area is pinned to top/left, 1 for bottom/right.
-     */
-    void updateSplitIconParams(View out, float onScreenRectCenterX,
-            float onScreenRectCenterY, float fullscreenScaleX, float fullscreenScaleY,
-            int drawableWidth, int drawableHeight, DeviceProfile dp,
-            @StagePosition int stagePosition);
-
-    /**
-     * Sets positioning and rotation for a SplitInstructionsView.
-     * @param out The SplitInstructionsView that needs to be positioned.
-     * @param dp The device profile, used to report rotation and device type.
-     * @param splitInstructionsHeight The SplitInstructionView's height.
-     * @param splitInstructionsWidth  The SplitInstructionView's width.
-     */
-    void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
-            int splitInstructionsWidth);
-
-    /**
-     * @param splitDividerSize height of split screen drag handle in portrait, width in landscape
-     * @param stagePosition the split position option (top/left, bottom/right) of the first
-     *                           task selected for entering split
-     * @param out1 the bounds for where the first selected app will be
-     * @param out2 the bounds for where the second selected app will be, complimentary to
-     *             {@param out1} based on {@param initialSplitOption}
-     */
-    void getFinalSplitPlaceholderBounds(int splitDividerSize, DeviceProfile dp,
-            @StagePosition int stagePosition, Rect out1, Rect out2);
-
-    int getDefaultSplitPosition(DeviceProfile deviceProfile);
-
-    /**
-     * @param outRect This is expected to be the rect that has the dimensions for a non-split,
-     *                fullscreen task in overview. This will directly be modified.
-     * @param desiredStagePosition Which stage position (topLeft/rightBottom) we want to resize
-     *                           outRect for
-     */
-    void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect, SplitBounds splitInfo,
-            @SplitConfigurationOptions.StagePosition int desiredStagePosition);
-
-    void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
-            int parentWidth, int parentHeight,
-            SplitBounds splitBoundsConfig, DeviceProfile dp, boolean isRtl);
-
-    /**
-     * Creates two Points representing the dimensions of the two tasks in a GroupedTaskView
-     *
-     * @return first -> primary task snapshot, second -> secondary task snapshot.
-     * x -> width, y -> height
-     */
-    Pair<Point, Point> getGroupedTaskViewSizes(DeviceProfile dp, SplitBounds splitBoundsConfig,
-            int parentWidth, int parentHeight);
-
-    // Overview TaskMenuView methods
-    /** Sets layout params on a task's app icon. Only use this when app chip is disabled. */
-    void setTaskIconParams(FrameLayout.LayoutParams iconParams,
-            int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl);
-
-    /**
-     * Sets layout params on the children of an app chip. Only use this when app chip is enabled.
-     */
-    void setIconAppChipChildrenParams(
-            FrameLayout.LayoutParams iconParams, int chipChildMarginStart);
-
-    void setIconAppChipMenuParams(IconAppChipView iconAppChipView,
-            FrameLayout.LayoutParams iconMenuParams,
-            int iconMenuMargin, int thumbnailTopMargin);
-    void setSplitIconParams(View primaryIconView, View secondaryIconView,
-            int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
-            DeviceProfile deviceProfile, SplitBounds splitConfig);
-
-    /*
-     * The following two methods try to center the TaskMenuView in landscape by finding the center
-     * of the thumbnail view and then subtracting half of the taskMenu width. In this case, the
-     * taskMenu width is the same size as the thumbnail width (what got set below in
-     * getTaskMenuWidth()), so we directly use that in the calculations.
-     */
-    float getTaskMenuX(float x, View thumbnailView, DeviceProfile deviceProfile,
-            float taskInsetMargin, View taskViewIcon);
-    float getTaskMenuY(float y, View thumbnailView, int stagePosition,
-            View taskMenuView, float taskInsetMargin, View taskViewIcon);
-    int getTaskMenuWidth(View thumbnailView, DeviceProfile deviceProfile,
-            @StagePosition int stagePosition);
-
-    int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile, float taskMenuX,
-            float taskMenuY);
-    /**
-     * Sets linear layout orientation for {@link com.android.launcher3.popup.SystemShortcut} items
-     * inside task menu view.
-     */
-    void setTaskOptionsMenuLayoutOrientation(DeviceProfile deviceProfile,
-            LinearLayout taskMenuLayout, int dividerSpacing,
-            ShapeDrawable dividerDrawable);
-    /**
-     * Sets layout param attributes for {@link com.android.launcher3.popup.SystemShortcut} child
-     * views inside task menu view.
-     */
-    void setLayoutParamsForTaskMenuOptionItem(LinearLayout.LayoutParams lp,
-            LinearLayout viewGroup, DeviceProfile deviceProfile);
-
-    /**
-     * Calculates the position where a Digital Wellbeing Banner should be placed on its parent
-     * TaskView.
-     * @return A Pair of Floats representing the proper x and y translations.
-     */
-    Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
-            int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile,
-            View[] thumbnailViews, int desiredTaskId, View banner);
-
-    // The following are only used by TaskViewTouchHandler.
-    /** @return Either VERTICAL or HORIZONTAL. */
-    SingleAxisSwipeDetector.Direction getUpDownSwipeDirection();
-    /** @return Given {@link #getUpDownSwipeDirection()}, whether POSITIVE or NEGATIVE is up. */
-    int getUpDirection(boolean isRtl);
-    /** @return Whether the displacement is going towards the top of the screen. */
-    boolean isGoingUp(float displacement, boolean isRtl);
-    /** @return Either 1 or -1, a factor to multiply by so the animation goes the correct way. */
-    int getTaskDragDisplacementFactor(boolean isRtl);
-
-    /**
-     * Maps the velocity from the coordinate plane of the foreground app to that
-     * of Launcher's (which now will always be portrait)
-     */
-    void adjustFloatingIconStartVelocity(PointF velocity);
-
-    /**
-     * Ensures that outStartRect left bound is within the DeviceProfile's visual boundaries
-     * @param outStartRect The start rect that will directly be modified
-     */
-    void fixBoundsForHomeAnimStartRect(RectF outStartRect, DeviceProfile deviceProfile);
-
-    /**
-     * Determine the target translation for animating the FloatingTaskView out. This value could
-     * either be an x-coordinate or a y-coordinate, depending on which way the FloatingTaskView was
-     * docked.
-     *
-     * @param floatingTask The FloatingTaskView.
-     * @param onScreenRect The current on-screen dimensions of the FloatingTaskView.
-     * @param stagePosition STAGE_POSITION_TOP_OR_LEFT or STAGE_POSITION_BOTTOM_OR_RIGHT.
-     * @param dp The device profile.
-     * @return A float. When an animation translates the FloatingTaskView to this position, it will
-     * appear to tuck away off the edge of the screen.
-     */
-    float getFloatingTaskOffscreenTranslationTarget(View floatingTask, RectF onScreenRect,
-            @StagePosition int stagePosition, DeviceProfile dp);
-
-    /**
-     * Sets the translation of a FloatingTaskView along its "slide-in/slide-out" axis (could be
-     * either x or y), depending on how the view is oriented.
-     *
-     * @param floatingTask The FloatingTaskView to be translated.
-     * @param translation The target translation value.
-     * @param dp The current device profile.
-     */
-    void setFloatingTaskPrimaryTranslation(View floatingTask, float translation, DeviceProfile dp);
-
-    /**
-     * Gets the translation of a FloatingTaskView along its "slide-in/slide-out" axis (could be
-     * either x or y), depending on how the view is oriented.
-     *
-     * @param floatingTask The FloatingTaskView in question.
-     * @param dp The current device profile.
-     * @return The current translation value.
-     */
-    Float getFloatingTaskPrimaryTranslation(View floatingTask, DeviceProfile dp);
-}
diff --git a/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
new file mode 100644
index 0000000..6c82890
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/orientation/RecentsPagedOrientationHandler.kt
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.orientation
+
+import android.graphics.Point
+import android.graphics.PointF
+import android.graphics.Rect
+import android.graphics.RectF
+import android.graphics.drawable.ShapeDrawable
+import android.util.FloatProperty
+import android.util.Pair
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.LinearLayout
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.touch.PagedOrientationHandler
+import com.android.launcher3.touch.PagedOrientationHandler.Float2DAction
+import com.android.launcher3.touch.PagedOrientationHandler.Int2DAction
+import com.android.launcher3.touch.SingleAxisSwipeDetector
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
+import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
+import com.android.quickstep.views.IconAppChipView
+
+/**
+ * Abstraction layer to separate horizontal and vertical specific implementations for
+ * [com.android.quickstep.views.RecentsView]. Majority of these implementations are (should be) as
+ * simple as choosing the correct X and Y analogous methods.
+ */
+interface RecentsPagedOrientationHandler : PagedOrientationHandler {
+    fun <T> setSecondary(target: T, action: Float2DAction<T>, param: Float)
+
+    operator fun <T> set(target: T, action: Int2DAction<T>, primaryParam: Int, secondaryParam: Int)
+
+    fun getPrimarySize(view: View): Int
+
+    fun getPrimarySize(rect: RectF): Float
+
+    val secondaryTranslationDirectionFactor: Int
+
+    val degreesRotated: Float
+
+    val rotation: Int
+
+    val isLayoutNaturalToLauncher: Boolean
+
+    fun <T> getPrimaryValue(x: T, y: T): T
+
+    fun <T> getSecondaryValue(x: T, y: T): T
+
+    fun setPrimaryScale(view: View, scale: Float)
+
+    fun setSecondaryScale(view: View, scale: Float)
+
+    fun getStart(rect: RectF): Float
+
+    fun getEnd(rect: RectF): Float
+
+    fun getClearAllSidePadding(view: View, isRtl: Boolean): Int
+
+    fun getSecondaryDimension(view: View): Int
+
+    val primaryViewTranslate: FloatProperty<View>
+    val secondaryViewTranslate: FloatProperty<View>
+
+    fun getSplitTranslationDirectionFactor(
+        @StagePosition stagePosition: Int,
+        deviceProfile: DeviceProfile
+    ): Int
+
+    fun <T> getSplitSelectTaskOffset(
+        primary: FloatProperty<T>,
+        secondary: FloatProperty<T>,
+        deviceProfile: DeviceProfile
+    ): Pair<FloatProperty<T>, FloatProperty<T>>
+
+    fun getDistanceToBottomOfRect(dp: DeviceProfile, rect: Rect): Int
+
+    fun getSplitPositionOptions(dp: DeviceProfile): List<SplitPositionOption>
+
+    /** @param placeholderHeight height of placeholder view in portrait, width in landscape */
+    fun getInitialSplitPlaceholderBounds(
+        placeholderHeight: Int,
+        placeholderInset: Int,
+        dp: DeviceProfile,
+        @StagePosition stagePosition: Int,
+        out: Rect
+    )
+
+    /**
+     * Centers an icon in the split staging area, accounting for insets.
+     *
+     * @param out The icon that needs to be centered.
+     * @param onScreenRectCenterX The x-center of the on-screen staging area (most of the Rect is
+     *   offscreen).
+     * @param onScreenRectCenterY The y-center of the on-screen staging area (most of the Rect is
+     *   offscreen).
+     * @param fullscreenScaleX A x-scaling factor used to convert coordinates back into pixels.
+     * @param fullscreenScaleY A y-scaling factor used to convert coordinates back into pixels.
+     * @param drawableWidth The icon's drawable (final) width.
+     * @param drawableHeight The icon's drawable (final) height.
+     * @param dp The device profile, used to report rotation and hardware insets.
+     * @param stagePosition 0 if the staging area is pinned to top/left, 1 for bottom/right.
+     */
+    fun updateSplitIconParams(
+        out: View,
+        onScreenRectCenterX: Float,
+        onScreenRectCenterY: Float,
+        fullscreenScaleX: Float,
+        fullscreenScaleY: Float,
+        drawableWidth: Int,
+        drawableHeight: Int,
+        dp: DeviceProfile,
+        @StagePosition stagePosition: Int
+    )
+
+    /**
+     * Sets positioning and rotation for a SplitInstructionsView.
+     *
+     * @param out The SplitInstructionsView that needs to be positioned.
+     * @param dp The device profile, used to report rotation and device type.
+     * @param splitInstructionsHeight The SplitInstructionView's height.
+     * @param splitInstructionsWidth The SplitInstructionView's width.
+     */
+    fun setSplitInstructionsParams(
+        out: View,
+        dp: DeviceProfile,
+        splitInstructionsHeight: Int,
+        splitInstructionsWidth: Int
+    )
+
+    /**
+     * @param splitDividerSize height of split screen drag handle in portrait, width in landscape
+     * @param stagePosition the split position option (top/left, bottom/right) of the first task
+     *   selected for entering split
+     * @param out1 the bounds for where the first selected app will be
+     * @param out2 the bounds for where the second selected app will be, complimentary to {@param
+     *   out1} based on {@param initialSplitOption}
+     */
+    fun getFinalSplitPlaceholderBounds(
+        splitDividerSize: Int,
+        dp: DeviceProfile,
+        @StagePosition stagePosition: Int,
+        out1: Rect,
+        out2: Rect
+    )
+
+    fun getDefaultSplitPosition(deviceProfile: DeviceProfile): Int
+
+    /**
+     * @param outRect This is expected to be the rect that has the dimensions for a non-split,
+     *   fullscreen task in overview. This will directly be modified.
+     * @param desiredStagePosition Which stage position (topLeft/rightBottom) we want to resize
+     *   outRect for
+     */
+    fun setSplitTaskSwipeRect(
+        dp: DeviceProfile,
+        outRect: Rect,
+        splitInfo: SplitConfigurationOptions.SplitBounds,
+        @StagePosition desiredStagePosition: Int
+    )
+
+    fun measureGroupedTaskViewThumbnailBounds(
+        primarySnapshot: View,
+        secondarySnapshot: View,
+        parentWidth: Int,
+        parentHeight: Int,
+        splitBoundsConfig: SplitConfigurationOptions.SplitBounds,
+        dp: DeviceProfile,
+        isRtl: Boolean
+    )
+
+    /**
+     * Creates two Points representing the dimensions of the two tasks in a GroupedTaskView
+     *
+     * @return first -> primary task snapshot, second -> secondary task snapshot. x -> width, y ->
+     *   height
+     */
+    fun getGroupedTaskViewSizes(
+        dp: DeviceProfile,
+        splitBoundsConfig: SplitConfigurationOptions.SplitBounds,
+        parentWidth: Int,
+        parentHeight: Int
+    ): Pair<Point, Point>
+    // Overview TaskMenuView methods
+    /** Sets layout params on a task's app icon. Only use this when app chip is disabled. */
+    fun setTaskIconParams(
+        iconParams: FrameLayout.LayoutParams,
+        taskIconMargin: Int,
+        taskIconHeight: Int,
+        thumbnailTopMargin: Int,
+        isRtl: Boolean
+    )
+
+    /**
+     * Sets layout params on the children of an app chip. Only use this when app chip is enabled.
+     */
+    fun setIconAppChipChildrenParams(
+        iconParams: FrameLayout.LayoutParams,
+        chipChildMarginStart: Int
+    )
+
+    fun setIconAppChipMenuParams(
+        iconAppChipView: IconAppChipView,
+        iconMenuParams: FrameLayout.LayoutParams,
+        iconMenuMargin: Int,
+        thumbnailTopMargin: Int
+    )
+
+    fun setSplitIconParams(
+        primaryIconView: View,
+        secondaryIconView: View,
+        taskIconHeight: Int,
+        primarySnapshotWidth: Int,
+        primarySnapshotHeight: Int,
+        groupedTaskViewHeight: Int,
+        groupedTaskViewWidth: Int,
+        isRtl: Boolean,
+        deviceProfile: DeviceProfile,
+        splitConfig: SplitConfigurationOptions.SplitBounds
+    )
+
+    /*
+     * The following two methods try to center the TaskMenuView in landscape by finding the center
+     * of the thumbnail view and then subtracting half of the taskMenu width. In this case, the
+     * taskMenu width is the same size as the thumbnail width (what got set below in
+     * getTaskMenuWidth()), so we directly use that in the calculations.
+     */
+    fun getTaskMenuX(
+        x: Float,
+        thumbnailView: View,
+        deviceProfile: DeviceProfile,
+        taskInsetMargin: Float,
+        taskViewIcon: View
+    ): Float
+
+    fun getTaskMenuY(
+        y: Float,
+        thumbnailView: View,
+        stagePosition: Int,
+        taskMenuView: View,
+        taskInsetMargin: Float,
+        taskViewIcon: View
+    ): Float
+
+    fun getTaskMenuWidth(
+        thumbnailView: View,
+        deviceProfile: DeviceProfile,
+        @StagePosition stagePosition: Int
+    ): Int
+
+    fun getTaskMenuHeight(
+        taskInsetMargin: Float,
+        deviceProfile: DeviceProfile,
+        taskMenuX: Float,
+        taskMenuY: Float
+    ): Int
+
+    /**
+     * Sets linear layout orientation for [com.android.launcher3.popup.SystemShortcut] items inside
+     * task menu view.
+     */
+    fun setTaskOptionsMenuLayoutOrientation(
+        deviceProfile: DeviceProfile,
+        taskMenuLayout: LinearLayout,
+        dividerSpacing: Int,
+        dividerDrawable: ShapeDrawable
+    )
+
+    /**
+     * Sets layout param attributes for [com.android.launcher3.popup.SystemShortcut] child views
+     * inside task menu view.
+     */
+    fun setLayoutParamsForTaskMenuOptionItem(
+        lp: LinearLayout.LayoutParams,
+        viewGroup: LinearLayout,
+        deviceProfile: DeviceProfile
+    )
+
+    /**
+     * Calculates the position where a Digital Wellbeing Banner should be placed on its parent
+     * TaskView.
+     *
+     * @return A Pair of Floats representing the proper x and y translations.
+     */
+    fun getDwbLayoutTranslations(
+        taskViewWidth: Int,
+        taskViewHeight: Int,
+        splitBounds: SplitConfigurationOptions.SplitBounds?,
+        deviceProfile: DeviceProfile,
+        thumbnailViews: Array<View>,
+        desiredTaskId: Int,
+        banner: View
+    ): Pair<Float, Float>
+    // The following are only used by TaskViewTouchHandler.
+
+    /** @return Either VERTICAL or HORIZONTAL. */
+    val upDownSwipeDirection: SingleAxisSwipeDetector.Direction
+
+    /** @return Given [.getUpDownSwipeDirection], whether POSITIVE or NEGATIVE is up. */
+    fun getUpDirection(isRtl: Boolean): Int
+
+    /** @return Whether the displacement is going towards the top of the screen. */
+    fun isGoingUp(displacement: Float, isRtl: Boolean): Boolean
+
+    /** @return Either 1 or -1, a factor to multiply by so the animation goes the correct way. */
+    fun getTaskDragDisplacementFactor(isRtl: Boolean): Int
+
+    /**
+     * Maps the velocity from the coordinate plane of the foreground app to that of Launcher's
+     * (which now will always be portrait)
+     */
+    fun adjustFloatingIconStartVelocity(velocity: PointF)
+
+    /**
+     * Ensures that outStartRect left bound is within the DeviceProfile's visual boundaries
+     *
+     * @param outStartRect The start rect that will directly be modified
+     */
+    fun fixBoundsForHomeAnimStartRect(outStartRect: RectF, deviceProfile: DeviceProfile)
+
+    /**
+     * Determine the target translation for animating the FloatingTaskView out. This value could
+     * either be an x-coordinate or a y-coordinate, depending on which way the FloatingTaskView was
+     * docked.
+     *
+     * @param floatingTask The FloatingTaskView.
+     * @param onScreenRect The current on-screen dimensions of the FloatingTaskView.
+     * @param stagePosition STAGE_POSITION_TOP_OR_LEFT or STAGE_POSITION_BOTTOM_OR_RIGHT.
+     * @param dp The device profile.
+     * @return A float. When an animation translates the FloatingTaskView to this position, it will
+     *   appear to tuck away off the edge of the screen.
+     */
+    fun getFloatingTaskOffscreenTranslationTarget(
+        floatingTask: View,
+        onScreenRect: RectF,
+        @StagePosition stagePosition: Int,
+        dp: DeviceProfile
+    ): Float
+
+    /**
+     * Sets the translation of a FloatingTaskView along its "slide-in/slide-out" axis (could be
+     * either x or y), depending on how the view is oriented.
+     *
+     * @param floatingTask The FloatingTaskView to be translated.
+     * @param translation The target translation value.
+     * @param dp The current device profile.
+     */
+    fun setFloatingTaskPrimaryTranslation(floatingTask: View, translation: Float, dp: DeviceProfile)
+
+    /**
+     * Gets the translation of a FloatingTaskView along its "slide-in/slide-out" axis (could be
+     * either x or y), depending on how the view is oriented.
+     *
+     * @param floatingTask The FloatingTaskView in question.
+     * @param dp The current device profile.
+     * @return The current translation value.
+     */
+    fun getFloatingTaskPrimaryTranslation(floatingTask: View, dp: DeviceProfile): Float
+
+    companion object {
+        @JvmField val PORTRAIT: RecentsPagedOrientationHandler = PortraitPagedViewHandler()
+        @JvmField val LANDSCAPE: RecentsPagedOrientationHandler = LandscapePagedViewHandler()
+        @JvmField val SEASCAPE: RecentsPagedOrientationHandler = SeascapePagedViewHandler()
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java
deleted file mode 100644
index 89c678c..0000000
--- a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.java
+++ /dev/null
@@ -1,418 +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.orientation;
-
-import static android.view.Gravity.BOTTOM;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.view.Gravity.END;
-import static android.view.Gravity.RIGHT;
-import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
-import static android.view.View.LAYOUT_DIRECTION_RTL;
-
-import static com.android.launcher3.Flags.enableOverviewIconMenu;
-import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
-import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
-
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.util.Pair;
-import android.view.Gravity;
-import android.view.Surface;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.touch.SingleAxisSwipeDetector;
-import com.android.launcher3.util.SplitConfigurationOptions;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
-import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
-import com.android.launcher3.views.BaseDragLayer;
-import com.android.quickstep.views.IconAppChipView;
-
-import java.util.Collections;
-import java.util.List;
-
-public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
-
-    @Override
-    public int getSecondaryTranslationDirectionFactor() {
-        return -1;
-    }
-
-    @Override
-    public int getSplitTranslationDirectionFactor(int stagePosition, DeviceProfile deviceProfile) {
-        if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
-            return -1;
-        } else {
-            return 1;
-        }
-    }
-
-    @Override
-    public boolean getRecentsRtlSetting(Resources resources) {
-        return Utilities.isRtl(resources);
-    }
-
-    @Override
-    public float getDegreesRotated() {
-        return 270;
-    }
-
-    @Override
-    public int getRotation() {
-        return Surface.ROTATION_270;
-    }
-
-    @Override
-    public void adjustFloatingIconStartVelocity(PointF velocity) {
-        float oldX = velocity.x;
-        float oldY = velocity.y;
-        velocity.set(oldY, -oldX);
-    }
-
-    @Override
-    public float getTaskMenuX(float x, View thumbnailView,
-            DeviceProfile deviceProfile, float taskInsetMargin, View taskViewIcon) {
-        return x + taskInsetMargin;
-    }
-
-    @Override
-    public float getTaskMenuY(float y, View thumbnailView, int stagePosition,
-            View taskMenuView, float taskInsetMargin, View taskViewIcon) {
-        if (enableOverviewIconMenu()) {
-            return y;
-        }
-        BaseDragLayer.LayoutParams lp = (BaseDragLayer.LayoutParams) taskMenuView.getLayoutParams();
-        int taskMenuWidth = lp.width;
-        if (stagePosition == STAGE_POSITION_UNDEFINED) {
-            return y + taskInsetMargin
-                    + (thumbnailView.getMeasuredHeight() + taskMenuWidth) / 2f;
-        } else {
-            return y + taskMenuWidth + taskInsetMargin;
-        }
-    }
-
-    @Override
-    public int getTaskMenuHeight(float taskInsetMargin, DeviceProfile deviceProfile,
-            float taskMenuX, float taskMenuY) {
-        return (int) (deviceProfile.availableWidthPx - taskInsetMargin - taskMenuX);
-    }
-
-    @Override
-    public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect, SplitBounds splitInfo,
-            int desiredStagePosition) {
-        float topLeftTaskPercent = splitInfo.appsStackedVertically
-                ? splitInfo.topTaskPercent
-                : splitInfo.leftTaskPercent;
-        float dividerBarPercent = splitInfo.appsStackedVertically
-                ? splitInfo.dividerHeightPercent
-                : splitInfo.dividerWidthPercent;
-
-        // In seascape, the primary thumbnail is counterintuitively placed at the physical bottom of
-        // the screen. This is to preserve consistency when the user rotates: From the user's POV,
-        // the primary should always be on the left.
-        if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
-            outRect.top += (int) (outRect.height() * ((1 - topLeftTaskPercent)));
-        } else {
-            outRect.bottom -= (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
-        }
-    }
-
-    @Override
-    public Pair<Float, Float> getDwbLayoutTranslations(int taskViewWidth,
-            int taskViewHeight, SplitBounds splitBounds, DeviceProfile deviceProfile,
-            View[] thumbnailViews, int desiredTaskId, View banner) {
-        boolean isRtl = banner.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        float translationX = 0;
-        float translationY = 0;
-        FrameLayout.LayoutParams bannerParams = (FrameLayout.LayoutParams) banner.getLayoutParams();
-        banner.setPivotX(0);
-        banner.setPivotY(0);
-        banner.setRotation(getDegreesRotated());
-        translationX = taskViewWidth - banner.getHeight();
-        FrameLayout.LayoutParams snapshotParams =
-                (FrameLayout.LayoutParams) thumbnailViews[0]
-                        .getLayoutParams();
-        bannerParams.gravity = BOTTOM | (isRtl ? END : START);
-
-        if (splitBounds == null) {
-            // Single, fullscreen case
-            bannerParams.width = taskViewHeight - snapshotParams.topMargin;
-            translationY = banner.getHeight();
-            return new Pair<>(translationX, translationY);
-        }
-
-        // Set correct width
-        if (desiredTaskId == splitBounds.leftTopTaskId) {
-            bannerParams.width = thumbnailViews[0].getMeasuredHeight();
-        } else {
-            bannerParams.width = thumbnailViews[1].getMeasuredHeight();
-        }
-
-        // Set translations
-        if (desiredTaskId == splitBounds.rightBottomTaskId) {
-            translationY = banner.getHeight();
-        }
-        if (desiredTaskId == splitBounds.leftTopTaskId) {
-            float bottomRightTaskPlusDividerPercent = splitBounds.appsStackedVertically
-                    ? (1f - splitBounds.topTaskPercent)
-                    : (1f - splitBounds.leftTaskPercent);
-            translationY = banner.getHeight()
-                    - ((taskViewHeight - snapshotParams.topMargin)
-                    * bottomRightTaskPlusDividerPercent);
-        }
-        return new Pair<>(translationX, translationY);
-    }
-
-    @Override
-    public int getDistanceToBottomOfRect(DeviceProfile dp, Rect rect) {
-        return dp.widthPx - rect.right;
-    }
-
-    @Override
-    public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
-        // Add "right" option which is actually the top
-        return Collections.singletonList(new SplitPositionOption(
-                R.drawable.ic_split_horizontal, R.string.recent_task_option_split_screen,
-                STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
-    }
-
-    @Override
-    public void setSplitInstructionsParams(View out, DeviceProfile dp, int splitInstructionsHeight,
-            int splitInstructionsWidth) {
-        out.setPivotX(0);
-        out.setPivotY(splitInstructionsHeight);
-        out.setRotation(getDegreesRotated());
-        int distanceToEdge = out.getResources().getDimensionPixelSize(
-                R.dimen.split_instructions_bottom_margin_phone_landscape);
-        // Adjust for any insets on the right edge
-        int insetCorrectionX = dp.getInsets().right;
-        // Center the view in case of unbalanced insets on top or bottom of screen
-        int insetCorrectionY = (dp.getInsets().bottom - dp.getInsets().top) / 2;
-        out.setTranslationX(splitInstructionsWidth - distanceToEdge + insetCorrectionX);
-        out.setTranslationY(((-splitInstructionsHeight + splitInstructionsWidth) / 2f)
-                + insetCorrectionY);
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) out.getLayoutParams();
-        // Setting gravity to RIGHT instead of the lint-recommended END because we always want this
-        // view to be screen-right when phone is in seascape, regardless of the RtL setting.
-        lp.gravity = RIGHT | CENTER_VERTICAL;
-        out.setLayoutParams(lp);
-    }
-
-    @Override
-    public void setTaskIconParams(FrameLayout.LayoutParams iconParams,
-            int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl) {
-        iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
-        iconParams.setMargins(-taskIconHeight - taskIconMargin / 2, thumbnailTopMargin / 2, 0, 0);
-    }
-
-    @Override
-    public void setIconAppChipChildrenParams(FrameLayout.LayoutParams iconParams,
-            int chipChildMarginStart) {
-        iconParams.setMargins(0, 0, 0, 0);
-        iconParams.setMarginStart(chipChildMarginStart);
-        iconParams.gravity = Gravity.START | Gravity.CENTER_VERTICAL;
-    }
-
-    @Override
-    public void setIconAppChipMenuParams(IconAppChipView iconAppChipView,
-            FrameLayout.LayoutParams iconMenuParams, int iconMenuMargin, int thumbnailTopMargin) {
-        boolean isRtl = iconAppChipView.getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        iconMenuParams.gravity = (isRtl ? TOP : BOTTOM) | (isRtl ? END : START);
-        iconMenuParams.setMarginStart(0);
-        iconMenuParams.topMargin = isRtl ? iconMenuMargin : 0;
-        iconMenuParams.bottomMargin = 0;
-        iconMenuParams.setMarginEnd(isRtl ? thumbnailTopMargin : 0);
-
-        // Use half menu height to place the pivot within the X/Y center of icon in the menu.
-        float iconCenter = iconAppChipView.getHeight() / 2f;
-        iconAppChipView.setPivotX(isRtl ? iconMenuParams.width / 2f : iconCenter);
-        iconAppChipView.setPivotY(
-                isRtl ? iconMenuParams.width / 2f : iconCenter - iconMenuMargin);
-        iconAppChipView.setSplitTranslationY(0);
-        iconAppChipView.setRotation(getDegreesRotated());
-    }
-
-    @Override
-    public void setSplitIconParams(View primaryIconView, View secondaryIconView,
-            int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
-            DeviceProfile deviceProfile, SplitBounds splitConfig) {
-        super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight,
-                primarySnapshotWidth, primarySnapshotHeight, groupedTaskViewHeight,
-                groupedTaskViewWidth, isRtl, deviceProfile, splitConfig);
-        FrameLayout.LayoutParams primaryIconParams =
-                (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
-        FrameLayout.LayoutParams secondaryIconParams =
-                (FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
-
-        // We calculate the "midpoint" of the thumbnail area, and place the icons there.
-        // This is the place where the thumbnail area splits by default, in a near-50/50 split.
-        // It is usually not exactly 50/50, due to insets/screen cutouts.
-        int fullscreenInsetThickness = deviceProfile.getInsets().top
-                - deviceProfile.getInsets().bottom;
-        int fullscreenMidpointFromBottom = ((deviceProfile.heightPx
-                - fullscreenInsetThickness) / 2);
-        float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
-        float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
-        int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
-        int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
-        int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
-        int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
-
-        int gravity = (isRtl ? TOP : BOTTOM) | (isRtl ? END : START);
-        primaryIconParams.gravity = gravity;
-        secondaryIconParams.gravity = gravity;
-        primaryIconView.setTranslationX(0);
-        secondaryIconView.setTranslationX(0);
-        if (enableOverviewIconMenu()) {
-            IconAppChipView primaryAppChipView = (IconAppChipView) primaryIconView;
-            IconAppChipView secondaryAppChipView = (IconAppChipView) secondaryIconView;
-            if (isRtl) {
-                primaryAppChipView.setSplitTranslationY(
-                        groupedTaskViewHeight - primarySnapshotHeight);
-                secondaryAppChipView.setSplitTranslationY(0);
-            } else {
-                secondaryAppChipView.setSplitTranslationY(-primarySnapshotHeight);
-                primaryAppChipView.setSplitTranslationY(0);
-            }
-        } else if (splitConfig.initiatedFromSeascape) {
-            // if the split was initiated from seascape,
-            // the task on the right (secondary) is slightly larger
-            if (isRtl) {
-                primaryIconView.setTranslationY(bottomToMidpointOffset - insetOffset
-                        + taskIconHeight);
-                secondaryIconView.setTranslationY(bottomToMidpointOffset - insetOffset);
-            } else {
-                primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
-                        + taskIconHeight);
-                secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
-            }
-        } else {
-            // if not,
-            // the task on the left (primary) is slightly larger
-            if (isRtl) {
-                primaryIconView.setTranslationY(bottomToMidpointOffset + taskIconHeight);
-                secondaryIconView.setTranslationY(bottomToMidpointOffset);
-            } else {
-                primaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
-                secondaryIconView.setTranslationY(-bottomToMidpointOffset);
-            }
-        }
-
-        primaryIconView.setLayoutParams(primaryIconParams);
-        secondaryIconView.setLayoutParams(secondaryIconParams);
-    }
-
-    @Override
-    public void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
-            int parentWidth, int parentHeight, SplitBounds splitBoundsConfig, DeviceProfile dp,
-            boolean isRtl) {
-        FrameLayout.LayoutParams primaryParams =
-                (FrameLayout.LayoutParams) primarySnapshot.getLayoutParams();
-        FrameLayout.LayoutParams secondaryParams =
-                (FrameLayout.LayoutParams) secondarySnapshot.getLayoutParams();
-
-        // Swap the margins that are set in TaskView#setRecentsOrientedState()
-        secondaryParams.topMargin = dp.overviewTaskThumbnailTopMarginPx;
-        primaryParams.topMargin = 0;
-
-        // Measure and layout the thumbnails bottom up, since the primary is on the visual left
-        // (portrait bottom) and secondary is on the right (portrait top)
-        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
-        int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
-        int dividerBar = Math.round(totalThumbnailHeight * (splitBoundsConfig.appsStackedVertically
-                ? splitBoundsConfig.dividerHeightPercent
-                : splitBoundsConfig.dividerWidthPercent));
-
-        Pair<Point, Point> taskViewSizes =
-                getGroupedTaskViewSizes(dp, splitBoundsConfig, parentWidth, parentHeight);
-
-        secondarySnapshot.setTranslationY(0);
-        primarySnapshot.setTranslationY(taskViewSizes.second.y + spaceAboveSnapshot + dividerBar);
-
-        primarySnapshot.measure(
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.first.x, View.MeasureSpec.EXACTLY),
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.first.y, View.MeasureSpec.EXACTLY)
-        );
-        secondarySnapshot.measure(
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.second.x, View.MeasureSpec.EXACTLY),
-                View.MeasureSpec.makeMeasureSpec(taskViewSizes.second.y, View.MeasureSpec.EXACTLY)
-        );
-    }
-
-    @Override
-    public Pair<Point, Point> getGroupedTaskViewSizes(
-            DeviceProfile dp,
-            SplitBounds splitBoundsConfig,
-            int parentWidth,
-            int parentHeight) {
-        // Measure and layout the thumbnails bottom up, since the primary is on the visual left
-        // (portrait bottom) and secondary is on the right (portrait top)
-        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
-        int totalThumbnailHeight = parentHeight - spaceAboveSnapshot;
-        int dividerBar = Math.round(totalThumbnailHeight * (splitBoundsConfig.appsStackedVertically
-                ? splitBoundsConfig.dividerHeightPercent
-                : splitBoundsConfig.dividerWidthPercent));
-        float taskPercent = splitBoundsConfig.appsStackedVertically
-                ? splitBoundsConfig.topTaskPercent
-                : splitBoundsConfig.leftTaskPercent;
-
-        Point firstTaskViewSize = new Point(
-                parentWidth,
-                (int) (totalThumbnailHeight * taskPercent)
-        );
-        Point secondTaskViewSize = new Point(
-                parentWidth,
-                totalThumbnailHeight - firstTaskViewSize.y - dividerBar
-        );
-
-        return new Pair<>(firstTaskViewSize, secondTaskViewSize);
-    }
-
-    /* ---------- The following are only used by TaskViewTouchHandler. ---------- */
-
-    @Override
-    public SingleAxisSwipeDetector.Direction getUpDownSwipeDirection() {
-        return HORIZONTAL;
-    }
-
-    @Override
-    public int getUpDirection(boolean isRtl) {
-        return isRtl ? SingleAxisSwipeDetector.DIRECTION_POSITIVE
-                : SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
-    }
-
-    @Override
-    public boolean isGoingUp(float displacement, boolean isRtl) {
-        return isRtl ? displacement > 0 : displacement < 0;
-    }
-
-    @Override
-    public int getTaskDragDisplacementFactor(boolean isRtl) {
-        return isRtl ? -1 : 1;
-    }
-
-    /* -------------------- */
-}
diff --git a/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
new file mode 100644
index 0000000..5bebf8c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/orientation/SeascapePagedViewHandler.kt
@@ -0,0 +1,398 @@
+/*
+ * 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.orientation
+
+import android.annotation.SuppressLint
+import android.content.res.Resources
+import android.graphics.Point
+import android.graphics.PointF
+import android.graphics.Rect
+import android.util.Pair
+import android.view.Gravity
+import android.view.Surface
+import android.view.View
+import android.view.View.MeasureSpec
+import android.widget.FrameLayout
+import androidx.core.util.component1
+import androidx.core.util.component2
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.Flags
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.touch.SingleAxisSwipeDetector
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+import com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN
+import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds
+import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption
+import com.android.launcher3.views.BaseDragLayer
+import com.android.quickstep.views.IconAppChipView
+
+class SeascapePagedViewHandler : LandscapePagedViewHandler() {
+    override val secondaryTranslationDirectionFactor: Int = -1
+
+    override fun getSplitTranslationDirectionFactor(
+        stagePosition: Int,
+        deviceProfile: DeviceProfile
+    ): Int = if (stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) -1 else 1
+
+    override fun getRecentsRtlSetting(resources: Resources): Boolean = Utilities.isRtl(resources)
+
+    override val degreesRotated: Float = 270f
+
+    override val rotation: Int = Surface.ROTATION_270
+
+    override fun adjustFloatingIconStartVelocity(velocity: PointF) =
+        velocity.set(velocity.y, -velocity.x)
+
+    override fun getTaskMenuX(
+        x: Float,
+        thumbnailView: View,
+        deviceProfile: DeviceProfile,
+        taskInsetMargin: Float,
+        taskViewIcon: View
+    ): Float = x + taskInsetMargin
+
+    override fun getTaskMenuY(
+        y: Float,
+        thumbnailView: View,
+        stagePosition: Int,
+        taskMenuView: View,
+        taskInsetMargin: Float,
+        taskViewIcon: View
+    ): Float {
+        if (Flags.enableOverviewIconMenu()) {
+            return y
+        }
+        val lp = taskMenuView.layoutParams as BaseDragLayer.LayoutParams
+        val taskMenuWidth = lp.width
+        return if (stagePosition == STAGE_POSITION_UNDEFINED) {
+            y + taskInsetMargin + (thumbnailView.measuredHeight + taskMenuWidth) / 2f
+        } else {
+            y + taskMenuWidth + taskInsetMargin
+        }
+    }
+
+    override fun getTaskMenuHeight(
+        taskInsetMargin: Float,
+        deviceProfile: DeviceProfile,
+        taskMenuX: Float,
+        taskMenuY: Float
+    ): Int = (deviceProfile.availableWidthPx - taskInsetMargin - taskMenuX).toInt()
+
+    override fun setSplitTaskSwipeRect(
+        dp: DeviceProfile,
+        outRect: Rect,
+        splitInfo: SplitBounds,
+        desiredStagePosition: Int
+    ) {
+        val topLeftTaskPercent: Float
+        val dividerBarPercent: Float
+        if (splitInfo.appsStackedVertically) {
+            topLeftTaskPercent = splitInfo.topTaskPercent
+            dividerBarPercent = splitInfo.dividerHeightPercent
+        } else {
+            topLeftTaskPercent = splitInfo.leftTaskPercent
+            dividerBarPercent = splitInfo.dividerWidthPercent
+        }
+
+        // In seascape, the primary thumbnail is counterintuitively placed at the physical bottom of
+        // the screen. This is to preserve consistency when the user rotates: From the user's POV,
+        // the primary should always be on the left.
+        if (desiredStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+            outRect.top += (outRect.height() * (1 - topLeftTaskPercent)).toInt()
+        } else {
+            outRect.bottom -= (outRect.height() * (topLeftTaskPercent + dividerBarPercent)).toInt()
+        }
+    }
+
+    override fun getDwbLayoutTranslations(
+        taskViewWidth: Int,
+        taskViewHeight: Int,
+        splitBounds: SplitBounds?,
+        deviceProfile: DeviceProfile,
+        thumbnailViews: Array<View>,
+        desiredTaskId: Int,
+        banner: View
+    ): Pair<Float, Float> {
+        val snapshotParams = thumbnailViews[0].layoutParams as FrameLayout.LayoutParams
+        val isRtl = banner.layoutDirection == View.LAYOUT_DIRECTION_RTL
+
+        val bannerParams = banner.layoutParams as FrameLayout.LayoutParams
+        bannerParams.gravity = Gravity.BOTTOM or if (isRtl) Gravity.END else Gravity.START
+        banner.pivotX = 0f
+        banner.pivotY = 0f
+        banner.rotation = degreesRotated
+
+        val translationX: Float = (taskViewWidth - banner.height).toFloat()
+        if (splitBounds == null) {
+            // Single, fullscreen case
+            bannerParams.width = taskViewHeight - snapshotParams.topMargin
+            return Pair(translationX, banner.height.toFloat())
+        }
+
+        // Set correct width and translations
+        val translationY: Float
+        if (desiredTaskId == splitBounds.leftTopTaskId) {
+            bannerParams.width = thumbnailViews[0].measuredHeight
+            val bottomRightTaskPlusDividerPercent =
+                if (splitBounds.appsStackedVertically) {
+                    1f - splitBounds.topTaskPercent
+                } else {
+                    1f - splitBounds.leftTaskPercent
+                }
+            translationY =
+                banner.height -
+                    (taskViewHeight - snapshotParams.topMargin) * bottomRightTaskPlusDividerPercent
+        } else {
+            bannerParams.width = thumbnailViews[1].measuredHeight
+            translationY = banner.height.toFloat()
+        }
+
+        return Pair(translationX, translationY)
+    }
+
+    override fun getDistanceToBottomOfRect(dp: DeviceProfile, rect: Rect): Int =
+        dp.widthPx - rect.right
+
+    override fun getSplitPositionOptions(dp: DeviceProfile): List<SplitPositionOption> =
+        // Add "right" option which is actually the top
+        listOf(
+            SplitPositionOption(
+                R.drawable.ic_split_horizontal,
+                R.string.recent_task_option_split_screen,
+                STAGE_POSITION_BOTTOM_OR_RIGHT,
+                STAGE_TYPE_MAIN
+            )
+        )
+
+    override fun setSplitInstructionsParams(
+        out: View,
+        dp: DeviceProfile,
+        splitInstructionsHeight: Int,
+        splitInstructionsWidth: Int
+    ) {
+        out.pivotX = 0f
+        out.pivotY = splitInstructionsHeight.toFloat()
+        out.rotation = degreesRotated
+        val distanceToEdge =
+            out.resources.getDimensionPixelSize(
+                R.dimen.split_instructions_bottom_margin_phone_landscape
+            )
+        // Adjust for any insets on the right edge
+        val insetCorrectionX = dp.insets.right
+        // Center the view in case of unbalanced insets on top or bottom of screen
+        val insetCorrectionY = (dp.insets.bottom - dp.insets.top) / 2
+        out.translationX = (splitInstructionsWidth - distanceToEdge + insetCorrectionX).toFloat()
+        out.translationY =
+            (-splitInstructionsHeight + splitInstructionsWidth) / 2f + insetCorrectionY
+        // Setting gravity to RIGHT instead of the lint-recommended END because we always want this
+        // view to be screen-right when phone is in seascape, regardless of the RtL setting.
+        val lp = out.layoutParams as FrameLayout.LayoutParams
+        lp.gravity = Gravity.RIGHT or Gravity.CENTER_VERTICAL
+        out.layoutParams = lp
+    }
+
+    override fun setTaskIconParams(
+        iconParams: FrameLayout.LayoutParams,
+        taskIconMargin: Int,
+        taskIconHeight: Int,
+        thumbnailTopMargin: Int,
+        isRtl: Boolean
+    ) {
+        iconParams.gravity =
+            if (isRtl) {
+                Gravity.END or Gravity.CENTER_VERTICAL
+            } else {
+                Gravity.START or Gravity.CENTER_VERTICAL
+            }
+        iconParams.setMargins(-taskIconHeight - taskIconMargin / 2, thumbnailTopMargin / 2, 0, 0)
+    }
+
+    override fun setIconAppChipChildrenParams(
+        iconParams: FrameLayout.LayoutParams,
+        chipChildMarginStart: Int
+    ) {
+        iconParams.setMargins(0, 0, 0, 0)
+        iconParams.marginStart = chipChildMarginStart
+        iconParams.gravity = Gravity.START or Gravity.CENTER_VERTICAL
+    }
+
+    override fun setIconAppChipMenuParams(
+        iconAppChipView: IconAppChipView,
+        iconMenuParams: FrameLayout.LayoutParams,
+        iconMenuMargin: Int,
+        thumbnailTopMargin: Int
+    ) {
+        val isRtl = iconAppChipView.layoutDirection == View.LAYOUT_DIRECTION_RTL
+        val iconCenter = iconAppChipView.getHeight() / 2f
+
+        if (isRtl) {
+            iconMenuParams.gravity = Gravity.TOP or Gravity.END
+            iconMenuParams.topMargin = iconMenuMargin
+            iconMenuParams.marginEnd = thumbnailTopMargin
+            // Use half menu height to place the pivot within the X/Y center of icon in the menu.
+            iconAppChipView.pivotX = iconMenuParams.width / 2f
+            iconAppChipView.pivotY = iconMenuParams.width / 2f
+        } else {
+            iconMenuParams.gravity = Gravity.BOTTOM or Gravity.START
+            iconMenuParams.topMargin = 0
+            iconMenuParams.marginEnd = 0
+            iconAppChipView.pivotX = iconCenter
+            iconAppChipView.pivotY = iconCenter - iconMenuMargin
+        }
+        iconMenuParams.marginStart = 0
+        iconMenuParams.bottomMargin = 0
+        iconAppChipView.setSplitTranslationY(0f)
+        iconAppChipView.setRotation(degreesRotated)
+    }
+
+    override fun measureGroupedTaskViewThumbnailBounds(
+        primarySnapshot: View,
+        secondarySnapshot: View,
+        parentWidth: Int,
+        parentHeight: Int,
+        splitBoundsConfig: SplitBounds,
+        dp: DeviceProfile,
+        isRtl: Boolean
+    ) {
+        val primaryParams = primarySnapshot.layoutParams as FrameLayout.LayoutParams
+        val secondaryParams = secondarySnapshot.layoutParams as FrameLayout.LayoutParams
+
+        // Swap the margins that are set in TaskView#setRecentsOrientedState()
+        secondaryParams.topMargin = dp.overviewTaskThumbnailTopMarginPx
+        primaryParams.topMargin = 0
+
+        // Measure and layout the thumbnails bottom up, since the primary is on the visual left
+        // (portrait bottom) and secondary is on the right (portrait top)
+        val spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx
+        val totalThumbnailHeight = parentHeight - spaceAboveSnapshot
+        val dividerBar = getDividerBarSize(totalThumbnailHeight, splitBoundsConfig)
+
+        val (taskViewFirst, taskViewSecond) =
+            getGroupedTaskViewSizes(dp, splitBoundsConfig, parentWidth, parentHeight)
+        secondarySnapshot.translationY = 0f
+        primarySnapshot.translationY =
+            (taskViewSecond.y + spaceAboveSnapshot + dividerBar).toFloat()
+        primarySnapshot.measure(
+            MeasureSpec.makeMeasureSpec(taskViewFirst.x, MeasureSpec.EXACTLY),
+            MeasureSpec.makeMeasureSpec(taskViewFirst.y, MeasureSpec.EXACTLY)
+        )
+        secondarySnapshot.measure(
+            MeasureSpec.makeMeasureSpec(taskViewSecond.x, MeasureSpec.EXACTLY),
+            MeasureSpec.makeMeasureSpec(taskViewSecond.y, MeasureSpec.EXACTLY)
+        )
+    }
+
+    override fun getGroupedTaskViewSizes(
+        dp: DeviceProfile,
+        splitBoundsConfig: SplitBounds,
+        parentWidth: Int,
+        parentHeight: Int
+    ): Pair<Point, Point> {
+        // Measure and layout the thumbnails bottom up, since the primary is on the visual left
+        // (portrait bottom) and secondary is on the right (portrait top)
+        val spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx
+        val totalThumbnailHeight = parentHeight - spaceAboveSnapshot
+        val dividerBar = getDividerBarSize(totalThumbnailHeight, splitBoundsConfig)
+
+        val taskPercent =
+            if (splitBoundsConfig.appsStackedVertically) {
+                splitBoundsConfig.topTaskPercent
+            } else {
+                splitBoundsConfig.leftTaskPercent
+            }
+        val firstTaskViewSize = Point(parentWidth, (totalThumbnailHeight * taskPercent).toInt())
+        val secondTaskViewSize =
+            Point(parentWidth, totalThumbnailHeight - firstTaskViewSize.y - dividerBar)
+        return Pair(firstTaskViewSize, secondTaskViewSize)
+    }
+
+    /* ---------- The following are only used by TaskViewTouchHandler. ---------- */
+    override val upDownSwipeDirection: SingleAxisSwipeDetector.Direction =
+        SingleAxisSwipeDetector.HORIZONTAL
+
+    override fun getUpDirection(isRtl: Boolean): Int =
+        if (isRtl) SingleAxisSwipeDetector.DIRECTION_POSITIVE
+        else SingleAxisSwipeDetector.DIRECTION_NEGATIVE
+
+    override fun isGoingUp(displacement: Float, isRtl: Boolean): Boolean =
+        if (isRtl) displacement > 0 else displacement < 0
+
+    override fun getTaskDragDisplacementFactor(isRtl: Boolean): Int = if (isRtl) -1 else 1
+    /* -------------------- */
+
+    override fun getSplitIconsPosition(
+        taskIconHeight: Int,
+        primarySnapshotHeight: Int,
+        totalThumbnailHeight: Int,
+        isRtl: Boolean,
+        overviewTaskMarginPx: Int,
+        dividerSize: Int,
+    ): SplitIconPositions {
+        return if (Flags.enableOverviewIconMenu()) {
+            if (isRtl) {
+                SplitIconPositions(
+                    topLeftY = totalThumbnailHeight - primarySnapshotHeight,
+                    bottomRightY = 0
+                )
+            } else {
+                SplitIconPositions(
+                    topLeftY = 0,
+                    bottomRightY = -(primarySnapshotHeight + dividerSize)
+                )
+            }
+        } else {
+            // In seascape, the icons are initially placed at the bottom start of the
+            // display (portrait locked). The values defined here are used to translate the icons
+            // from the bottom to the almost-center of the screen using the bottom margin.
+            // The primary snapshot is placed at the bottom, thus we translate the icons using
+            // the size of the primary snapshot minus the icon size for the top-left icon.
+            SplitIconPositions(
+                topLeftY = primarySnapshotHeight - taskIconHeight,
+                bottomRightY = primarySnapshotHeight + dividerSize
+            )
+        }
+    }
+
+    /**
+     * Updates icon view gravity and translation for split tasks
+     *
+     * @param iconView View to be updated
+     * @param translationY the translationY that should be applied
+     * @param isRtl Whether the layout direction is RTL (or false for LTR).
+     */
+    @SuppressLint("RtlHardcoded")
+    override fun updateSplitIconsPosition(iconView: View, translationY: Int, isRtl: Boolean) {
+        val layoutParams = iconView.layoutParams as FrameLayout.LayoutParams
+
+        if (Flags.enableOverviewIconMenu()) {
+            val appChipView = iconView as IconAppChipView
+            layoutParams.gravity =
+                if (isRtl) Gravity.TOP or Gravity.END else Gravity.BOTTOM or Gravity.START
+            appChipView.layoutParams = layoutParams
+            appChipView.setSplitTranslationX(0f)
+            appChipView.setSplitTranslationY(translationY.toFloat())
+        } else {
+            layoutParams.gravity = Gravity.BOTTOM or Gravity.LEFT
+            iconView.translationX = 0f
+            iconView.translationY = 0f
+            layoutParams.bottomMargin = translationY
+            iconView.layoutParams = layoutParams
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
index aeec36f..5efbb40 100644
--- a/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
+++ b/quickstep/src/com/android/quickstep/util/ActivityInitListener.java
@@ -57,16 +57,16 @@
      * Registers the activity-created listener. If the activity is already created, then the
      * callback provided in the constructor will be called synchronously.
      */
-    public void register() {
+    public void register(String reasonString) {
         mIsRegistered = true;
-        mActivityTracker.registerCallback(this);
+        mActivityTracker.registerCallback(this, reasonString);
     }
 
     /**
      * After calling this, we won't {@link #init} even when the activity is ready.
      */
-    public void unregister() {
-        mActivityTracker.unregisterCallback(this);
+    public void unregister(String reasonString) {
+        mActivityTracker.unregisterCallback(this, reasonString);
         mIsRegistered = false;
         mOnInitListener = null;
     }
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
index 16f2065..c9647f5 100644
--- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -18,7 +18,6 @@
 import static com.android.app.animation.Interpolators.DECELERATE;
 import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
-import static com.android.launcher3.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
 
@@ -35,17 +34,17 @@
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.statemanager.StateManager;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.touch.AllAppsSwipeController;
+import com.android.quickstep.DeviceConfigWrapper;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * Controls an animation that can go beyond progress = 1, at which point resistance should be
@@ -159,11 +158,12 @@
         PendingAnimation resistAnim = createRecentsResistanceAnim(params);
 
         // Apply All Apps animation during the resistance animation.
-        if (recentsOrientedState.getActivityInterface().allowAllAppsFromOverview()) {
-            StatefulActivity activity =
-                    recentsOrientedState.getActivityInterface().getCreatedActivity();
-            if (activity != null) {
-                StateManager<LauncherState> stateManager = activity.getStateManager();
+        if (recentsOrientedState.getContainerInterface().allowAllAppsFromOverview()) {
+            RecentsViewContainer container =
+                    recentsOrientedState.getContainerInterface().getCreatedContainer();
+            if (container != null) {
+                RecentsView recentsView = container.getOverviewPanel();
+                StateManager<LauncherState> stateManager = recentsView.getStateManager();
                 if (stateManager.isInStableState(LauncherState.BACKGROUND_APP)
                         && stateManager.isInTransition()) {
 
@@ -186,12 +186,12 @@
     private static float getAllAppsThreshold(Context context,
             RecentsOrientedState recentsOrientedState, DeviceProfile dp) {
         int transitionDragLength =
-                recentsOrientedState.getActivityInterface().getSwipeUpDestinationAndLength(
+                recentsOrientedState.getContainerInterface().getSwipeUpDestinationAndLength(
                         dp, context, TEMP_RECT,
                         recentsOrientedState.getOrientationHandler());
         float dragLengthFactor = (float) dp.heightPx / transitionDragLength;
         // -1s are because 0-1 is reserved for the normal transition.
-        float threshold = LauncherPrefs.get(context).get(ALL_APPS_OVERVIEW_THRESHOLD) / 100f;
+        float threshold = DeviceConfigWrapper.get().getAllAppsOverviewThreshold() / 100f;
         return (threshold - 1) / (dragLengthFactor - 1);
     }
 
@@ -204,7 +204,7 @@
         Rect startRect = new Rect();
         RecentsPagedOrientationHandler orientationHandler = params.recentsOrientedState
                 .getOrientationHandler();
-        params.recentsOrientedState.getActivityInterface()
+        params.recentsOrientedState.getContainerInterface()
                 .calculateTaskSize(params.context, params.dp, startRect, orientationHandler);
         long distanceToCover = startRect.bottom;
         PendingAnimation resistAnim = params.resistAnim != null
@@ -304,14 +304,14 @@
             this.translationProperty = translationProperty;
             if (dp.isTablet) {
                 resistanceParams =
-                        recentsOrientedState.getActivityInterface().allowAllAppsFromOverview()
+                        recentsOrientedState.getContainerInterface().allowAllAppsFromOverview()
                                 ? RecentsResistanceParams.FROM_APP_TO_ALL_APPS_TABLET
                                 : enableGridOnlyOverview()
                                         ? RecentsResistanceParams.FROM_APP_TABLET_GRID_ONLY
                                         : RecentsResistanceParams.FROM_APP_TABLET;
             } else {
                 resistanceParams =
-                        recentsOrientedState.getActivityInterface().allowAllAppsFromOverview()
+                        recentsOrientedState.getContainerInterface().allowAllAppsFromOverview()
                                 ? RecentsResistanceParams.FROM_APP_TO_ALL_APPS
                                 : RecentsResistanceParams.FROM_APP;
             }
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index 59bf105..3f06571 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -42,10 +42,8 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.jank.Cuj;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.R;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.allapps.AllAppsStore;
 import com.android.launcher3.apppairs.AppPairIcon;
@@ -57,8 +55,10 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TopTaskTracker;
 import com.android.quickstep.views.GroupedTaskView;
@@ -158,11 +158,9 @@
                 member.bitmap = iconCache.getDefaultIcon(newAppPair.user);
                 iconCache.getTitleAndIcon(member, member.usingLowResIcon());
             });
-            newAppPair.title = getDefaultTitle(newAppPair.getFirstApp().title,
-                    newAppPair.getSecondApp().title);
             MAIN_EXECUTOR.execute(() -> {
                 LauncherAccessibilityDelegate delegate =
-                        Launcher.getLauncher(mContext).getAccessibilityDelegate();
+                        QuickstepLauncher.getLauncher(mContext).getAccessibilityDelegate();
                 if (delegate != null) {
                     delegate.addToWorkspace(newAppPair, true, (success) -> {
                         if (success) {
@@ -241,7 +239,8 @@
             return null;
         }
 
-        AllAppsStore appsStore = Launcher.getLauncher(mContext).getAppsView().getAppsStore();
+        AllAppsStore appsStore = ActivityContext.lookupContext(mContext)
+                .getAppsView().getAppsStore();
 
         // Lookup by ComponentKey
         AppInfo appInfo = appsStore.getApp(key);
@@ -489,13 +488,6 @@
     }
 
     /**
-     * Returns a formatted default title for the app pair.
-     */
-    public String getDefaultTitle(CharSequence app1, CharSequence app2) {
-        return mContext.getString(R.string.app_pair_default_title, app1, app2);
-    }
-
-    /**
      * Gets the TopTaskTracker, which is a cached record of the top running Task.
      */
     @VisibleForTesting
diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
index a854656..a3904bc 100644
--- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java
+++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
@@ -52,6 +52,38 @@
         return Optional.empty();
     }
 
+    /** Get the Launcher overridden long press nav handle duration to trigger Assistant. */
+    public Optional<Long> getLPNHDurationMillis() {
+        return Optional.empty();
+    }
+
+    /**
+     * Get the Launcher overridden long press nav handle touch slop multiplier to trigger Assistant.
+     */
+    public Optional<Float> getLPNHCustomSlopMultiplier() {
+        return Optional.empty();
+    }
+
+    /** Get the Launcher overridden long press home duration to trigger Assistant. */
+    public Optional<Long> getLPHDurationMillis() {
+        return Optional.empty();
+    }
+
+    /** Get the Launcher overridden long press home touch slop multiplier to trigger Assistant. */
+    public Optional<Float> getLPHCustomSlopMultiplier() {
+        return Optional.empty();
+    }
+
+    /** Get the long press duration data source. */
+    public int getDurationDataSource() {
+        return 0;
+    }
+
+    /** Get the long press touch slop multiplier data source. */
+    public int getSlopDataSource() {
+        return 0;
+    }
+
     /** Return {@code true} if the Settings toggle is enabled. */
     public boolean isSettingsAllEntrypointsEnabled() {
         return false;
diff --git a/quickstep/src/com/android/quickstep/util/BaseDepthController.java b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
index 99f564c..5d6bb1d 100644
--- a/quickstep/src/com/android/quickstep/util/BaseDepthController.java
+++ b/quickstep/src/com/android/quickstep/util/BaseDepthController.java
@@ -15,6 +15,8 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
+
 import android.app.WallpaperManager;
 import android.os.IBinder;
 import android.util.FloatProperty;
@@ -33,6 +35,9 @@
  * Utility class for applying depth effect
  */
 public class BaseDepthController {
+    public static final float DEPTH_0_PERCENT = 0f;
+    public static final float DEPTH_60_PERCENT = 0.6f;
+    public static final float DEPTH_70_PERCENT = 0.7f;
 
     private static final FloatProperty<BaseDepthController> DEPTH =
             new FloatProperty<BaseDepthController>("depth") {
@@ -127,10 +132,14 @@
         float depth = mDepth;
         IBinder windowToken = mLauncher.getRootView().getWindowToken();
         if (windowToken != null) {
-            // The API's full zoom-out is three times larger than the zoom-out we apply to the
-            // icons. To keep the two consistent throughout the animation while keeping Launcher's
-            // concept of full depth unchanged, we divide the depth by 3 here.
-            mWallpaperManager.setWallpaperZoomOut(windowToken, depth / 3);
+            if (enableScalingRevealHomeAnimation()) {
+                mWallpaperManager.setWallpaperZoomOut(windowToken, depth);
+            } else {
+                // The API's full zoom-out is three times larger than the zoom-out we apply to the
+                // icons. To keep the two consistent throughout the animation while keeping
+                // Launcher's concept of full depth unchanged, we divide the depth by 3 here.
+                mWallpaperManager.setWallpaperZoomOut(windowToken, depth / 3);
+            }
         }
 
         if (!BlurUtils.supportsBlursOnWindows()) {
@@ -150,8 +159,15 @@
         boolean hasOpaqueBg = mLauncher.getScrimView().isFullyOpaque();
         boolean isSurfaceOpaque = !mHasContentBehindLauncher && hasOpaqueBg && !mPauseBlurs;
 
+        float blurAmount;
+        if (enableScalingRevealHomeAnimation()) {
+            blurAmount = mapDepthToBlur(depth);
+        } else {
+            blurAmount = depth;
+        }
         mCurrentBlur = !mCrossWindowBlursEnabled || hasOpaqueBg || mPauseBlurs
-                ? 0 : (int) (depth * mMaxBlurRadius);
+                ? 0 : (int) (blurAmount * mMaxBlurRadius);
+
         SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()
                 .setBackgroundBlurRadius(mSurface, mCurrentBlur)
                 .setOpaque(mSurface, isSurfaceOpaque);
@@ -197,4 +213,12 @@
             applyDepthAndBlur();
         }
     }
+
+    /**
+     * Maps depth values to blur amounts as a percentage of the max blur.
+     * The blur percentage grows linearly with depth, and maxes out at 30% depth.
+     */
+    private static float mapDepthToBlur(float depth) {
+        return Math.min(3 * depth, 1f);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
new file mode 100644
index 0000000..544c64d
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/DeviceConfigHelper.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util
+
+import android.app.ActivityThread
+import android.content.Context
+import android.content.SharedPreferences
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener
+import android.provider.DeviceConfig
+import android.provider.DeviceConfig.OnPropertiesChangedListener
+import android.provider.DeviceConfig.Properties
+import androidx.annotation.WorkerThread
+import com.android.launcher3.BuildConfig
+import com.android.launcher3.util.Executors
+
+/** Utility class to manage a set of device configurations */
+class DeviceConfigHelper<ConfigType>(private val factory: (PropReader) -> ConfigType) {
+
+    var config: ConfigType
+        private set
+    private val allKeys: Set<String>
+    private val propertiesListener = OnPropertiesChangedListener { onDevicePropsChanges(it) }
+    private val sharedPrefChangeListener = OnSharedPreferenceChangeListener { _, _ ->
+        recreateConfig()
+    }
+
+    private val changeListeners = mutableListOf<Runnable>()
+
+    init {
+        // Initialize the default config once.
+        allKeys = HashSet()
+        config =
+            factory(
+                PropReader(
+                    object : PropProvider {
+                        override fun <T : Any> get(key: String, fallback: T): T {
+                            if (fallback is Int)
+                                return DeviceConfig.getInt(NAMESPACE_LAUNCHER, key, fallback) as T
+                            else if (fallback is Boolean)
+                                return DeviceConfig.getBoolean(NAMESPACE_LAUNCHER, key, fallback)
+                                    as T
+                            else return fallback
+                        }
+                    }
+                )
+            )
+
+        DeviceConfig.addOnPropertiesChangedListener(
+            NAMESPACE_LAUNCHER,
+            Executors.UI_HELPER_EXECUTOR,
+            propertiesListener
+        )
+        if (BuildConfig.IS_DEBUG_DEVICE) {
+            prefs.registerOnSharedPreferenceChangeListener(sharedPrefChangeListener)
+        }
+    }
+
+    @WorkerThread
+    private fun onDevicePropsChanges(properties: Properties) {
+        if (NAMESPACE_LAUNCHER != properties.namespace) return
+        if (!allKeys.any(properties.keyset::contains)) return
+        recreateConfig()
+    }
+
+    private fun recreateConfig() {
+        val myProps =
+            DeviceConfig.getProperties(NAMESPACE_LAUNCHER, *allKeys.toTypedArray<String>())
+        config =
+            factory(
+                PropReader(
+                    object : PropProvider {
+                        override fun <T : Any> get(key: String, fallback: T): T {
+                            if (fallback is Int) return myProps.getInt(key, fallback) as T
+                            else if (fallback is Boolean)
+                                return myProps.getBoolean(key, fallback) as T
+                            else return fallback
+                        }
+                    }
+                )
+            )
+        Executors.MAIN_EXECUTOR.execute { changeListeners.forEach(Runnable::run) }
+    }
+
+    /** Adds a listener for property changes */
+    fun addChangeListener(r: Runnable) = changeListeners.add(r)
+
+    /** Removes a previously added listener */
+    fun removeChangeListener(r: Runnable) = changeListeners.remove(r)
+
+    fun close() {
+        DeviceConfig.removeOnPropertiesChangedListener(propertiesListener)
+        if (BuildConfig.IS_DEBUG_DEVICE) {
+            prefs.unregisterOnSharedPreferenceChangeListener(sharedPrefChangeListener)
+        }
+    }
+
+    internal interface PropProvider {
+        fun <T : Any> get(key: String, fallback: T): T
+    }
+
+    /** The reader is sent to the config for initialization */
+    class PropReader internal constructor(private val f: PropProvider) {
+
+        @JvmOverloads
+        fun <T : Any> get(key: String, fallback: T, desc: String? = null): T {
+            val v = f.get(key, fallback)
+            if (BuildConfig.IS_DEBUG_DEVICE && desc != null) {
+                if (v is Int) {
+                    allProps[key] = DebugInfo(key, desc, true, fallback)
+                    return prefs.getInt(key, v) as T
+                } else if (v is Boolean) {
+                    allProps[key] = DebugInfo(key, desc, false, fallback)
+                    return prefs.getBoolean(key, v) as T
+                }
+            }
+            return v
+        }
+    }
+
+    class DebugInfo<T>(
+        val key: String,
+        val desc: String,
+        val isInt: Boolean,
+        val valueInCode: T,
+    )
+
+    companion object {
+        const val NAMESPACE_LAUNCHER = "launcher"
+
+        val allProps = mutableMapOf<String, DebugInfo<*>>()
+
+        private const val FLAGS_PREF_NAME = "featureFlags"
+
+        val prefs: SharedPreferences by lazy {
+            ActivityThread.currentApplication()
+                .createDeviceProtectedStorageContext()
+                .getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
+        }
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt b/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt
index 32a15a2..e6e94e6 100644
--- a/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt
+++ b/quickstep/src/com/android/quickstep/util/FadeOutRemoteTransition.kt
@@ -20,30 +20,15 @@
 import android.os.RemoteException
 import android.view.SurfaceControl
 import android.view.SurfaceControl.Transaction
-import android.window.IRemoteTransition
 import android.window.IRemoteTransitionFinishedCallback
+import android.window.RemoteTransitionStub
 import android.window.TransitionInfo
 import com.android.launcher3.anim.AnimatorListeners.forEndCallback
 import com.android.launcher3.util.Executors
 import com.android.wm.shell.shared.TransitionUtil
 
 /** Remote animation which fades out the closing targets */
-class FadeOutRemoteTransition : IRemoteTransition.Stub() {
-
-    override fun mergeAnimation(
-        iBinder: IBinder,
-        transitionInfo: TransitionInfo,
-        transaction: Transaction,
-        mergeTarget: IBinder,
-        finishCB: IRemoteTransitionFinishedCallback
-    ) {
-
-        try {
-            finishCB.onTransitionFinished(null, Transaction())
-        } catch (e: RemoteException) {
-            // Ignore
-        }
-    }
+class FadeOutRemoteTransition : RemoteTransitionStub() {
 
     override fun startAnimation(
         transition: IBinder,
@@ -83,6 +68,4 @@
 
         Executors.MAIN_EXECUTOR.execute { anim.start() }
     }
-
-    override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {}
 }
diff --git a/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java
index 8209c09..843619d 100644
--- a/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java
+++ b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java
@@ -17,11 +17,11 @@
 
 import androidx.annotation.UiThread;
 
-import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.BaseContainerInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
+import com.android.quickstep.views.RecentsViewContainer;
 
 import java.util.function.Supplier;
 
@@ -31,13 +31,13 @@
  */
 public class InputProxyHandlerFactory implements Supplier<InputConsumer> {
 
-    private final BaseActivityInterface mActivityInterface;
+    private final BaseContainerInterface mContainerInterface;
     private final GestureState mGestureState;
 
     @UiThread
-    public InputProxyHandlerFactory(BaseActivityInterface activityInterface,
+    public InputProxyHandlerFactory(BaseContainerInterface activityInterface,
             GestureState gestureState) {
-        mActivityInterface = activityInterface;
+        mContainerInterface = activityInterface;
         mGestureState = gestureState;
     }
 
@@ -46,8 +46,8 @@
      */
     @Override
     public InputConsumer get() {
-        StatefulActivity activity = mActivityInterface.getCreatedActivity();
-        return activity == null ? InputConsumer.NO_OP
-                : new OverviewInputConsumer(mGestureState, activity, null, true);
+        RecentsViewContainer container = mContainerInterface.getCreatedContainer();
+        return container == null ? InputConsumer.NO_OP
+                : new OverviewInputConsumer(mGestureState, container, null, true);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
index 61ba5ac..4474f33 100644
--- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
+++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java
@@ -30,9 +30,9 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.Hotseat;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.HorizontalInsettableView;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.unfold.LauncherJankMonitorTransitionProgressListener;
@@ -56,7 +56,7 @@
     private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
             HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
 
-    private final Launcher mLauncher;
+    private final QuickstepLauncher mLauncher;
     private final ScopedUnfoldTransitionProgressProvider mProgressProvider;
     private final NaturalRotationUnfoldProgressProvider mNaturalOrientationProgressProvider;
     private final UnfoldMoveFromCenterHotseatAnimator mUnfoldMoveFromCenterHotseatAnimator;
@@ -73,7 +73,7 @@
     private HorizontalInsettableView mQsbInsettable;
 
     public LauncherUnfoldAnimationController(
-            Launcher launcher,
+            QuickstepLauncher launcher,
             WindowManager windowManager,
             UnfoldTransitionProgressProvider unfoldTransitionProgressProvider,
             RotationChangeProvider rotationChangeProvider) {
diff --git a/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java b/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
index 1d008da..0b05c2e 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
@@ -19,39 +19,40 @@
 
 import android.animation.Animator;
 import android.animation.ObjectAnimator;
+import android.content.Context;
 
 import androidx.dynamicanimation.animation.DynamicAnimation;
 
 import com.android.launcher3.anim.SpringAnimationBuilder;
 import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 
-public class RecentsAtomicAnimationFactory<ACTIVITY_TYPE extends StatefulActivity, STATE_TYPE>
-        extends AtomicAnimationFactory<STATE_TYPE> {
+public class RecentsAtomicAnimationFactory<CONTAINER extends Context & RecentsViewContainer,
+        STATE_TYPE> extends AtomicAnimationFactory<STATE_TYPE> {
 
     public static final int INDEX_RECENTS_FADE_ANIM = AtomicAnimationFactory.NEXT_INDEX + 0;
     public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = AtomicAnimationFactory.NEXT_INDEX + 1;
 
     private static final int MY_ANIM_COUNT = 2;
 
-    protected final ACTIVITY_TYPE mActivity;
+    protected final CONTAINER mContainer;
 
-    public RecentsAtomicAnimationFactory(ACTIVITY_TYPE activity) {
+    public RecentsAtomicAnimationFactory(CONTAINER container) {
         super(MY_ANIM_COUNT);
-        mActivity = activity;
+        mContainer = container;
     }
 
     @Override
     public Animator createStateElementAnimation(int index, float... values) {
         switch (index) {
             case INDEX_RECENTS_FADE_ANIM:
-                ObjectAnimator alpha = ObjectAnimator.ofFloat(mActivity.getOverviewPanel(),
+                ObjectAnimator alpha = ObjectAnimator.ofFloat(mContainer.getOverviewPanel(),
                         RecentsView.CONTENT_ALPHA, values);
                 return alpha;
             case INDEX_RECENTS_TRANSLATE_X_ANIM: {
-                RecentsView rv = mActivity.getOverviewPanel();
-                return new SpringAnimationBuilder(mActivity)
+                RecentsView rv = mContainer.getOverviewPanel();
+                return new SpringAnimationBuilder(mContainer)
                         .setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE)
                         .setDampingRatio(0.8f)
                         .setStiffness(250)
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index cba628b..9335e7e 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -50,7 +50,7 @@
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.SettingsCache;
-import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.BaseContainerInterface;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskAnimationManager;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
@@ -118,7 +118,7 @@
                     | FLAG_SWIPE_UP_NOT_RUNNING;
 
     private final Context mContext;
-    private final BaseActivityInterface mActivityInterface;
+    private final BaseContainerInterface mContainerInterface;
     private final OrientationEventListener mOrientationListener;
     private final SettingsCache mSettingsCache;
     private final SettingsCache.OnChangeListener mRotationChangeListener =
@@ -138,10 +138,10 @@
      *                              is enabled
      * @see #setRotationWatcherEnabled(boolean)
      */
-    public RecentsOrientedState(Context context, BaseActivityInterface activityInterface,
+    public RecentsOrientedState(Context context, BaseContainerInterface containerInterface,
             IntConsumer rotationChangeListener) {
         mContext = context;
-        mActivityInterface = activityInterface;
+        mContainerInterface = containerInterface;
         mOrientationListener = new OrientationEventListener(context) {
             @Override
             public void onOrientationChanged(int degrees) {
@@ -153,7 +153,7 @@
             }
         };
 
-        mFlags = mActivityInterface.rotationSupportedByActivity
+        mFlags = mContainerInterface.rotationSupportedByActivity
                 ? FLAG_MULTIPLE_ORIENTATION_SUPPORTED_BY_ACTIVITY : 0;
 
         mFlags |= FLAG_SWIPE_UP_NOT_RUNNING;
@@ -161,8 +161,8 @@
         initFlags();
     }
 
-    public BaseActivityInterface getActivityInterface() {
-        return mActivityInterface;
+    public BaseContainerInterface getContainerInterface() {
+        return mContainerInterface;
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
index 245dde2..c39056d 100644
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -15,6 +15,8 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
+
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.animation.Animator;
@@ -104,6 +106,8 @@
     private float mCurrentScaleProgress;
     private FlingSpringAnim mRectXAnim;
     private FlingSpringAnim mRectYAnim;
+    private SpringAnimation mRectXSpring;
+    private SpringAnimation mRectYSpring;
     private SpringAnimation mRectScaleAnim;
     private boolean mAnimsStarted;
     private boolean mRectXAnimEnded;
@@ -166,27 +170,47 @@
     }
 
     public void onTargetPositionChanged() {
-        if (mRectXAnim != null && mRectXAnim.getTargetPosition() != mTargetRect.centerX()) {
-            mRectXAnim.updatePosition(mCurrentCenterX, mTargetRect.centerX());
-        }
+        if (enableScalingRevealHomeAnimation()) {
+            if (mRectXSpring != null) {
+                mRectXSpring.animateToFinalPosition(mTargetRect.centerX());
+            }
 
-        if (mRectYAnim != null) {
-            switch (mTracking) {
-                case TRACKING_TOP:
-                    if (mRectYAnim.getTargetPosition() != mTargetRect.top) {
-                        mRectYAnim.updatePosition(mCurrentY, mTargetRect.top);
-                    }
-                    break;
-                case TRACKING_BOTTOM:
-                    if (mRectYAnim.getTargetPosition() != mTargetRect.bottom) {
-                        mRectYAnim.updatePosition(mCurrentY, mTargetRect.bottom);
-                    }
-                    break;
-                case TRACKING_CENTER:
-                    if (mRectYAnim.getTargetPosition() != mTargetRect.centerY()) {
-                        mRectYAnim.updatePosition(mCurrentY, mTargetRect.centerY());
-                    }
-                    break;
+            if (mRectYSpring != null) {
+                switch (mTracking) {
+                    case TRACKING_TOP:
+                        mRectYSpring.animateToFinalPosition(mTargetRect.top);
+                        break;
+                    case TRACKING_BOTTOM:
+                        mRectYSpring.animateToFinalPosition(mTargetRect.bottom);
+                        break;
+                    case TRACKING_CENTER:
+                        mRectYSpring.animateToFinalPosition(mTargetRect.centerY());
+                        break;
+                }
+            }
+        } else {
+            if (mRectXAnim != null && mRectXAnim.getTargetPosition() != mTargetRect.centerX()) {
+                mRectXAnim.updatePosition(mCurrentCenterX, mTargetRect.centerX());
+            }
+
+            if (mRectYAnim != null) {
+                switch (mTracking) {
+                    case TRACKING_TOP:
+                        if (mRectYAnim.getTargetPosition() != mTargetRect.top) {
+                            mRectYAnim.updatePosition(mCurrentY, mTargetRect.top);
+                        }
+                        break;
+                    case TRACKING_BOTTOM:
+                        if (mRectYAnim.getTargetPosition() != mTargetRect.bottom) {
+                            mRectYAnim.updatePosition(mCurrentY, mTargetRect.bottom);
+                        }
+                        break;
+                    case TRACKING_CENTER:
+                        if (mRectYAnim.getTargetPosition() != mTargetRect.centerY()) {
+                            mRectYAnim.updatePosition(mCurrentY, mTargetRect.centerY());
+                        }
+                        break;
+                }
             }
         }
     }
@@ -215,59 +239,126 @@
             maybeOnEnd();
         });
 
-        // We dampen the user velocity here to keep the natural feeling and to prevent the
-        // rect from straying too from a linear path.
-        final float xVelocityPxPerS = velocityPxPerMs.x * 1000;
-        final float yVelocityPxPerS = velocityPxPerMs.y * 1000;
-        final float dampedXVelocityPxPerS = OverScroll.dampedScroll(
-                Math.abs(xVelocityPxPerS), mMaxVelocityPxPerS) * Math.signum(xVelocityPxPerS);
-        final float dampedYVelocityPxPerS = OverScroll.dampedScroll(
-                Math.abs(yVelocityPxPerS), mMaxVelocityPxPerS) * Math.signum(yVelocityPxPerS);
-
+        float xVelocityPxPerS = velocityPxPerMs.x * 1000;
+        float yVelocityPxPerS = velocityPxPerMs.y * 1000;
         float startX = mCurrentCenterX;
         float endX = mTargetRect.centerX();
-        float minXValue = Math.min(startX, endX);
-        float maxXValue = Math.max(startX, endX);
-
-        mRectXAnim = new FlingSpringAnim(this, context, RECT_CENTER_X, startX, endX,
-                dampedXVelocityPxPerS, mMinVisChange, minXValue, maxXValue, mDampingX, mStiffnessX,
-                onXEndListener);
-
         float startY = mCurrentY;
         float endY = getTrackedYFromRect(mTargetRect);
-        float minYValue = Math.min(startY, endY);
-        float maxYValue = Math.max(startY, endY);
-        mRectYAnim = new FlingSpringAnim(this, context, RECT_Y, startY, endY, dampedYVelocityPxPerS,
-                mMinVisChange, minYValue, maxYValue, mDampingY, mStiffnessY, onYEndListener);
-
         float minVisibleChange = Math.abs(1f / mStartRect.height());
-        ResourceProvider rp = DynamicResource.provider(context);
-        float damping = rp.getFloat(R.dimen.swipe_up_rect_scale_damping_ratio);
 
-        // Increase the stiffness for devices where we want the window size to transform quicker.
-        boolean shouldUseHigherStiffness = profile != null
-                && (profile.isLandscape || profile.isTablet);
-        float stiffness = shouldUseHigherStiffness
-                ? rp.getFloat(R.dimen.swipe_up_rect_scale_higher_stiffness)
-                : rp.getFloat(R.dimen.swipe_up_rect_scale_stiffness);
+        if (enableScalingRevealHomeAnimation()) {
+            ResourceProvider rp = DynamicResource.provider(context);
+            long minVelocityXPxPerS = rp.getInt(R.dimen.swipe_up_min_velocity_x_px_per_s);
+            long maxVelocityXPxPerS = rp.getInt(R.dimen.swipe_up_max_velocity_x_px_per_s);
+            long minVelocityYPxPerS = rp.getInt(R.dimen.swipe_up_min_velocity_y_px_per_s);
+            long maxVelocityYPxPerS = rp.getInt(R.dimen.swipe_up_max_velocity_y_px_per_s);
+            float fallOffFactor = rp.getFloat(R.dimen.swipe_up_max_velocity_fall_off_factor);
 
-        mRectScaleAnim = new SpringAnimation(this, RECT_SCALE_PROGRESS)
-                .setSpring(new SpringForce(1f)
-                .setDampingRatio(damping)
-                .setStiffness(stiffness))
-                .setStartVelocity(velocityPxPerMs.y * minVisibleChange)
-                .setMaxValue(1f)
-                .setMinimumVisibleChange(minVisibleChange)
-                .addEndListener((animation, canceled, value, velocity) -> {
-                    mRectScaleAnimEnded = true;
-                    maybeOnEnd();
-                });
+            // We want the actual initial velocity to never dip below the minimum, and to taper off
+            // once it's above the soft cap so that we can prevent the window from flying off
+            // screen, while maintaining a natural feel.
+            xVelocityPxPerS = adjustVelocity(
+                    xVelocityPxPerS, minVelocityXPxPerS, maxVelocityXPxPerS, fallOffFactor);
+            yVelocityPxPerS = adjustVelocity(
+                    yVelocityPxPerS, minVelocityYPxPerS, maxVelocityYPxPerS, fallOffFactor);
 
-        setCanRelease(false);
-        mAnimsStarted = true;
+            float stiffnessX = rp.getFloat(R.dimen.swipe_up_rect_x_stiffness);
+            float dampingX = rp.getFloat(R.dimen.swipe_up_rect_x_damping_ratio);
+            mRectXSpring =
+                    new SpringAnimation(this, RECT_CENTER_X)
+                            .setSpring(
+                                    new SpringForce(endX)
+                                            .setStiffness(stiffnessX)
+                                            .setDampingRatio(dampingX)
+                            ).setStartValue(startX)
+                            .setStartVelocity(xVelocityPxPerS)
+                            .addEndListener(onXEndListener);
 
-        mRectXAnim.start();
-        mRectYAnim.start();
+            float stiffnessY = rp.getFloat(R.dimen.swipe_up_rect_y_stiffness);
+            float dampingY = rp.getFloat(R.dimen.swipe_up_rect_y_damping_ratio);
+            mRectYSpring =
+                    new SpringAnimation(this, RECT_Y)
+                            .setSpring(
+                                    new SpringForce(endY)
+                                            .setStiffness(stiffnessY)
+                                            .setDampingRatio(dampingY)
+                            )
+                            .setStartValue(startY)
+                            .setStartVelocity(yVelocityPxPerS)
+                            .addEndListener(onYEndListener);
+
+            float stiffnessZ = rp.getFloat(R.dimen.swipe_up_rect_scale_stiffness_v2);
+            float dampingZ = rp.getFloat(R.dimen.swipe_up_rect_scale_damping_ratio_v2);
+            mRectScaleAnim =
+                    new SpringAnimation(this, RECT_SCALE_PROGRESS)
+                            .setSpring(
+                                    new SpringForce(1f)
+                                            .setStiffness(stiffnessZ)
+                                            .setDampingRatio(dampingZ))
+                            .setStartVelocity(velocityPxPerMs.y * minVisibleChange)
+                            .setMinimumVisibleChange(minVisibleChange)
+                            .addEndListener((animation, canceled, value, velocity) -> {
+                                mRectScaleAnimEnded = true;
+                                maybeOnEnd();
+                            });
+
+            setCanRelease(false);
+            mAnimsStarted = true;
+
+            mRectXSpring.start();
+            mRectYSpring.start();
+        } else {
+            // We dampen the user velocity here to keep the natural feeling and to prevent the
+            // rect from straying too from a linear path.
+            final float dampedXVelocityPxPerS = OverScroll.dampedScroll(
+                    Math.abs(xVelocityPxPerS), mMaxVelocityPxPerS) * Math.signum(xVelocityPxPerS);
+            final float dampedYVelocityPxPerS = OverScroll.dampedScroll(
+                    Math.abs(yVelocityPxPerS), mMaxVelocityPxPerS) * Math.signum(yVelocityPxPerS);
+
+            float minXValue = Math.min(startX, endX);
+            float maxXValue = Math.max(startX, endX);
+
+            mRectXAnim = new FlingSpringAnim(this, context, RECT_CENTER_X, startX, endX,
+                    dampedXVelocityPxPerS, mMinVisChange, minXValue, maxXValue, mDampingX,
+                    mStiffnessX, onXEndListener);
+
+            float minYValue = Math.min(startY, endY);
+            float maxYValue = Math.max(startY, endY);
+            mRectYAnim = new FlingSpringAnim(this, context, RECT_Y, startY, endY,
+                    dampedYVelocityPxPerS, mMinVisChange, minYValue, maxYValue, mDampingY,
+                    mStiffnessY, onYEndListener);
+
+            ResourceProvider rp = DynamicResource.provider(context);
+            float damping = rp.getFloat(R.dimen.swipe_up_rect_scale_damping_ratio);
+
+            // Increase the stiffness for devices where we want the window size to transform
+            // quicker.
+            boolean shouldUseHigherStiffness = profile != null
+                    && (profile.isLandscape || profile.isTablet);
+            float stiffness = shouldUseHigherStiffness
+                    ? rp.getFloat(R.dimen.swipe_up_rect_scale_higher_stiffness)
+                    : rp.getFloat(R.dimen.swipe_up_rect_scale_stiffness);
+
+            mRectScaleAnim = new SpringAnimation(this, RECT_SCALE_PROGRESS)
+                    .setSpring(new SpringForce(1f)
+                            .setDampingRatio(damping)
+                            .setStiffness(stiffness))
+                    .setStartVelocity(velocityPxPerMs.y * minVisibleChange)
+                    .setMaxValue(1f)
+                    .setMinimumVisibleChange(minVisibleChange)
+                    .addEndListener((animation, canceled, value, velocity) -> {
+                        mRectScaleAnimEnded = true;
+                        maybeOnEnd();
+                    });
+
+            setCanRelease(false);
+            mAnimsStarted = true;
+
+            mRectXAnim.start();
+            mRectYAnim.start();
+        }
+
         mRectScaleAnim.start();
         for (Animator.AnimatorListener animatorListener : mAnimatorListeners) {
             animatorListener.onAnimationStart(null);
@@ -276,8 +367,17 @@
 
     public void end() {
         if (mAnimsStarted) {
-            mRectXAnim.end();
-            mRectYAnim.end();
+            if (enableScalingRevealHomeAnimation()) {
+                if (mRectXSpring.canSkipToEnd()) {
+                    mRectXSpring.skipToEnd();
+                }
+                if (mRectYSpring.canSkipToEnd()) {
+                    mRectYSpring.skipToEnd();
+                }
+            } else {
+                mRectXAnim.end();
+                mRectYAnim.end();
+            }
             if (mRectScaleAnim.canSkipToEnd()) {
                 mRectScaleAnim.skipToEnd();
             }
@@ -357,6 +457,32 @@
         end();
     }
 
+    /**
+     * Modify the given velocity so that it's never below the minimum value, and falls off by the
+     * given factor once it goes above the maximum value.
+     * In order for the max soft cap to be enforced, the fall-off factor must be >1.
+     */
+    private static float adjustVelocity(float velocity, long min, long max, float factor) {
+        float sign = Math.signum(velocity);
+        float magnitude = Math.abs(velocity);
+
+        // If the absolute velocity is less than the min, bump it up.
+        if (magnitude < min) {
+            return min * sign;
+        }
+
+        // If the absolute velocity falls between min and max, or the fall-off factor is invalid,
+        // do nothing.
+        if (magnitude <= max || factor <= 1) {
+            return velocity;
+        }
+
+        // Scale the excess velocity by the fall-off factor.
+        float excess = magnitude - max;
+        float scaled = (float) Math.pow(excess, 1f / factor);
+        return (max + scaled) * sign;
+    }
+
     public interface OnUpdateListener {
         /**
          * Called when an update is made to the animation.
diff --git a/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
new file mode 100644
index 0000000..48c2407
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/ScalingWorkspaceRevealAnim.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.util
+
+import android.view.View
+import com.android.app.animation.Interpolators
+import com.android.app.animation.Interpolators.EMPHASIZED
+import com.android.app.animation.Interpolators.LINEAR
+import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY
+import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE
+import com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY
+import com.android.launcher3.LauncherState
+import com.android.launcher3.anim.AnimatorListeners
+import com.android.launcher3.anim.PendingAnimation
+import com.android.launcher3.anim.PropertySetter
+import com.android.launcher3.states.StateAnimationConfig
+import com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER
+import com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW
+import com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM
+import com.android.launcher3.uioverrides.QuickstepLauncher
+import com.android.quickstep.views.RecentsView
+
+/**
+ * Creates an animation where the workspace and hotseat fade in while revealing from the center of
+ * the screen outwards radially. This is used in conjunction with the swipe up to home animation.
+ */
+class ScalingWorkspaceRevealAnim(launcher: QuickstepLauncher) {
+    companion object {
+        private const val FADE_DURATION_MS = 200L
+        private const val SCALE_DURATION_MS = 1000L
+        private const val MAX_ALPHA = 1f
+        private const val MIN_ALPHA = 0f
+        private const val MAX_SIZE = 1f
+        private const val MIN_SIZE = 0.85f
+    }
+
+    private val animation = PendingAnimation(SCALE_DURATION_MS)
+
+    init {
+        // Make sure the starting state is right for the animation.
+        val config = StateAnimationConfig()
+        config.animFlags = SKIP_OVERVIEW.or(SKIP_DEPTH_CONTROLLER).or(SKIP_SCRIM)
+        config.duration = 0
+        launcher.stateManager
+            .createAtomicAnimation(LauncherState.BACKGROUND_APP, LauncherState.NORMAL, config)
+            .start()
+        launcher
+            .getOverviewPanel<RecentsView<QuickstepLauncher, LauncherState>>()
+            .forceFinishScroller()
+        launcher.workspace.stateTransitionAnimation.setScrim(
+            PropertySetter.NO_ANIM_PROPERTY_SETTER,
+            LauncherState.BACKGROUND_APP,
+            config
+        )
+
+        val workspace = launcher.workspace
+        val hotseat = launcher.hotseat
+
+        // Scale the Workspace and Hotseat around the same pivot.
+        animation.addFloat(
+            workspace,
+            WORKSPACE_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE],
+            MIN_SIZE,
+            MAX_SIZE,
+            EMPHASIZED,
+        )
+        workspace.setPivotToScaleWithSelf(hotseat)
+        animation.addFloat(
+            hotseat,
+            HOTSEAT_SCALE_PROPERTY_FACTORY[SCALE_INDEX_WORKSPACE_STATE],
+            MIN_SIZE,
+            MAX_SIZE,
+            EMPHASIZED,
+        )
+
+        // Fade in quickly at the beginning of the animation, so the content doesn't look like it's
+        // popping into existence out of nowhere.
+        val fadeClamp = FADE_DURATION_MS.toFloat() / SCALE_DURATION_MS
+        workspace.alpha = MIN_ALPHA
+        animation.setViewAlpha(
+            workspace,
+            MAX_ALPHA,
+            Interpolators.clampToProgress(LINEAR, 0f, fadeClamp)
+        )
+        hotseat.alpha = MIN_ALPHA
+        animation.setViewAlpha(
+            hotseat,
+            MAX_ALPHA,
+            Interpolators.clampToProgress(LINEAR, 0f, fadeClamp)
+        )
+
+        // Match the Wallpaper animation to the rest of the content.
+        val depthController = (launcher as? QuickstepLauncher)?.depthController
+        val depthConfig = StateAnimationConfig()
+        depthConfig.setInterpolator(StateAnimationConfig.ANIM_DEPTH, EMPHASIZED)
+        depthController?.setStateWithAnimation(LauncherState.NORMAL, depthConfig, animation)
+
+        // Needed to avoid text artefacts during the scale animation.
+        workspace.setLayerType(View.LAYER_TYPE_HARDWARE, null)
+        hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null)
+        animation.addListener(
+            AnimatorListeners.forEndCallback(
+                Runnable {
+                    workspace.setLayerType(View.LAYER_TYPE_NONE, null)
+                    hotseat.setLayerType(View.LAYER_TYPE_NONE, null)
+                }
+            )
+        )
+    }
+
+    fun start() {
+        animation.buildAnim().start()
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt b/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt
index 9f7b46d..dbeedd3 100644
--- a/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt
+++ b/quickstep/src/com/android/quickstep/util/SlideInRemoteTransition.kt
@@ -23,8 +23,8 @@
 import android.os.RemoteException
 import android.view.SurfaceControl
 import android.view.SurfaceControl.Transaction
-import android.window.IRemoteTransition
 import android.window.IRemoteTransitionFinishedCallback
+import android.window.RemoteTransitionStub
 import android.window.TransitionInfo
 import com.android.launcher3.anim.AnimatorListeners.forEndCallback
 import com.android.launcher3.util.Executors
@@ -36,24 +36,9 @@
     private val pageSpacing: Int,
     private val cornerRadius: Float,
     private val interpolator: TimeInterpolator,
-) : IRemoteTransition.Stub() {
+) : RemoteTransitionStub() {
     private val animationDurationMs = 500L
 
-    override fun mergeAnimation(
-        iBinder: IBinder,
-        transitionInfo: TransitionInfo,
-        transaction: Transaction,
-        mergeTarget: IBinder,
-        finishCB: IRemoteTransitionFinishedCallback
-    ) {
-
-        try {
-            finishCB.onTransitionFinished(null, Transaction())
-        } catch (e: RemoteException) {
-            // Ignore
-        }
-    }
-
     override fun startAnimation(
         transition: IBinder,
         info: TransitionInfo,
@@ -121,6 +106,4 @@
 
         Executors.MAIN_EXECUTOR.execute { anim.start() }
     }
-
-    override fun onTransitionConsumed(transition: IBinder?, aborted: Boolean) {}
 }
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index a2d3859..021c455 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -24,6 +24,7 @@
 import android.animation.ValueAnimator
 import android.app.ActivityManager.RunningTaskInfo
 import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW
+import android.content.Context
 import android.graphics.Bitmap
 import android.graphics.Rect
 import android.graphics.RectF
@@ -41,8 +42,9 @@
 import com.android.app.animation.Interpolators
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.Flags.enableOverviewIconMenu
-import com.android.launcher3.Launcher
+import com.android.launcher3.InsettableFrameLayout
 import com.android.launcher3.QuickstepTransitionManager
+import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.launcher3.anim.PendingAnimation
 import com.android.launcher3.apppairs.AppPairIcon
@@ -50,8 +52,8 @@
 import com.android.launcher3.logging.StatsLogManager.EventEnum
 import com.android.launcher3.statehandlers.DepthController
 import com.android.launcher3.statemanager.StateManager
-import com.android.launcher3.statemanager.StatefulActivity
 import com.android.launcher3.taskbar.TaskbarActivityContext
+import com.android.launcher3.uioverrides.QuickstepLauncher
 import com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE
 import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
 import com.android.launcher3.views.BaseDragLayer
@@ -61,6 +63,7 @@
 import com.android.quickstep.views.GroupedTaskView
 import com.android.quickstep.views.IconAppChipView
 import com.android.quickstep.views.RecentsView
+import com.android.quickstep.views.RecentsViewContainer
 import com.android.quickstep.views.SplitInstructionsView
 import com.android.quickstep.views.TaskThumbnailView
 import com.android.quickstep.views.TaskView
@@ -268,13 +271,58 @@
         }
     }
 
+    /**
+     * Creates and returns a view to fade in at .4 animation progress and adds it to the provided
+     * [pendingAnimation]. Assumes that animation will be the final split placeholder launch anim.
+     *
+     * [secondPlaceholderEndingBounds] refers to the second placeholder view that gets added on
+     * screen, not the logical second app.
+     * For landscape it's the left app and for portrait the top one.
+     */
+    fun addDividerPlaceholderViewToAnim(pendingAnimation: PendingAnimation,
+                                        container: RecentsViewContainer,
+                                        secondPlaceholderEndingBounds: Rect,
+                                        context: Context) : View {
+        val mSplitDividerPlaceholderView = View(context)
+        val recentsView = container.getOverviewPanel<RecentsView<*, *>>()
+        val dp : com.android.launcher3.DeviceProfile = container.getDeviceProfile()
+        // Add it before/under the most recently added first floating taskView
+        val firstAddedSplitViewIndex: Int = container.getDragLayer().indexOfChild(
+                recentsView.splitSelectController.firstFloatingTaskView)
+        container.getDragLayer().addView(mSplitDividerPlaceholderView, firstAddedSplitViewIndex)
+        val lp = mSplitDividerPlaceholderView.layoutParams as InsettableFrameLayout.LayoutParams
+        lp.topMargin = 0
+
+        if (dp.isLeftRightSplit) {
+            lp.height = secondPlaceholderEndingBounds.height()
+            lp.width = container.asContext().resources.
+                getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
+            mSplitDividerPlaceholderView.translationX = secondPlaceholderEndingBounds.right - lp.width / 2f
+            mSplitDividerPlaceholderView.translationY = 0f
+        } else {
+            lp.height = container.asContext().resources
+                    .getDimensionPixelSize(R.dimen.split_divider_handle_region_height)
+            lp.width = secondPlaceholderEndingBounds.width()
+            mSplitDividerPlaceholderView.translationY = secondPlaceholderEndingBounds.top - lp.height / 2f
+            mSplitDividerPlaceholderView.translationX = 0f
+        }
+
+        mSplitDividerPlaceholderView.alpha = 0f
+        mSplitDividerPlaceholderView.setBackgroundColor(container.asContext().resources
+                .getColor(R.color.taskbar_background_dark))
+        val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet)
+        pendingAnimation.setViewAlpha(mSplitDividerPlaceholderView, 1f,
+                Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f))
+        return mSplitDividerPlaceholderView
+    }
+
     /** Does not play any animation if user is not currently in split selection state. */
-    fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>, splitDismissEvent: EventEnum) {
+    fun playPlaceholderDismissAnim(container: RecentsViewContainer, splitDismissEvent: EventEnum) {
         if (!splitSelectStateController.isSplitSelectActive) {
             return
         }
 
-        val anim = createPlaceholderDismissAnim(launcher, splitDismissEvent, null /*duration*/)
+        val anim = createPlaceholderDismissAnim(container, splitDismissEvent, null /*duration*/)
         anim.start()
     }
 
@@ -283,18 +331,18 @@
      * for why split is being dismissed
      */
     fun createPlaceholderDismissAnim(
-        launcher: StatefulActivity<*>,
+        container: RecentsViewContainer,
         splitDismissEvent: EventEnum,
         duration: Long?
     ): AnimatorSet {
         val animatorSet = AnimatorSet()
         duration?.let { animatorSet.duration = it }
-        val recentsView: RecentsView<*, *> = launcher.getOverviewPanel()
+        val recentsView: RecentsView<*, *> = container.getOverviewPanel()
         val floatingTask: FloatingTaskView =
             splitSelectStateController.firstFloatingTaskView ?: return animatorSet
 
         // We are in split selection state currently, transitioning to another state
-        val dragLayer: BaseDragLayer<*> = launcher.dragLayer
+        val dragLayer: BaseDragLayer<*> = container.dragLayer
         val onScreenRectF = RectF()
         Utilities.getBoundsForViewInDragLayer(
             dragLayer,
@@ -320,7 +368,7 @@
                     floatingTask,
                     onScreenRectF,
                     floatingTask.stagePosition,
-                    launcher.deviceProfile
+                    container.deviceProfile
                 )
             )
         )
@@ -329,7 +377,7 @@
                 override fun onAnimationEnd(animation: Animator) {
                     splitSelectStateController.resetState()
                     safeRemoveViewFromDragLayer(
-                        launcher,
+                        container,
                         splitSelectStateController.splitInstructionsView
                     )
                 }
@@ -343,11 +391,11 @@
      * Returns a [PendingAnimation] to animate in the chip to instruct a user to select a second app
      * for splitscreen
      */
-    fun getShowSplitInstructionsAnim(launcher: StatefulActivity<*>): PendingAnimation {
-        safeRemoveViewFromDragLayer(launcher, splitSelectStateController.splitInstructionsView)
-        val splitInstructionsView = SplitInstructionsView.getSplitInstructionsView(launcher)
+    fun getShowSplitInstructionsAnim(container: RecentsViewContainer): PendingAnimation {
+        safeRemoveViewFromDragLayer(container, splitSelectStateController.splitInstructionsView)
+        val splitInstructionsView = SplitInstructionsView.getSplitInstructionsView(container)
         splitSelectStateController.splitInstructionsView = splitInstructionsView
-        val timings = AnimUtils.getDeviceOverviewToSplitTimings(launcher.deviceProfile.isTablet)
+        val timings = AnimUtils.getDeviceOverviewToSplitTimings(container.deviceProfile.isTablet)
         val anim = PendingAnimation(100 /*duration */)
         splitInstructionsView.alpha = 0f
         anim.setViewAlpha(
@@ -374,8 +422,8 @@
     }
 
     /** Removes the split instructions view from [launcher] drag layer. */
-    fun removeSplitInstructionsView(launcher: StatefulActivity<*>) {
-        safeRemoveViewFromDragLayer(launcher, splitSelectStateController.splitInstructionsView)
+    fun removeSplitInstructionsView(container: RecentsViewContainer) {
+        safeRemoveViewFromDragLayer(container, splitSelectStateController.splitInstructionsView)
     }
 
     /**
@@ -384,22 +432,23 @@
      * TODO(b/276361926): Remove the [resetCallback] option once contextual launches
      */
     fun playAnimPlaceholderToFullscreen(
-        launcher: StatefulActivity<*>,
+        container: RecentsViewContainer,
         view: View,
         resetCallback: Optional<Runnable>
     ) {
         val stagedTaskView = view as FloatingTaskView
 
-        val isTablet: Boolean = launcher.deviceProfile.isTablet
+        val isTablet: Boolean = container.deviceProfile.isTablet
         val duration =
             if (isTablet) SplitAnimationTimings.TABLET_CONFIRM_DURATION
             else SplitAnimationTimings.PHONE_CONFIRM_DURATION
+
         val pendingAnimation = PendingAnimation(duration.toLong())
         val firstTaskStartingBounds = Rect()
         val firstTaskEndingBounds = Rect()
 
         stagedTaskView.getBoundsOnScreen(firstTaskStartingBounds)
-        launcher.dragLayer.getBoundsOnScreen(firstTaskEndingBounds)
+        container.dragLayer.getBoundsOnScreen(firstTaskEndingBounds)
         splitSelectStateController.setLaunchingFirstAppFullscreen()
 
         stagedTaskView.addConfirmAnimation(
@@ -589,7 +638,7 @@
         }
 
         // Else we are in Launcher and can launch with the full icon stretch-and-split animation.
-        val launcher = Launcher.getLauncher(launchingIconView.context)
+        val launcher = QuickstepLauncher.getLauncher(launchingIconView.context)
         val dp = launcher.deviceProfile
 
         // Create an AnimatorSet that will run both shell and launcher transitions together
@@ -880,11 +929,30 @@
             }
         }
 
+        if (splitRoot1 != null) {
+            // Set the highest level split root alpha; we could technically use the parent of
+            // either splitRoot1 or splitRoot2
+            val parentToken = splitRoot1.parent
+            var rootLayer: Change? = null
+            if (parentToken != null) {
+                rootLayer = transitionInfo.getChange(parentToken)
+            }
+            if (rootLayer != null && rootLayer.leash != null) {
+                openingTargets.add(rootLayer.leash)
+            }
+        }
+
         val animTransaction = Transaction()
         val animator = ValueAnimator.ofFloat(0f, 1f)
         animator.setDuration(QuickstepTransitionManager.SPLIT_LAUNCH_DURATION.toLong())
         animator.addUpdateListener { valueAnimator: ValueAnimator ->
-            val progress = valueAnimator.animatedFraction
+            val progress =
+                    Interpolators.clampToProgress(
+                            Interpolators.LINEAR,
+                            valueAnimator.animatedFraction,
+                            0.8f,
+                            1f
+                    )
             for (leash in openingTargets) {
                 animTransaction.setAlpha(leash, progress)
             }
@@ -906,26 +974,13 @@
             }
         )
 
-        if (splitRoot1 != null) {
-            // Set the highest level split root alpha; we could technically use the parent of
-            // either splitRoot1 or splitRoot2
-            val parentToken = splitRoot1.parent
-            var rootLayer: Change? = null
-            if (parentToken != null) {
-                rootLayer = transitionInfo.getChange(parentToken)
-            }
-            if (rootLayer != null && rootLayer.leash != null) {
-                t.setAlpha(rootLayer.leash, 1f)
-            }
-        }
-
         t.apply()
         animator.start()
     }
 
-    private fun safeRemoveViewFromDragLayer(launcher: StatefulActivity<*>, view: View?) {
+    private fun safeRemoveViewFromDragLayer(container: RecentsViewContainer, view: View?) {
         if (view != null) {
-            launcher.dragLayer.removeView(view)
+            container.dragLayer.removeView(view)
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 44da8b1..c257be6 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -35,7 +35,6 @@
 import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_PENDINGINTENT;
 import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_SHORTCUT;
 import static com.android.quickstep.util.SplitSelectDataHolder.SPLIT_TASK_TASK;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.wm.shell.common.split.SplitScreenConstants.KEY_EXTRA_WIDGET_INTENT;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50;
 
@@ -64,15 +63,15 @@
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationTarget;
 import android.view.SurfaceControl;
-import android.window.IRemoteTransition;
 import android.window.IRemoteTransitionFinishedCallback;
 import android.window.RemoteTransition;
+import android.window.RemoteTransitionStub;
 import android.window.TransitionInfo;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.logging.InstanceId;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.apppairs.AppPairIcon;
@@ -82,9 +81,9 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.statemanager.StateManager;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.BackPressHandler;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
@@ -100,6 +99,7 @@
 import com.android.quickstep.views.FloatingTaskView;
 import com.android.quickstep.views.GroupedTaskView;
 import com.android.quickstep.views.RecentsView;
+import com.android.quickstep.views.RecentsViewContainer;
 import com.android.quickstep.views.SplitInstructionsView;
 import com.android.systemui.animation.RemoteAnimationRunnerCompat;
 import com.android.systemui.shared.recents.model.Task;
@@ -121,7 +121,7 @@
 public class SplitSelectStateController {
     private static final String TAG = "SplitSelectStateCtor";
 
-    private StatefulActivity mContext;
+    private RecentsViewContainer mContainer;
     private final Handler mHandler;
     private final RecentsModel mRecentTasksModel;
     @Nullable
@@ -132,6 +132,7 @@
     private final StatsLogManager mStatsLogManager;
     private final SystemUiProxy mSystemUiProxy;
     private final StateManager mStateManager;
+    @Nullable
     private SplitFromDesktopController mSplitFromDesktopController;
     @Nullable
     private DepthController mDepthController;
@@ -178,7 +179,7 @@
         public void onBackInvoked() {
             // When exiting from split selection, leave current context to go to
             // homescreen as well
-            getSplitAnimationController().playPlaceholderDismissAnim(mContext,
+            getSplitAnimationController().playPlaceholderDismissAnim(mContainer,
                     LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
             if (mActivityBackCallback != null) {
                 mActivityBackCallback.run();
@@ -186,11 +187,11 @@
         }
     };
 
-    public SplitSelectStateController(StatefulActivity context, Handler handler,
+    public SplitSelectStateController(RecentsViewContainer container, Handler handler,
             StateManager stateManager, DepthController depthController,
             StatsLogManager statsLogManager, SystemUiProxy systemUiProxy, RecentsModel recentsModel,
             Runnable activityBackCallback) {
-        mContext = context;
+        mContainer = container;
         mHandler = handler;
         mStatsLogManager = statsLogManager;
         mSystemUiProxy = systemUiProxy;
@@ -199,15 +200,18 @@
         mRecentTasksModel = recentsModel;
         mActivityBackCallback = activityBackCallback;
         mSplitAnimationController = new SplitAnimationController(this);
-        mAppPairsController = new AppPairsController(context, this, statsLogManager);
-        mSplitSelectDataHolder = new SplitSelectDataHolder(mContext);
+        mAppPairsController = new AppPairsController(mContainer.asContext(), this, statsLogManager);
+        mSplitSelectDataHolder = new SplitSelectDataHolder(mContainer.asContext());
     }
 
     public void onDestroy() {
-        mContext = null;
+        mContainer = null;
         mActivityBackCallback = null;
         mAppPairsController.onDestroy();
         mSplitSelectDataHolder.onDestroy();
+        if (mSplitFromDesktopController != null) {
+            mSplitFromDesktopController.onDestroy();
+        }
     }
 
     /**
@@ -642,8 +646,13 @@
         }
     }
 
-    public void initSplitFromDesktopController(Launcher launcher) {
-        mSplitFromDesktopController = new SplitFromDesktopController(launcher);
+    public void initSplitFromDesktopController(QuickstepLauncher launcher) {
+        initSplitFromDesktopController(new SplitFromDesktopController(launcher));
+    }
+
+    @VisibleForTesting
+    void initSplitFromDesktopController(SplitFromDesktopController controller) {
+        mSplitFromDesktopController = controller;
     }
 
     private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
@@ -721,7 +730,7 @@
     /**
      * Requires Shell Transitions
      */
-    private class RemoteSplitLaunchTransitionRunner extends IRemoteTransition.Stub {
+    private class RemoteSplitLaunchTransitionRunner extends RemoteTransitionStub {
 
         private final int mInitialTaskId;
         private final int mSecondTaskId;
@@ -770,11 +779,6 @@
         }
 
         @Override
-        public void mergeAnimation(IBinder transition, TransitionInfo info,
-                SurfaceControl.Transaction t, IBinder mergeTarget,
-                IRemoteTransitionFinishedCallback finishedCallback) { }
-
-        @Override
         public void onTransitionConsumed(IBinder transition, boolean aborted)
                 throws RemoteException {
             MAIN_EXECUTOR.execute(() -> {
@@ -944,7 +948,7 @@
     public class SplitFromDesktopController {
         private static final String TAG = "SplitFromDesktopController";
 
-        private final Launcher mLauncher;
+        private final QuickstepLauncher mLauncher;
         private final OverviewComponentObserver mOverviewComponentObserver;
         private final int mSplitPlaceholderSize;
         private final int mSplitPlaceholderInset;
@@ -952,7 +956,7 @@
         private ISplitSelectListener mSplitSelectListener;
         private Drawable mAppIcon;
 
-        public SplitFromDesktopController(Launcher launcher) {
+        public SplitFromDesktopController(QuickstepLauncher launcher) {
             mLauncher = launcher;
             RecentsAnimationDeviceState deviceState = new RecentsAnimationDeviceState(
                     launcher.getApplicationContext());
@@ -966,7 +970,6 @@
                 @Override
                 public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
                         int splitPosition, Rect taskBounds) {
-                    if (!isDesktopModeSupported()) return false;
                     MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo, splitPosition,
                             taskBounds));
                     return true;
@@ -975,6 +978,11 @@
             SystemUiProxy.INSTANCE.get(mLauncher).registerSplitSelectListener(mSplitSelectListener);
         }
 
+        void onDestroy() {
+            SystemUiProxy.INSTANCE.get(mLauncher).unregisterSplitSelectListener(
+                    mSplitSelectListener);
+        }
+
         /**
          * Enter split select from desktop mode.
          * @param taskInfo the desktop task to move to split stage
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index e068301..b6e6bf7 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -17,7 +17,6 @@
 package com.android.quickstep.util;
 
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -36,7 +35,6 @@
 
 import com.android.internal.jank.Cuj;
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.PendingAnimation;
@@ -47,6 +45,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.quickstep.views.FloatingTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -54,13 +53,14 @@
 /** Handles when the stage split lands on the home screen. */
 public class SplitToWorkspaceController {
 
-    private final Launcher mLauncher;
+    private final QuickstepLauncher mLauncher;
     private final SplitSelectStateController mController;
 
     private final int mHalfDividerSize;
     private final IconCache mIconCache;
 
-    public SplitToWorkspaceController(Launcher launcher, SplitSelectStateController controller) {
+    public SplitToWorkspaceController(QuickstepLauncher launcher,
+            SplitSelectStateController controller) {
         mLauncher = launcher;
         mController = controller;
         mIconCache = LauncherAppState.getInstanceNoCreate().getIconCache();
@@ -163,6 +163,10 @@
                 new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
                 false /* fadeWithThumbnail */, true /* isStagedTask */);
 
+        View mSplitDividerPlaceholderView = recentsView.getSplitSelectController()
+                .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation,
+                        mLauncher, secondTaskEndingBounds, view.getContext());
+
         FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher,
                 view, bitmap, icon, secondTaskStartingBounds);
         secondFloatingTaskView.setAlpha(1);
@@ -173,6 +177,11 @@
             private boolean mIsCancelled = false;
 
             @Override
+            public void onAnimationStart(Animator animation) {
+                mController.launchSplitTasks(aBoolean -> cleanUp());
+            }
+
+            @Override
             public void onAnimationCancel(Animator animation) {
                 mIsCancelled = true;
                 cleanUp();
@@ -181,7 +190,6 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (!mIsCancelled) {
-                    mController.launchSplitTasks(aBoolean -> cleanUp());
                     InteractionJankMonitorWrapper.end(Cuj.CUJ_SPLIT_SCREEN_ENTER);
                 }
             }
@@ -189,6 +197,7 @@
             private void cleanUp() {
                 mLauncher.getDragLayer().removeView(firstFloatingTaskView);
                 mLauncher.getDragLayer().removeView(secondFloatingTaskView);
+                mLauncher.getDragLayer().removeView(mSplitDividerPlaceholderView);
                 mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher);
                 mController.resetState();
             }
@@ -197,8 +206,6 @@
     }
 
     private boolean shouldIgnoreSecondSplitLaunch() {
-        return (!FeatureFlags.enableSplitContextually()
-                && !isDesktopModeSupported())
-                || !mController.isSplitSelectActive();
+        return !FeatureFlags.enableSplitContextually() || !mController.isSplitSelectActive();
     }
 }
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index 6b3199f..997a842 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -38,7 +38,6 @@
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Hotseat;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.QuickstepTransitionManager;
 import com.android.launcher3.R;
@@ -65,7 +64,7 @@
     // Should be used for animations running alongside this StaggeredWorkspaceAnim.
     public static final int DURATION_MS = 250;
     public static final int DURATION_TASKBAR_MS =
-            QuickstepTransitionManager.TASKBAR_TO_HOME_DURATION;
+            QuickstepTransitionManager.getTaskbarToHomeDuration();
 
     private static final float MAX_VELOCITY_PX_PER_S = 22f;
 
@@ -75,13 +74,13 @@
     private final AnimatorSet mAnimators = new AnimatorSet();
     private final @Nullable View mIgnoredView;
 
-    public StaggeredWorkspaceAnim(Launcher launcher, float velocity, boolean animateOverviewScrim,
-            @Nullable View ignoredView) {
+    public StaggeredWorkspaceAnim(QuickstepLauncher launcher, float velocity,
+            boolean animateOverviewScrim, @Nullable View ignoredView) {
         this(launcher, velocity, animateOverviewScrim, ignoredView, true);
     }
 
-    public StaggeredWorkspaceAnim(Launcher launcher, float velocity, boolean animateOverviewScrim,
-            @Nullable View ignoredView, boolean staggerWorkspace) {
+    public StaggeredWorkspaceAnim(QuickstepLauncher launcher, float velocity,
+            boolean animateOverviewScrim, @Nullable View ignoredView, boolean staggerWorkspace) {
         prepareToAnimate(launcher, animateOverviewScrim);
 
         mIgnoredView = ignoredView;
@@ -124,7 +123,8 @@
                 for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
                     View child = hotseatIcons.getChildAt(i);
                     CellLayoutLayoutParams lp = ((CellLayoutLayoutParams) child.getLayoutParams());
-                    addStaggeredAnimationForView(child, lp.getCellY() + 1, totalRows, duration);
+                    addStaggeredAnimationForView(child, lp.getCellY() + 1,
+                            totalRows, duration);
                 }
             } else {
                 final int hotseatRow, qsbRow;
@@ -194,7 +194,8 @@
         for (int i = itemsContainer.getChildCount() - 1; i >= 0; i--) {
             View child = itemsContainer.getChildAt(i);
             CellLayoutLayoutParams lp = ((CellLayoutLayoutParams) child.getLayoutParams());
-            addStaggeredAnimationForView(child, lp.getCellY() + lp.cellVSpan, totalRows, duration);
+            addStaggeredAnimationForView(child, lp.getCellY() + lp.cellVSpan,
+                    totalRows, duration);
         }
 
         mAnimators.addListener(new AnimatorListenerAdapter() {
@@ -209,7 +210,7 @@
     /**
      * Setup workspace with 0 duration to prepare for our staggered animation.
      */
-    private void prepareToAnimate(Launcher launcher, boolean animateOverviewScrim) {
+    private void prepareToAnimate(QuickstepLauncher launcher, boolean animateOverviewScrim) {
         StateAnimationConfig config = new StateAnimationConfig();
         config.animFlags = SKIP_OVERVIEW | SKIP_DEPTH_CONTROLLER | SKIP_SCRIM;
         config.duration = 0;
@@ -294,12 +295,10 @@
         mAnimators.play(alpha);
     }
 
-    private void addDepthAnimationForState(Launcher launcher, LauncherState state, long duration) {
-        if (!(launcher instanceof QuickstepLauncher)) {
-            return;
-        }
+    private void addDepthAnimationForState(QuickstepLauncher launcher, LauncherState state,
+            long duration) {
         PendingAnimation builder = new PendingAnimation(duration);
-        DepthController depthController = ((QuickstepLauncher) launcher).getDepthController();
+        DepthController depthController = launcher.getDepthController();
         depthController.setStateWithAnimation(state, new StateAnimationConfig(), builder);
         mAnimators.play(builder.buildAnim());
     }
diff --git a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
index cdadd71..89d8cc4 100644
--- a/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
+++ b/quickstep/src/com/android/quickstep/util/TaskRemovedDuringLaunchListener.java
@@ -24,8 +24,8 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.launcher3.BaseActivity;
 import com.android.quickstep.RecentsModel;
+import com.android.quickstep.views.RecentsViewContainer;
 
 /**
  * This class tracks the failure of a task launch through the TaskView.launchTask() call, in an
@@ -38,7 +38,7 @@
  */
 public class TaskRemovedDuringLaunchListener {
 
-    private BaseActivity mActivity;
+    private RecentsViewContainer mContainer;
     private int mLaunchedTaskId = INVALID_TASK_ID;
     private Runnable mTaskLaunchFailedCallback = null;
 
@@ -49,16 +49,16 @@
      * Registers a failure listener callback if it detects a scenario in which an app launch
      * failed before the transition finished.
      */
-    public void register(BaseActivity activity, int launchedTaskId,
+    public void register(RecentsViewContainer container, int launchedTaskId,
             @NonNull Runnable taskLaunchFailedCallback) {
         // The normal task launch case, Launcher stops and updates its state correctly
-        activity.addEventCallback(EVENT_STOPPED, mUnregisterCallback);
+        container.addEventCallback(EVENT_STOPPED, mUnregisterCallback);
         // The transition hasn't finished but Launcher was resumed, check if the launch failed
-        activity.addEventCallback(EVENT_RESUMED, mResumeCallback);
+        container.addEventCallback(EVENT_RESUMED, mResumeCallback);
         // If we somehow don't get any of the above signals, then just unregister this listener
-        activity.addEventCallback(EVENT_DESTROYED, mUnregisterCallback);
+        container.addEventCallback(EVENT_DESTROYED, mUnregisterCallback);
 
-        mActivity = activity;
+        mContainer = container;
         mLaunchedTaskId = launchedTaskId;
         mTaskLaunchFailedCallback = taskLaunchFailedCallback;
     }
@@ -67,11 +67,11 @@
      * Unregisters the failure listener.
      */
     private void unregister() {
-        mActivity.removeEventCallback(EVENT_STOPPED, mUnregisterCallback);
-        mActivity.removeEventCallback(EVENT_RESUMED, mResumeCallback);
-        mActivity.removeEventCallback(EVENT_DESTROYED, mUnregisterCallback);
+        mContainer.removeEventCallback(EVENT_STOPPED, mUnregisterCallback);
+        mContainer.removeEventCallback(EVENT_RESUMED, mResumeCallback);
+        mContainer.removeEventCallback(EVENT_DESTROYED, mUnregisterCallback);
 
-        mActivity = null;
+        mContainer = null;
         mLaunchedTaskId = INVALID_TASK_ID;
         mTaskLaunchFailedCallback = null;
     }
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 1152de2..fcb865f 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -51,6 +51,7 @@
 import com.android.launcher3.util.SplitConfigurationOptions.SplitBounds;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.BaseContainerInterface;
 import com.android.quickstep.TaskAnimationManager;
 import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
 import com.android.quickstep.views.TaskView.FullscreenDrawParams;
@@ -70,7 +71,7 @@
     private final float[] mTempPoint = new float[2];
 
     private final Context mContext;
-    private final BaseActivityInterface mSizeStrategy;
+    private final BaseContainerInterface mSizeStrategy;
 
     @NonNull
     private RecentsOrientedState mOrientationState;
@@ -122,7 +123,7 @@
     private int mTaskRectTranslationX;
     private int mTaskRectTranslationY;
 
-    public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
+    public TaskViewSimulator(Context context, BaseContainerInterface sizeStrategy) {
         mContext = context;
         mSizeStrategy = sizeStrategy;
 
diff --git a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
index 7bbde30..c63a58e 100644
--- a/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
+++ b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
@@ -28,6 +28,8 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 
@@ -41,21 +43,20 @@
     private final float mMinFlingVelocity;
     private final boolean mDisableHorizontalSwipe;
     private final NavBarPosition mNavBarPosition;
-    private final Runnable mOnInterceptTouch;
+
+    @NonNull
     private final OnSwipeUpListener mOnSwipeUp;
 
     private boolean mInterceptedTouch;
     private VelocityTracker mVelocityTracker;
 
     public TriggerSwipeUpTouchTracker(Context context, boolean disableHorizontalSwipe,
-            NavBarPosition navBarPosition, Runnable onInterceptTouch,
-            OnSwipeUpListener onSwipeUp) {
+            NavBarPosition navBarPosition, @NonNull OnSwipeUpListener onSwipeUp) {
         mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
         mMinFlingVelocity = context.getResources().getDimension(
                 R.dimen.quickstep_fling_threshold_speed);
         mNavBarPosition = navBarPosition;
         mDisableHorizontalSwipe = disableHorizontalSwipe;
-        mOnInterceptTouch = onInterceptTouch;
         mOnSwipeUp = onSwipeUp;
 
         init();
@@ -103,10 +104,7 @@
                         }
 
                         mInterceptedTouch = true;
-
-                        if (mOnInterceptTouch != null) {
-                            mOnInterceptTouch.run();
-                        }
+                        mOnSwipeUp.onSwipeUpTouchIntercepted();
                     }
                 }
                 break;
@@ -124,7 +122,8 @@
         }
     }
 
-    private void endTouchTracking() {
+    /** Finishes the tracking. All events after this call are ignored */
+    public void endTouchTracking() {
         if (mVelocityTracker != null) {
             mVelocityTracker.recycle();
             mVelocityTracker = null;
@@ -151,12 +150,10 @@
             isSwipeUp = squaredHypot(displacementX, displacementY) >= mSquaredTouchSlop;
         }
 
-        if (mOnSwipeUp != null) {
-            if (isSwipeUp) {
-                mOnSwipeUp.onSwipeUp(wasFling, new PointF(velocityX, velocityY));
-            } else {
-                mOnSwipeUp.onSwipeUpCancelled();
-            }
+        if (isSwipeUp) {
+            mOnSwipeUp.onSwipeUp(wasFling, new PointF(velocityX, velocityY));
+        } else {
+            mOnSwipeUp.onSwipeUpCancelled();
         }
     }
 
@@ -172,6 +169,9 @@
         void onSwipeUp(boolean wasFling, PointF finalVelocity);
 
         /** Called on touch up if a swipe up was not detected. */
-        void onSwipeUpCancelled();
+        default void onSwipeUpCancelled() { }
+
+        /** Called when the touch for swipe up is intercepted. */
+        default void onSwipeUpTouchIntercepted() { }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
index c8141b4..4aea1b8 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterHotseatAnimator.java
@@ -20,7 +20,7 @@
 import android.view.WindowManager;
 
 import com.android.launcher3.Hotseat;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 
 /**
@@ -28,10 +28,10 @@
  */
 public class UnfoldMoveFromCenterHotseatAnimator extends BaseUnfoldMoveFromCenterAnimator {
 
-    private final Launcher mLauncher;
+    private final QuickstepLauncher mLauncher;
 
-    public UnfoldMoveFromCenterHotseatAnimator(Launcher launcher, WindowManager windowManager,
-            RotationChangeProvider rotationChangeProvider) {
+    public UnfoldMoveFromCenterHotseatAnimator(QuickstepLauncher launcher,
+            WindowManager windowManager, RotationChangeProvider rotationChangeProvider) {
         super(windowManager, rotationChangeProvider);
         mLauncher = launcher;
     }
diff --git a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
index c05b38f..0ec3ae0 100644
--- a/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/UnfoldMoveFromCenterWorkspaceAnimator.java
@@ -19,9 +19,9 @@
 import android.view.WindowManager;
 
 import com.android.launcher3.CellLayout;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.ShortcutAndWidgetContainer;
 import com.android.launcher3.Workspace;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.systemui.unfold.updates.RotationChangeProvider;
 
 /**
@@ -29,10 +29,10 @@
  */
 public class UnfoldMoveFromCenterWorkspaceAnimator extends BaseUnfoldMoveFromCenterAnimator {
 
-    private final Launcher mLauncher;
+    private final QuickstepLauncher mLauncher;
 
-    public UnfoldMoveFromCenterWorkspaceAnimator(Launcher launcher, WindowManager windowManager,
-            RotationChangeProvider rotationChangeProvider) {
+    public UnfoldMoveFromCenterWorkspaceAnimator(QuickstepLauncher launcher,
+            WindowManager windowManager, RotationChangeProvider rotationChangeProvider) {
         super(windowManager, rotationChangeProvider);
         mLauncher = launcher;
     }
diff --git a/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt b/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt
index 54d317d..09563f5 100644
--- a/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt
+++ b/quickstep/src/com/android/quickstep/util/unfold/LauncherUnfoldTransitionController.kt
@@ -21,15 +21,15 @@
 import com.android.launcher3.Alarm
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener
-import com.android.launcher3.Launcher
 import com.android.launcher3.anim.PendingAnimation
 import com.android.launcher3.config.FeatureFlags
+import com.android.launcher3.uioverrides.QuickstepLauncher
 import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
 
 /** Controls animations that are happening during unfolding foldable devices */
 class LauncherUnfoldTransitionController(
-    private val launcher: Launcher,
+    private val launcher: QuickstepLauncher,
     private val progressProvider: ProxyUnfoldTransitionProvider
 ) : OnDeviceProfileChangeListener, ActivityLifecycleCallbacksAdapter, TransitionProgressListener {
 
diff --git a/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt b/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt
index d2c4728..2f90ee7 100644
--- a/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt
+++ b/quickstep/src/com/android/quickstep/util/unfold/UnfoldAnimationBuilder.kt
@@ -20,7 +20,6 @@
 import com.android.app.animation.Interpolators.LINEAR
 import com.android.app.animation.Interpolators.clampToProgress
 import com.android.launcher3.CellLayout
-import com.android.launcher3.Launcher
 import com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY
 import com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION
 import com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X
@@ -28,6 +27,7 @@
 import com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY
 import com.android.launcher3.Workspace
 import com.android.launcher3.anim.PendingAnimation
+import com.android.launcher3.uioverrides.QuickstepLauncher
 import com.android.launcher3.util.HorizontalInsettableView
 
 private typealias ViewGroupAction = (ViewGroup, Boolean) -> Unit
@@ -112,7 +112,7 @@
      * Builds an animation for the unfold experience and adds it to the provided PendingAnimation
      */
     fun buildUnfoldAnimation(
-        launcher: Launcher,
+        launcher: QuickstepLauncher,
         isVerticalFold: Boolean,
         screenSize: Point,
         anim: PendingAnimation
diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
index 32ef904..b8afd9d 100644
--- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java
+++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
@@ -17,15 +17,28 @@
 package com.android.quickstep.views;
 
 import static com.android.launcher3.Flags.enableGridOnlyOverview;
+import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.widget.Button;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
+import com.android.launcher3.R;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.quickstep.orientation.RecentsPagedOrientationHandler;
+import com.android.quickstep.util.BorderAnimator;
+
+import kotlin.Unit;
 
 public class ClearAllButton extends Button {
 
@@ -55,7 +68,7 @@
                 }
             };
 
-    private final StatefulActivity mActivity;
+    private final RecentsViewContainer mContainer;
     private float mScrollAlpha = 1;
     private float mContentAlpha = 1;
     private float mVisibilityAlpha = 1;
@@ -71,11 +84,71 @@
     private float mScrollOffsetPrimary;
 
     private int mSidePadding;
+    private int mOutlinePadding;
+    private boolean mBorderEnabled;
+    @Nullable
+    private final BorderAnimator mFocusBorderAnimator;
 
     public ClearAllButton(Context context, AttributeSet attrs) {
         super(context, attrs);
         mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        mActivity = StatefulActivity.fromContext(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
+
+        if (Flags.enableFocusOutline()) {
+            TypedArray styledAttrs = context.obtainStyledAttributes(attrs,
+                    R.styleable.ClearAllButton);
+            Resources resources = getResources();
+            mOutlinePadding = resources.getDimensionPixelSize(
+                    R.dimen.recents_clear_all_outline_padding);
+            mFocusBorderAnimator =
+                    BorderAnimator.createSimpleBorderAnimator(
+                            /* borderRadiusPx= */ resources.getDimensionPixelSize(
+                                    R.dimen.recents_clear_all_outline_radius),
+                            /* borderWidthPx= */ context.getResources().getDimensionPixelSize(
+                                    R.dimen.keyboard_quick_switch_border_width),
+                            /* boundsBuilder= */ this::updateBorderBounds,
+                            /* targetView= */ this,
+                            /* borderColor= */ styledAttrs.getColor(
+                                    R.styleable.ClearAllButton_focusBorderColor,
+                                    DEFAULT_BORDER_COLOR));
+            styledAttrs.recycle();
+        } else {
+            mFocusBorderAnimator = null;
+        }
+    }
+
+    private Unit updateBorderBounds(@NonNull Rect bounds) {
+        bounds.set(0, 0, getWidth(), getHeight());
+        // Make the value negative to form a padding between button and outline
+        bounds.inset(-mOutlinePadding, -mOutlinePadding);
+        return Unit.INSTANCE;
+    }
+
+    @Override
+    public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+        if (mFocusBorderAnimator != null && mBorderEnabled) {
+            mFocusBorderAnimator.setBorderVisibility(gainFocus, /* animated= */ true);
+        }
+    }
+
+    /**
+     * Enable or disable showing border on focus change
+     */
+    public void setBorderEnabled(boolean enabled) {
+        mBorderEnabled = enabled;
+        if (mFocusBorderAnimator != null) {
+            mFocusBorderAnimator.setBorderVisibility(/* visible= */
+                    enabled && isFocused(), /* animated= */true);
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        if (mFocusBorderAnimator != null) {
+            mFocusBorderAnimator.drawBorder(canvas);
+        }
+        super.draw(canvas);
     }
 
     @Override
@@ -253,7 +326,7 @@
      * Get the Y translation that is set in the original layout position, before scrolling.
      */
     private float getOriginalTranslationY() {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         if (deviceProfile.isTablet) {
             if (enableGridOnlyOverview()) {
                 return (getRecentsView().getLastComputedTaskSize().height()
diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
index a5be142..6a9a268 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
@@ -33,6 +33,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 
 /**
  * Floating view show on launcher home screen that notifies the user that an app will be launched to
@@ -47,7 +48,7 @@
     private static final int SHOW_CONTENT_ALPHA_DURATION = 83;
     private static final int HIDE_DURATION = 83;
 
-    private final Launcher mLauncher;
+    private final RecentsViewContainer mContainer;
 
     private View mText;
     private View mCloseButton;
@@ -71,7 +72,7 @@
     public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mLauncher = Launcher.getLauncher(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
     }
 
     /**
@@ -104,7 +105,7 @@
     }
 
     private void show() {
-        mLauncher.getDragLayer().addView(this);
+        mContainer.getDragLayer().addView(this);
 
         // Set up initial values
         getBackground().setAlpha(0);
@@ -163,7 +164,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 super.onAnimationEnd(animation);
-                mLauncher.getDragLayer().removeView(DesktopAppSelectView.this);
+                mContainer.getDragLayer().removeView(DesktopAppSelectView.this);
                 mHideAnimation = null;
             }
         });
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index f2c9f27..78b1763 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -51,7 +51,6 @@
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.QuickStepContract;
-import com.android.window.flags.Flags;
 
 import kotlin.Unit;
 
@@ -88,11 +87,6 @@
 
     private int mChildCountAtInflation;
 
-    /** Check whether desktop windowing is enabled */
-    public static boolean isDesktopModeSupported() {
-        return Flags.enableDesktopWindowingMode();
-    }
-
     public DesktopTaskView(Context context) {
         this(context, null);
     }
@@ -124,7 +118,7 @@
         mBackgroundView = findViewById(R.id.background);
 
         int topMarginPx =
-                mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+                mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
         FrameLayout.LayoutParams params = (LayoutParams) mBackgroundView.getLayoutParams();
         params.topMargin = topMarginPx;
         mBackgroundView.setLayoutParams(params);
@@ -309,7 +303,7 @@
 
     @Override
     protected void setThumbnailOrientation(RecentsOrientedState orientationState) {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
 
         LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
@@ -426,7 +420,7 @@
 
         setMeasuredDimension(containerWidth, containerHeight);
 
-        int thumbnailTopMarginPx = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+        int thumbnailTopMarginPx = mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
         containerHeight -= thumbnailTopMarginPx;
 
         int thumbnails = mSnapshotViewMap.size();
@@ -434,8 +428,8 @@
             return;
         }
 
-        int windowWidth = mActivity.getDeviceProfile().widthPx;
-        int windowHeight = mActivity.getDeviceProfile().heightPx;
+        int windowWidth = mContainer.getDeviceProfile().widthPx;
+        int windowHeight = mContainer.getDeviceProfile().heightPx;
 
         float scaleWidth = containerWidth / (float) windowWidth;
         float scaleHeight = containerHeight / (float) windowHeight;
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 840382d..8fa5375 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -45,8 +45,6 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
-import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
@@ -83,7 +81,7 @@
 
     private static final String TAG = DigitalWellBeingToast.class.getSimpleName();
 
-    private final BaseDraggingActivity mActivity;
+    private final RecentsViewContainer mContainer;
     private final TaskView mTaskView;
     private final LauncherApps mLauncherApps;
 
@@ -102,10 +100,10 @@
     private float mSplitOffsetTranslationY;
     private float mSplitOffsetTranslationX;
 
-    public DigitalWellBeingToast(BaseDraggingActivity activity, TaskView taskView) {
-        mActivity = activity;
+    public DigitalWellBeingToast(RecentsViewContainer container, TaskView taskView) {
+        mContainer = container;
         mTaskView = taskView;
-        mLauncherApps = activity.getSystemService(LauncherApps.class);
+        mLauncherApps = container.asContext().getSystemService(LauncherApps.class);
     }
 
     private void setNoLimit() {
@@ -120,9 +118,10 @@
         mAppUsageLimitTimeMs = appUsageLimitTimeMs;
         mAppRemainingTimeMs = appRemainingTimeMs;
         mHasLimit = true;
-        TextView toast = mActivity.getViewCache().getView(R.layout.digital_wellbeing_toast,
-                mActivity, mTaskView);
-        toast.setText(prefixTextWithIcon(mActivity, R.drawable.ic_hourglass_top, getText()));
+        TextView toast = mContainer.getViewCache().getView(R.layout.digital_wellbeing_toast,
+                mContainer.asContext(), mTaskView);
+        toast.setText(prefixTextWithIcon(mContainer.asContext(), R.drawable.ic_hourglass_top,
+                getText()));
         toast.setOnClickListener(this::openAppUsageSettings);
         replaceBanner(toast);
 
@@ -170,14 +169,14 @@
     public void setSplitConfiguration(SplitBounds splitBounds) {
         mSplitBounds = splitBounds;
         if (mSplitBounds == null
-                || !mActivity.getDeviceProfile().isTablet
+                || !mContainer.getDeviceProfile().isTablet
                 || mTaskView.isFocusedTask()) {
             mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
             return;
         }
 
         // For portrait grid only height of task changes, not width. So we keep the text the same
-        if (!mActivity.getDeviceProfile().isLeftRightSplit) {
+        if (!mContainer.getDeviceProfile().isLeftRightSplit) {
             mSplitBannerConfig = SPLIT_GRID_BANNER_LARGE;
             return;
         }
@@ -226,7 +225,7 @@
 
         // Use a specific string for usage less than one minute but non-zero.
         if (duration.compareTo(Duration.ZERO) > 0) {
-            return mActivity.getString(durationLessThanOneMinuteStringId);
+            return mContainer.asContext().getString(durationLessThanOneMinuteStringId);
         }
 
         // Otherwise, return 0-minute string.
@@ -250,7 +249,7 @@
                 R.string.shorter_duration_less_than_one_minute,
                 false /* forceFormatWidth */);
         if (forContentDesc || mSplitBannerConfig == SPLIT_BANNER_FULLSCREEN) {
-            return mActivity.getString(
+            return mContainer.asContext().getString(
                     R.string.time_left_for_app,
                     readableDuration);
         }
@@ -270,11 +269,12 @@
                         mTask.getTopComponent().getPackageName()).addFlags(
                         Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         try {
-            final BaseActivity activity = BaseActivity.fromContext(view.getContext());
+            final RecentsViewContainer container =
+                    RecentsViewContainer.containerFromContext(view.getContext());
             final ActivityOptions options = ActivityOptions.makeScaleUpAnimation(
                     view, 0, 0,
                     view.getWidth(), view.getHeight());
-            activity.startActivity(intent, options.toBundle());
+            container.asContext().startActivity(intent, options.toBundle());
 
             // TODO: add WW logging on the app usage settings click.
         } catch (ActivityNotFoundException e) {
@@ -286,7 +286,7 @@
     private String getContentDescriptionForTask(
             Task task, long appUsageLimitTimeMs, long appRemainingTimeMs) {
         return appUsageLimitTimeMs >= 0 && appRemainingTimeMs >= 0 ?
-                mActivity.getString(
+                mContainer.asContext().getString(
                         R.string.task_contents_description_with_remaining_time,
                         task.titleDescription,
                         getText(appRemainingTimeMs, true /* forContentDesc */)) :
@@ -303,7 +303,7 @@
             mBanner.setOutlineProvider(mOldBannerOutlineProvider);
             mTaskView.removeView(mBanner);
             mBanner.setOnClickListener(null);
-            mActivity.getViewCache().recycleView(R.layout.digital_wellbeing_toast, mBanner);
+            mContainer.getViewCache().recycleView(R.layout.digital_wellbeing_toast, mBanner);
         }
     }
 
@@ -318,7 +318,7 @@
     private void setupAndAddBanner() {
         FrameLayout.LayoutParams layoutParams =
                 (FrameLayout.LayoutParams) mBanner.getLayoutParams();
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         layoutParams.bottomMargin = ((ViewGroup.MarginLayoutParams)
                 mTaskView.getThumbnail().getLayoutParams()).bottomMargin;
         RecentsPagedOrientationHandler orientationHandler = mTaskView.getPagedOrientationHandler();
diff --git a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
index 1c1e167..0d49309 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
+++ b/quickstep/src/com/android/quickstep/views/FloatingAppPairBackground.kt
@@ -26,7 +26,6 @@
 import android.os.Build
 import android.view.animation.Interpolator
 import com.android.app.animation.Interpolators
-import com.android.launcher3.Launcher
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.quickstep.util.AnimUtils
@@ -55,7 +54,7 @@
         private val ARRAY_OF_ZEROES = FloatArray(8)
     }
 
-    private val launcher: Launcher
+    private val container: RecentsViewContainer
     private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG)
 
     // Animation interpolators
@@ -70,15 +69,15 @@
     private val desiredSplitRatio: Float
 
     init {
-        launcher = Launcher.getLauncher(context)
-        val dp = launcher.deviceProfile
+        container = RecentsViewContainer.containerFromContext(context)
+        val dp = container.deviceProfile
         // Set up background paint color
         val ta = context.theme.obtainStyledAttributes(R.styleable.FolderIconPreview)
         backgroundPaint.style = Paint.Style.FILL
         backgroundPaint.color = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0)
         ta.recycle()
         // Set up timings and interpolators
-        val timings = AnimUtils.getDeviceAppPairLaunchTimings(launcher.deviceProfile.isTablet)
+        val timings = AnimUtils.getDeviceAppPairLaunchTimings(container.deviceProfile.isTablet)
         expandXInterpolator =
             Interpolators.clampToProgress(
                 timings.getStagedRectScaleXInterpolator(),
@@ -105,9 +104,9 @@
             )
 
         // Find device-specific measurements
-        deviceCornerRadius = QuickStepContract.getWindowCornerRadius(launcher)
+        deviceCornerRadius = QuickStepContract.getWindowCornerRadius(container.asContext())
         deviceHalfDividerSize =
-            launcher.resources.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2f
+                container.asContext().resources.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2f
         val dividerCenterPos = dividerPos + deviceHalfDividerSize
         desiredSplitRatio =
             if (dp.isLeftRightSplit) dividerCenterPos / dp.widthPx
@@ -115,7 +114,7 @@
     }
 
     override fun draw(canvas: Canvas) {
-        if (launcher.deviceProfile.isLeftRightSplit) {
+        if (container.deviceProfile.isLeftRightSplit) {
             drawLeftRightSplit(canvas)
         } else {
             drawTopBottomSplit(canvas)
@@ -150,39 +149,37 @@
         val dividerCenterPos = width * desiredSplitRatio
 
         // The left half of the background image
-        val leftSide = RectF(
-            0f,
-            0f,
-            dividerCenterPos - changingDividerSize,
-            height
-        )
+        val leftSide = RectF(0f, 0f, dividerCenterPos - changingDividerSize, height)
         // The right half of the background image
-        val rightSide = RectF(
-            dividerCenterPos + changingDividerSize,
-            0f,
-            width,
-            height
-        )
+        val rightSide = RectF(dividerCenterPos + changingDividerSize, 0f, width, height)
 
         // Draw background
         drawCustomRoundedRect(
             canvas,
             leftSide,
             floatArrayOf(
-                cornerRadiusX, cornerRadiusY,
-                changingInnerRadiusX, changingInnerRadiusY,
-                changingInnerRadiusX, changingInnerRadiusY,
-                cornerRadiusX, cornerRadiusY
+                cornerRadiusX,
+                cornerRadiusY,
+                changingInnerRadiusX,
+                changingInnerRadiusY,
+                changingInnerRadiusX,
+                changingInnerRadiusY,
+                cornerRadiusX,
+                cornerRadiusY,
             )
         )
         drawCustomRoundedRect(
             canvas,
             rightSide,
             floatArrayOf(
-                changingInnerRadiusX, changingInnerRadiusY,
-                cornerRadiusX, cornerRadiusY,
-                cornerRadiusX, cornerRadiusY,
-                changingInnerRadiusX, changingInnerRadiusY
+                changingInnerRadiusX,
+                changingInnerRadiusY,
+                cornerRadiusX,
+                cornerRadiusY,
+                cornerRadiusX,
+                cornerRadiusY,
+                changingInnerRadiusX,
+                changingInnerRadiusY,
             )
         )
 
@@ -250,39 +247,37 @@
         val dividerCenterPos = height * desiredSplitRatio
 
         // The top half of the background image
-        val topSide = RectF(
-            0f,
-            0f,
-            width,
-            dividerCenterPos - changingDividerSize
-        )
+        val topSide = RectF(0f, 0f, width, dividerCenterPos - changingDividerSize)
         // The bottom half of the background image
-        val bottomSide = RectF(
-            0f,
-            dividerCenterPos + changingDividerSize,
-            width,
-            height
-        )
+        val bottomSide = RectF(0f, dividerCenterPos + changingDividerSize, width, height)
 
         // Draw background
         drawCustomRoundedRect(
             canvas,
             topSide,
             floatArrayOf(
-                cornerRadiusX, cornerRadiusY,
-                cornerRadiusX, cornerRadiusY,
-                changingInnerRadiusX, changingInnerRadiusY,
-                changingInnerRadiusX, changingInnerRadiusY
+                cornerRadiusX,
+                cornerRadiusY,
+                cornerRadiusX,
+                cornerRadiusY,
+                changingInnerRadiusX,
+                changingInnerRadiusY,
+                changingInnerRadiusX,
+                changingInnerRadiusY
             )
         )
         drawCustomRoundedRect(
             canvas,
             bottomSide,
             floatArrayOf(
-                changingInnerRadiusX, changingInnerRadiusY,
-                changingInnerRadiusX, changingInnerRadiusY,
-                cornerRadiusX, cornerRadiusY,
-                cornerRadiusX, cornerRadiusY
+                changingInnerRadiusX,
+                changingInnerRadiusY,
+                changingInnerRadiusX,
+                changingInnerRadiusY,
+                cornerRadiusX,
+                cornerRadiusY,
+                cornerRadiusX,
+                cornerRadiusY
             )
         )
 
@@ -338,8 +333,10 @@
             // Fallback rectangle with uniform rounded corners
             val scaleFactorX = floatingView.scaleX
             val scaleFactorY = floatingView.scaleY
-            val cornerRadiusX = QuickStepContract.getWindowCornerRadius(launcher) / scaleFactorX
-            val cornerRadiusY = QuickStepContract.getWindowCornerRadius(launcher) / scaleFactorY
+            val cornerRadiusX =
+                QuickStepContract.getWindowCornerRadius(container.asContext()) / scaleFactorX
+            val cornerRadiusY =
+                QuickStepContract.getWindowCornerRadius(container.asContext()) / scaleFactorY
             c.drawRoundRect(rect, cornerRadiusX, cornerRadiusY, backgroundPaint)
         }
     }
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 18922a6..0e451b5 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -36,12 +36,10 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseActivity;
 import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.views.BaseDragLayer;
@@ -54,7 +52,7 @@
 
 /**
  * Create an instance via
- * {@link #getFloatingTaskView(StatefulActivity, View, Bitmap, Drawable, RectF)} to
+ * {@link #getFloatingTaskView(RecentsViewContainer, View, Bitmap, Drawable, RectF)} to
  * which will have the thumbnail from the provided existing TaskView overlaying the taskview itself.
  *
  * Can then animate the taskview using
@@ -67,32 +65,32 @@
 
     public static final FloatProperty<FloatingTaskView> PRIMARY_TRANSLATE_OFFSCREEN =
             new FloatProperty<FloatingTaskView>("floatingTaskPrimaryTranslateOffscreen") {
-        @Override
-        public void setValue(FloatingTaskView view, float translation) {
-            ((RecentsView) view.mActivity.getOverviewPanel()).getPagedOrientationHandler()
-                    .setFloatingTaskPrimaryTranslation(
-                            view,
-                            translation,
-                            view.mActivity.getDeviceProfile()
-                    );
-        }
+                @Override
+                public void setValue(FloatingTaskView view, float translation) {
+                    ((RecentsView) view.mContainer.getOverviewPanel()).getPagedOrientationHandler()
+                            .setFloatingTaskPrimaryTranslation(
+                                    view,
+                                    translation,
+                                    view.mContainer.getDeviceProfile()
+                            );
+                }
 
-        @Override
-        public Float get(FloatingTaskView view) {
-            return ((RecentsView) view.mActivity.getOverviewPanel())
-                    .getPagedOrientationHandler()
-                    .getFloatingTaskPrimaryTranslation(
-                            view,
-                            view.mActivity.getDeviceProfile()
-                    );
-        }
-    };
+                @Override
+                public Float get(FloatingTaskView view) {
+                        return ((RecentsView) view.mContainer.getOverviewPanel())
+                                .getPagedOrientationHandler()
+                                .getFloatingTaskPrimaryTranslation(
+                                        view,
+                                        view.mContainer.getDeviceProfile()
+                                );
+                }
+            };
 
     private int mSplitHolderSize;
     private FloatingTaskThumbnailView mThumbnailView;
     private SplitPlaceholderView mSplitPlaceholderView;
     private RectF mStartingPosition;
-    private final StatefulActivity mActivity;
+    private final RecentsViewContainer mContainer;
     private final boolean mIsRtl;
     private final FullscreenDrawParams mFullscreenParams;
     private RecentsPagedOrientationHandler mOrientationHandler;
@@ -110,7 +108,7 @@
 
     public FloatingTaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mActivity = BaseActivity.fromContext(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
         mIsRtl = Utilities.isRtl(getResources());
         mFullscreenParams = new FullscreenDrawParams(context);
 
@@ -126,7 +124,7 @@
         mSplitPlaceholderView.setAlpha(0);
     }
 
-    private void init(StatefulActivity launcher, View originalView, @Nullable Bitmap thumbnail,
+    private void init(RecentsViewContainer launcher, View originalView, @Nullable Bitmap thumbnail,
             Drawable icon, RectF positionOut) {
         mStartingPosition = positionOut;
         updateInitialPositionForView(originalView);
@@ -153,7 +151,7 @@
      * Configures and returns a an instance of {@link FloatingTaskView} initially matching the
      * appearance of {@code originalView}.
      */
-    public static FloatingTaskView getFloatingTaskView(StatefulActivity launcher,
+    public static FloatingTaskView getFloatingTaskView(RecentsViewContainer launcher,
             View originalView, @Nullable Bitmap thumbnail, Drawable icon, RectF positionOut) {
         final ViewGroup dragLayer = launcher.getDragLayer();
         final FloatingTaskView floatingView = (FloatingTaskView) launcher.getLayoutInflater()
@@ -167,7 +165,7 @@
             // Add to top if not
             openTaskViewIndex = dragLayer.getChildCount();
         }
-        dragLayer.addView(floatingView, openTaskViewIndex - 1);
+        dragLayer.addView(floatingView, openTaskViewIndex);
         return floatingView;
     }
 
@@ -179,13 +177,13 @@
             originalView.getBoundsOnScreen(mTmpRect);
             mStartingPosition.set(mTmpRect);
             int[] dragLayerPositionRelativeToScreen =
-                    mActivity.getDragLayer().getLocationOnScreen();
+                    mContainer.getDragLayer().getLocationOnScreen();
             mStartingPosition.offset(
                     -dragLayerPositionRelativeToScreen[0],
                     -dragLayerPositionRelativeToScreen[1]);
         } else {
             Rect viewBounds = new Rect(0, 0, originalView.getWidth(), originalView.getHeight());
-            Utilities.getBoundsForViewInDragLayer(mActivity.getDragLayer(), originalView,
+            Utilities.getBoundsForViewInDragLayer(mContainer.getDragLayer(), originalView,
                     viewBounds, false /* ignoreTransform */, null /* recycle */,
                     mStartingPosition);
         }
@@ -235,7 +233,7 @@
         // Position the floating view exactly on top of the original
         lp.topMargin = Math.round(pos.top);
         if (mIsRtl) {
-            lp.setMarginStart(mActivity.getDeviceProfile().widthPx - Math.round(pos.right));
+            lp.setMarginStart(mContainer.getDeviceProfile().widthPx - Math.round(pos.right));
         } else {
             lp.setMarginStart(Math.round(pos.left));
         }
@@ -252,7 +250,7 @@
      */
     public void addStagingAnimation(PendingAnimation animation, RectF startingBounds,
             Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
-        boolean isTablet = mActivity.getDeviceProfile().isTablet;
+        boolean isTablet = mContainer.getDeviceProfile().isTablet;
         boolean splittingFromOverview = fadeWithThumbnail;
         SplitAnimationTimings timings;
 
@@ -276,7 +274,7 @@
     public void addConfirmAnimation(PendingAnimation animation, RectF startingBounds,
             Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
         SplitAnimationTimings timings =
-                AnimUtils.getDeviceSplitToConfirmTimings(mActivity.getDeviceProfile().isTablet);
+                AnimUtils.getDeviceSplitToConfirmTimings(mContainer.getDeviceProfile().isTablet);
 
         addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
                 timings);
@@ -291,7 +289,7 @@
             Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask,
             SplitAnimationTimings timings) {
         mFullscreenParams.setIsStagedTask(isStagedTask);
-        final BaseDragLayer dragLayer = mActivity.getDragLayer();
+        final BaseDragLayer dragLayer = mContainer.getDragLayer();
         int[] dragLayerBounds = new int[2];
         dragLayer.getLocationOnScreen(dragLayerBounds);
         SplitOverlayProperties prop = new SplitOverlayProperties(endBounds,
@@ -299,7 +297,6 @@
 
         ValueAnimator transitionAnimator = ValueAnimator.ofFloat(0, 1);
         animation.add(transitionAnimator);
-        long animDuration = animation.getDuration();
         RectF floatingTaskViewBounds = new RectF();
 
         if (fadeWithThumbnail) {
@@ -391,7 +388,7 @@
         mOrientationHandler.updateSplitIconParams(iconView, onScreenRectCenterX,
                 onScreenRectCenterY, mFullscreenParams.mScaleX, mFullscreenParams.mScaleY,
                 iconView.getDrawableWidth(), iconView.getDrawableHeight(),
-                mActivity.getDeviceProfile(), mStagePosition);
+                mContainer.getDeviceProfile(), mStagePosition);
     }
 
     public int getStagePosition() {
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
index 6431bdf..4dde635 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java
@@ -33,10 +33,10 @@
 
 import androidx.annotation.Nullable;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.FloatingView;
 import com.android.launcher3.views.ListenerView;
@@ -49,7 +49,7 @@
         OnGlobalLayoutListener, FloatingView {
     private static final Matrix sTmpMatrix = new Matrix();
 
-    private final Launcher mLauncher;
+    private final QuickstepLauncher mLauncher;
     private final ListenerView mListenerView;
     private final FloatingWidgetBackgroundView mBackgroundView;
     private final RectF mBackgroundOffset = new RectF();
@@ -80,7 +80,7 @@
 
     public FloatingWidgetView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(context);
+        mLauncher = QuickstepLauncher.getLauncher(context);
         mListenerView = new ListenerView(context, attrs);
         mBackgroundView = new FloatingWidgetBackgroundView(context, attrs, defStyleAttr);
         addView(mBackgroundView);
@@ -283,7 +283,7 @@
      * @param windowSize               the size of the window when launched
      * @param windowCornerRadius       the corner radius of the window
      */
-    public static FloatingWidgetView getFloatingWidgetView(Launcher launcher,
+    public static FloatingWidgetView getFloatingWidgetView(QuickstepLauncher launcher,
             LauncherAppWidgetHostView originalView, RectF widgetBackgroundPosition,
             Size windowSize, float windowCornerRadius, boolean appTargetsAreTranslucent,
             int fallbackBackgroundColor) {
@@ -305,7 +305,8 @@
      */
     public static int getDefaultBackgroundColor(
             Context context, RemoteAnimationTarget target) {
-        return (target != null && target.taskInfo.taskDescription != null)
+        return (target != null && target.taskInfo != null
+                && target.taskInfo.taskDescription != null)
                 ? target.taskInfo.taskDescription.getBackgroundColor()
                 : Themes.getColorBackground(context);
     }
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 259927d..9e1c856 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -41,11 +41,11 @@
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 import com.android.wm.shell.common.split.SplitScreenConstants.PersistentSnapPosition;
 
+import kotlin.Unit;
+
 import java.util.HashMap;
 import java.util.function.Consumer;
 
-import kotlin.Unit;
-
 /**
  * TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
  *
@@ -81,7 +81,7 @@
 
     public GroupedTaskView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mDigitalWellBeingToast2 = new DigitalWellBeingToast(mActivity, this);
+        mDigitalWellBeingToast2 = new DigitalWellBeingToast(mContainer, this);
     }
 
     @Override
@@ -356,7 +356,7 @@
         if (initSplitTaskId == INVALID_TASK_ID) {
             getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
                     mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
-                    mActivity.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL);
+                    mContainer.getDeviceProfile(), getLayoutDirection() == LAYOUT_DIRECTION_RTL);
             // Should we be having a separate translation step apart from the measuring above?
             // The following only applies to large screen for now, but for future reference
             // we'd want to abstract this out in PagedViewHandlers to get the primary/secondary
@@ -373,7 +373,7 @@
             container.getThumbnailView().measure(widthMeasureSpec,
                     View.MeasureSpec.makeMeasureSpec(
                             heightSize -
-                                    mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx,
+                                    mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx,
                             MeasureSpec.EXACTLY));
         }
         if (!enableOverviewIconMenu()) {
@@ -392,7 +392,7 @@
 
     @Override
     public void setOrientationState(RecentsOrientedState orientationState) {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         if (enableOverviewIconMenu() && mSplitBoundsConfig != null) {
             ViewGroup.LayoutParams layoutParams = getLayoutParams();
             Pair<Point, Point> groupedTaskViewSizes =
@@ -425,7 +425,7 @@
             return;
         }
 
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
         boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
 
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 97f3d81..06c2aa3 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -26,7 +26,6 @@
 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -73,7 +72,7 @@
 
     public LauncherRecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr, LauncherActivityInterface.INSTANCE);
-        mActivity.getStateManager().addStateListener(this);
+        getStateManager().addStateListener(this);
     }
 
     @Override
@@ -86,28 +85,33 @@
 
     @Override
     protected void handleStartHome(boolean animated) {
-        StateManager stateManager = mActivity.getStateManager();
+        StateManager stateManager = getStateManager();
         animated &= stateManager.shouldAnimateStateChange();
         stateManager.goToState(NORMAL, animated);
         if (FeatureFlags.enableSplitContextually()) {
             mSplitSelectStateController.getSplitAnimationController()
-                    .playPlaceholderDismissAnim(mActivity, LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
+                    .playPlaceholderDismissAnim(mContainer, LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
         }
-        AbstractFloatingView.closeAllOpenViews(mActivity, animated);
+        AbstractFloatingView.closeAllOpenViews(mContainer, animated);
     }
 
     @Override
     protected boolean canStartHomeSafely() {
-        return mActivity.canStartHomeSafely();
+        return mContainer.canStartHomeSafely();
+    }
+
+    @Override
+    public StateManager<LauncherState> getStateManager() {
+        return mContainer.getStateManager();
     }
 
     @Override
     protected void onTaskLaunchAnimationEnd(boolean success) {
         if (success) {
-            mActivity.getStateManager().moveToRestState();
+            getStateManager().moveToRestState();
         } else {
-            LauncherState state = mActivity.getStateManager().getState();
-            mActivity.getAllAppsController().setState(state);
+            LauncherState state = getStateManager().getState();
+            mContainer.getAllAppsController().setState(state);
         }
         super.onTaskLaunchAnimationEnd(success);
     }
@@ -116,14 +120,14 @@
     public void onTaskIconChanged(int taskId) {
         super.onTaskIconChanged(taskId);
         // If Launcher needs to return to split select state, do it now, after the icon has updated.
-        if (mActivity.hasPendingSplitSelectInfo()) {
-            PendingSplitSelectInfo recoveryData = mActivity.getPendingSplitSelectInfo();
+        if (mContainer.hasPendingSplitSelectInfo()) {
+            PendingSplitSelectInfo recoveryData = mContainer.getPendingSplitSelectInfo();
             if (recoveryData.getStagedTaskId() == taskId) {
                 initiateSplitSelect(
                         getTaskViewByTaskId(recoveryData.getStagedTaskId()),
                         recoveryData.getStagePosition(), recoveryData.getSource()
                 );
-                mActivity.finishSplitSelectRecovery();
+                mContainer.finishSplitSelectRecovery();
             }
         }
     }
@@ -140,7 +144,7 @@
     public void onStateTransitionStart(LauncherState toState) {
         setOverviewStateEnabled(toState.overviewUi);
 
-        setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
+        setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
         setOverviewFullscreenEnabled(toState.getOverviewFullscreenProgress() == 1);
         if (toState == OVERVIEW_MODAL_TASK) {
             setOverviewSelectEnabled(true);
@@ -154,8 +158,8 @@
         }
 
         setFreezeViewVisibility(true);
-        if (mActivity.getDesktopVisibilityController() != null) {
-            mActivity.getDesktopVisibilityController().onLauncherStateChanged(toState);
+        if (mContainer.getDesktopVisibilityController() != null) {
+            mContainer.getDesktopVisibilityController().onLauncherStateChanged(toState);
         }
     }
 
@@ -187,8 +191,8 @@
     public void setOverviewStateEnabled(boolean enabled) {
         super.setOverviewStateEnabled(enabled);
         if (enabled) {
-            LauncherState state = mActivity.getStateManager().getState();
-            boolean hasClearAllButton = (state.getVisibleElements(mActivity)
+            LauncherState state = getStateManager().getState();
+            boolean hasClearAllButton = (state.getVisibleElements(mContainer)
                     & CLEAR_ALL_BUTTON) != 0;
             setDisallowScrollToClearAll(!hasClearAllButton);
         }
@@ -198,30 +202,28 @@
     public boolean onTouchEvent(MotionEvent ev) {
         boolean result = super.onTouchEvent(ev);
         // Do not let touch escape to siblings below this view.
-        return result || mActivity.getStateManager().getState().overviewUi;
+        return result || getStateManager().getState().overviewUi;
     }
 
     @Override
     protected DepthController getDepthController() {
-        return mActivity.getDepthController();
+        return mContainer.getDepthController();
     }
 
     @Override
     public void setModalStateEnabled(int taskId, boolean animate) {
         if (taskId != INVALID_TASK_ID) {
             setSelectedTask(taskId);
-            mActivity.getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK, animate);
-        } else {
-            if (mActivity.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
-                mActivity.getStateManager().goToState(LauncherState.OVERVIEW, animate);
-            }
+            getStateManager().goToState(LauncherState.OVERVIEW_MODAL_TASK, animate);
+        } else if (mContainer.isInState(LauncherState.OVERVIEW_MODAL_TASK)) {
+            getStateManager().goToState(LauncherState.OVERVIEW, animate);
         }
     }
 
     @Override
     protected void onDismissAnimationEnds() {
         super.onDismissAnimationEnds();
-        if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
+        if (mContainer.isInState(OVERVIEW_SPLIT_SELECT)) {
             // We want to keep the tasks translations in this temporary state
             // after resetting the rest above
             setTaskViewsPrimarySplitTranslation(mTaskViewsPrimarySplitTranslation);
@@ -234,13 +236,13 @@
             @SplitConfigurationOptions.StagePosition int stagePosition,
             StatsLogManager.EventEnum splitEvent) {
         super.initiateSplitSelect(taskView, stagePosition, splitEvent);
-        mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
+        getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
     }
 
     @Override
     public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
         super.initiateSplitSelect(splitSelectSource);
-        mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
+        getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
     }
 
     @Override
@@ -248,7 +250,7 @@
         if (FeatureFlags.enableSplitContextually()) {
             return !mSplitSelectStateController.isSplitSelectActive();
         } else {
-            return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+            return !mContainer.isInState(OVERVIEW_SPLIT_SELECT);
         }
     }
 
@@ -257,7 +259,7 @@
             RotationTouchHelper rotationTouchHelper) {
         super.onGestureAnimationStart(runningTasks, rotationTouchHelper);
         DesktopVisibilityController desktopVisibilityController =
-                mActivity.getDesktopVisibilityController();
+                mContainer.getDesktopVisibilityController();
         if (desktopVisibilityController != null) {
             desktopVisibilityController.setRecentsGestureStart();
         }
@@ -265,14 +267,15 @@
 
     @Override
     public void onGestureAnimationEnd() {
-        DesktopVisibilityController desktopVisibilityController = null;
+        DesktopVisibilityController desktopVisibilityController =
+                mContainer.getDesktopVisibilityController();
         boolean showDesktopApps = false;
         GestureState.GestureEndTarget endTarget = null;
-        if (isDesktopModeSupported()) {
-            desktopVisibilityController = mActivity.getDesktopVisibilityController();
+        if (desktopVisibilityController != null) {
+            desktopVisibilityController = mContainer.getDesktopVisibilityController();
             endTarget = mCurrentGestureEndTarget;
             if (endTarget == GestureState.GestureEndTarget.LAST_TASK
-                    && desktopVisibilityController.areFreeformTasksVisible()) {
+                    && desktopVisibilityController.areDesktopTasksVisible()) {
                 // Recents gesture was cancelled and we are returning to the previous task.
                 // After super class has handled clean up, show desktop apps on top again
                 showDesktopApps = true;
@@ -283,7 +286,7 @@
             desktopVisibilityController.setRecentsGestureEnd(endTarget);
         }
         if (showDesktopApps) {
-            SystemUiProxy.INSTANCE.get(mActivity).showDesktopApps(mActivity.getDisplayId(),
+            SystemUiProxy.INSTANCE.get(mContainer).showDesktopApps(mContainer.getDisplayId(),
                     null /* transition */);
         }
     }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c42bad3..791ef04 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -61,7 +61,6 @@
 import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_TAB;
 import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_UP;
 import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
@@ -69,6 +68,7 @@
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE;
+import static com.android.window.flags.Flags.enableDesktopWindowingMode;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -129,7 +129,6 @@
 import androidx.core.graphics.ColorUtils;
 
 import com.android.internal.jank.Cuj;
-import com.android.launcher3.BaseActivity;
 import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
@@ -149,7 +148,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.statemanager.BaseState;
-import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.touch.OverScroll;
@@ -163,10 +162,11 @@
 import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.util.TraceHelper;
 import com.android.launcher3.util.TranslateEdgeEffect;
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.launcher3.util.ViewPool;
-import com.android.quickstep.BaseActivityInterface;
+import com.android.quickstep.BaseContainerInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.OverviewCommandHelper;
 import com.android.quickstep.RecentsAnimationController;
@@ -226,8 +226,11 @@
 
 /**
  * A list of recent tasks.
+ * @param <CONTAINER_TYPE> : the container that should host recents view
+ * @param <STATE_TYPE> : the type of base state that will be used
  */
-public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>,
+
+public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewContainer,
         STATE_TYPE extends BaseState<STATE_TYPE>> extends PagedView implements Insettable,
         TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
         TaskVisualsChangeListener {
@@ -443,7 +446,7 @@
     private static final float FOREGROUND_SCRIM_TINT = 0.32f;
 
     protected final RecentsOrientedState mOrientationState;
-    protected final BaseActivityInterface<STATE_TYPE, ACTIVITY_TYPE> mSizeStrategy;
+    protected final BaseContainerInterface<STATE_TYPE, CONTAINER_TYPE> mSizeStrategy;
     @Nullable
     protected RecentsAnimationController mRecentsAnimationController;
     @Nullable
@@ -463,7 +466,6 @@
     protected final Rect mLastComputedTaskSize = new Rect();
     protected final Rect mLastComputedGridSize = new Rect();
     protected final Rect mLastComputedGridTaskSize = new Rect();
-    protected final Rect mLastComputedDesktopTaskSize = new Rect();
     private TaskView mSelectedTask = null;
     // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot.
     @Nullable
@@ -481,7 +483,7 @@
     // The threshold at which we update the SystemUI flags when animating from the task into the app
     public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
 
-    protected final ACTIVITY_TYPE mActivity;
+    protected final CONTAINER_TYPE mContainer;
     private final float mFastFlingVelocity;
     private final int mScrollHapticMinGapMillis;
     private final RecentsModel mModel;
@@ -721,6 +723,7 @@
     private int mSplitHiddenTaskViewIndex = -1;
     @Nullable
     private FloatingTaskView mSecondFloatingTaskView;
+    private View mSplitDividerPlaceholderView;
 
     /**
      * The task to be removed and immediately re-added. Should not be added to task pool.
@@ -768,14 +771,14 @@
     private final RecentsFilterState mFilterState = new RecentsFilterState();
 
     public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
-            BaseActivityInterface sizeStrategy) {
+            BaseContainerInterface sizeStrategy) {
         super(context, attrs, defStyleAttr);
         setEnableFreeScroll(true);
         mSizeStrategy = sizeStrategy;
-        mActivity = BaseActivity.fromContext(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
         mOrientationState = new RecentsOrientedState(
                 context, mSizeStrategy, this::animateRecentsRotationInPlace);
-        final int rotation = mActivity.getDisplay().getRotation();
+        final int rotation = mContainer.getDisplay().getRotation();
         mOrientationState.setRecentsRotation(rotation);
 
         mScrollHapticMinGapMillis = getResources()
@@ -827,7 +830,7 @@
                 R.string.task_overlay_factory_class);
 
         // Initialize quickstep specific cache params here, as this is constructed only once
-        mActivity.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
+        mContainer.getViewCache().setCacheSize(R.layout.digital_wellbeing_toast, 5);
 
         mTintingColor = getForegroundScrimDimColor(context);
 
@@ -835,9 +838,9 @@
         if (FeatureFlags.ENABLE_MULTI_INSTANCE.get()) {
             // invalidate the current list of tasks if filter changes with a fading in/out animation
             mFilterState.setOnFilterUpdatedListener(() -> {
-                Animator animatorFade = mActivity.getStateManager().createStateElementAnimation(
+                Animator animatorFade = getStateManager().createStateElementAnimation(
                         RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM, 1f, 0f);
-                Animator animatorAppear = mActivity.getStateManager().createStateElementAnimation(
+                Animator animatorAppear = getStateManager().createStateElementAnimation(
                         RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM, 0f, 1f);
                 animatorFade.addListener(new AnimatorListenerAdapter() {
                     @Override
@@ -1089,13 +1092,13 @@
         super.onAttachedToWindow();
         updateTaskStackListenerState();
         mModel.getThumbnailCache().getHighResLoadingState().addCallback(this);
-        mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
+        mContainer.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
         TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
         mSyncTransactionApplier = new SurfaceTransactionApplier(this);
         runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
                 .setSyncTransactionApplier(mSyncTransactionApplier));
         RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this);
-        mIPipAnimationListener.setActivityAndRecentsView(mActivity, this);
+        mIPipAnimationListener.setActivityAndRecentsView(mContainer, this);
         SystemUiProxy.INSTANCE.get(getContext()).setPipAnimationListener(
                 mIPipAnimationListener);
         mOrientationState.initListeners();
@@ -1110,7 +1113,7 @@
         super.onDetachedFromWindow();
         updateTaskStackListenerState();
         mModel.getThumbnailCache().getHighResLoadingState().removeCallback(this);
-        mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
+        mContainer.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener);
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
         mSyncTransactionApplier = null;
         runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTransformParams()
@@ -1250,20 +1253,27 @@
         if (taskView == null || !isTaskViewVisible(taskView)) {
             // TODO: Refine this animation.
             SurfaceTransactionApplier surfaceApplier =
-                    new SurfaceTransactionApplier(mActivity.getDragLayer());
+                    new SurfaceTransactionApplier(mContainer.getDragLayer());
             ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
             appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
             appAnimator.setInterpolator(ACCELERATE_DECELERATE);
+            final Matrix matrix = new Matrix();
             appAnimator.addUpdateListener(valueAnimator -> {
                 float percent = valueAnimator.getAnimatedFraction();
                 SurfaceTransaction transaction = new SurfaceTransaction();
-                Matrix matrix = new Matrix();
-                matrix.postScale(percent, percent);
-                matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
-                        mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
-                transaction.forSurface(apps[apps.length - 1].leash)
-                        .setAlpha(percent)
-                        .setMatrix(matrix);
+                for (int i = apps.length - 1; i >= 0; --i) {
+                    RemoteAnimationTarget app = apps[i];
+
+                    float dx = mContainer.getDeviceProfile().widthPx * (1 - percent) / 2
+                            + app.screenSpaceBounds.left * percent;
+                    float dy = mContainer.getDeviceProfile().heightPx * (1 - percent) / 2
+                            + app.screenSpaceBounds.top * percent;
+                    matrix.setScale(percent, percent);
+                    matrix.postTranslate(dx, dy);
+                    transaction.forSurface(app.leash)
+                            .setAlpha(percent)
+                            .setMatrix(matrix);
+                }
                 surfaceApplier.scheduleApply(transaction);
             });
             appAnimator.addListener(new AnimatorListenerAdapter() {
@@ -1273,6 +1283,8 @@
                     final SurfaceTransaction showTransaction = new SurfaceTransaction();
                     for (int i = apps.length - 1; i >= 0; --i) {
                         showTransaction.getTransaction().show(apps[i].leash);
+                        showTransaction.forSurface(apps[i].leash).setLayer(
+                                Integer.MAX_VALUE - 1000 + apps[i].prefixOrderIndex);
                     }
                     surfaceApplier.scheduleApply(showTransaction);
                 }
@@ -1286,7 +1298,7 @@
             });
         } else {
             TaskViewUtils.composeRecentsLaunchAnimator(anim, taskView, apps, wallpaper, nonApps,
-                    true /* launcherClosing */, mActivity.getStateManager(), this,
+                    true /* launcherClosing */, getStateManager(), this,
                     getDepthController());
         }
         anim.start();
@@ -1446,6 +1458,7 @@
             TaskView taskView = requireTaskViewAt(i);
             taskView.setBorderEnabled(enabled);
         }
+        mClearAllButton.setBorderEnabled(enabled);
     }
 
     /**
@@ -1462,7 +1475,7 @@
     @Override
     protected void onPageBeginTransition() {
         super.onPageBeginTransition();
-        if (!mActivity.getDeviceProfile().isTablet) {
+        if (!mContainer.getDeviceProfile().isTablet) {
             mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
         }
         if (mOverviewStateEnabled) { // only when in overview
@@ -1475,7 +1488,7 @@
         super.onPageEndTransition();
         ActiveGestureLog.INSTANCE.addLog(
                 "onPageEndTransition: current page index updated", getNextPage());
-        if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
+        if (isClearAllHidden() && !mContainer.getDeviceProfile().isTablet) {
             mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
         }
         if (getNextPage() > 0) {
@@ -1486,7 +1499,7 @@
 
     @Override
     protected boolean isSignificantMove(float absoluteDelta, int pageOrientedSize) {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         if (!deviceProfile.isTablet) {
             return super.isSignificantMove(absoluteDelta, pageOrientedSize);
         }
@@ -1496,6 +1509,15 @@
     }
 
     @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        boolean intercept = super.onInterceptTouchEvent(ev);
+        if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            Log.d("b/318590728", "onInterceptTouchEvent: " + ev);
+        }
+        return intercept;
+    }
+
+    @Override
     public boolean onTouchEvent(MotionEvent ev) {
         super.onTouchEvent(ev);
 
@@ -1635,7 +1657,7 @@
      * required to move the running task in grid.
      */
     public void moveRunningTaskToFront() {
-        if (!mActivity.getDeviceProfile().isTablet) {
+        if (!mContainer.getDeviceProfile().isTablet) {
             return;
         }
 
@@ -1660,15 +1682,8 @@
         removeView(runningTaskView);
         mMovingTaskView = null;
         runningTaskView.resetPersistentViewTransforms();
-        int frontTaskIndex = 0;
-        if (isDesktopModeSupported() && mDesktopTaskView != null
-                && !runningTaskView.isDesktopTask()) {
-            // If desktop mode is enabled, desktop task view is pinned at first position if present.
-            // Move running task to position 1.
-            frontTaskIndex = 1;
-        }
-        addView(runningTaskView, frontTaskIndex);
-        setCurrentPage(frontTaskIndex);
+        addView(runningTaskView, 0);
+        setCurrentPage(0);
 
         updateTaskSize();
     }
@@ -1745,7 +1760,6 @@
 
         // Clear out desktop view if it is set
         mDesktopTaskView = null;
-        DesktopTask desktopTask = null;
 
         // Add views as children based on whether it's grouped or single task. Looping through
         // taskGroups backwards populates the thumbnail grid from least recent to most recent.
@@ -1754,12 +1768,6 @@
             boolean isRemovalNeeded = stagedTaskIdToBeRemovedFromGrid != INVALID_TASK_ID
                     && groupTask.containsTask(stagedTaskIdToBeRemovedFromGrid);
 
-            if (groupTask instanceof DesktopTask) {
-                desktopTask = (DesktopTask) groupTask;
-                // Desktop task will be added separately in the end
-                continue;
-            }
-
             TaskView taskView;
             if (isRemovalNeeded && groupTask.hasMultipleTasks()) {
                 // If we need to remove half of a pair of tasks, force a TaskView with Type.SINGLE
@@ -1790,6 +1798,10 @@
 
                 ((GroupedTaskView) taskView).bind(leftTopTask, rightBottomTask, mOrientationState,
                         groupTask.mSplitBounds);
+            } else if (taskView instanceof DesktopTaskView) {
+                ((DesktopTaskView) taskView).bind(((DesktopTask) groupTask).tasks,
+                        mOrientationState);
+                mDesktopTaskView = (DesktopTaskView) taskView;
             } else {
                 taskView.bind(groupTask.task1, mOrientationState);
             }
@@ -1802,19 +1814,6 @@
 
         if (!taskGroups.isEmpty()) {
             addView(mClearAllButton);
-            if (isDesktopModeSupported()) {
-                // Check if we have apps on the desktop
-                if (desktopTask != null && !desktopTask.tasks.isEmpty()) {
-                    // If we are actively choosing apps for split, skip the desktop tile
-                    if (!getSplitSelectController().isSplitSelectActive()) {
-                        mDesktopTaskView = (DesktopTaskView) getTaskViewFromPool(
-                                TaskView.Type.DESKTOP);
-                        // Always add a desktop task to the first position
-                        addView(mDesktopTaskView, 0);
-                        mDesktopTaskView.bind(desktopTask.tasks, mOrientationState);
-                    }
-                }
-            }
         }
 
         // Keep same previous focused task
@@ -1822,12 +1821,6 @@
         // If the list changed, maybe the focused task doesn't exist anymore
         if (newFocusedTaskView == null && getTaskViewCount() > 0) {
             newFocusedTaskView = getTaskViewAt(0);
-            // Check if the first task is the desktop.
-            // If first task is desktop, try to find another task to set as the focused task
-            if (newFocusedTaskView != null && newFocusedTaskView.isDesktopTask()
-                    && getTaskViewCount() > 1) {
-                newFocusedTaskView = getTaskViewAt(1);
-            }
         }
         mFocusedTaskViewId = newFocusedTaskView != null && !enableGridOnlyOverview()
                 ? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID;
@@ -1871,12 +1864,7 @@
             if (hasAnyValidTaskIds(runningTaskId)) {
                 targetPage = indexOfChild(newRunningTaskView);
             } else if (getTaskViewCount() > 0) {
-                TaskView taskView = requireTaskViewAt(0);
-                // If first task id desktop, try to find another task to set the target page
-                if (taskView.isDesktopTask() && getTaskViewCount() > 1) {
-                    taskView = requireTaskViewAt(1);
-                }
-                targetPage = indexOfChild(taskView);
+                targetPage = indexOfChild(requireTaskViewAt(0));
             }
         }
         if (targetPage != -1 && mCurrentPage != targetPage) {
@@ -2037,9 +2025,9 @@
         mInsets.set(insets);
 
         // Update DeviceProfile dependant state.
-        DeviceProfile dp = mActivity.getDeviceProfile();
+        DeviceProfile dp = mContainer.getDeviceProfile();
         setOverviewGridEnabled(
-                mActivity.getStateManager().getState().displayOverviewTasksAsGrid(dp));
+                getStateManager().getState().displayOverviewTasksAsGrid(dp));
         if (enableGridOnlyOverview()) {
             mActionsView.updateHiddenFlags(HIDDEN_ACTIONS_IN_MENU, dp.isTablet);
         }
@@ -2076,7 +2064,7 @@
         if (forceRecreateDragLayerControllers
                 || !getPagedOrientationHandler().equals(oldOrientationHandler)) {
             // Changed orientations, update controllers so they intercept accordingly.
-            mActivity.getDragLayer().recreateControllers();
+            mContainer.getDragLayer().recreateControllers();
             onOrientationChanged();
             resetTaskVisuals();
         }
@@ -2108,24 +2096,21 @@
 
     // Update task size and padding that are dependent on DeviceProfile and insets.
     private void updateSizeAndPadding() {
-        DeviceProfile dp = mActivity.getDeviceProfile();
+        DeviceProfile dp = mContainer.getDeviceProfile();
         getTaskSize(mLastComputedTaskSize);
         mTaskWidth = mLastComputedTaskSize.width();
         mTaskHeight = mLastComputedTaskSize.height();
-
         setPadding(mLastComputedTaskSize.left - mInsets.left,
                 mLastComputedTaskSize.top - dp.overviewTaskThumbnailTopMarginPx - mInsets.top,
                 dp.widthPx - mInsets.right - mLastComputedTaskSize.right,
                 dp.heightPx - mInsets.bottom - mLastComputedTaskSize.bottom);
 
-        mSizeStrategy.calculateGridSize(dp, mActivity, mLastComputedGridSize);
-        mSizeStrategy.calculateGridTaskSize(mActivity, dp, mLastComputedGridTaskSize,
+        mSizeStrategy.calculateGridSize(dp, mContainer, mLastComputedGridSize);
+        mSizeStrategy.calculateGridTaskSize(mContainer, dp, mLastComputedGridTaskSize,
                 getPagedOrientationHandler());
-        if (isDesktopModeSupported()) {
-            mSizeStrategy.calculateDesktopTaskSize(mActivity, dp, mLastComputedDesktopTaskSize);
-        }
+
         if (enableGridOnlyOverview()) {
-            mSizeStrategy.calculateCarouselTaskSize(mActivity, dp, mLastComputedCarouselTaskSize,
+            mSizeStrategy.calculateCarouselTaskSize(mContainer, dp, mLastComputedCarouselTaskSize,
                     getPagedOrientationHandler());
         }
 
@@ -2159,7 +2144,7 @@
 
         float accumulatedTranslationX = 0;
         float translateXToMiddle = 0;
-        if (enableGridOnlyOverview() && mActivity.getDeviceProfile().isTablet) {
+        if (enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet) {
             translateXToMiddle = mIsRtl
                     ? mLastComputedCarouselTaskSize.right - mLastComputedTaskSize.right
                     : mLastComputedCarouselTaskSize.left - mLastComputedTaskSize.left;
@@ -2181,7 +2166,7 @@
     }
 
     public void getTaskSize(Rect outRect) {
-        mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
+        mSizeStrategy.calculateTaskSize(mContainer, mContainer.getDeviceProfile(), outRect,
                 getPagedOrientationHandler());
     }
 
@@ -2224,18 +2209,13 @@
         return mLastComputedGridTaskSize;
     }
 
-    /** Gets the last computed desktop task size */
-    public Rect getLastComputedDesktopTaskSize() {
-        return mLastComputedDesktopTaskSize;
-    }
-
     public Rect getLastComputedCarouselTaskSize() {
         return mLastComputedCarouselTaskSize;
     }
 
     /** Gets the task size for modal state. */
     public void getModalTaskSize(Rect outRect) {
-        mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect,
+        mSizeStrategy.calculateModalTaskSize(mContainer, mContainer.getDeviceProfile(), outRect,
                 getPagedOrientationHandler());
     }
 
@@ -2301,7 +2281,7 @@
 
     @Override
     protected int getDestinationPage(int scaledScroll) {
-        if (!mActivity.getDeviceProfile().isTablet) {
+        if (!mContainer.getDeviceProfile().isTablet) {
             return super.getDestinationPage(scaledScroll);
         }
         if (!isPageScrollsInitialized()) {
@@ -2451,7 +2431,7 @@
     }
 
     public void startHome() {
-        startHome(mActivity.isStarted());
+        startHome(mContainer.isStarted());
     }
 
     public void startHome(boolean animated) {
@@ -2464,6 +2444,8 @@
     /** Returns whether user can start home based on state in {@link OverviewCommandHelper}. */
     protected abstract boolean canStartHomeSafely();
 
+    public abstract StateManager<STATE_TYPE> getStateManager();
+
     public void reset() {
         setCurrentTask(-1);
         mCurrentPageScrollDiff = 0;
@@ -2603,6 +2585,7 @@
      */
     public void onGestureAnimationStart(
             Task[] runningTasks, RotationTouchHelper rotationTouchHelper) {
+        Log.d(TAG, "onGestureAnimationStart");
         mActiveGestureRunningTasks = runningTasks;
         // This needs to be called before the other states are set since it can create the task view
         if (mOrientationState.setGestureActive(true)) {
@@ -2641,7 +2624,7 @@
         AnimatorSet pa = setRecentsChangedOrientation(true);
         pa.addListener(AnimatorListeners.forSuccessCallback(() -> {
             setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
-            mActivity.getDragLayer().recreateControllers();
+            mContainer.getDragLayer().recreateControllers();
             setRecentsChangedOrientation(false).start();
         }));
         pa.start();
@@ -2670,7 +2653,7 @@
         if (!shouldRotateMenuForFakeRotation) {
             return;
         }
-        TaskMenuView tv = (TaskMenuView) getTopOpenViewWithType(mActivity, TYPE_TASK_MENU);
+        TaskMenuView tv = (TaskMenuView) getTopOpenViewWithType(mContainer, TYPE_TASK_MENU);
         if (tv != null) {
             // Rotation is supported on phone (details at b/254198019#comment4)
             tv.onRotationChanged();
@@ -2691,7 +2674,7 @@
         }
 
         BaseState<?> endState = mSizeStrategy.stateFromGestureEndTarget(endTarget);
-        if (endState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
+        if (endState.displayOverviewTasksAsGrid(mContainer.getDeviceProfile())) {
             TaskView runningTaskView = getRunningTaskView();
             float runningTaskPrimaryGridTranslation = 0;
             float runningTaskSecondaryGridTranslation = 0;
@@ -2834,7 +2817,7 @@
     }
 
     private boolean hasDesktopTask(Task[] runningTasks) {
-        if (!isDesktopModeSupported()) {
+        if (!enableDesktopWindowingMode()) {
             return false;
         }
         for (Task task : runningTasks) {
@@ -2954,7 +2937,7 @@
             return;
         }
 
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
 
         int topRowWidth = 0;
@@ -2979,8 +2962,6 @@
         TaskView homeTaskView = getHomeTaskView();
         TaskView nextFocusedTaskView = null;
 
-        int desktopTaskIndex = Integer.MAX_VALUE;
-
         if (!isTaskDismissal) {
             mTopRowIdSet.clear();
         }
@@ -3007,21 +2988,6 @@
                     // If focused task is snapped, the row width is just task width and spacing.
                     snappedTaskRowWidth = taskWidthAndSpacing;
                 }
-            } else if (taskView.isDesktopTask()) {
-                // Desktop task was not focused. Pin it to the right of focused
-                desktopTaskIndex = i;
-                if (taskView.getVisibility() == View.GONE) {
-                    // Desktop task view is hidden, skip it from grid calculations
-                    continue;
-                }
-                if (!enableGridOnlyOverview()) {
-                    // Only apply x-translation when using legacy overview grid
-                    gridTranslations[i] += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
-                }
-
-                // Center view vertically in case it's from different orientation.
-                taskView.setGridTranslationY((mLastComputedDesktopTaskSize.height() + taskTopMargin
-                        - taskView.getLayoutParams().height) / 2f);
             } else {
                 if (i > focusedTaskIndex) {
                     // For tasks after the focused task, shift by focused task's width and spacing.
@@ -3062,7 +3028,7 @@
                     // Move horizontally into empty space.
                     float widthOffset = 0;
                     for (int j = i - 1; !topSet.contains(j) && j >= 0; j--) {
-                        if (j == focusedTaskIndex || j == desktopTaskIndex) {
+                        if (j == focusedTaskIndex) {
                             continue;
                         }
                         widthOffset += requireTaskViewAt(j).getLayoutParams().width + mPageSpacing;
@@ -3081,7 +3047,7 @@
                     // Move horizontally into empty space.
                     float widthOffset = 0;
                     for (int j = i - 1; !bottomSet.contains(j) && j >= 0; j--) {
-                        if (j == focusedTaskIndex || j == desktopTaskIndex) {
+                        if (j == focusedTaskIndex) {
                             continue;
                         }
                         widthOffset += requireTaskViewAt(j).getLayoutParams().width + mPageSpacing;
@@ -3295,7 +3261,7 @@
         int secondaryTaskDimension = getPagedOrientationHandler().getSecondaryDimension(taskView);
         int verticalFactor = getPagedOrientationHandler().getSecondaryTranslationDirectionFactor();
 
-        ResourceProvider rp = DynamicResource.provider(mActivity);
+        ResourceProvider rp = DynamicResource.provider(mContainer);
         SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_START)
                 .setDampingRatio(rp.getFloat(R.dimen.dismiss_task_trans_y_damping_ratio))
                 .setStiffness(rp.getFloat(R.dimen.dismiss_task_trans_y_stiffness));
@@ -3323,10 +3289,10 @@
      */
     private void createInitialSplitSelectAnimation(PendingAnimation anim) {
         getPagedOrientationHandler().getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
-                mSplitPlaceholderInset, mActivity.getDeviceProfile(),
+                mSplitPlaceholderInset, mContainer.getDeviceProfile(),
                 mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
         SplitAnimationTimings timings =
-                AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
+                AnimUtils.getDeviceOverviewToSplitTimings(mContainer.getDeviceProfile().isTablet);
 
         RectF startingTaskRect = new RectF();
         safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
@@ -3342,7 +3308,7 @@
                     timings.getIconFadeEndOffset()));
         }
 
-        FloatingTaskView firstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
+        FloatingTaskView firstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mContainer,
                 splitAnimInitProps.getOriginalView(),
                 splitAnimInitProps.getOriginalBitmap(),
                 splitAnimInitProps.getIconDrawable(), startingTaskRect);
@@ -3354,13 +3320,13 @@
         // Allow user to click staged app to launch into fullscreen
         firstFloatingTaskView.setOnClickListener(view ->
                 mSplitSelectStateController.getSplitAnimationController().
-                        playAnimPlaceholderToFullscreen(mActivity, view,
+                        playAnimPlaceholderToFullscreen(mContainer, view,
                                 Optional.of(() -> resetFromSplitSelectionState())));
 
         // SplitInstructionsView: animate in
         safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
         SplitInstructionsView splitInstructionsView =
-                SplitInstructionsView.getSplitInstructionsView(mActivity);
+                SplitInstructionsView.getSplitInstructionsView(mContainer);
         splitInstructionsView.setAlpha(0);
         anim.setViewAlpha(splitInstructionsView, 1, clampToProgress(LINEAR,
                 timings.getInstructionsContainerFadeInStartOffset(),
@@ -3486,7 +3452,7 @@
         boolean isClearAllHidden = isClearAllHidden();
         boolean snapToLastTask = false;
         boolean isLeftRightSplit =
-                mActivity.getDeviceProfile().isLeftRightSplit && isSplitSelectionActive();
+                mContainer.getDeviceProfile().isLeftRightSplit && isSplitSelectionActive();
         TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
         int currentPageScroll = getScrollForPage(mCurrentPage);
         int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
@@ -3531,7 +3497,7 @@
                     // and adjust accordingly to the new shortTotalCompensation after dismiss.
                     int newClearAllShortTotalWidthTranslation = 0;
                     if (longRowWidth < mLastComputedGridSize.width()) {
-                        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+                        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
                         newClearAllShortTotalWidthTranslation =
                                 (mIsRtl
                                         ? mLastComputedTaskSize.right
@@ -3618,7 +3584,7 @@
         }
 
         SplitAnimationTimings splitTimings =
-                AnimUtils.getDeviceOverviewToSplitTimings(mActivity.getDeviceProfile().isTablet);
+                AnimUtils.getDeviceOverviewToSplitTimings(mContainer.getDeviceProfile().isTablet);
 
         int distanceFromDismissedTask = 0;
         for (int i = 0; i < count; i++) {
@@ -3827,7 +3793,7 @@
                             }
                             announceForAccessibility(
                                     getResources().getString(R.string.task_view_closed));
-                            mActivity.getStatsLogManager().logger()
+                            mContainer.getStatsLogManager().logger()
                                     .withItemInfo(dismissedTaskView.getItemInfo())
                                     .log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                         }
@@ -3993,7 +3959,7 @@
                         // Update various scroll-dependent UI.
                         dispatchScrollChanged();
                         updateActionsViewFocusedScroll();
-                        if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
+                        if (isClearAllHidden() && !mContainer.getDeviceProfile().isTablet) {
                             mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING,
                                     false);
                         }
@@ -4023,10 +3989,8 @@
         // tasks.
         mActionsView.updateForGroupedTask(isCurrentSplit);
 
-        if (isDesktopModeSupported()) {
-            boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
-            mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
-        }
+        boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
+        mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
     }
 
     /** Returns if app pairs are supported in this launcher. Overridden in subclasses. */
@@ -4217,7 +4181,7 @@
     @SuppressWarnings("unused")
     private void dismissAllTasks(View view) {
         runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION));
-        mActivity.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL);
+        mContainer.getStatsLogManager().logger().log(LAUNCHER_TASK_CLEAR_ALL);
     }
 
     private void dismissCurrentTask() {
@@ -4229,30 +4193,31 @@
 
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            switch (event.getKeyCode()) {
-                case KeyEvent.KEYCODE_TAB:
-                    return snapToPageRelative(event.isShiftPressed() ? -1 : 1, true /* cycle */,
-                            DIRECTION_TAB);
-                case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    return snapToPageRelative(mIsRtl ? -1 : 1, true /* cycle */, DIRECTION_RIGHT);
-                case KeyEvent.KEYCODE_DPAD_LEFT:
-                    return snapToPageRelative(mIsRtl ? 1 : -1, true /* cycle */, DIRECTION_LEFT);
-                case KeyEvent.KEYCODE_DPAD_UP:
-                    return snapToPageRelative(1, false /* cycle */, DIRECTION_UP);
-                case KeyEvent.KEYCODE_DPAD_DOWN:
-                    return snapToPageRelative(1, false /* cycle */, DIRECTION_DOWN);
-                case KeyEvent.KEYCODE_DEL:
-                case KeyEvent.KEYCODE_FORWARD_DEL:
+        if (isHandlingTouch() || event.getAction() != KeyEvent.ACTION_DOWN) {
+            return super.dispatchKeyEvent(event);
+        }
+        switch (event.getKeyCode()) {
+            case KeyEvent.KEYCODE_TAB:
+                return snapToPageRelative(event.isShiftPressed() ? -1 : 1, true /* cycle */,
+                        DIRECTION_TAB);
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                return snapToPageRelative(mIsRtl ? -1 : 1, true /* cycle */, DIRECTION_RIGHT);
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                return snapToPageRelative(mIsRtl ? 1 : -1, true /* cycle */, DIRECTION_LEFT);
+            case KeyEvent.KEYCODE_DPAD_UP:
+                return snapToPageRelative(1, false /* cycle */, DIRECTION_UP);
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                return snapToPageRelative(1, false /* cycle */, DIRECTION_DOWN);
+            case KeyEvent.KEYCODE_DEL:
+            case KeyEvent.KEYCODE_FORWARD_DEL:
+                dismissCurrentTask();
+                return true;
+            case KeyEvent.KEYCODE_NUMPAD_DOT:
+                if (event.isAltPressed()) {
+                    // Numpad DEL pressed while holding Alt.
                     dismissCurrentTask();
                     return true;
-                case KeyEvent.KEYCODE_NUMPAD_DOT:
-                    if (event.isAltPressed()) {
-                        // Numpad DEL pressed while holding Alt.
-                        dismissCurrentTask();
-                        return true;
-                    }
-            }
+                }
         }
         return super.dispatchKeyEvent(event);
     }
@@ -4345,7 +4310,8 @@
      * Updates {@link RecentsOrientedState}'s cached RecentsView rotation.
      */
     public void updateRecentsRotation() {
-        final int rotation = mActivity.getDisplay().getRotation();
+        final int rotation = TraceHelper.allowIpcs(
+                "RecentsView.updateRecentsRotation", () -> mContainer.getDisplay().getRotation());
         mOrientationState.setRecentsRotation(rotation);
     }
 
@@ -4459,14 +4425,14 @@
         } else {
             // Only update pivot when it is tablet and not in grid yet, so the pivot is correct
             // for non-current tasks when swiping up to overview
-            if (enableGridOnlyOverview() && mActivity.getDeviceProfile().isTablet
+            if (enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet
                     && !mOverviewGridEnabled) {
                 mTempRect.set(mLastComputedCarouselTaskSize);
             } else {
                 mTempRect.set(mLastComputedTaskSize);
             }
             getPagedViewOrientedState().getFullScreenScaleAndPivot(mTempRect,
-                    mActivity.getDeviceProfile(), mTempPointF);
+                    mContainer.getDeviceProfile(), mTempPointF);
         }
         setPivotX(mTempPointF.x);
         setPivotY(mTempPointF.y);
@@ -4566,7 +4532,7 @@
             TaskView taskView = (TaskView) child;
             outRect.offset(taskView.getPersistentTranslationX(),
                     taskView.getPersistentTranslationY());
-            outRect.top += mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+            outRect.top += mContainer.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
 
             mTempMatrix.reset();
             float persistentScale = taskView.getPersistentScale();
@@ -4678,7 +4644,7 @@
         if (isTopShift) {
             distanceToOffscreen = -taskPosition.bottom;
         } else if (isBottomShift) {
-            distanceToOffscreen = mActivity.getDeviceProfile().heightPx - taskPosition.top;
+            distanceToOffscreen = mContainer.getDeviceProfile().heightPx - taskPosition.top;
         }
         return distanceToOffscreen * offsetProgress;
     }
@@ -4734,7 +4700,7 @@
      */
     public void initiateSplitSelect(TaskView taskView) {
         int defaultSplitPosition = getPagedOrientationHandler()
-                .getDefaultSplitPosition(mActivity.getDeviceProfile());
+                .getDefaultSplitPosition(mContainer.getDeviceProfile());
         initiateSplitSelect(taskView, defaultSplitPosition, LAUNCHER_OVERVIEW_ACTIONS_SPLIT);
     }
 
@@ -4747,9 +4713,7 @@
         mSplitSelectStateController.setAnimateCurrentTaskDismissal(
                 true /*animateCurrentTaskDismissal*/);
         mSplitHiddenTaskViewIndex = indexOfChild(taskView);
-        if (isDesktopModeSupported()) {
-            updateDesktopTaskVisibility(false /* visible */);
-        }
+        updateDesktopTaskVisibility(false /* visible */);
     }
 
     /**
@@ -4771,9 +4735,7 @@
         mSplitSelectStateController.setInitialTaskSelect(splitSelectSource.intent,
                 splitSelectSource.position.stagePosition, splitSelectSource.itemInfo,
                 splitSelectSource.splitEvent, splitSelectSource.alreadyRunningTaskId);
-        if (isDesktopModeSupported()) {
-            updateDesktopTaskVisibility(false /* visible */);
-        }
+        updateDesktopTaskVisibility(false /* visible */);
     }
 
     private void updateDesktopTaskVisibility(boolean visible) {
@@ -4803,7 +4765,7 @@
             TaskThumbnailView thumbnail = taskIdAttributeContainer.getThumbnailView();
             mSplitSelectStateController.getSplitAnimationController()
                     .addInitialSplitFromPair(taskIdAttributeContainer, builder,
-                            mActivity.getDeviceProfile(),
+                            mContainer.getDeviceProfile(),
                             mSplitHiddenTaskView.getWidth(), mSplitHiddenTaskView.getHeight(),
                             primaryTaskSelected);
             builder.addOnFrameCallback(() ->{
@@ -4871,17 +4833,20 @@
         Rect firstTaskStartingBounds = new Rect();
         Rect firstTaskEndingBounds = mTempRect;
 
-        boolean isTablet = mActivity.getDeviceProfile().isTablet;
+        boolean isTablet = mContainer.getDeviceProfile().isTablet;
         SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
         PendingAnimation pendingAnimation = new PendingAnimation(timings.getDuration());
 
         int halfDividerSize = getResources()
                 .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
         getPagedOrientationHandler().getFinalSplitPlaceholderBounds(halfDividerSize,
-                mActivity.getDeviceProfile(),
+                mContainer.getDeviceProfile(),
                 mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds,
                 secondTaskEndingBounds);
 
+        mSplitDividerPlaceholderView = mSplitSelectStateController
+                .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation,
+                        mContainer, secondTaskEndingBounds, getContext());
         FloatingTaskView firstFloatingTaskView =
                 mSplitSelectStateController.getFirstFloatingTaskView();
         firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
@@ -4891,7 +4856,7 @@
 
         safeRemoveDragLayerView(mSecondFloatingTaskView);
 
-        mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity, secondView,
+        mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mContainer, secondView,
                 thumbnail, drawable, secondTaskStartingBounds);
         mSecondFloatingTaskView.setAlpha(1);
         mSecondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
@@ -4936,10 +4901,11 @@
             safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
             safeRemoveDragLayerView(mSecondFloatingTaskView);
             safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView());
+            safeRemoveDragLayerView(mSplitDividerPlaceholderView);
             mSecondFloatingTaskView = null;
             mSplitSelectSource = null;
             mSplitSelectStateController.getSplitAnimationController()
-                    .removeSplitInstructionsView(mActivity);
+                    .removeSplitInstructionsView(mContainer);
         }
 
         if (mSecondSplitHiddenView != null) {
@@ -4960,7 +4926,7 @@
         if (mSplitHiddenTaskViewIndex == -1) {
             return;
         }
-        if (!mActivity.getDeviceProfile().isTablet) {
+        if (!mContainer.getDeviceProfile().isTablet) {
             int pageToSnapTo = mCurrentPage;
             if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
                 pageToSnapTo += 1;
@@ -4977,14 +4943,12 @@
             mSplitHiddenTaskView.setThumbnailVisibility(VISIBLE, INVALID_TASK_ID);
             mSplitHiddenTaskView = null;
         }
-        if (isDesktopModeSupported()) {
-            updateDesktopTaskVisibility(true /* visible */);
-        }
+        updateDesktopTaskVisibility(true /* visible */);
     }
 
     private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
         if (viewToRemove != null) {
-            mActivity.getDragLayer().removeView(viewToRemove);
+            mContainer.getDragLayer().removeView(viewToRemove);
         }
     }
 
@@ -4993,11 +4957,11 @@
      * Note that the translation can be its primary or secondary dimension.
      */
     public float getSplitSelectTranslation() {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         RecentsPagedOrientationHandler orientationHandler = getPagedOrientationHandler();
         int splitPosition = getSplitSelectController().getActiveSplitStagePosition();
         int splitPlaceholderSize =
-                mActivity.getResources().getDimensionPixelSize(R.dimen.split_placeholder_size);
+                mContainer.getResources().getDimensionPixelSize(R.dimen.split_placeholder_size);
         int direction = orientationHandler.getSplitTranslationDirectionFactor(
                 splitPosition, deviceProfile);
 
@@ -5020,7 +4984,7 @@
 
     protected void onRotateInSplitSelectionState() {
         getPagedOrientationHandler().getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
-                mSplitPlaceholderInset, mActivity.getDeviceProfile(),
+                mSplitPlaceholderInset, mContainer.getDeviceProfile(),
                 mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
         mTempRectF.set(mTempRect);
         FloatingTaskView firstFloatingTaskView =
@@ -5029,10 +4993,10 @@
         firstFloatingTaskView.update(mTempRectF, /*progress=*/1f);
 
         RecentsPagedOrientationHandler orientationHandler = getPagedOrientationHandler();
-        Pair<FloatProperty, FloatProperty> taskViewsFloat =
+        Pair<FloatProperty<RecentsView>, FloatProperty<RecentsView>> taskViewsFloat =
                 orientationHandler.getSplitSelectTaskOffset(
                         TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
-                        mActivity.getDeviceProfile());
+                        mContainer.getDeviceProfile());
         taskViewsFloat.first.set(this, getSplitSelectTranslation());
         taskViewsFloat.second.set(this, 0f);
 
@@ -5165,17 +5129,21 @@
      * Returns the scale up required on the view, so that it coves the screen completely
      */
     public float getMaxScaleForFullScreen() {
-        if (enableGridOnlyOverview() && mActivity.getDeviceProfile().isTablet
+        if (enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet
                 && !mOverviewGridEnabled) {
+            if (mLastComputedCarouselTaskSize.isEmpty()) {
+                mSizeStrategy.calculateCarouselTaskSize(mContainer, mContainer.getDeviceProfile(),
+                        mLastComputedCarouselTaskSize, getPagedOrientationHandler());
+            }
             mTempRect.set(mLastComputedCarouselTaskSize);
         } else {
-            if (mLastComputedTaskSize.height() == 0 || mLastComputedTaskSize.width() == 0) {
+            if (mLastComputedTaskSize.isEmpty()) {
                 getTaskSize(mLastComputedTaskSize);
             }
             mTempRect.set(mLastComputedTaskSize);
         }
         return getPagedViewOrientedState().getFullScreenScaleAndPivot(
-                mTempRect, mActivity.getDeviceProfile(), mTempPointF);
+                mTempRect, mContainer.getDeviceProfile(), mTempPointF);
     }
 
     public PendingAnimation createTaskLaunchAnimation(
@@ -5201,10 +5169,10 @@
             // Once we pass a certain threshold, update the sysui flags to match the target
             // tasks' flags
             if (animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD) {
-                mActivity.getSystemUiController().updateUiState(
+                mContainer.getSystemUiController().updateUiState(
                         UI_STATE_FULLSCREEN_TASK, targetSysUiFlags);
             } else {
-                mActivity.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
+                mContainer.getSystemUiController().updateUiState(UI_STATE_FULLSCREEN_TASK, 0);
             }
 
             // Passing the threshold from taskview to fullscreen app will vibrate
@@ -5226,7 +5194,7 @@
         DepthController depthController = getDepthController();
         if (depthController != null) {
             ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController.stateDepth,
-                    MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mActivity));
+                    MULTI_PROPERTY_VALUE, BACKGROUND_APP.getDepth(mContainer));
             anim.play(depthAnimator);
         }
         anim.play(ObjectAnimator.ofFloat(this, TASK_THUMBNAIL_SPLASH_ALPHA, 0f, 1f));
@@ -5259,7 +5227,7 @@
                 }
                 Task task = tv.getTask();
                 if (task != null) {
-                    mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
+                    mContainer.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
                             .log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
                 }
             } else {
@@ -5363,7 +5331,7 @@
         }
 
         RemoteTargetGluer gluer;
-        if (isDesktopModeSupported() && recentsAnimationTargets.hasDesktopTasks()) {
+        if (recentsAnimationTargets.hasDesktopTasks()) {
             gluer = new RemoteTargetGluer(getContext(), getSizeStrategy(), recentsAnimationTargets,
                     true /* forDesktop */);
             mRemoteTargetHandles = gluer.assignTargetsForDesktop(recentsAnimationTargets);
@@ -5386,7 +5354,7 @@
 
             TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
             tvs.setOrientationState(mOrientationState);
-            tvs.setDp(mActivity.getDeviceProfile());
+            tvs.setDp(mContainer.getDeviceProfile());
             tvs.recentsViewScale.value = 1;
         });
 
@@ -5418,6 +5386,10 @@
         finishRecentsAnimation(toRecents, true /* shouldPip */, onFinishComplete);
     }
 
+    /**
+     * NOTE: Whatever value gets passed through to the toRecents param may need to also be set on
+     * {@link #mRecentsAnimationController#setWillFinishToHome}.
+     */
     public void finishRecentsAnimation(boolean toRecents, boolean shouldPip,
             @Nullable Runnable onFinishComplete) {
         Log.d(TAG, "finishRecentsAnimation - mRecentsAnimationController: "
@@ -5437,7 +5409,7 @@
             // Notify the SysUI to use fade-in animation when entering PiP from live tile.
             final SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(getContext());
             systemUiProxy.setPipAnimationTypeToAlpha();
-            systemUiProxy.setShelfHeight(true, mActivity.getDeviceProfile().hotseatBarSizePx);
+            systemUiProxy.setShelfHeight(true, mContainer.getDeviceProfile().hotseatBarSizePx);
             // Transaction to hide the task to avoid flicker for entering PiP from split-screen.
             // See also {@link AbsSwipeUpHandler#maybeFinishSwipeToHome}.
             PictureInPictureSurfaceTransaction tx =
@@ -5463,6 +5435,8 @@
      * Called when a running recents animation has finished or canceled.
      */
     public void onRecentsAnimationComplete() {
+        Log.d(TAG, "onRecentsAnimationComplete - mRecentsAnimationController: "
+                + mRecentsAnimationController);
         // At this point, the recents animation is not running and if the animation was canceled
         // by a display rotation then reset this state to show the screenshot
         setRunningTaskViewShowScreenshot(true);
@@ -5506,7 +5480,7 @@
 
     protected int getClearAllExtraPageSpacing() {
         return showAsGrid()
-                ? Math.max(mActivity.getDeviceProfile().overviewGridSideMargin - mPageSpacing, 0)
+                ? Math.max(mContainer.getDeviceProfile().overviewGridSideMargin - mPageSpacing, 0)
                 : 0;
     }
 
@@ -5538,10 +5512,6 @@
     }
 
     private int getFirstViewIndex() {
-        if (isDesktopModeSupported() && mDesktopTaskView != null) {
-            // Desktop task is at position 0, that is the first view
-            return 0;
-        }
         TaskView focusedTaskView = mShowAsGridLastOnLayout ? getFocusedTaskView() : null;
         return focusedTaskView != null ? indexOfChild(focusedTaskView) : 0;
     }
@@ -5959,7 +5929,7 @@
         return mTaskOverlayFactory;
     }
 
-    public BaseActivityInterface getSizeStrategy() {
+    public BaseContainerInterface getSizeStrategy() {
         return mSizeStrategy;
     }
 
@@ -5991,7 +5961,7 @@
             requireTaskViewAt(i).setColorTint(mColorTint, mTintingColor);
         }
 
-        Drawable scrimBg = mActivity.getScrimView().getBackground();
+        Drawable scrimBg = mContainer.getScrimView().getBackground();
         if (scrimBg != null) {
             if (tintAmount == 0f) {
                 scrimBg.setTintList(null);
@@ -6010,8 +5980,8 @@
     /** Returns {@code true} if the overview tasks are displayed as a grid. */
     public boolean showAsGrid() {
         return mOverviewGridEnabled || (mCurrentGestureEndTarget != null
-                && mSizeStrategy.stateFromGestureEndTarget(
-                mCurrentGestureEndTarget).displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
+                && mSizeStrategy.stateFromGestureEndTarget(mCurrentGestureEndTarget)
+                    .displayOverviewTasksAsGrid(mContainer.getDeviceProfile()));
     }
 
     private boolean showAsFullscreen() {
@@ -6177,7 +6147,7 @@
         }
     }
 
-    private static class PinnedStackAnimationListener<T extends BaseActivity> extends
+    private static class PinnedStackAnimationListener<T extends RecentsViewContainer> extends
             IPipAnimationListener.Stub {
         @Nullable
         private T mActivity;
@@ -6243,7 +6213,7 @@
     public void updateLocusId() {
         String locusId = "Overview";
 
-        if (mOverviewStateEnabled && mActivity.isStarted()) {
+        if (mOverviewStateEnabled && mContainer.isStarted()) {
             locusId += "|ENABLED";
         } else {
             locusId += "|DISABLED";
@@ -6251,7 +6221,28 @@
 
         final LocusId id = new LocusId(locusId);
         // Set locus context is a binder call, don't want it to happen during a transition
-        UI_HELPER_EXECUTOR.post(() -> mActivity.setLocusContext(id, Bundle.EMPTY));
+        UI_HELPER_EXECUTOR.post(() -> mContainer.setLocusContext(id, Bundle.EMPTY));
+    }
+
+    /**
+     * Moves the provided task into desktop mode, and invoke {@code successCallback} if succeeded.
+     */
+    public void moveTaskToDesktop(TaskIdAttributeContainer taskContainer,
+            Runnable successCallback) {
+        if (!enableDesktopWindowingMode()) {
+            return;
+        }
+        switchToScreenshot(() -> finishRecentsAnimation(/* toRecents= */true, /* shouldPip= */false,
+                () -> moveTaskToDesktopInternal(taskContainer, successCallback)));
+    }
+
+    private void moveTaskToDesktopInternal(TaskIdAttributeContainer taskContainer,
+            Runnable successCallback) {
+        if (mDesktopRecentsTransitionController == null) {
+            return;
+        }
+        mDesktopRecentsTransitionController.moveToDesktop(taskContainer.getTask().key.id);
+        successCallback.run();
     }
 
     public interface TaskLaunchListener {
diff --git a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
index a3e5a35..a56d51e 100644
--- a/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitInstructionsView.java
@@ -43,6 +43,7 @@
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.states.StateAnimationConfig;
+
 import com.android.quickstep.util.SplitSelectStateController;
 
 /**
@@ -57,7 +58,7 @@
     private static final float BOUNCE_HEIGHT = 20;
     private static final int DURATION_DEFAULT_SPLIT_DISMISS = 350;
 
-    private final StatefulActivity mLauncher;
+    private final RecentsViewContainer mContainer;
     public boolean mIsCurrentlyAnimating = false;
 
     public static final FloatProperty<SplitInstructionsView> UNFOLD =
@@ -96,13 +97,13 @@
 
     public SplitInstructionsView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = (StatefulActivity) context;
+        mContainer = RecentsViewContainer.containerFromContext(context);
     }
 
-    public static SplitInstructionsView getSplitInstructionsView(StatefulActivity launcher) {
-        ViewGroup dragLayer = launcher.getDragLayer();
+    public static SplitInstructionsView getSplitInstructionsView(RecentsViewContainer container) {
+        ViewGroup dragLayer = container.getDragLayer();
         final SplitInstructionsView splitInstructionsView =
-                (SplitInstructionsView) launcher.getLayoutInflater().inflate(
+                (SplitInstructionsView) container.getLayoutInflater().inflate(
                         R.layout.split_instructions_view,
                         dragLayer,
                         false
@@ -139,12 +140,12 @@
     }
 
     private void exitSplitSelection() {
-        SplitSelectStateController splitSelectController =
-                ((RecentsView) mLauncher.getOverviewPanel()).getSplitSelectController();
+        RecentsView recentsView = mContainer.getOverviewPanel();
+        SplitSelectStateController splitSelectController = recentsView.getSplitSelectController();
 
-        StateManager stateManager = mLauncher.getStateManager();
+        StateManager stateManager = recentsView.getStateManager();
         BaseState startState = stateManager.getState();
-        long duration = startState.getTransitionDuration(mLauncher, false);
+        long duration = startState.getTransitionDuration(mContainer.asContext(), false);
         if (duration == 0) {
             // Case where we're in contextual on workspace (NORMAL), which by default has 0
             // transition duration
@@ -155,7 +156,7 @@
         AnimatorSet stateAnim = stateManager.createAtomicAnimation(
                 startState, NORMAL, config);
         AnimatorSet dismissAnim = splitSelectController.getSplitAnimationController()
-                .createPlaceholderDismissAnim(mLauncher,
+                .createPlaceholderDismissAnim(mContainer,
                         LAUNCHER_SPLIT_SELECTION_EXIT_CANCEL_BUTTON, duration);
         stateAnim.play(dismissAnim);
         stateManager.setCurrentAnimation(stateAnim, NORMAL);
@@ -163,10 +164,10 @@
     }
 
     void ensureProperRotation() {
-        ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler()
+        ((RecentsView) mContainer.getOverviewPanel()).getPagedOrientationHandler()
                 .setSplitInstructionsParams(
                         this,
-                        mLauncher.getDeviceProfile(),
+                        mContainer.getDeviceProfile(),
                         getMeasuredHeight(),
                         getMeasuredWidth()
                 );
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index c9aad1a..fcbb45b 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -46,7 +46,6 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimationSuccessListener;
@@ -69,7 +68,7 @@
     private static final int REVEAL_OPEN_DURATION = enableOverviewIconMenu() ? 417 : 150;
     private static final int REVEAL_CLOSE_DURATION = enableOverviewIconMenu() ? 333 : 100;
 
-    private BaseDraggingActivity mActivity;
+    private RecentsViewContainer mContainer;
     private TextView mTaskName;
     @Nullable
     private AnimatorSet mOpenCloseAnimator;
@@ -89,7 +88,7 @@
     public TaskMenuView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
 
-        mActivity = BaseDraggingActivity.fromContext(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
         setClipToOutline(true);
     }
 
@@ -103,7 +102,7 @@
     @Override
     public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            BaseDragLayer dl = mActivity.getDragLayer();
+            BaseDragLayer dl = mContainer.getDragLayer();
             if (!dl.isEventOverView(this, ev)) {
                 // TODO: log this once we have a new container type for it?
                 close(true);
@@ -140,9 +139,14 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        int maxMenuHeight = calculateMaxHeight();
-        if (MeasureSpec.getSize(heightMeasureSpec) > maxMenuHeight) {
-            heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxMenuHeight, MeasureSpec.AT_MOST);
+        if (!(enableOverviewIconMenu()
+                && ((RecentsView) mContainer.getOverviewPanel()).isOnGridBottomRow(mTaskView))) {
+            // TODO(b/326952853): Cap menu height for grid bottom row in a way that doesn't break
+            // additionalTranslationY.
+            int maxMenuHeight = calculateMaxHeight();
+            if (MeasureSpec.getSize(heightMeasureSpec) > maxMenuHeight) {
+                heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxMenuHeight, MeasureSpec.AT_MOST);
+            }
         }
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
@@ -161,10 +165,10 @@
 
     public static boolean showForTask(TaskIdAttributeContainer taskContainer,
             @Nullable Runnable onClosingStartCallback) {
-        BaseDraggingActivity activity = BaseDraggingActivity.fromContext(
+        RecentsViewContainer container = RecentsViewContainer.containerFromContext(
                 taskContainer.getTaskView().getContext());
-        final TaskMenuView taskMenuView = (TaskMenuView) activity.getLayoutInflater().inflate(
-                        R.layout.task_menu, activity.getDragLayer(), false);
+        final TaskMenuView taskMenuView = (TaskMenuView) container.getLayoutInflater().inflate(
+                        R.layout.task_menu, container.getDragLayer(), false);
         taskMenuView.setOnClosingStartCallback(onClosingStartCallback);
         return taskMenuView.populateAndShowForTask(taskContainer);
     }
@@ -177,7 +181,7 @@
         if (isAttachedToWindow()) {
             return false;
         }
-        mActivity.getDragLayer().addView(this);
+        mContainer.getDragLayer().addView(this);
         mTaskView = taskContainer.getTaskView();
         mTaskContainer = taskContainer;
         if (!populateAndLayoutMenu()) {
@@ -210,7 +214,7 @@
     }
 
     private void addMenuOption(SystemShortcut menuOption) {
-        LinearLayout menuOptionView = (LinearLayout) mActivity.getLayoutInflater().inflate(
+        LinearLayout menuOptionView = (LinearLayout) mContainer.getLayoutInflater().inflate(
                 R.layout.task_view_menu_option, this, false);
         if (enableOverviewIconMenu()) {
             ((GradientDrawable) menuOptionView.getBackground()).setCornerRadius(0);
@@ -219,7 +223,7 @@
                 menuOptionView.findViewById(R.id.icon), menuOptionView.findViewById(R.id.text));
         LayoutParams lp = (LayoutParams) menuOptionView.getLayoutParams();
         mTaskView.getPagedOrientationHandler().setLayoutParamsForTaskMenuOptionItem(lp,
-                menuOptionView, mActivity.getDeviceProfile());
+                menuOptionView, mContainer.getDeviceProfile());
         // Set an onClick listener on each menu option. The onClick method is responsible for
         // ending LiveTile mode on the thumbnail if needed.
         menuOptionView.setOnClickListener(menuOption::onClick);
@@ -227,19 +231,19 @@
     }
 
     private void orientAroundTaskView(TaskIdAttributeContainer taskContainer) {
-        RecentsView recentsView = mActivity.getOverviewPanel();
+        RecentsView recentsView = mContainer.getOverviewPanel();
         RecentsPagedOrientationHandler orientationHandler =
                 recentsView.getPagedOrientationHandler();
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
 
         // Get Position
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
-        mActivity.getDragLayer().getDescendantRectRelativeToSelf(
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
+        mContainer.getDragLayer().getDescendantRectRelativeToSelf(
                 enableOverviewIconMenu()
                         ? getIconView().findViewById(R.id.icon_view_menu_anchor)
                         : taskContainer.getThumbnailView(),
                 sTempRect);
-        Rect insets = mActivity.getDragLayer().getInsets();
+        Rect insets = mContainer.getDragLayer().getInsets();
         BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
         params.width = orientationHandler.getTaskMenuWidth(taskContainer.getThumbnailView(),
                 deviceProfile, taskContainer.getStagePosition());
@@ -301,6 +305,7 @@
 
     private void animateOpenOrClosed(boolean closing) {
         if (mOpenCloseAnimator != null && mOpenCloseAnimator.isRunning()) {
+            testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE, "getting canceled");
             mOpenCloseAnimator.cancel();
         }
         mOpenCloseAnimator = new AnimatorSet();
@@ -319,12 +324,12 @@
             IconAppChipView iconAppChip = (IconAppChipView) mTaskContainer.getIconView().asView();
 
             float additionalTranslationY = 0;
-            if (((RecentsView) mActivity.getOverviewPanel()).isOnGridBottomRow(mTaskView)) {
+            if (((RecentsView) mContainer.getOverviewPanel()).isOnGridBottomRow(mTaskView)) {
                 // Animate menu up for enough room to display full menu when task on bottom row.
                 float menuBottom = getHeight() + mMenuTranslationYBeforeOpen;
                 float taskBottom = mTaskView.getHeight() + mTaskView.getPersistentTranslationY();
-                float taskbarTop = mActivity.getDeviceProfile().heightPx
-                        - mActivity.getDeviceProfile().getOverviewActionsClaimedSpaceBelow();
+                float taskbarTop = mContainer.getDeviceProfile().heightPx
+                        - mContainer.getDeviceProfile().getOverviewActionsClaimedSpaceBelow();
                 float midpoint = (taskBottom + taskbarTop) / 2f;
                 additionalTranslationY = -Math.max(menuBottom - midpoint, 0);
             }
@@ -339,11 +344,11 @@
             menuTranslationYAnim.setInterpolator(EMPHASIZED);
 
             float additionalTranslationX = 0;
-            if (mActivity.getDeviceProfile().isLandscape
+            if (mContainer.getDeviceProfile().isLandscape
                     && mTaskContainer.getStagePosition() == STAGE_POSITION_BOTTOM_OR_RIGHT) {
                 // Animate menu and icon when split task would display off the side of the screen.
                 additionalTranslationX = Math.max(
-                        getTranslationX() + getWidth() - (mActivity.getDeviceProfile().widthPx
+                        getTranslationX() + getWidth() - (mContainer.getDeviceProfile().widthPx
                                 - getResources().getDimensionPixelSize(
                                 R.dimen.task_menu_edge_padding) * 2), 0);
             }
@@ -357,11 +362,14 @@
                     iconAppChip.getMenuTranslationX(),
                     MULTI_PROPERTY_VALUE, closing ? 0 : -additionalTranslationX);
             menuTranslationXAnim.setInterpolator(EMPHASIZED);
+            testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
+                    "TaskMenuView.java.animateOpenOrClosed: running translation animations");
 
             mOpenCloseAnimator.playTogether(translationYAnim, translationXAnim,
                     menuTranslationXAnim, menuTranslationYAnim);
         }
-
+        testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
+                "TaskMenuView.java.animateOpenOrClosed: running animation 2");
         mOpenCloseAnimator.playTogether(mRevealAnimator,
                 ObjectAnimator.ofFloat(
                         mTaskContainer.getThumbnailView(), DIM_ALPHA,
@@ -379,6 +387,13 @@
             }
 
             @Override
+            public void onAnimationCancel(Animator animation) {
+                super.onAnimationCancel(animation);
+                testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
+                        "TaskMenuView.java.animateOpenOrClosed: onAnimationCancel");
+            }
+
+            @Override
             public void onAnimationSuccess(Animator animator) {
                 testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE,
                         "TaskMenuView.java.animateOpenOrClosed: onAnimationSuccess");
@@ -392,8 +407,9 @@
     }
 
     private void closeComplete() {
+        testLogD(TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE, "TaskMenuView.java.closeComplete");
         mIsOpen = false;
-        mActivity.getDragLayer().removeView(this);
+        mContainer.getDragLayer().removeView(this);
         mRevealAnimator = null;
     }
 
@@ -416,7 +432,7 @@
     private int calculateMaxHeight() {
         float taskInsetMargin = getResources().getDimension(R.dimen.task_card_margin);
         return mTaskView.getPagedOrientationHandler().getTaskMenuHeight(taskInsetMargin,
-                mActivity.getDeviceProfile(), getTranslationX(), getTranslationY());
+                mContainer.getDeviceProfile(), getTranslationX(), getTranslationY());
     }
 
     private void setOnClosingStartCallback(Runnable onClosingStartCallback) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
index 12b8b6f..c124f03 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuViewWithArrow.kt
@@ -29,7 +29,6 @@
 import android.view.ViewGroup
 import android.widget.FrameLayout
 import android.widget.LinearLayout
-import com.android.launcher3.BaseDraggingActivity
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.InsettableFrameLayout
 import com.android.launcher3.R
@@ -40,24 +39,22 @@
 import com.android.quickstep.TaskOverlayFactory
 import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
 
-class TaskMenuViewWithArrow<T : BaseDraggingActivity> : ArrowPopup<T> {
+class TaskMenuViewWithArrow<T> : ArrowPopup<T> where T : RecentsViewContainer, T : Context {
     companion object {
         const val TAG = "TaskMenuViewWithArrow"
 
-        fun showForTask(
+        fun <T> showForTask(
             taskContainer: TaskIdAttributeContainer,
             alignedOptionIndex: Int = 0
-        ): Boolean {
-            val activity =
-                BaseDraggingActivity.fromContext<BaseDraggingActivity>(
-                    taskContainer.taskView.context
-                )
+        ): Boolean where T : RecentsViewContainer, T : Context {
+            val container: RecentsViewContainer =
+                RecentsViewContainer.containerFromContext(taskContainer.taskView.context)
             val taskMenuViewWithArrow =
-                activity.layoutInflater.inflate(
+                container.layoutInflater.inflate(
                     R.layout.task_menu_with_arrow,
-                    activity.dragLayer,
+                    container.dragLayer,
                     false
-                ) as TaskMenuViewWithArrow<*>
+                ) as TaskMenuViewWithArrow<T>
 
             return taskMenuViewWithArrow.populateAndShowForTask(taskContainer, alignedOptionIndex)
         }
@@ -124,6 +121,25 @@
         optionLayout = requireViewById(R.id.menu_option_layout)
     }
 
+    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
+        val maxMenuHeight: Int = calculateMaxHeight()
+        val newHeightMeasureSpec =
+            if (MeasureSpec.getSize(heightMeasureSpec) > maxMenuHeight) {
+                MeasureSpec.makeMeasureSpec(maxMenuHeight, MeasureSpec.AT_MOST)
+            } else heightMeasureSpec
+        super.onMeasure(widthMeasureSpec, newHeightMeasureSpec)
+    }
+
+    private fun calculateMaxHeight(): Int {
+        val taskInsetMargin = resources.getDimension(R.dimen.task_card_margin)
+        return taskView.pagedOrientationHandler.getTaskMenuHeight(
+            taskInsetMargin,
+            mActivityContext.deviceProfile,
+            translationX,
+            translationY
+        )
+    }
+
     private fun populateAndShowForTask(
         taskContainer: TaskIdAttributeContainer,
         alignedOptionIndex: Int
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 077247b..7e46739 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -48,7 +48,6 @@
 import androidx.annotation.RequiresApi;
 import androidx.core.graphics.ColorUtils;
 
-import com.android.launcher3.BaseActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.util.MainThreadInitializedObject;
@@ -122,7 +121,7 @@
                 }
             };
 
-    private final BaseActivity mActivity;
+    private final RecentsViewContainer mContainer;
     @Nullable
     private TaskOverlay mOverlay;
     private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -171,7 +170,7 @@
         mBackgroundPaint.setColor(Color.WHITE);
         mSplashBackgroundPaint.setColor(Color.WHITE);
         mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
-        mActivity = BaseActivity.fromContext(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
         // Initialize with placeholder value. It is overridden later by TaskView
         mFullscreenParams = TEMP_PARAMS.get(context);
 
@@ -308,7 +307,7 @@
         RectF boundsInBitmapSpace = new RectF();
         boundsToBitmapSpace.mapRect(boundsInBitmapSpace, viewRect);
 
-        DeviceProfile dp = mActivity.getDeviceProfile();
+        DeviceProfile dp = mContainer.getDeviceProfile();
         int bottomInset = dp.isTablet
                 ? Math.round(bitmapRect.bottom - boundsInBitmapSpace.bottom) : 0;
         return Insets.of(0, 0, 0, bottomInset);
@@ -549,7 +548,7 @@
     }
 
     private void updateThumbnailMatrix() {
-        DeviceProfile dp = mActivity.getDeviceProfile();
+        DeviceProfile dp = mContainer.getDeviceProfile();
         mPreviewPositionHelper.setOrientationChanged(false);
         if (mBitmapShader != null && mThumbnailData != null) {
             mPreviewRect.set(0, 0, mThumbnailData.thumbnail.getWidth(),
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 085c502..ec57115 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -29,6 +29,9 @@
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
+import static com.android.launcher3.testing.shared.TestProtocol.SUCCESSFUL_GESTURE_MISMATCH_EVENTS;
+import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
@@ -37,7 +40,6 @@
 import static com.android.quickstep.TaskOverlayFactory.getEnabledShortcuts;
 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
 import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
-import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -83,8 +85,8 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.util.ActivityOptionsWrapper;
@@ -116,8 +118,6 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 
-import kotlin.Unit;
-
 import java.lang.annotation.Retention;
 import java.util.Arrays;
 import java.util.Collections;
@@ -126,14 +126,14 @@
 import java.util.function.Consumer;
 import java.util.stream.Stream;
 
+import kotlin.Unit;
+
 /**
  * A task in the Recents view.
  */
 public class TaskView extends FrameLayout implements Reusable {
 
     private static final String TAG = TaskView.class.getSimpleName();
-    private static final boolean DEBUG = false;
-
     public static final int FLAG_UPDATE_ICON = 1;
     public static final int FLAG_UPDATE_THUMBNAIL = FLAG_UPDATE_ICON << 1;
     public static final int FLAG_UPDATE_CORNER_RADIUS = FLAG_UPDATE_THUMBNAIL << 1;
@@ -181,7 +181,7 @@
             Collections.singletonList(new Rect());
 
     public static final FloatProperty<TaskView> FOCUS_TRANSITION =
-            new FloatProperty<TaskView>("focusTransition") {
+            new FloatProperty<>("focusTransition") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setIconsAndBannersTransitionProgress(v, false /* invert */);
@@ -194,7 +194,7 @@
             };
 
     private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_X =
-            new FloatProperty<TaskView>("splitSelectTranslationX") {
+            new FloatProperty<>("splitSelectTranslationX") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setSplitSelectTranslationX(v);
@@ -207,7 +207,7 @@
             };
 
     private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_Y =
-            new FloatProperty<TaskView>("splitSelectTranslationY") {
+            new FloatProperty<>("splitSelectTranslationY") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setSplitSelectTranslationY(v);
@@ -220,7 +220,7 @@
             };
 
     private static final FloatProperty<TaskView> DISMISS_TRANSLATION_X =
-            new FloatProperty<TaskView>("dismissTranslationX") {
+            new FloatProperty<>("dismissTranslationX") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setDismissTranslationX(v);
@@ -233,7 +233,7 @@
             };
 
     private static final FloatProperty<TaskView> DISMISS_TRANSLATION_Y =
-            new FloatProperty<TaskView>("dismissTranslationY") {
+            new FloatProperty<>("dismissTranslationY") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setDismissTranslationY(v);
@@ -246,7 +246,7 @@
             };
 
     private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_X =
-            new FloatProperty<TaskView>("taskOffsetTranslationX") {
+            new FloatProperty<>("taskOffsetTranslationX") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setTaskOffsetTranslationX(v);
@@ -259,7 +259,7 @@
             };
 
     private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_Y =
-            new FloatProperty<TaskView>("taskOffsetTranslationY") {
+            new FloatProperty<>("taskOffsetTranslationY") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setTaskOffsetTranslationY(v);
@@ -272,7 +272,7 @@
             };
 
     private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_X =
-            new FloatProperty<TaskView>("taskResistanceTranslationX") {
+            new FloatProperty<>("taskResistanceTranslationX") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setTaskResistanceTranslationX(v);
@@ -285,7 +285,7 @@
             };
 
     private static final FloatProperty<TaskView> TASK_RESISTANCE_TRANSLATION_Y =
-            new FloatProperty<TaskView>("taskResistanceTranslationY") {
+            new FloatProperty<>("taskResistanceTranslationY") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setTaskResistanceTranslationY(v);
@@ -298,7 +298,7 @@
             };
 
     public static final FloatProperty<TaskView> GRID_END_TRANSLATION_X =
-            new FloatProperty<TaskView>("gridEndTranslationX") {
+            new FloatProperty<>("gridEndTranslationX") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setGridEndTranslationX(v);
@@ -311,7 +311,7 @@
             };
 
     public static final FloatProperty<TaskView> SNAPSHOT_SCALE =
-            new FloatProperty<TaskView>("snapshotScale") {
+            new FloatProperty<>("snapshotScale") {
                 @Override
                 public void setValue(TaskView taskView, float v) {
                     taskView.setSnapshotScale(v);
@@ -334,7 +334,7 @@
     private float mNonGridScale = 1;
     private float mDismissScale = 1;
     protected final FullscreenDrawParams mCurrentFullscreenParams;
-    protected final StatefulActivity mActivity;
+    protected final RecentsViewContainer mContainer;
 
     // Various causes of changing primary translation, which we aggregate to setTranslationX/Y().
     private float mDismissTranslationX;
@@ -416,14 +416,14 @@
             int defStyleRes, BorderAnimator focusBorderAnimator,
             BorderAnimator hoverBorderAnimator) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        mActivity = StatefulActivity.fromContext(context);
+        mContainer = RecentsViewContainer.containerFromContext(context);
         setOnClickListener(this::onClick);
 
         mCurrentFullscreenParams = new FullscreenDrawParams(context);
-        mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this);
+        mDigitalWellBeingToast = new DigitalWellBeingToast(mContainer, this);
 
         boolean keyboardFocusHighlightEnabled = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
-                || isDesktopModeSupported();
+                || Flags.enableFocusOutline();
         boolean cursorHoverStatesEnabled = enableCursorHoverStates();
 
         setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled);
@@ -486,7 +486,11 @@
         return getItemInfo(mTask);
     }
 
-    protected WorkspaceItemInfo getItemInfo(@Nullable Task task) {
+    /**
+     * Builds proto for logging
+     */
+    @VisibleForTesting
+    public WorkspaceItemInfo getItemInfo(@Nullable Task task) {
         WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
         stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
         stubInfo.container = LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
@@ -501,6 +505,11 @@
         if (getRecentsView() != null) {
             stubInfo.screenId = getRecentsView().indexOfChild(this);
         }
+        if (Flags.privateSpaceRestrictAccessibilityDrag()) {
+            if (UserCache.getInstance(getContext()).getUserInfo(componentKey.user).isPrivate()) {
+                stubInfo.runtimeStatusFlags |= FLAG_NOT_PINNABLE;
+            }
+        }
         return stubInfo;
     }
 
@@ -595,10 +604,7 @@
         if (event.getAction() == MotionEvent.ACTION_DOWN) {
             computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
         }
-        if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
-            return true;
-        }
-        return false;
+        return mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event);
     }
 
     protected void computeAndSetIconTouchDelegate(TaskViewIcon view, float[] tempCenterCoords,
@@ -610,7 +616,7 @@
         float viewHalfHeight = view.getHeight() / 2f;
         tempCenterCoords[0] = viewHalfWidth;
         tempCenterCoords[1] = viewHalfHeight;
-        getDescendantCoordRelativeToAncestor(view.asView(), mActivity.getDragLayer(),
+        getDescendantCoordRelativeToAncestor(view.asView(), mContainer.getDragLayer(),
                 tempCenterCoords, false);
         transformingTouchDelegate.setBounds(
                 (int) (tempCenterCoords[0] - viewHalfWidth),
@@ -640,12 +646,10 @@
 
     /**
      * Updates this task view to the given {@param task}.
-     *
-     * TODO(b/142282126) Re-evaluate if we need to pass in isMultiWindowMode after
-     *   that issue is fixed
      */
     public void bind(Task task, RecentsOrientedState orientedState) {
         cancelPendingLoadTasks();
+        testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS, "TaskView.bind: task=" + task);
         mTask = task;
         mTaskIdContainer[0] = mTask.key.id;
         mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView, mIconView,
@@ -812,13 +816,19 @@
 
     private void onClick(View view) {
         if (getTask() == null) {
+            Log.d("b/310064698", "onClick - task is null");
             return;
         }
         if (confirmSecondSplitSelectApp()) {
+            Log.d("b/310064698", mTask + " - onClick - split select is active");
             return;
         }
-        launchTasks();
-        mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
+        RunnableList callbackList = launchTasks();
+        Log.d("b/310064698", mTask + " - onClick - callbackList: " + callbackList);
+        if (callbackList != null) {
+            callbackList.add(() -> Log.d("b/310064698", mTask + " - onClick - launchCompleted"));
+        }
+        mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
                 .log(LAUNCHER_TASK_LAUNCH_TAP);
     }
 
@@ -853,10 +863,14 @@
      */
     @Nullable
     public RunnableList launchTaskAnimated() {
+        testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+                "TaskView.launchTaskAnimated: mTask=" + mTask);
         if (mTask != null) {
+            testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+                    "TaskView.launchTaskAnimated: startActivityFromRecentsAsync");
             TestLogging.recordEvent(
                     TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
-            ActivityOptionsWrapper opts =  mActivity.getActivityLaunchOptions(this, null);
+            ActivityOptionsWrapper opts =  mContainer.getActivityLaunchOptions(this, null);
             opts.options.setLaunchDisplayId(
                     getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
             if (ActivityManagerWrapper.getInstance()
@@ -901,7 +915,10 @@
      * Starts the task associated with this view without any animation
      */
     public void launchTask(@NonNull Consumer<Boolean> callback, boolean isQuickswitch) {
+        testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS, "TaskView.launchTask: mTask=" + mTask);
         if (mTask != null) {
+            testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+                    "TaskView.launchTask: startActivityFromRecentsAsync");
             TestLogging.recordEvent(
                     TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
 
@@ -911,7 +928,7 @@
                 // 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(mActivity, mTask.key.id, () -> {
+                failureListener.register(mContainer, mTask.key.id, () -> {
                     notifyTaskLaunchFailed(TAG);
                     RecentsView rv = getRecentsView();
                     if (rv != null) {
@@ -969,6 +986,9 @@
     public RunnableList launchTasks() {
         RecentsView recentsView = getRecentsView();
         RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
+        testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+                "TaskView.launchTasks: isRunningTask=" + isRunningTask() + ", "
+                        + "remoteTargetHandles == null?" + (remoteTargetHandles == null));
         if (isRunningTask() && remoteTargetHandles != null) {
             if (!mIsClickableAsLiveTile) {
                 Log.e(TAG, "TaskView is not clickable as a live tile; returning to home.");
@@ -995,6 +1015,8 @@
             if (targets == null) {
                 // If the recents animation is cancelled somehow between the parent if block and
                 // here, try to launch the task as a non live tile task.
+                testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+                        "TaskView.launchTasks: recents animation is cancelled");
                 RunnableList runnableList = launchTaskAnimated();
                 if (runnableList == null) {
                     Log.e(TAG, "Recents animation cancelled and cannot launch task as non-live tile"
@@ -1009,12 +1031,14 @@
             TaskViewUtils.composeRecentsLaunchAnimator(
                     anim, this, targets.apps,
                     targets.wallpapers, targets.nonApps, true /* launcherClosing */,
-                    mActivity.getStateManager(), recentsView,
+                    recentsView.getStateManager(), recentsView,
                     recentsView.getDepthController());
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animator) {
                     if (mTask != null && mTask.key.displayId != getRootViewDisplayId()) {
+                        testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+                                "TaskView.launchTasks: onAnimationEnd");
                         launchTaskAnimated();
                     }
                     mIsClickableAsLiveTile = true;
@@ -1118,12 +1142,12 @@
             return true;
         }
 
-        if (!mActivity.getDeviceProfile().isTablet
+        if (!mContainer.getDeviceProfile().isTablet
                 && !getRecentsView().isClearAllHidden()) {
             getRecentsView().snapToPage(getRecentsView().indexOfChild(this));
             return false;
         } else {
-            mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
+            mContainer.getStatsLogManager().logger().withItemInfo(getItemInfo())
                     .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
             return showTaskMenuWithContainer(iconView);
         }
@@ -1132,7 +1156,7 @@
     protected boolean showTaskMenuWithContainer(TaskViewIcon iconView) {
         TaskIdAttributeContainer menuContainer =
                 mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1];
-        DeviceProfile dp = mActivity.getDeviceProfile();
+        DeviceProfile dp = mContainer.getDeviceProfile();
         if (enableOverviewIconMenu() && iconView instanceof IconAppChipView) {
             ((IconAppChipView) iconView).revealAnim(/* isRevealing= */ true);
             return TaskMenuView.showForTask(menuContainer,
@@ -1186,7 +1210,7 @@
     }
 
     protected void setThumbnailOrientation(RecentsOrientedState orientationState) {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         int thumbnailTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
 
         // TODO(b/271468547), we should default to setting trasnlations only on the snapshot instead
@@ -1203,7 +1227,7 @@
      * Returns whether the task is part of overview grid and not being focused.
      */
     public boolean isGridTask() {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         return deviceProfile.isTablet && !isFocusedTask();
     }
 
@@ -1310,7 +1334,7 @@
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        if (mActivity.getDeviceProfile().isTablet) {
+        if (mContainer.getDeviceProfile().isTablet) {
             setPivotX(getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : right - left);
             setPivotY(mSnapshotView.getTop());
         } else {
@@ -1576,19 +1600,6 @@
         mEndQuickswitchCuj = endQuickswitchCuj;
     }
 
-    private int getExpectedViewHeight(View view) {
-        int expectedHeight;
-        int h = view.getLayoutParams().height;
-        if (h > 0) {
-            expectedHeight = h;
-        } else {
-            int m = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY - 1, MeasureSpec.AT_MOST);
-            view.measure(m, m);
-            expectedHeight = view.getMeasuredHeight();
-        }
-        return expectedHeight;
-    }
-
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
@@ -1680,10 +1691,10 @@
         mFullscreenProgress = progress;
         mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
         mSnapshotView.getTaskOverlay().setFullscreenProgress(progress);
-
+        RecentsView recentsView = mContainer.getOverviewPanel();
         // Animate icons and DWB banners in/out, except in QuickSwitch state, when tiles are
         // oversized and banner would look disproportionately large.
-        if (mActivity.getStateManager().getState() != BACKGROUND_APP) {
+        if (recentsView.getStateManager().getState() != BACKGROUND_APP) {
             setIconsAndBannersTransitionProgress(progress, true);
         }
 
@@ -1717,7 +1728,7 @@
         float boxTranslationY;
         int expectedWidth;
         int expectedHeight;
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        DeviceProfile deviceProfile = mContainer.getDeviceProfile();
         final int thumbnailPadding = deviceProfile.overviewTaskThumbnailTopMarginPx;
         final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
         final int taskWidth = lastComputedTaskSize.width();
@@ -1726,12 +1737,7 @@
             int boxWidth;
             int boxHeight;
             boolean isFocusedTask = isFocusedTask();
-            if (isDesktopTask()) {
-                Rect lastComputedDesktopTaskSize =
-                        getRecentsView().getLastComputedDesktopTaskSize();
-                boxWidth = lastComputedDesktopTaskSize.width();
-                boxHeight = lastComputedDesktopTaskSize.height();
-            } else if (isFocusedTask) {
+            if (isFocusedTask) {
                 // Task will be focused and should use focused task size. Use focusTaskRatio
                 // that is associated with the original orientation of the focused task.
                 boxWidth = taskWidth;
diff --git a/quickstep/tests/src/com/android/launcher3/model/AppEventProducerTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/model/AppEventProducerTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/launcher3/model/AppEventProducerTest.java
rename to quickstep/tests/multivalentTests/src/com/android/launcher3/model/AppEventProducerTest.java
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
rename to quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/RecentsHitboxExtenderTest.java
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
rename to quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarNavButtonControllerTest.java
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
new file mode 100644
index 0000000..b478efa
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.animation
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.content.Context
+import android.graphics.Color
+import android.graphics.Path
+import android.graphics.drawable.ColorDrawable
+import android.view.LayoutInflater
+import android.view.View.INVISIBLE
+import android.view.View.VISIBLE
+import android.widget.FrameLayout
+import androidx.core.animation.AnimatorTestRule
+import androidx.core.animation.doOnEnd
+import androidx.core.graphics.drawable.toBitmap
+import androidx.dynamicanimation.animation.DynamicAnimation
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.R
+import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
+import com.android.launcher3.taskbar.bubbles.BubbleBarOverflow
+import com.android.launcher3.taskbar.bubbles.BubbleBarView
+import com.android.launcher3.taskbar.bubbles.BubbleStashController
+import com.android.launcher3.taskbar.bubbles.BubbleView
+import com.android.wm.shell.common.bubbles.BubbleInfo
+import com.android.wm.shell.shared.animation.PhysicsAnimatorTestUtils
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Semaphore
+import java.util.concurrent.TimeUnit
+import org.junit.Before
+import org.junit.ClassRule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class BubbleBarViewAnimatorTest {
+
+    private val context = ApplicationProvider.getApplicationContext<Context>()
+    private val animatorScheduler = TestBubbleBarViewAnimatorScheduler()
+
+    companion object {
+        @JvmField @ClassRule val animatorTestRule = AnimatorTestRule()
+    }
+
+    @Before
+    fun setUp() {
+        PhysicsAnimatorTestUtils.prepareForTest()
+    }
+
+    @Test
+    fun animateBubbleInForStashed() {
+        lateinit var overflowView: BubbleView
+        lateinit var bubbleView: BubbleView
+        lateinit var bubble: BubbleBarBubble
+        val bubbleBarView = BubbleBarView(context)
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            bubbleBarView.layoutParams = FrameLayout.LayoutParams(0, 0)
+            val inflater = LayoutInflater.from(context)
+
+            val bitmap = ColorDrawable(Color.WHITE).toBitmap(width = 20, height = 20)
+            overflowView =
+                inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
+            overflowView.setOverflow(BubbleBarOverflow(overflowView), bitmap)
+            bubbleBarView.addView(overflowView)
+
+            val bubbleInfo = BubbleInfo("key", 0, null, null, 0, context.packageName, null, false)
+            bubbleView =
+                inflater.inflate(R.layout.bubblebar_item_view, bubbleBarView, false) as BubbleView
+            bubble =
+                BubbleBarBubble(bubbleInfo, bubbleView, bitmap, bitmap, Color.WHITE, Path(), "")
+            bubbleView.setBubble(bubble)
+            bubbleBarView.addView(bubbleView)
+        }
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+
+        val bubbleStashController = mock<BubbleStashController>()
+        whenever(bubbleStashController.isStashed).thenReturn(true)
+
+        val semaphore = Semaphore(0)
+        val hideHandleAnimator = AnimatorSet()
+        hideHandleAnimator.duration = 0
+        whenever(bubbleStashController.buildHideHandleAnimationForNewBubble())
+            .thenReturn(hideHandleAnimator)
+        // add an end listener to the hide handle animation. we add it when the animation starts
+        // to ensure that it gets called after all other end listeners.
+        hideHandleAnimator.doOnStart { hideHandleAnimator.doOnEnd { semaphore.release() } }
+
+        val animator =
+            BubbleBarViewAnimator(bubbleBarView, bubbleStashController, animatorScheduler)
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animator.animateBubbleInForStashed(bubble)
+        }
+
+        // wait for the stash handle animation to complete
+        assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
+        // stash handle animation finished. verify that the stash handle is now hidden
+        verify(bubbleStashController).setStashAlpha(0f)
+
+        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
+
+        assertThat(overflowView.visibility).isEqualTo(INVISIBLE)
+        assertThat(bubbleBarView.visibility).isEqualTo(VISIBLE)
+        assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
+
+        // wait for the show bubble animation to complete
+        PhysicsAnimatorTestUtils.blockUntilAnimationsEnd(
+            DynamicAnimation.ALPHA,
+            DynamicAnimation.TRANSLATION_Y,
+            DynamicAnimation.SCALE_Y,
+        )
+
+        assertThat(bubbleView.alpha).isEqualTo(1)
+        assertThat(bubbleView.translationY).isEqualTo(-50)
+        assertThat(bubbleView.scaleY).isEqualTo(1)
+
+        val showHandleAnimator = AnimatorSet()
+        showHandleAnimator.duration = 0
+        whenever(bubbleStashController.buildShowHandleAnimationForNewBubble())
+            .thenReturn(showHandleAnimator)
+        var showHandleAnimationStarted = false
+        showHandleAnimator.doOnStart { showHandleAnimationStarted = true }
+
+        // execute the hide bubble animation
+        assertThat(animatorScheduler.delayedBlock).isNotNull()
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(animatorScheduler.delayedBlock!!)
+        // finish the hide bubble animation
+        InstrumentationRegistry.getInstrumentation().runOnMainSync {
+            animatorTestRule.advanceTimeBy(250)
+        }
+
+        assertThat(showHandleAnimationStarted).isTrue()
+
+        assertThat(bubbleView.alpha).isEqualTo(1)
+        assertThat(bubbleView.visibility).isEqualTo(VISIBLE)
+        assertThat(bubbleView.translationY).isEqualTo(0)
+        assertThat(bubbleBarView.alpha).isEqualTo(0)
+        assertThat(overflowView.alpha).isEqualTo(1)
+        assertThat(overflowView.visibility).isEqualTo(VISIBLE)
+    }
+
+    private fun AnimatorSet.doOnStart(onStart: () -> Unit) {
+        addListener(
+            object : AnimatorListenerAdapter() {
+                override fun onAnimationStart(animator: Animator) {
+                    onStart()
+                }
+            }
+        )
+    }
+
+    private class TestBubbleBarViewAnimatorScheduler : BubbleBarViewAnimator.Scheduler {
+
+        var delayedBlock: (() -> Unit)? = null
+            private set
+
+        override fun post(block: () -> Unit) {
+            block.invoke()
+        }
+
+        override fun postDelayed(delayMillis: Long, block: () -> Unit) {
+            check(delayedBlock == null) { "there is already a pending block waiting to run" }
+            delayedBlock = block
+        }
+    }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
similarity index 100%
rename from quickstep/tests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactoryTest.kt
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt
new file mode 100644
index 0000000..73b35e8
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AllAppsActionManagerTest.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import android.app.PendingIntent
+import android.content.IIntentSender
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR
+import com.android.launcher3.util.TestUtil
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Semaphore
+import java.util.concurrent.TimeUnit.SECONDS
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val TIMEOUT = 5L
+
+@RunWith(AndroidJUnit4::class)
+class AllAppsActionManagerTest {
+    private val callbackSemaphore = Semaphore(0)
+    private val bgExecutor = UI_HELPER_EXECUTOR
+
+    private val allAppsActionManager =
+        AllAppsActionManager(
+            InstrumentationRegistry.getInstrumentation().targetContext,
+            bgExecutor,
+        ) {
+            callbackSemaphore.release()
+            PendingIntent(IIntentSender.Default())
+        }
+
+    @Test
+    fun taskbarPresent_actionRegistered() {
+        allAppsActionManager.isTaskbarPresent = true
+        assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue()
+        assertThat(allAppsActionManager.isActionRegistered).isTrue()
+    }
+
+    @Test
+    fun homeAndOverviewSame_actionRegistered() {
+        allAppsActionManager.isHomeAndOverviewSame = true
+        assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue()
+        assertThat(allAppsActionManager.isActionRegistered).isTrue()
+    }
+
+    @Test
+    fun toggleTaskbar_destroyedAfterActionRegistered_actionUnregistered() {
+        allAppsActionManager.isTaskbarPresent = true
+        assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue()
+
+        allAppsActionManager.isTaskbarPresent = false
+        TestUtil.runOnExecutorSync(bgExecutor) {} // Force system action to unregister.
+        assertThat(allAppsActionManager.isActionRegistered).isFalse()
+    }
+
+    @Test
+    fun toggleTaskbar_destroyedBeforeActionRegistered_pendingActionUnregistered() {
+        allAppsActionManager.isTaskbarPresent = true
+        allAppsActionManager.isTaskbarPresent = false
+
+        TestUtil.runOnExecutorSync(bgExecutor) {} // Force system action to unregister.
+        assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue()
+        assertThat(allAppsActionManager.isActionRegistered).isFalse()
+    }
+
+    @Test
+    fun changeHome_sameAsOverviewBeforeActionUnregistered_actionRegisteredAgain() {
+        allAppsActionManager.isHomeAndOverviewSame = true // Initialize to same.
+        assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue()
+
+        allAppsActionManager.isHomeAndOverviewSame = false
+        allAppsActionManager.isHomeAndOverviewSame = true
+        assertThat(callbackSemaphore.tryAcquire(TIMEOUT, SECONDS)).isTrue()
+        assertThat(allAppsActionManager.isActionRegistered).isTrue()
+    }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/NavigationBarRotationContextTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/NavigationBarRotationContextTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/NavigationBarRotationContextTest.java
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/NavigationBarRotationContextTest.java
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RobolectricTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/RobolectricTest.kt
new file mode 100644
index 0000000..0694aec
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RobolectricTest.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class RobolectricTest {
+    @Test
+    fun test1() {
+        val actual = 1 + 1
+        assertThat(actual).isEqualTo(2)
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/LandscapePagedViewHandlerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/LandscapePagedViewHandlerTest.kt
new file mode 100644
index 0000000..ea52842
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/LandscapePagedViewHandlerTest.kt
@@ -0,0 +1,195 @@
+/*
+ * 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.orientation
+
+import android.platform.test.flag.junit.SetFlagsRule
+import android.view.Gravity
+import android.view.View
+import android.widget.FrameLayout
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.Flags
+import com.android.quickstep.orientation.LandscapePagedViewHandler.SplitIconPositions
+import com.android.quickstep.views.IconAppChipView
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.`when`
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@RunWith(AndroidJUnit4::class)
+class LandscapePagedViewHandlerTest {
+
+    @get:Rule val setFlagsRule = SetFlagsRule()
+
+    private val sut = LandscapePagedViewHandler()
+
+    private fun enableGridOnlyOverview(isEnabled: Boolean) {
+        if (isEnabled) {
+            setFlagsRule.enableFlags(
+                Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW,
+                Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU
+            )
+        } else {
+            setFlagsRule.disableFlags(
+                Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW,
+                Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU
+            )
+        }
+    }
+
+    /** [ Test getSplitIconsPosition ] */
+    private fun getSplitIconsPosition(isRTL: Boolean): SplitIconPositions {
+        return sut.getSplitIconsPosition(
+            TASK_ICON_HEIGHT_PX,
+            PRIMARY_SNAPSHOT,
+            TOTAL_THUMBNAIL_HEIGHT,
+            isRTL,
+            OVERVIEW_TASK_MARGIN_PX,
+            DIVIDER_SIZE_PX,
+        )
+    }
+
+    @Test
+    fun testIcon_getSplitIconsPositions() {
+        enableGridOnlyOverview(false)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = false)
+
+        // Top-Left icon should be at the end of the primary snapshot height
+        assertThat(topLeftY).isEqualTo(250)
+        // Bottom-Right icon should be at the end of the primary height + divider + icon size
+        assertThat(bottomRightY).isEqualTo(374)
+    }
+
+    @Test
+    fun testIcon_getSplitIconsPositions_isRTL() {
+        enableGridOnlyOverview(false)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = true)
+
+        // Top-Left icon should be at the end of the primary snapshot height
+        assertThat(topLeftY).isEqualTo(250)
+        // Bottom-Right icon should be at the end of the primary height + divider + icon size
+        assertThat(bottomRightY).isEqualTo(374)
+    }
+
+    @Test
+    fun testChip_getSplitIconsPositions() {
+        enableGridOnlyOverview(true)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = false)
+
+        // Top-Left app chip should always be at the initial position of the first snapshot
+        assertThat(topLeftY).isEqualTo(0)
+        // Bottom-Right app chip should be at the end of the primary height + divider
+        assertThat(bottomRightY).isEqualTo(266)
+    }
+
+    @Test
+    fun testChip_getSplitIconsPositions_isRTL() {
+        enableGridOnlyOverview(true)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = true)
+
+        // TODO(b/326377497): When started in fake seascape and rotated to landscape,
+        //  the icon chips are in RTL and wrongly positioned at the right side of the snapshot.
+        //  Top-Left app chip should be placed at the top left of the first snapshot, but because
+        //  this issue, it's displayed at the top-right of the second snapshot.
+        //  The Bottom-Right app chip is displayed at the top-right of the first snapshot because
+        //  of this issue.
+        assertThat(topLeftY).isEqualTo(0)
+        assertThat(bottomRightY).isEqualTo(-316)
+    }
+
+    /** Test updateSplitIconsPosition */
+    @Test
+    fun testIcon_updateSplitIconsPosition() {
+        enableGridOnlyOverview(false)
+
+        val expectedTranslationY = 250
+        val expectedGravity = Gravity.TOP or Gravity.RIGHT
+
+        val iconView = mock<View>()
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, false)
+        assertThat(frameLayout.gravity).isEqualTo(expectedGravity)
+        assertThat(frameLayout.topMargin).isEqualTo(expectedTranslationY)
+        verify(iconView).translationX = 0f
+        verify(iconView).translationY = 0f
+    }
+
+    @Test
+    fun testIcon_updateSplitIconsPosition_isRTL() {
+        enableGridOnlyOverview(false)
+
+        val expectedTranslationY = 250
+        val expectedGravity = Gravity.TOP or Gravity.RIGHT
+
+        val iconView = mock<View>()
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, true)
+        assertThat(frameLayout.gravity).isEqualTo(expectedGravity)
+        assertThat(frameLayout.topMargin).isEqualTo(expectedTranslationY)
+        verify(iconView).translationX = 0f
+        verify(iconView).translationY = 0f
+    }
+
+    @Test
+    fun testChip_updateSplitIconsPosition() {
+        enableGridOnlyOverview(true)
+
+        val expectedTranslationY = 250
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        val iconView = mock<IconAppChipView>()
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, false)
+        assertThat(frameLayout.gravity).isEqualTo(Gravity.TOP or Gravity.END)
+        verify(iconView).setSplitTranslationX(0f)
+        verify(iconView).setSplitTranslationY(expectedTranslationY.toFloat())
+    }
+
+    @Test
+    fun testChip_updateSplitIconsPosition_isRTL() {
+        enableGridOnlyOverview(true)
+
+        val expectedTranslationY = 250
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        val iconView = mock<IconAppChipView>()
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, true)
+        assertThat(frameLayout.gravity).isEqualTo(Gravity.BOTTOM or Gravity.START)
+        verify(iconView).setSplitTranslationX(0f)
+        verify(iconView).setSplitTranslationY(expectedTranslationY.toFloat())
+    }
+
+    private companion object {
+        const val TASK_ICON_HEIGHT_PX = 108
+        const val OVERVIEW_TASK_MARGIN_PX = 0
+        const val DIVIDER_SIZE_PX = 16
+        const val PRIMARY_SNAPSHOT = 250
+        const val SECONDARY_SNAPSHOT = 300
+        const val TOTAL_THUMBNAIL_HEIGHT = PRIMARY_SNAPSHOT + SECONDARY_SNAPSHOT + DIVIDER_SIZE_PX
+    }
+}
diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt
new file mode 100644
index 0000000..2bc182c
--- /dev/null
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/orientation/SeascapePagedViewHandlerTest.kt
@@ -0,0 +1,197 @@
+/*
+ * 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.orientation
+
+import android.platform.test.flag.junit.SetFlagsRule
+import android.view.Gravity
+import android.view.View
+import android.widget.FrameLayout
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.Flags
+import com.android.quickstep.orientation.LandscapePagedViewHandler.SplitIconPositions
+import com.android.quickstep.views.IconAppChipView
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.`when`
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@RunWith(AndroidJUnit4::class)
+class SeascapePagedViewHandlerTest {
+
+    @get:Rule val setFlagsRule = SetFlagsRule()
+
+    private val sut = SeascapePagedViewHandler()
+
+    private fun enableGridOnlyOverview(isEnabled: Boolean) {
+        if (isEnabled) {
+            setFlagsRule.enableFlags(
+                Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW,
+                Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU
+            )
+        } else {
+            setFlagsRule.disableFlags(
+                Flags.FLAG_ENABLE_GRID_ONLY_OVERVIEW,
+                Flags.FLAG_ENABLE_OVERVIEW_ICON_MENU
+            )
+        }
+    }
+
+    /** [ Test getSplitIconsPosition ] */
+    private fun getSplitIconsPosition(isRTL: Boolean): SplitIconPositions {
+        return sut.getSplitIconsPosition(
+            TASK_ICON_HEIGHT_PX,
+            PRIMARY_SNAPSHOT,
+            TOTAL_THUMBNAIL_HEIGHT,
+            isRTL,
+            OVERVIEW_TASK_MARGIN_PX,
+            DIVIDER_SIZE_PX,
+        )
+    }
+
+    @Test
+    fun testIcon_getSplitIconsPositions() {
+        enableGridOnlyOverview(false)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = false)
+
+        // The top-left icon is translated from the bottom of the screen to the end of
+        // the primary snapshot minus the icon size.
+        assertThat(topLeftY).isEqualTo(142)
+        // The bottom-right icon is placed at the end of the primary snapshot plus the divider.
+        assertThat(bottomRightY).isEqualTo(266)
+    }
+
+    @Test
+    fun testIcon_getSplitIconsPositions_isRTL() {
+        enableGridOnlyOverview(false)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = true)
+
+        // The top-left icon is translated from the bottom of the screen to the end of
+        // the primary snapshot minus the icon size.
+        assertThat(topLeftY).isEqualTo(142)
+        // The bottom-right icon is placed at the end of the primary snapshot plus the divider.
+        assertThat(bottomRightY).isEqualTo(266)
+    }
+
+    @Test
+    fun testChip_getSplitIconsPositions() {
+        enableGridOnlyOverview(true)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = false)
+
+        // Top-Left app chip should always be at the initial position of the first snapshot
+        assertThat(topLeftY).isEqualTo(0)
+        // Bottom-Right app chip should be at the end of the primary height + divider
+        assertThat(bottomRightY).isEqualTo(-266)
+    }
+
+    @Test
+    fun testChip_getSplitIconsPositions_isRTL() {
+        enableGridOnlyOverview(true)
+
+        val (topLeftY, bottomRightY) = getSplitIconsPosition(isRTL = true)
+
+        // TODO(b/326377497): When started in fake seascape and rotated to landscape,
+        //  the icon chips are in RTL and wrongly positioned at the right side of the snapshot.
+        //  Top-Left app chip should be placed at the top left of the first snapshot, but because
+        //  this issue, it's displayed at the top-right of the second snapshot.
+        //  The Bottom-Right app chip is displayed at the top-right of the first snapshot because
+        //  of this issue.
+        assertThat(topLeftY).isEqualTo(316)
+        assertThat(bottomRightY).isEqualTo(0)
+    }
+
+    /** Test updateSplitIconsPosition */
+    @Test
+    fun testIcon_updateSplitIconsPosition() {
+        enableGridOnlyOverview(false)
+
+        val expectedTranslationY = 250
+        val expectedGravity = Gravity.BOTTOM or Gravity.LEFT
+
+        val iconView = mock<View>()
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, false)
+        assertThat(frameLayout.gravity).isEqualTo(expectedGravity)
+        assertThat(frameLayout.bottomMargin).isEqualTo(expectedTranslationY)
+        verify(iconView).translationX = 0f
+        verify(iconView).translationY = 0f
+    }
+
+    @Test
+    fun testIcon_updateSplitIconsPosition_isRTL() {
+        enableGridOnlyOverview(false)
+
+        val expectedTranslationY = 250
+        val expectedGravity = Gravity.BOTTOM or Gravity.LEFT
+
+        val iconView = mock<View>()
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, true)
+        assertThat(frameLayout.gravity).isEqualTo(expectedGravity)
+        assertThat(frameLayout.bottomMargin).isEqualTo(expectedTranslationY)
+        verify(iconView).translationX = 0f
+        verify(iconView).translationY = 0f
+    }
+
+    @Test
+    fun testChip_updateSplitIconsPosition() {
+        enableGridOnlyOverview(true)
+
+        val expectedTranslationY = 250
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        val iconView = mock<IconAppChipView>()
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, false)
+        assertThat(frameLayout.gravity).isEqualTo(Gravity.BOTTOM or Gravity.START)
+        verify(iconView).setSplitTranslationX(0f)
+        verify(iconView).setSplitTranslationY(expectedTranslationY.toFloat())
+    }
+
+    @Test
+    fun testChip_updateSplitIconsPosition_isRTL() {
+        enableGridOnlyOverview(true)
+
+        val expectedTranslationY = 250
+        val frameLayout = FrameLayout.LayoutParams(100, 100)
+        val iconView = mock<IconAppChipView>()
+        `when`(iconView.layoutParams).thenReturn(frameLayout)
+
+        sut.updateSplitIconsPosition(iconView, expectedTranslationY, true)
+        assertThat(frameLayout.gravity).isEqualTo(Gravity.TOP or Gravity.END)
+        verify(iconView).setSplitTranslationX(0f)
+        verify(iconView).setSplitTranslationY(expectedTranslationY.toFloat())
+    }
+
+    private companion object {
+        const val TASK_ICON_HEIGHT_PX = 108
+        const val OVERVIEW_TASK_MARGIN_PX = 0
+        const val DIVIDER_SIZE_PX = 16
+        const val PRIMARY_SNAPSHOT = 250
+        const val SECONDARY_SNAPSHOT = 300
+        const val TOTAL_THUMBNAIL_HEIGHT = PRIMARY_SNAPSHOT + SECONDARY_SNAPSHOT + DIVIDER_SIZE_PX
+    }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
similarity index 96%
rename from quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index 18b1ea0..0de5f19 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -36,6 +36,8 @@
 import com.android.launcher3.util.SplitConfigurationOptions
 import com.android.quickstep.RecentsModel
 import com.android.quickstep.SystemUiProxy
+import com.android.quickstep.util.SplitSelectStateController.SplitFromDesktopController
+import com.android.quickstep.views.RecentsViewContainer
 import com.android.systemui.shared.recents.model.Task
 import com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_50
 import java.util.function.Consumer
@@ -62,9 +64,10 @@
     private val statsLogger: StatsLogger = mock()
     private val stateManager: StateManager<LauncherState> = mock()
     private val handler: Handler = mock()
-    private val context: StatefulActivity<*> = mock()
+    private val context: RecentsViewContainer = mock()
     private val recentsModel: RecentsModel = mock()
     private val pendingIntent: PendingIntent = mock()
+    private val splitFromDesktopController: SplitFromDesktopController = mock()
 
     private lateinit var splitSelectStateController: SplitSelectStateController
 
@@ -607,6 +610,18 @@
         assertTrue(splitSelectStateController.isBothSplitAppsConfirmed)
     }
 
+    @Test
+    fun splitSelectStateControllerDestroyed_SplitFromDesktopControllerAlsoDestroyed() {
+        // Initiate split from desktop controller
+        splitSelectStateController.initSplitFromDesktopController(splitFromDesktopController)
+
+        // Simulate default controller being destroyed
+        splitSelectStateController.onDestroy()
+
+        // Verify desktop controller is also destroyed
+        verify(splitFromDesktopController).onDestroy()
+    }
+
     // Generate GroupTask with default userId.
     private fun generateGroupTask(
         task1ComponentName: ComponentName,
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskGridNavHelperTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskGridNavHelperTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/TaskGridNavHelperTest.java
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskGridNavHelperTest.java
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskKeyByLastActiveTimeCacheTest.java
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
similarity index 100%
rename from quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
rename to quickstep/tests/multivalentTests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
diff --git a/quickstep/tests/multivalentTestsForDevice b/quickstep/tests/multivalentTestsForDevice
new file mode 120000
index 0000000..fa0fabf
--- /dev/null
+++ b/quickstep/tests/multivalentTestsForDevice
@@ -0,0 +1 @@
+./multivalentTests
\ No newline at end of file
diff --git a/quickstep/tests/multivalentTestsForDeviceless b/quickstep/tests/multivalentTestsForDeviceless
new file mode 120000
index 0000000..fa0fabf
--- /dev/null
+++ b/quickstep/tests/multivalentTestsForDeviceless
@@ -0,0 +1 @@
+./multivalentTests
\ No newline at end of file
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index 37dde10..8702f70 100644
--- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.model;
 
+import static android.content.pm.ApplicationInfo.CATEGORY_PRODUCTIVITY;
+import static android.content.pm.ApplicationInfo.FLAG_INSTALLED;
 import static android.os.Process.myUserHandle;
 
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
@@ -37,6 +39,8 @@
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.LauncherApps;
 import android.os.UserHandle;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.text.TextUtils;
@@ -81,6 +85,8 @@
     private FakeBgDataModelCallback mCallback = new FakeBgDataModelCallback();
     private LauncherModelHelper mModelHelper;
     private UserHandle mUserHandle;
+    private LauncherApps mLauncherApps;
+
 
     @Before
     public void setup() throws Exception {
@@ -103,12 +109,18 @@
         allWidgets = Arrays.asList(mApp1Provider1, mApp1Provider2, mApp2Provider1,
                 mApp4Provider1, mApp4Provider2, mApp5Provider1);
 
+        mLauncherApps = mModelHelper.sandboxContext.spyService(LauncherApps.class);
         doAnswer(i -> {
             String pkg = i.getArgument(0);
-            return ApplicationInfoBuilder.newBuilder().setPackageName(pkg).setName(
-                    "App " + pkg).build();
-        }).when(mModelHelper.sandboxContext.getPackageManager())
-                .getApplicationInfo(anyString(), anyInt());
+            ApplicationInfo applicationInfo = ApplicationInfoBuilder.newBuilder()
+                    .setPackageName(pkg)
+                    .setName("App " + pkg)
+                    .build();
+            applicationInfo.category = CATEGORY_PRODUCTIVITY;
+            applicationInfo.flags = FLAG_INSTALLED;
+            return applicationInfo;
+        }).when(mLauncherApps).getApplicationInfo(anyString(), anyInt(), any());
+
         AppWidgetManager manager = mModelHelper.sandboxContext.spyService(AppWidgetManager.class);
         doReturn(allWidgets).when(manager).getInstalledProviders();
         doReturn(allWidgets).when(manager).getInstalledProvidersForProfile(eq(myUserHandle()));
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredictionsRequesterTest.kt b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredictionsRequesterTest.kt
new file mode 100644
index 0000000..5c7b4ab
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredictionsRequesterTest.kt
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model
+
+import android.app.prediction.AppTarget
+import android.app.prediction.AppTargetEvent
+import android.app.prediction.AppTargetId
+import android.appwidget.AppWidgetProviderInfo
+import android.content.ComponentName
+import android.content.Context
+import android.os.Process.myUserHandle
+import android.os.UserHandle
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.icons.IconCache
+import com.android.launcher3.model.WidgetPredictionsRequester.buildBundleForPredictionSession
+import com.android.launcher3.model.WidgetPredictionsRequester.filterPredictions
+import com.android.launcher3.model.WidgetPredictionsRequester.notOnUiSurfaceFilter
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.util.PackageUserKey
+import com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
+import com.google.common.truth.Truth.assertThat
+import java.util.function.Predicate
+import junit.framework.Assert.assertNotNull
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidJUnit4::class)
+class WidgetsPredictionsRequesterTest {
+
+    private lateinit var mUserHandle: UserHandle
+    private lateinit var context: Context
+    private lateinit var deviceProfile: DeviceProfile
+    private lateinit var testInvariantProfile: InvariantDeviceProfile
+
+    private lateinit var widget1aInfo: AppWidgetProviderInfo
+    private lateinit var widget1bInfo: AppWidgetProviderInfo
+    private lateinit var widget2Info: AppWidgetProviderInfo
+
+    private lateinit var widgetItem1a: WidgetItem
+    private lateinit var widgetItem1b: WidgetItem
+    private lateinit var widgetItem2: WidgetItem
+
+    private lateinit var allWidgets: Map<PackageUserKey, List<WidgetItem>>
+
+    @Mock private lateinit var iconCache: IconCache
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        mUserHandle = myUserHandle()
+        context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        testInvariantProfile = LauncherAppState.getIDP(context)
+        deviceProfile = testInvariantProfile.getDeviceProfile(context).copy(context)
+
+        widget1aInfo =
+            createAppWidgetProviderInfo(
+                ComponentName.createRelative(APP_1_PACKAGE_NAME, APP_1_PROVIDER_A_CLASS_NAME)
+            )
+        widget1bInfo =
+            createAppWidgetProviderInfo(
+                ComponentName.createRelative(APP_1_PACKAGE_NAME, APP_1_PROVIDER_B_CLASS_NAME)
+            )
+        widgetItem1a = createWidgetItem(widget1aInfo)
+        widgetItem1b = createWidgetItem(widget1bInfo)
+
+        widget2Info =
+            createAppWidgetProviderInfo(
+                ComponentName.createRelative(APP_2_PACKAGE_NAME, APP_2_PROVIDER_1_CLASS_NAME)
+            )
+        widgetItem2 = createWidgetItem(widget2Info)
+
+        allWidgets =
+            mapOf(
+                PackageUserKey(APP_1_PACKAGE_NAME, mUserHandle) to
+                    listOf(widgetItem1a, widgetItem1b),
+                PackageUserKey(APP_2_PACKAGE_NAME, mUserHandle) to listOf(widgetItem2),
+            )
+    }
+
+    @Test
+    fun buildBundleForPredictionSession_includesAddedAppWidgets() {
+        val existingWidgets = arrayListOf(widget1aInfo, widget1bInfo, widget2Info)
+
+        val bundle = buildBundleForPredictionSession(existingWidgets, TEST_UI_SURFACE)
+        val addedWidgetsBundleExtra =
+            bundle.getParcelableArrayList(BUNDLE_KEY_ADDED_APP_WIDGETS, AppTarget::class.java)
+
+        assertNotNull(addedWidgetsBundleExtra)
+        assertThat(addedWidgetsBundleExtra)
+            .containsExactly(
+                buildExpectedAppTargetEvent(
+                    /*pkg=*/ APP_1_PACKAGE_NAME,
+                    /*providerClassName=*/ APP_1_PROVIDER_A_CLASS_NAME,
+                    /*user=*/ mUserHandle
+                ),
+                buildExpectedAppTargetEvent(
+                    /*pkg=*/ APP_1_PACKAGE_NAME,
+                    /*providerClassName=*/ APP_1_PROVIDER_B_CLASS_NAME,
+                    /*user=*/ mUserHandle
+                ),
+                buildExpectedAppTargetEvent(
+                    /*pkg=*/ APP_2_PACKAGE_NAME,
+                    /*providerClassName=*/ APP_2_PROVIDER_1_CLASS_NAME,
+                    /*user=*/ mUserHandle
+                )
+            )
+    }
+
+    @Test
+    fun filterPredictions_notOnUiSurfaceFilter_returnsOnlyEligiblePredictions() {
+        val widgetsAlreadyOnSurface = arrayListOf(widget1bInfo)
+        val filter: Predicate<WidgetItem> = notOnUiSurfaceFilter(widgetsAlreadyOnSurface)
+
+        val predictions =
+            listOf(
+                // already on surface
+                AppTarget(
+                    AppTargetId(APP_1_PACKAGE_NAME),
+                    APP_1_PACKAGE_NAME,
+                    APP_1_PROVIDER_B_CLASS_NAME,
+                    mUserHandle
+                ),
+                // eligible
+                AppTarget(
+                    AppTargetId(APP_2_PACKAGE_NAME),
+                    APP_2_PACKAGE_NAME,
+                    APP_2_PROVIDER_1_CLASS_NAME,
+                    mUserHandle
+                )
+            )
+
+        // only 2 was eligible
+        assertThat(filterPredictions(predictions, allWidgets, filter)).containsExactly(widgetItem2)
+    }
+
+    @Test
+    fun filterPredictions_appPredictions_returnsWidgetFromPackage() {
+        val widgetsAlreadyOnSurface = arrayListOf(widget1bInfo)
+        val filter: Predicate<WidgetItem> = notOnUiSurfaceFilter(widgetsAlreadyOnSurface)
+
+        val predictions =
+            listOf(
+                AppTarget(
+                    AppTargetId(APP_1_PACKAGE_NAME),
+                    APP_1_PACKAGE_NAME,
+                    "$APP_1_PACKAGE_NAME.SomeActivity",
+                    mUserHandle
+                ),
+                AppTarget(
+                    AppTargetId(APP_2_PACKAGE_NAME),
+                    APP_2_PACKAGE_NAME,
+                    "$APP_2_PACKAGE_NAME.SomeActivity2",
+                    mUserHandle
+                ),
+            )
+
+        assertThat(filterPredictions(predictions, allWidgets, filter))
+            .containsExactly(widgetItem1a, widgetItem2)
+    }
+
+    private fun createWidgetItem(
+        providerInfo: AppWidgetProviderInfo,
+    ): WidgetItem {
+        val widgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(context, providerInfo)
+        return WidgetItem(widgetInfo, testInvariantProfile, iconCache, context)
+    }
+
+    companion object {
+        const val TEST_UI_SURFACE = "widgets_test"
+        const val BUNDLE_KEY_ADDED_APP_WIDGETS = "added_app_widgets"
+
+        const val APP_1_PACKAGE_NAME = "com.example.app1"
+        const val APP_1_PROVIDER_A_CLASS_NAME = "app1Provider1"
+        const val APP_1_PROVIDER_B_CLASS_NAME = "app1Provider2"
+
+        const val APP_2_PACKAGE_NAME = "com.example.app2"
+        const val APP_2_PROVIDER_1_CLASS_NAME = "app2Provider1"
+
+        const val TEST_PACKAGE = "pkg"
+
+        private fun buildExpectedAppTargetEvent(
+            pkg: String,
+            providerClassName: String,
+            userHandle: UserHandle
+        ): AppTargetEvent {
+            val appTarget =
+                AppTarget.Builder(
+                        /*id=*/ AppTargetId("widget:$pkg"),
+                        /*packageName=*/ pkg,
+                        /*user=*/ userHandle
+                    )
+                    .setClassName(providerClassName)
+                    .build()
+            return AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_PIN)
+                .setLaunchLocation(TEST_UI_SURFACE)
+                .build()
+        }
+    }
+}
diff --git a/quickstep/tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java b/quickstep/tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java
new file mode 100644
index 0000000..68ac3d5
--- /dev/null
+++ b/quickstep/tests/src/com/android/launcher3/testcomponent/ExcludeFromRecentsTestActivity.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.testcomponent;
+
+/**
+ * Extension of BaseTestingActivity to help test excludeFromRecents="true".
+ */
+public class ExcludeFromRecentsTestActivity extends BaseTestingActivity {}
diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
index 6a48b77..44c23ba 100644
--- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
+++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java
@@ -23,9 +23,9 @@
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.Until;
 
-import com.android.launcher3.Launcher;
 import com.android.launcher3.tapl.LaunchedAppState;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.quickstep.views.RecentsView;
 
 import org.junit.rules.RuleChain;
@@ -34,7 +34,7 @@
 /**
  * Base class for all instrumentation tests that deal with Quickstep.
  */
-public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest {
+public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest<QuickstepLauncher> {
     public static final boolean ENABLE_SHELL_TRANSITIONS =
             SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
     @Override
@@ -46,7 +46,7 @@
     }
 
     @Override
-    protected void onLauncherActivityClose(Launcher launcher) {
+    protected void onLauncherActivityClose(QuickstepLauncher launcher) {
         RecentsView recentsView = launcher.getOverviewPanel();
         if (recentsView != null) {
             recentsView.finishRecentsAnimation(false /* toRecents */, null);
diff --git a/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
new file mode 100644
index 0000000..7dabbca
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/DesktopSystemShortcutTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep
+
+import android.content.ComponentName
+import android.content.Intent
+import android.platform.test.flag.junit.SetFlagsRule
+import com.android.launcher3.AbstractFloatingView
+import com.android.launcher3.AbstractFloatingViewHelper
+import com.android.launcher3.Launcher
+import com.android.launcher3.logging.StatsLogManager
+import com.android.launcher3.logging.StatsLogManager.LauncherEvent
+import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.uioverrides.QuickstepLauncher
+import com.android.launcher3.util.SplitConfigurationOptions
+import com.android.quickstep.views.LauncherRecentsView
+import com.android.quickstep.views.TaskView
+import com.android.systemui.shared.recents.model.Task
+import com.android.systemui.shared.recents.model.Task.TaskKey
+import com.android.window.flags.Flags
+import com.google.common.truth.Truth.assertThat
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+/** Test for DesktopSystemShortcut */
+class DesktopSystemShortcutTest {
+
+    @get:Rule val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT)
+
+    private val launcher: QuickstepLauncher = mock()
+    private val statsLogManager: StatsLogManager = mock()
+    private val statsLogger: StatsLogManager.StatsLogger = mock()
+    private val recentsView: LauncherRecentsView = mock()
+    private val taskView: TaskView = mock()
+    private val workspaceItemInfo: WorkspaceItemInfo = mock()
+    private val abstractFloatingViewHelper: AbstractFloatingViewHelper = mock()
+    private val factory: TaskShortcutFactory =
+        DesktopSystemShortcut.createFactory(abstractFloatingViewHelper)
+
+    @Test
+    fun createDesktopTaskShortcutFactory_featureOff() {
+        setFlagsRule.disableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+
+        val task =
+            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+                isDockable = true
+            }
+        val taskContainer =
+            taskView.TaskIdAttributeContainer(
+                task,
+                null,
+                null,
+                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+            )
+
+        val shortcuts = factory.getShortcuts(launcher, taskContainer)
+        assertThat(shortcuts).isNull()
+    }
+
+    @Test
+    fun createDesktopTaskShortcutFactory_undockable() {
+        setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+
+        val task =
+            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+                isDockable = false
+            }
+        val taskContainer =
+            taskView.TaskIdAttributeContainer(
+                task,
+                null,
+                null,
+                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+            )
+
+        val shortcuts = factory.getShortcuts(launcher, taskContainer)
+        assertThat(shortcuts).isNull()
+    }
+
+    @Test
+    fun desktopSystemShortcutClicked() {
+        setFlagsRule.enableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+
+        val task =
+            Task(TaskKey(1, 0, Intent(), ComponentName("", ""), 0, 2000)).apply {
+                isDockable = true
+            }
+        val taskContainer =
+            taskView.TaskIdAttributeContainer(
+                task,
+                null,
+                null,
+                SplitConfigurationOptions.STAGE_POSITION_UNDEFINED
+            )
+
+        whenever(launcher.getOverviewPanel<LauncherRecentsView>()).thenReturn(recentsView)
+        whenever(launcher.statsLogManager).thenReturn(statsLogManager)
+        whenever(statsLogManager.logger()).thenReturn(statsLogger)
+        whenever(statsLogger.withItemInfo(any())).thenReturn(statsLogger)
+        whenever(taskView.getItemInfo(task)).thenReturn(workspaceItemInfo)
+        whenever(recentsView.moveTaskToDesktop(any(), any())).thenAnswer {
+            val successCallback = it.getArgument<Runnable>(1)
+            successCallback.run()
+        }
+
+        val shortcuts = factory.getShortcuts(launcher, taskContainer)
+        assertThat(shortcuts).hasSize(1)
+        assertThat(shortcuts!!.first()).isInstanceOf(DesktopSystemShortcut::class.java)
+
+        val desktopShortcut = shortcuts.first() as DesktopSystemShortcut
+
+        desktopShortcut.onClick(taskView)
+
+        val allTypesExceptRebindSafe =
+            AbstractFloatingView.TYPE_ALL and AbstractFloatingView.TYPE_REBIND_SAFE.inv()
+        verify(abstractFloatingViewHelper).closeOpenViews(launcher, true, allTypesExceptRebindSafe)
+        verify(recentsView).moveTaskToDesktop(eq(taskContainer), any())
+        verify(statsLogger).withItemInfo(workspaceItemInfo)
+        verify(statsLogger).log(LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP)
+    }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
index 213f58f..e4d8e92 100644
--- a/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
+++ b/quickstep/tests/src/com/android/quickstep/FallbackRecentsTest.java
@@ -22,6 +22,7 @@
 import static com.android.launcher3.tapl.LauncherInstrumentation.WAIT_TIME_MS;
 import static com.android.launcher3.tapl.TestHelpers.getHomeIntentInPackage;
 import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
+import static com.android.launcher3.testing.shared.TestProtocol.UPDATE_OVERVIEW_TARGETS_RUNNING_LATE;
 import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_ACTIVITY_TIMEOUT;
 import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_BROADCAST_TIMEOUT_SECS;
 import static com.android.launcher3.ui.AbstractLauncherUiTest.DEFAULT_UI_TIMEOUT;
@@ -44,6 +45,7 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.os.RemoteException;
+import android.util.Log;
 
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -59,6 +61,7 @@
 import com.android.launcher3.testcomponent.TestCommandReceiver;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.util.Wait;
+import com.android.launcher3.util.rule.ExtendedLongPressTimeoutRule;
 import com.android.launcher3.util.rule.FailureWatcher;
 import com.android.launcher3.util.rule.SamplerRule;
 import com.android.launcher3.util.rule.ScreenRecordRule;
@@ -76,17 +79,21 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.model.Statement;
 
+import java.io.IOException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
 public class FallbackRecentsTest {
 
     private static final String FALLBACK_LAUNCHER_TITLE = "Test launcher";
+    private static final Pattern COMPONENT_INFO_REGEX = Pattern.compile("ComponentInfo\\{(.*)\\}");
 
     private final UiDevice mDevice;
     private final LauncherInstrumentation mLauncher;
@@ -101,6 +108,9 @@
     @Rule
     public ScreenRecordRule mScreenRecordRule = new ScreenRecordRule();
 
+    @Rule
+    public ExtendedLongPressTimeoutRule mLongPressTimeoutRule = new ExtendedLongPressTimeoutRule();
+
     public FallbackRecentsTest() throws RemoteException {
         Instrumentation instrumentation = getInstrumentation();
         Context context = instrumentation.getContext();
@@ -125,6 +135,13 @@
                         getLauncherCommand(mOtherLauncherActivity));
                 updateHandler.mChangeCounter
                         .await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS);
+                Log.d(UPDATE_OVERVIEW_TARGETS_RUNNING_LATE,
+                        "AFTER AWAIT: mObserver home intent package name="
+                                + updateHandler.mObserver.getHomeIntent()
+                                        .getComponent().getPackageName());
+                Log.d(UPDATE_OVERVIEW_TARGETS_RUNNING_LATE,
+                        "AFTER AWAIT: mOtherLauncherActivity package name="
+                                + mOtherLauncherActivity.packageName);
                 try {
                     base.evaluate();
                 } finally {
@@ -253,7 +270,7 @@
     //@NavigationModeSwitch
     @Test
     @ScreenRecordRule.ScreenRecord // b/321775748
-    public void testOverview() {
+    public void testOverview() throws IOException {
         startAppFast(getAppPackageName());
         startAppFast(resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR));
         startTestActivity(2);
@@ -261,7 +278,10 @@
         Wait.atMost("Expected three apps in the task list",
                 () -> mLauncher.getRecentTasks().size() >= 3, DEFAULT_ACTIVITY_TIMEOUT, mLauncher);
 
+        checkTestLauncher();
         BaseOverview overview = mLauncher.getLaunchedAppState().switchToOverview();
+        checkTestLauncher();
+
         executeOnRecents(recents -> {
             assertTrue("Don't have at least 3 tasks", getTaskCount(recents) >= 3);
         });
@@ -303,6 +323,17 @@
                 mOtherLauncherActivity.packageName).text(FALLBACK_LAUNCHER_TITLE)), WAIT_TIME_MS));
     }
 
+    private void checkTestLauncher() throws IOException {
+        final Matcher matcher = COMPONENT_INFO_REGEX.matcher(
+                mDevice.executeShellCommand("cmd shortcut get-default-launcher"));
+        assertTrue("Incorrect output from get-default-launcher", matcher.find());
+        assertEquals("Current Launcher activity is incorrect",
+                "com.google.android.apps.nexuslauncher.tests/com.android"
+                        + ".launcher3.testcomponent.TestLauncherActivity",
+                matcher.group(1)
+        );
+    }
+
     private int getCurrentOverviewPage(RecentsActivity recents) {
         return recents.<RecentsView>getOverviewPanel().getCurrentPage();
     }
@@ -322,12 +353,25 @@
             mRads = new RecentsAnimationDeviceState(ctx);
             mObserver = new OverviewComponentObserver(ctx, mRads);
             mChangeCounter = new CountDownLatch(1);
+            Log.d(UPDATE_OVERVIEW_TARGETS_RUNNING_LATE,
+                    "OverviewUpdateHandler(Constructor): mObserver home intent package name="
+                            + mObserver.getHomeIntent().getComponent().getPackageName());
+            Log.d(UPDATE_OVERVIEW_TARGETS_RUNNING_LATE,
+                    "OverviewUpdateHandler(Constructor): mOtherLauncherActivity package name="
+                            + mOtherLauncherActivity.packageName);
             if (mObserver.getHomeIntent().getComponent()
                     .getPackageName().equals(mOtherLauncherActivity.packageName)) {
                 // Home already same
                 mChangeCounter.countDown();
             } else {
-                mObserver.setOverviewChangeListener(b -> mChangeCounter.countDown());
+                mObserver.setOverviewChangeListener(b -> {
+                    Log.d(UPDATE_OVERVIEW_TARGETS_RUNNING_LATE,
+                            "OverviewChangeListener(Callback): isHomeAndOverviewSame=" + b);
+                    Log.d(UPDATE_OVERVIEW_TARGETS_RUNNING_LATE,
+                            "OverviewChangeListener(Callback): mObserver home intent package name="
+                                    + mObserver.getHomeIntent().getComponent().getPackageName());
+                    mChangeCounter.countDown();
+                });
             }
         }
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
index 3f3b9ed..fa10b61 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplOverviewIconTest.java
@@ -27,6 +27,7 @@
 import com.android.launcher3.tapl.OverviewTask.OverviewSplitTask;
 import com.android.launcher3.tapl.OverviewTaskMenu;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.rule.TestStabilityRule;
 
 import org.junit.Test;
@@ -35,7 +36,7 @@
  * This test run in both Out of process (Oop) and in-process (Ipc).
  * Tests the app Icon in overview.
  */
-public class TaplOverviewIconTest extends AbstractLauncherUiTest {
+public class TaplOverviewIconTest extends AbstractLauncherUiTest<QuickstepLauncher> {
 
     private static final String CALCULATOR_APP_PACKAGE =
             resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
diff --git a/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
new file mode 100644
index 0000000..0c143b4
--- /dev/null
+++ b/quickstep/tests/src/com/android/quickstep/TaplPrivateSpaceTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep;
+
+import static com.android.launcher3.LauncherState.ALL_APPS;
+import static com.android.launcher3.LauncherState.NORMAL;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
+import android.util.Log;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+
+import com.android.launcher3.tapl.LauncherInstrumentation;
+
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.util.Objects;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class TaplPrivateSpaceTest extends AbstractQuickStepTest {
+
+    private int mProfileUserId;
+    private boolean mPrivateProfileSetupSuccessful;
+    private static final String TAG = "TaplPrivateSpaceTest";
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        initialize(this);
+
+        createAndStartPrivateProfileUser();
+        assumeTrue("Private Profile Setup not successful, aborting",
+                mPrivateProfileSetupSuccessful);
+
+        mDevice.pressHome();
+        waitForLauncherCondition("Launcher didn't start", Objects::nonNull);
+        waitForStateTransitionToEnd("Launcher internal state didn't switch to Normal",
+                () -> NORMAL);
+        waitForResumed("Launcher internal state is still Background");
+        mLauncher.getWorkspace().switchToAllApps();
+        waitForStateTransitionToEnd("Launcher internal state didn't switch to All Apps",
+                () -> ALL_APPS);
+
+        // Wait for Private Space being available in Launcher.
+        waitForPrivateSpaceSetup();
+        // Wait for Launcher UI to be updated with Private Space Items.
+        waitForLauncherUIUpdate();
+    }
+
+    private void createAndStartPrivateProfileUser() {
+        String createUserOutput = executeShellCommand("pm create-user --profileOf 0 --user-type "
+                + "android.os.usertype.profile.PRIVATE LauncherPrivateProfile");
+        updatePrivateProfileSetupSuccessful("pm create-user", createUserOutput);
+        String[] tokens = createUserOutput.split("\\s+");
+        mProfileUserId = Integer.parseInt(tokens[tokens.length - 1]);
+        StringBuilder logStr = new StringBuilder().append("profileId: ").append(mProfileUserId);
+        for (String str : tokens) {
+            logStr.append(str).append("\n");
+        }
+        String startUserOutput = executeShellCommand("am start-user " + mProfileUserId);
+        updatePrivateProfileSetupSuccessful("am start-user", startUserOutput);
+    }
+
+    @After
+    public void removePrivateProfile() {
+        String output = executeShellCommand("pm remove-user " + mProfileUserId);
+        updateProfileRemovalSuccessful("pm remove-user", output);
+        waitForPrivateSpaceRemoval();
+    }
+
+    @Test
+    public void testPrivateSpaceContainerIsPresent() {
+        assumeTrue(mPrivateProfileSetupSuccessful);
+        // Scroll to the bottom of All Apps
+        executeOnLauncher(launcher -> launcher.getAppsView().resetAndScrollToPrivateSpaceHeader());
+        waitForResumed("Launcher internal state is still Background");
+
+        // Verify Unlocked View elements are present.
+        assertNotNull("Private Space Unlocked View not found, or is not correct",
+                mLauncher.getAllApps().getPrivateSpaceUnlockedView());
+    }
+
+    private void waitForPrivateSpaceSetup() {
+        waitForLauncherCondition("Private Profile not setup",
+                launcher -> launcher.getAppsView().hasPrivateProfile(),
+                LauncherInstrumentation.WAIT_TIME_MS);
+    }
+
+    private void waitForPrivateSpaceRemoval() {
+        waitForLauncherCondition("Private Profile not setup",
+                launcher -> !launcher.getAppsView().hasPrivateProfile(),
+                LauncherInstrumentation.WAIT_TIME_MS);
+    }
+
+    private void waitForLauncherUIUpdate() {
+        // Wait for model thread completion as it may be processing
+        // the install event from the SystemService
+        mLauncher.waitForModelQueueCleared();
+        // Wait for Launcher UI thread completion, as it may be processing updating the UI in
+        // response to the model update. Not that `waitForLauncherInitialized` is just a proxy
+        // method, we can use any method which touches Launcher UI thread,
+        mLauncher.waitForLauncherInitialized();
+    }
+
+    private void updatePrivateProfileSetupSuccessful(String cli, String output) {
+        Log.d(TAG, "updatePrivateProfileSetupSuccessful, cli=" + cli + " " + "output="
+                + output);
+        mPrivateProfileSetupSuccessful = output.startsWith("Success");
+    }
+
+    private void updateProfileRemovalSuccessful(String cli, String output) {
+        Log.d(TAG, "updateProfileRemovalSuccessful, cli=" + cli + " " + "output=" + output);
+        assertTrue(output, output.startsWith("Success"));
+    }
+
+    private String executeShellCommand(String command) {
+        try {
+            return mDevice.executeShellCommand(command);
+        } catch (IOException e) {
+            Log.e(TAG, "error running shell command", e);
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java
index b31f470..e4caa26 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplStartLauncherViaGestureTests.java
@@ -16,13 +16,9 @@
 
 package com.android.quickstep;
 
-import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
-import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
-
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.util.rule.TestStabilityRule.Stability;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
 
 import org.junit.Before;
@@ -47,8 +43,6 @@
 
     @Test
     @NavigationModeSwitch
-    // Stress tests are long. We permanently demote them from presubmit to match the presubmit SLO.
-    @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
     public void testStressPressHome() {
         for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
             // Destroy Launcher activity.
@@ -61,8 +55,6 @@
 
     @Test
     @NavigationModeSwitch
-    // Stress tests are long. We permanently demote them from presubmit to match the presubmit SLO.
-    @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
     public void testStressSwipeToOverview() {
         for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
             // Destroy Launcher activity.
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
index df73e09..a9ff161 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsPersistentTaskbar.java
@@ -15,6 +15,8 @@
  */
 package com.android.quickstep;
 
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.PERSISTENT;
 
 import android.graphics.Rect;
@@ -23,6 +25,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
+import com.android.launcher3.util.rule.TestStabilityRule;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
 
@@ -45,6 +48,7 @@
 
     @Test
     @NavigationModeSwitch(mode = NavigationModeSwitchRule.Mode.THREE_BUTTON)
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
     public void testThreeButtonsTaskbarBoundsAfterConfigChangeDuringIme() {
         Rect taskbarBoundsBefore = getTaskbar().getVisibleBounds();
         // Go home and to an IME activity (any configuration change would do, as long as it
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 45a9527..81a2d54 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -21,6 +21,7 @@
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
 
 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 static org.junit.Assume.assumeFalse;
@@ -35,9 +36,9 @@
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.Until;
 
-import com.android.launcher3.Flags;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.tapl.BaseOverview;
 import com.android.launcher3.tapl.LaunchedAppState;
 import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
 import com.android.launcher3.tapl.Overview;
@@ -55,6 +56,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -421,7 +423,6 @@
                 READ_DEVICE_CONFIG_PERMISSION);
         // Debug if we need to goHome to prevent wrong previous state b/315525621
         mLauncher.goHome();
-        assumeFalse(Flags.enablePredictiveBackGesture());
         mLauncher.getWorkspace().switchToAllApps().pressBackToWorkspace();
         waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL);
 
@@ -434,6 +435,7 @@
     @PortraitLandscape
     @TaskbarModeSwitch()
     @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/309820115
+    @Ignore("b/315376057")
     @ScreenRecord // b/309820115
     public void testOverviewForTablet() throws Exception {
         assumeTrue(mLauncher.isTablet());
@@ -503,7 +505,6 @@
 
     @Test
     @PortraitLandscape
-    @ScreenRecord // b/326839375
     public void testOverviewDeadzones() throws Exception {
         startTestAppsWithCheck();
 
@@ -583,4 +584,25 @@
             mLauncher.getDevice().setOrientationNatural();
         }
     }
+
+    @Test
+    public void testExcludeFromRecents() throws Exception {
+        startExcludeFromRecentsTestActivity();
+        OverviewTask currentTask = getAndAssertLaunchedApp().switchToOverview().getCurrentTask();
+        // TODO(b/326565120): the expected content description shouldn't be null but for now there
+        // is a bug that causes it to sometimes be for excludeForRecents tasks.
+        assertTrue("Can't find ExcludeFromRecentsTestActivity after entering Overview from it",
+                currentTask.containsContentDescription("ExcludeFromRecents")
+                        || currentTask.containsContentDescription(null));
+        // Going home should clear out the excludeFromRecents task.
+        BaseOverview overview = mLauncher.goHome().switchToOverview();
+        if (overview.hasTasks()) {
+            currentTask = overview.getCurrentTask();
+            assertFalse("Found ExcludeFromRecentsTestActivity after entering Overview from Home",
+                    currentTask.containsContentDescription("ExcludeFromRecents")
+                            || currentTask.containsContentDescription(null));
+        } else {
+            // Presumably the test started with 0 tasks and remains that way after going home.
+        }
+    }
 }
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index ec8e00d..2a54057 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -117,18 +117,21 @@
     }
 
     @Test
-    public void testSaveAppPairMenuItemExistsOnSplitPair() throws Exception {
+    public void testSaveAppPairMenuItemOrActionExistsOnSplitPair() {
         assumeTrue("App pairs feature is currently not enabled, no test needed",
                 Flags.enableAppPairs());
 
         createAndLaunchASplitPair();
 
-        assertTrue("Save app pair menu item is missing",
-                mLauncher.goHome()
-                        .switchToOverview()
-                        .getCurrentTask()
-                        .tapMenu()
-                        .hasMenuItem("Save app pair"));
+        Overview overview = mLauncher.goHome().switchToOverview();
+        if (mLauncher.isGridOnlyOverviewEnabled() || !mLauncher.isTablet()) {
+            assertTrue("Save app pair menu item is missing",
+                    overview.getCurrentTask()
+                            .tapMenu()
+                            .hasMenuItem("Save app pair"));
+        } else {
+            overview.getOverviewActions().assertHasAction("Save app pair");
+        }
     }
 
     @Test
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index aa8c7b5..374722e 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -19,7 +19,6 @@
 import static com.android.quickstep.NavigationModeSwitchRule.Mode.ZERO_BUTTON;
 
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
 import android.app.Instrumentation;
@@ -28,7 +27,6 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.launcher3.Flags;
 import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
 import com.android.launcher3.tapl.Workspace;
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
@@ -69,7 +67,6 @@
     @NavigationModeSwitch(mode = ZERO_BUTTON)
     public void pressBack() throws Exception {
         assumeTrue(mLauncher.isTablet());
-        assumeFalse(Flags.enablePredictiveBackGesture());
         Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
 
         try {
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
index 38d6046..d04e389 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTransientTaskbar.java
@@ -17,6 +17,8 @@
 
 import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.util.TestConstants.AppNames.TEST_APP_NAME;
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 import static com.android.quickstep.TaskbarModeSwitchRule.Mode.TRANSIENT;
 
 import static org.junit.Assume.assumeTrue;
@@ -26,6 +28,7 @@
 
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
+import com.android.launcher3.util.rule.TestStabilityRule;
 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
 
 import org.junit.Test;
@@ -71,6 +74,7 @@
     @TaskbarModeSwitch(mode = TRANSIENT)
     @PortraitLandscape
     @ScreenRecord // b/317798731
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/321083190
     public void testSwipeToStashAndUnstash() {
         getTaskbar().swipeDownToStash();
         mLauncher.getLaunchedAppState().swipeUpToUnstashTaskbar();
diff --git a/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
index 6093816..208920a 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplViewInflationDuringSwipeUp.java
@@ -190,16 +190,14 @@
             info.spanX = 2;
             info.spanY = 2;
             AtomicInteger widgetId = new AtomicInteger();
-            new FavoriteItemsTransaction(mTargetContext)
+
+            commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext)
                     .addItem(() -> {
                         LauncherAppWidgetInfo item = createWidgetInfo(info, mTargetContext, true);
                         item.screenId = FIRST_SCREEN_ID;
                         widgetId.set(item.appWidgetId);
                         return item;
-                    })
-                    .commitAndLoadHome(mLauncher);
-
-
+                    }));
 
             assertTrue("Widget is not present",
                     mLauncher.goHome().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT) != null);
diff --git a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
index d744194..8eec903 100644
--- a/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
+++ b/quickstep/tests/src/com/android/quickstep/TaskViewTest.java
@@ -35,6 +35,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.quickstep.util.BorderAnimator;
 import com.android.quickstep.views.TaskView;
 
@@ -47,7 +48,7 @@
 public class TaskViewTest {
 
     @Mock
-    private StatefulActivity mContext;
+    private QuickstepLauncher mContext;
     @Mock
     private Resources mResource;
     @Mock
diff --git a/res/color-night-v31/material_color_surface_container_high.xml b/res/color-night-v31/material_color_surface_container_high.xml
index 002b88e..edd36fc 100644
--- a/res/color-night-v31/material_color_surface_container_high.xml
+++ b/res/color-night-v31/material_color_surface_container_high.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="17" />
 </selector>
\ No newline at end of file
diff --git a/res/color-night-v31/material_color_surface_container_highest.xml b/res/color-night-v31/material_color_surface_container_highest.xml
index 002b88e..e54f953 100644
--- a/res/color-night-v31/material_color_surface_container_highest.xml
+++ b/res/color-night-v31/material_color_surface_container_highest.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="22" />
 </selector>
\ No newline at end of file
diff --git a/res/color-night-v31/material_color_surface_container_low.xml b/res/color-night-v31/material_color_surface_container_low.xml
index 002b88e..40f0d4c 100644
--- a/res/color-night-v31/material_color_surface_container_low.xml
+++ b/res/color-night-v31/material_color_surface_container_low.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="10" />
 </selector>
\ No newline at end of file
diff --git a/res/color-night-v31/material_color_surface_container_lowest.xml b/res/color-night-v31/material_color_surface_container_lowest.xml
index 002b88e..24f559b 100644
--- a/res/color-night-v31/material_color_surface_container_lowest.xml
+++ b/res/color-night-v31/material_color_surface_container_lowest.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="4" />
 </selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_high.xml b/res/color-v31/material_color_surface_container_high.xml
index b031c08..a996d51 100644
--- a/res/color-v31/material_color_surface_container_high.xml
+++ b/res/color-v31/material_color_surface_container_high.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="92" />
 </selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_highest.xml b/res/color-v31/material_color_surface_container_highest.xml
index b031c08..e7a535a 100644
--- a/res/color-v31/material_color_surface_container_highest.xml
+++ b/res/color-v31/material_color_surface_container_highest.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="90" />
 </selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_low.xml b/res/color-v31/material_color_surface_container_low.xml
index b031c08..b8fe01e 100644
--- a/res/color-v31/material_color_surface_container_low.xml
+++ b/res/color-v31/material_color_surface_container_low.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="96" />
 </selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_lowest.xml b/res/color-v31/material_color_surface_container_lowest.xml
index 674fc73..25e8666 100644
--- a/res/color-v31/material_color_surface_container_lowest.xml
+++ b/res/color-v31/material_color_surface_container_lowest.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License.
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+    <item android:color="@android:color/system_neutral1_500" android:lStar="100" />
 </selector>
\ No newline at end of file
diff --git a/res/color/taskbar_background_dark.xml b/res/color/taskbar_background_dark.xml
new file mode 100644
index 0000000..0727b8a
--- /dev/null
+++ b/res/color/taskbar_background_dark.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+<!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!--  Want to use @android:color/system_neutral1_500, but that causes build errors  -->
+    <item android:color="#76777D" android:lStar="6" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/bg_ps_header.xml b/res/drawable/bg_ps_header.xml
index 526bb5a..da31445 100644
--- a/res/drawable/bg_ps_header.xml
+++ b/res/drawable/bg_ps_header.xml
@@ -14,9 +14,13 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <corners android:radius="@dimen/ps_container_corner_radius" />
-    <solid android:color="?attr/materialColorSurfaceContainerHigh" />
-</shape>
\ No newline at end of file
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/accent_ripple_color">
+    <item>
+        <shape xmlns:android="http://schemas.android.com/apk/res/android"
+            android:shape="rectangle">
+            <corners android:radius="@dimen/ps_container_corner_radius" />
+            <solid android:color="?attr/materialColorSurfaceContainerHigh" />
+        </shape>
+    </item>
+</ripple>
diff --git a/res/drawable/ic_allapps_search.xml b/res/drawable/ic_allapps_search.xml
index 0c3ab78..53b4f91 100644
--- a/res/drawable/ic_allapps_search.xml
+++ b/res/drawable/ic_allapps_search.xml
@@ -18,8 +18,9 @@
     android:height="24dp"
     android:viewportHeight="24.0"
     android:viewportWidth="24.0"
-    android:autoMirrored="true">
+    android:autoMirrored="true"
+    android:tint="?attr/widgetPickerSearchTextColor">
     <path
-        android:fillColor="?attr/widgetPickerSearchTextColor"
+        android:fillColor="#FFFFFF"
         android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z" />
 </vector>
diff --git a/res/drawable/ic_info_no_shadow.xml b/res/drawable/ic_info_no_shadow.xml
index 7c43779..29a81bd 100644
--- a/res/drawable/ic_info_no_shadow.xml
+++ b/res/drawable/ic_info_no_shadow.xml
@@ -18,7 +18,7 @@
         android:height="24dp"
         android:viewportWidth="24"
         android:viewportHeight="24"
-        android:tint="?android:attr/textColorPrimary">
+        android:tint="?attr/materialColorOnSurface">
 
     <path
         android:fillColor="@android:color/white"
diff --git a/res/drawable/ic_install_no_shadow.xml b/res/drawable/ic_install_no_shadow.xml
index eaad0de..6e0125a 100644
--- a/res/drawable/ic_install_no_shadow.xml
+++ b/res/drawable/ic_install_no_shadow.xml
@@ -18,7 +18,7 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24"
-    android:tint="?android:attr/textColorPrimary">
+    android:tint="?attr/materialColorOnSurface">
 
     <path
         android:fillColor="@android:color/white"
diff --git a/res/drawable/ic_install_to_private.xml b/res/drawable/ic_install_to_private.xml
index 0e9833c..45723b0 100644
--- a/res/drawable/ic_install_to_private.xml
+++ b/res/drawable/ic_install_to_private.xml
@@ -20,7 +20,7 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24"
-    android:tint="?android:attr/textColorPrimary">
+    android:tint="?attr/materialColorOnSurface">
 
     <path
         android:fillColor="@android:color/white"
diff --git a/res/drawable/ic_plus.xml b/res/drawable/ic_plus.xml
new file mode 100644
index 0000000..3ab926a
--- /dev/null
+++ b/res/drawable/ic_plus.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="19dp"
+    android:height="18dp"
+    android:viewportWidth="19"
+    android:viewportHeight="18">
+  <path
+      android:pathData="M15.5,9.75H10.25V15H8.75V9.75H3.5V8.25H8.75V3H10.25V8.25H15.5V9.75Z"
+      android:fillColor="#ffffff"/>
+</vector>
diff --git a/res/drawable/ic_private_space_with_background.xml b/res/drawable/ic_private_space_with_background.xml
index 59a33dd..da199f0 100644
--- a/res/drawable/ic_private_space_with_background.xml
+++ b/res/drawable/ic_private_space_with_background.xml
@@ -12,14 +12,15 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:viewportWidth="48"
     android:viewportHeight="48"
     android:width="48dp"
     android:height="48dp">
     <path
         android:pathData="M48 24A24 24 0 0 1 0 24A24 24 0 0 1 48 24Z"
-        android:fillColor="?attr/materialColorOutlineVariant" />
+        android:fillColor="?androidprv:attr/materialColorSurfaceContainerLowest" />
     <path
         android:pathData="M33.3333 14.6667V33.3333H14.6667V14.6667H33.3333ZM33.3333 12H14.6667C13.2 12 12 13.2 12 14.6667V33.3333C12 34.8 13.2 36 14.6667 36H33.3333C34.8 36 36 34.8 36 33.3333V14.6667C36 13.2 34.8 12 33.3333 12Z"
         android:fillColor="?attr/materialColorOnSurface" />
diff --git a/res/drawable/ic_uninstall_no_shadow.xml b/res/drawable/ic_uninstall_no_shadow.xml
index fbabdd2..6200054 100644
--- a/res/drawable/ic_uninstall_no_shadow.xml
+++ b/res/drawable/ic_uninstall_no_shadow.xml
@@ -18,7 +18,7 @@
         android:height="20dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
-        android:tint="?android:attr/textColorPrimary" >
+        android:tint="?attr/materialColorOnSurface" >
     <path
         android:fillColor="@android:color/white"
         android:pathData="M15,4V3H9v1H4v2h1v13c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V6h1V4H15z M17,19H7V6h10V19z" />
diff --git a/res/drawable/page_indicator.xml b/res/drawable/page_indicator.xml
index c0ccc49..d4cb13f 100644
--- a/res/drawable/page_indicator.xml
+++ b/res/drawable/page_indicator.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="?attr/folderPaginationColor"/>
+    <solid android:color="?attr/pageIndicatorDotColor"/>
     <size android:width="@dimen/page_indicator_size" android:height="@dimen/page_indicator_size"/>
 </shape>
\ No newline at end of file
diff --git a/res/drawable/ps_lock_background.xml b/res/drawable/ps_lock_background.xml
index b81c23f..0be83db 100644
--- a/res/drawable/ps_lock_background.xml
+++ b/res/drawable/ps_lock_background.xml
@@ -15,13 +15,17 @@
   ~ limitations under the License.
   -->
 
-<inset xmlns:android="http://schemas.android.com/apk/res/android"
-    android:inset="4dp">
-    <shape android:shape="rectangle">
-        <corners android:radius="@dimen/ps_lock_corner_radius" />
-        <solid android:color="?attr/materialColorPrimaryFixedDim" />
-        <padding
-            android:left="@dimen/ps_lock_button_background_padding"
-            android:right="@dimen/ps_lock_button_background_padding" />
-    </shape>
-</inset>
\ No newline at end of file
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+    android:color="@color/accent_ripple_color">
+    <item>
+        <inset android:inset="4dp">
+            <shape android:shape="rectangle">
+                <corners android:radius="@dimen/ps_lock_corner_radius" />
+                <solid android:color="?attr/materialColorPrimaryFixedDim" />
+                <padding
+                    android:left="@dimen/ps_lock_button_background_padding"
+                    android:right="@dimen/ps_lock_button_background_padding" />
+            </shape>
+        </inset>
+    </item>
+</ripple>
diff --git a/res/drawable/widget_cell_add_button_background.xml b/res/drawable/widget_cell_add_button_background.xml
new file mode 100644
index 0000000..860d1cd
--- /dev/null
+++ b/res/drawable/widget_cell_add_button_background.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<inset
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <ripple
+        android:color="?android:attr/colorControlHighlight">
+        <item>
+            <shape android:shape="rectangle">
+                <corners
+                    android:radius="50dp"/>
+                <solid android:color="?attr/widgetPickerAddButtonBackgroundColor" />
+            </shape>
+        </item>
+    </ripple>
+</inset>
\ No newline at end of file
diff --git a/res/layout/develop_options_edit_text.xml b/res/layout/develop_options_edit_text.xml
new file mode 100644
index 0000000..5e44228
--- /dev/null
+++ b/res/layout/develop_options_edit_text.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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.
+  -->
+
+<com.android.launcher3.ExtendedEditText
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:minWidth="100dp"
+    android:inputType="numberSigned"
+    android:id="@+id/pref_edit_text"
+    android:selectAllOnFocus="true"
+    android:imeOptions="actionDone"
+    android:maxLines="1" />
\ No newline at end of file
diff --git a/res/layout/developer_options_top_bar.xml b/res/layout/developer_options_top_bar.xml
index 1b138ea..ca46311 100644
--- a/res/layout/developer_options_top_bar.xml
+++ b/res/layout/developer_options_top_bar.xml
@@ -11,16 +11,17 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_marginHorizontal="@dimen/developer_options_filter_margins"
+        android:background="@drawable/rounded_action_button"
+        android:layout_marginTop="4dp"
+        android:layout_marginLeft="16dp"
+        android:layout_marginRight="16dp"
+        android:padding="12dp"
+        android:drawableStart="@drawable/ic_allapps_search"
+        android:drawableTint="?android:attr/textColorSecondary"
+        android:drawablePadding="8dp"
         android:hint="@string/developer_options_filter_hint"
         android:inputType="text"
         android:maxLines="1"
         android:imeOptions="actionDone"
         />
-    <Button
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:gravity="center_vertical"
-        android:text="Apply"
-        android:visibility="invisible"
-        android:id="@+id/flag_apply_btn" />
 </LinearLayout>
\ No newline at end of file
diff --git a/res/layout/hotseat.xml b/res/layout/hotseat.xml
index 82b0b8d..d14dcd5 100644
--- a/res/layout/hotseat.xml
+++ b/res/layout/hotseat.xml
@@ -21,4 +21,6 @@
     android:layout_height="match_parent"
     android:theme="@style/HomeScreenElementTheme"
     android:importantForAccessibility="no"
+    android:clickable="false"
+    android:longClickable="false"
     launcher:containerType="hotseat" />
\ No newline at end of file
diff --git a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml b/res/layout/predicted_app_icon.xml
similarity index 60%
copy from quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
copy to res/layout/predicted_app_icon.xml
index dde9cac..52df694 100644
--- a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
+++ b/res/layout/predicted_app_icon.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 The Android Open Source Project
+<!-- Copyright (C) 2008 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.
@@ -13,11 +13,5 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<ImageView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:scaleType="centerCrop"
-    android:background="@drawable/keyboard_quick_switch_task_view_background"
-    android:clipToOutline="true"
-    android:importantForAccessibility="no"/>
+
+<com.android.launcher3.views.DoubleShadowBubbleTextView style="@style/BaseIcon.Workspace" />
diff --git a/res/layout/private_space_header.xml b/res/layout/private_space_header.xml
index 0b0af87..185207b 100644
--- a/res/layout/private_space_header.xml
+++ b/res/layout/private_space_header.xml
@@ -33,7 +33,7 @@
         android:layout_centerVertical="true"
         android:gravity="center_vertical"
         android:layout_alignParentEnd="true"
-        android:animateLayoutChanges="true">
+        android:animateLayoutChanges="false">
         <ImageButton
             android:id="@+id/ps_settings_button"
             android:layout_width="@dimen/ps_header_image_height"
@@ -87,7 +87,8 @@
     <TextView
         android:id="@+id/ps_container_header"
         android:layout_width="wrap_content"
-        android:layout_height="@dimen/ps_header_text_height"
+        android:layout_height="wrap_content"
+        android:minHeight="@dimen/ps_header_text_height"
         android:layout_alignParentStart="true"
         android:layout_centerVertical="true"
         android:layout_toStartOf="@+id/settingsAndLockGroup"
diff --git a/res/layout/snackbar.xml b/res/layout/snackbar.xml
index b818943..6bc1729 100644
--- a/res/layout/snackbar.xml
+++ b/res/layout/snackbar.xml
@@ -39,6 +39,7 @@
         android:paddingLeft="8dp"
         android:paddingRight="8dp"
         android:background="?android:attr/selectableItemBackground"
+        android:longClickable="false"
         android:textStyle="bold"
         android:textSize="@dimen/snackbar_max_text_size"
         android:textColor="?android:attr/colorAccent"
diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml
index 31f4870..43a8aac 100644
--- a/res/layout/user_folder_icon_normalized.xml
+++ b/res/layout/user_folder_icon_normalized.xml
@@ -18,6 +18,7 @@
     xmlns:launcher="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
+    android:defaultFocusHighlightEnabled="false"
     android:orientation="vertical" >
 
     <com.android.launcher3.folder.FolderPagedView
diff --git a/res/layout/widget_cell.xml b/res/layout/widget_cell.xml
index 55dd1de..4533873 100644
--- a/res/layout/widget_cell.xml
+++ b/res/layout/widget_cell.xml
@@ -17,7 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="0dp"
     android:layout_height="wrap_content"
-    android:paddingHorizontal="@dimen/widget_cell_horizontal_padding"
+    android:layout_marginStart="@dimen/widget_cell_horizontal_padding"
+    android:layout_marginEnd="@dimen/widget_cell_horizontal_padding"
     android:paddingVertical="@dimen/widget_cell_vertical_padding"
     android:layout_weight="1"
     android:orientation="vertical"
diff --git a/res/layout/widget_cell_content.xml b/res/layout/widget_cell_content.xml
index 0c606f6..12453a5 100644
--- a/res/layout/widget_cell_content.xml
+++ b/res/layout/widget_cell_content.xml
@@ -35,50 +35,71 @@
             android:layout_height="match_parent"
             android:importantForAccessibility="no"
             android:layout_gravity="fill"/>
-
-        <ImageView
-            android:id="@+id/widget_badge"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:importantForAccessibility="no"
-            android:layout_gravity="end|bottom"
-            android:layout_margin="@dimen/profile_badge_margin"/>
     </com.android.launcher3.widget.WidgetCellPreview>
 
-    <!-- The name of the widget. -->
-    <TextView
-        android:id="@+id/widget_name"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:ellipsize="end"
-        android:fadingEdge="horizontal"
-        android:gravity="center_horizontal|center_vertical"
-        android:singleLine="true"
-        android:maxLines="1"
-        android:textColor="?android:attr/textColorPrimary"
-        android:drawablePadding="@dimen/widget_cell_app_icon_padding"
-        android:textSize="@dimen/widget_cell_font_size" />
-
-    <!-- The original dimensions of the widget -->
-    <TextView
-        android:id="@+id/widget_dims"
+    <FrameLayout
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center_horizontal"
-        android:textColor="?android:attr/textColorSecondary"
-        android:textSize="@dimen/widget_cell_font_size"
-        android:alpha="0.7" />
+        android:layout_height="wrap_content">
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:id="@+id/widget_text_container"
+            android:orientation="vertical">
+            <!-- The name of the widget. -->
+            <TextView
+                android:id="@+id/widget_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:ellipsize="end"
+                android:fadingEdge="horizontal"
+                android:layout_gravity="center_horizontal"
+                android:gravity="center_horizontal|center_vertical"
+                android:singleLine="true"
+                android:maxLines="1"
+                android:textColor="?android:attr/textColorPrimary"
+                android:drawablePadding="@dimen/widget_cell_app_icon_padding"
+                android:textSize="@dimen/widget_cell_font_size" />
 
-    <TextView
-        android:id="@+id/widget_description"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center_horizontal"
-        android:textSize="@dimen/widget_cell_font_size"
-        android:textColor="?android:attr/textColorSecondary"
-        android:maxLines="2"
-        android:ellipsize="end"
-        android:fadingEdge="horizontal"
-        android:alpha="0.7" />
+                <!-- The original dimensions of the widget -->
+                <TextView
+                    android:id="@+id/widget_dims"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_horizontal"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:textSize="@dimen/widget_cell_font_size"
+                    android:alpha="0.7" />
 
-</merge>
\ No newline at end of file
+                <TextView
+                    android:id="@+id/widget_description"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_horizontal"
+                    android:textSize="@dimen/widget_cell_font_size"
+                    android:textColor="?android:attr/textColorSecondary"
+                    android:maxLines="2"
+                    android:ellipsize="end"
+                    android:fadingEdge="horizontal"
+                    android:alpha="0.7" />
+        </LinearLayout>
+
+        <Button
+            android:id="@+id/widget_add_button"
+            android:layout_width="wrap_content"
+            android:layout_height="@dimen/widget_cell_add_button_height"
+            android:layout_gravity="center"
+            android:minWidth="0dp"
+            android:paddingStart="@dimen/widget_cell_add_button_start_padding"
+            android:paddingEnd="@dimen/widget_cell_add_button_end_padding"
+            android:text="@string/widget_add_button_label"
+            android:textColor="?attr/widgetPickerAddButtonTextColor"
+            android:textSize="@dimen/widget_cell_font_size"
+            android:gravity="center"
+            android:visibility="gone"
+            android:drawableStart="@drawable/ic_plus"
+            android:drawablePadding="8dp"
+            android:drawableTint="?attr/widgetPickerAddButtonTextColor"
+            android:background="@drawable/widget_cell_add_button_background" />
+    </FrameLayout>
+</merge>
diff --git a/res/layout/widget_recommendations.xml b/res/layout/widget_recommendations.xml
index 89821ac..5879b0f 100644
--- a/res/layout/widget_recommendations.xml
+++ b/res/layout/widget_recommendations.xml
@@ -28,17 +28,21 @@
         android:layout_marginTop="16dp"
         android:accessibilityLiveRegion="polite"
         android:gravity="center_horizontal"
+        android:layout_gravity="top"
         android:lineHeight="20sp"
         android:textColor="?attr/widgetPickerTitleColor"
         android:textFontWeight="500"
         android:textSize="16sp"
+        android:maxLines="1"
+        android:paddingHorizontal="8dp"
+        android:ellipsize="end"
         android:visibility="gone" />
     <!-- Shown when there are more than one pages -->
     <com.android.launcher3.pageindicators.PageIndicatorDots
         android:id="@+id/widget_recommendations_page_indicator"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
+        android:layout_gravity="center_horizontal|top"
         android:elevation="1dp"
         android:visibility="gone" />
     <!--
@@ -50,8 +54,9 @@
     <com.android.launcher3.widget.picker.WidgetRecommendationsView
         android:id="@+id/widget_recommendations_view"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="0dp"
         android:layout_gravity="center"
+        android:layout_weight="1"
         android:background="@drawable/widgets_surface_background"
         android:importantForAccessibility="yes"
         launcher:pageIndicator="@+id/widget_recommendations_page_indicator" />
diff --git a/res/layout/widget_recommendations_table.xml b/res/layout/widget_recommendations_table.xml
index e3f0562..b53d2d5 100644
--- a/res/layout/widget_recommendations_table.xml
+++ b/res/layout/widget_recommendations_table.xml
@@ -17,5 +17,4 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:paddingHorizontal="@dimen/widget_recommendations_table_horizontal_padding"
     android:paddingVertical="@dimen/widget_recommendations_table_vertical_padding" />
diff --git a/res/layout/widgets_full_sheet_paged_view.xml b/res/layout/widgets_full_sheet_paged_view.xml
index 1d37043..8dc785a 100644
--- a/res/layout/widgets_full_sheet_paged_view.xml
+++ b/res/layout/widgets_full_sheet_paged_view.xml
@@ -79,6 +79,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dp"
+            android:layout_marginBottom="8dp"
             android:background="@drawable/widgets_surface_background"
             android:orientation="vertical"
             android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
@@ -92,7 +93,7 @@
             android:layout_height="64dp"
             android:gravity="center_horizontal"
             android:orientation="horizontal"
-            android:paddingVertical="8dp"
+            android:paddingBottom="8dp"
             android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
             android:background="?attr/widgetPickerPrimarySurfaceColor"
             style="@style/TextHeadline"
diff --git a/res/layout/widgets_full_sheet_recyclerview.xml b/res/layout/widgets_full_sheet_recyclerview.xml
index dca08ff..5427732 100644
--- a/res/layout/widgets_full_sheet_recyclerview.xml
+++ b/res/layout/widgets_full_sheet_recyclerview.xml
@@ -29,7 +29,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@id/collapse_handle"
-        android:paddingBottom="16dp"
+        android:paddingBottom="8dp"
         android:layout_marginHorizontal="@dimen/widget_list_horizontal_margin"
         android:clipToOutline="true"
         android:orientation="vertical">
@@ -62,6 +62,7 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_marginTop="8dp"
+            android:layout_marginBottom="8dp"
             android:background="@drawable/widgets_surface_background"
             android:orientation="vertical"
             android:visibility="gone">
diff --git a/res/layout/widgets_two_pane_sheet.xml b/res/layout/widgets_two_pane_sheet.xml
index 8e45740f..6c4810c 100644
--- a/res/layout/widgets_two_pane_sheet.xml
+++ b/res/layout/widgets_two_pane_sheet.xml
@@ -122,7 +122,7 @@
                         <LinearLayout
                             android:id="@+id/widget_recommendations_container"
                             android:layout_width="match_parent"
-                            android:layout_height="wrap_content"
+                            android:layout_height="match_parent"
                             android:background="@drawable/widgets_surface_background"
                             android:orientation="vertical"
                             android:visibility="gone">
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 262038d..7c6aa83 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Hierdie apppaar word nie op hierdie toestel gesteun nie"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Vou die toestel oop om hierdie apppaar te gebruik"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Apppaar is nie beskikbaar nie"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Raak en hou om \'n legstuk te skuif."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en hou om \'n legstuk te skuif of gebruik gepasmaakte handelinge."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed by %2$d hoog"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk, %2$d wyd en %3$d hoog"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Raak en hou die legstuk om dit op die tuisskerm rond te beweeg"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Voeg by tuisskerm"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk by tuisskerm gevoeg"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Voorstelle"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Jou daaglikse noodsaaklikhede"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Nuus vir jou"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Noodsaaklikhede"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nuus en tydskrifte"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jou ontspansone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Bereik jou fiksheiddoelwitte"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Spring die weer voor"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Jy hou dalk ook van"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Vermaak"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosiaal"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gesondheid en fiksheid"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weer"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Voorgestel vir jou"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-legstukke aan die regterkant, soektog en opsies aan die linkerkant"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# legstuk}other{# legstukke}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# kortpad}other{# kortpaaie}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Werk"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Gesprekke"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Neem notas"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Voeg by"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Voeg <xliff:g id="WIDGET_NAME">%1$s</xliff:g>-legstuk by"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Nuttige inligting binne jou bereik"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Jy kan legstukke by jou tuisskerm voeg om inligting te kry sonder om programme oop te maak"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tik om legstukinstellings te verander"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Misluk: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privaat ruimte"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Hou privaat apps gesluit en versteek"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tik om op te stel of oop te maak"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privaat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privaat Ruimte-instellings"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Sluit/ontsluit Privaat Ruimte"</string>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index e404506..fe5b51a 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ይህ የመተግበሪያ ጥምረት በዚህ መሣሪያ ላይ አይደገፍም"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ይህን የመተግበሪያ ጥምረት ለመጠቀም መሣሪያን ይዘርጉ"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"የመተግበሪያ ጥምረት አይገኝም"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ምግብርን ለማንቀሳቀስ ይንኩ እና ይያዙ።"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ምግብርን ለማንቀሳቀስ ወይም ብጁ እርምጃዎችን ለመጠቀም ሁለቴ መታ ያድርጉ እና ይያዙ።"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ስፋት በ%2$d ከፍታ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"የ<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"የ<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር፣ %2$d ስፋት በ%3$d ቁመት"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"በመነሻ ማያ ገፅ አካባቢ ላይ ለማንቀሳቀስ ነክተው ይያዙት"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ወደ መነሻ ማያ ገፅ አክል"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ምግብር ወደ መነሻ ማያ ገፅ ታክሏል"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"የአስተያየት ጥቆማዎች"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"የእርስዎ ዕለታዊ መሠረታዊ ነገሮች"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ዜና ለእርስዎ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ጠቃሚ ነገሮች"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ዜና እና መጽሔቶች"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"የሚያርፉበት ቦታዎ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"የአካል ብቃት ግቦችዎን ያሳኩ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"ለአየር ሁኔታው አስቀድመው ያቅዱ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ይህንንም ሊወዱት ይችላሉ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"መዝናኛ"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ማህበራዊ"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ጤና እና የአካል ብቃት"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"የአየር ሁኔታ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ለእርስዎ የተጠቆሙ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ምግብሮች በቀኝ በኩል፣ ፍለጋ እና አማራጮች በግራ በኩል"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ምግብር}one{# ምግብሮች}other{# ምግብሮች}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# አቋራጭ}one{# አቋራጭ}other{# አቋራጮች}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ሥራ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"ውይይቶች"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"የማስታወሻ አያያዝ"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"አክል"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"ምግብር <xliff:g id="WIDGET_NAME">%1$s</xliff:g>ን አክል"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"በጣቶችዎ ጫፎች ላይ ጠቃሚ መረጃ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"መተግበሪያዎችን ሳይከፍቱ መረጃ ለማግኘት በመነሻ ማያ ገጽዎ ላይ ምግብሮችን ማከል ይችላሉ"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"የምግብር ቅንብሮችን ለመለወጥ መታ ያድርጉ"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"አጣራ"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"አልተሳካም፦ <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"የግል ቦታ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"የግል መተግበሪያዎች እንደተቆለፉ እና እንደተበቁ እንዲቆዩ ያድርጉ"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ለማዋቀር ወይም ለመክፈት መታ ያድርጉ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"የግል"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"የግል ቦታ ቅንብሮች"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"የግል ቦታን ቆልፍ/ክፈት"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 618e994..6963bb7 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | ‏<xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"لا يمكن استخدام هذين التطبيقَين في الوقت نفسه على هذا الجهاز"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"افتح الجهاز لاستخدام هذين التطبيقَين في الوقت نفسه"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"ميزة \"استخدام تطبيقين في الوقت نفسه\" غير متوفّرة"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"انقر مع الاستمرار لنقل أداة."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"انقر مرتين مع تثبيت إصبعك لنقل أداة أو استخدام الإجراءات المخصّصة."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏العرض %1$d الطول %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"أداة <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"‏التطبيق المصغّرة \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\"، بعرض ‎%2$d وارتفاع ‎%3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"انقر مع الاستمرار على التطبيق المصغّر لنقله إلى الشاشة الرئيسية"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"إضافة إلى الشاشة الرئيسية"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"تمت إضافة الأداة <xliff:g id="WIDGET_NAME">%1$s</xliff:g> إلى الشاشة الرئيسية."</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"اقتراحات"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"تطبيقات أساسية للحياة اليومية"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"أخبار مقترَحة لك"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"الأساسيات"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"الأخبار والمجلات"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"محتوى ترفيهي مقترَح"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"تحقيق أهداف اللياقة البدنية"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"معرفة حالة الطقس أولاً بأول"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"محتوى قد يعجبك أيضًا"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"الترفيه"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"التواصل الاجتماعي"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"الصحة واللياقة البدنية"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"الطقس"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"محتوى مقترَح لك"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"تطبيقات \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" المصغّرة على اليسار، والبحث والخيارات على اليمين"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{تطبيق مصغّر واحد}zero{# تطبيق مصغّر}two{تطبيقان مصغّران}few{# تطبيقات مصغّرة}many{# تطبيقًا مصغّرًا}other{# تطبيق مصغّر}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{اختصار واحد}zero{# اختصار}two{اختصاران}few{# اختصارات}many{# اختصارًا}other{# اختصار}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"تطبيقات العمل"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"المحادثات"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"تدوين الملاحظات"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"إضافة"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"إضافة التطبيق المصغّر \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
     <string name="widget_education_header" msgid="4874760613775913787">"معلومات مفيدة في متناول يديك"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"للحصول على معلومات بدون فتح التطبيقات، يمكنك إضافة التطبيقات المصغّرة إلى الشاشة الرئيسية."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"انقر لتغيير إعدادات الأداة"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"فلتر"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"تعذَّر <xliff:g id="WHAT">%1$s</xliff:g>."</string>
     <string name="private_space_label" msgid="2359721649407947001">"مساحة خاصة"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"إبقاء التطبيقات الخاصة مقفلة ومخفية"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"النقر للإعداد أو الفتح"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"المساحة الخاصة"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"إعدادات المساحة الخاصة"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"قفل المساحة الخاصة أو فتح قفلها"</string>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 0abdd36..7872e45 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"এই ডিভাইচটোত এই এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো সমৰ্থিত নহয়"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"এই এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো ব্যৱহাৰ কৰিবলৈ ডিভাইচটো আনফ’ল্ড কৰক"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"এপ্‌ পেয়াৰ কৰাৰ সুবিধাটো উপলব্ধ নহয়"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ৱিজেট স্থানান্তৰ কৰিবলৈ টিপি ধৰি ৰাখক।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"কোনো ৱিজেট স্থানান্তৰ কৰিবলৈ দুবাৰ টিপি ধৰি ৰাখক অথবা কাষ্টম কাৰ্য ব্যৱহাৰ কৰক।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d বহল x %2$d ওখ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেট"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেট, %2$d বহল %3$d ওখ"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ৱিজেটটো গৃহ স্ক্ৰীনৰ আশে-পাশে নিবলৈ সেইটোত স্পৰ্শ কৰি ধৰি ৰাখক"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"গৃহ স্ক্ৰীনত যোগ কৰক"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেটটো গৃহ স্ক্ৰীনত যোগ দিয়া হৈছে"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"পৰামৰ্শ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"আপোনাৰ দৈনিক অত্যাৱশ্যকীয় সামগ্ৰী"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"আপোনাৰ বাবে বাতৰি"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"অত্যাৱশ্যকীয়সমূহ"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"বাতৰি আৰু আলোচনী"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"আপোনাৰ পচন্দৰ স্থান"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"আপোনাৰ সুস্থতাৰ লক্ষ্যত উপনীত হওক"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"বতৰৰ বিষয়ে আগতীয়াকৈ জানক"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"আপুনি হয়তো এইটোও পচন্দ কৰিব"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"মনোৰঞ্জন"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"সামাজিক"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"স্বাস্থ্য আৰু সুস্থতা"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"বতৰ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"আপোনাৰ বাবে পৰামৰ্শ হিচাপে আগবঢ়োৱা"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ৱিজেট সোঁফালে, সন্ধান আৰু বিকল্পসমূহ বাওঁফালে"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# টা ৱিজেট}one{# টা ৱিজেট}other{# টা ৱিজেট}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# টা শ্বৰ্টকাট}one{# টা শ্বৰ্টকাট}other{# টা শ্বৰ্টকাট}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"কৰ্মস্থান"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"বাৰ্তালাপ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"টোকা গ্ৰহণ কৰা"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"যোগ দিয়ক"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ৱিজেট যোগ দিয়ক"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"আপোনাৰ আঙুলিৰে টিপতে উপযোগী তথ্য পাওক"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"এপ্ নোখোলাকৈ তথ্য পাবলৈ আপুনি নিজৰ গৃহ স্ক্ৰীনত ৱিজেট যোগ দিব পাৰে"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ৱিজেটৰ ছেটিং সলনি কৰিবলৈ টিপক"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ফিল্টাৰ"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"বিফল: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"প্ৰাইভেট স্পে\'চ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ব্যক্তিগত এপ্‌সমূহ লক কৰি লুকুৱাই ৰাখক"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ছেট আপ কৰিবলৈ টিপক অথবা খোলক"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ব্যক্তিগত"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ব্যক্তিগত স্পে’চৰ ছেটিং"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"প্ৰাইভেট স্পে\'চ লক/আনলক কৰক"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index d11c4a7..0f67a22 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Bu tətbiq cütü bu cihazda dəstəklənmir"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Bu tətbiq cütündən istifadə üçün cihazı açın"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Tətbiq cütü əlçatan deyil"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidceti daşımaq üçün toxunub saxlayın."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidceti daşımaq üçün iki dəfə toxunub saxlayın və ya fərdi əməliyyatlardan istifadə edin."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%2$d hündürlük %1$d enində"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti, eni - %2$d, hündürlüyü - %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Əsas ekranda hərəkət etdirmək üçün vidcetə toxunub saxlayın"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Əsas ekrana əlavə edin"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidceti əsas ekrana əlavə edildi"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Təkliflər"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Gündəlik vacib vidcetlər"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Sizin üçün xəbərlər"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Əsaslar"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Xəbər və jurnallar"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"İstirahət zonası"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Fitnes hədəflərinə nail olun"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Hava barədə məlumatlı olun"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Tövsiyələr"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Əyləncə"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sağlamlıq və fitnes"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hava"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Təklif edirik"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidcetləri sağda, axtarış və seçimlər solda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidcet}other{# vidcet}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# qısayol}other{# qısayol}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"İş"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Söhbətlər"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Qeydgötürmə"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Əlavə edin"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidcet əlavə edin"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Faydalı məlumatlar barmaqlarınızın ucunda"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Tətbiqləri açmadan məlumat almaq üçün Əsas ekrana vidcet əlavə edə bilərsiniz"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Vidcet ayarlarını dəyişmək üçün toxunun"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtr"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Alınmadı: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Şəxsi yer"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Şəxsi tətbiqləri kilidli və gizli saxlayın"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toxunaraq ayarlayın və ya açın"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Şəxsi"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Şəxsi məkan ayarları"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Şəxsi məkanı kilidləyin/kiliddən çıxarın"</string>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index a3b80a6..59c4700 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ovaj par aplikacija nije podržan na ovom uređaju"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Otvorite uređaj da biste koristili ovaj par aplikacija"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacija nije dostupan"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite radi pomeranja vidžeta."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da biste pomerali vidžet ili koristite prilagođene radnje."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"širina od %1$d i visina od %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidžet"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidžet, širina %2$d i visina %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dodirnite i zadržite vidžet da biste ga pomerali po početnom ekranu"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na početni ekran"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Dodali ste vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> na početni ekran"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlozi"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Osnovni vidžeti za svaki dan"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Vesti za vas"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Neophodne aplikacije"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Novosti i časopisi"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona za opuštanje"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Ostvarite fitnes ciljeve"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Budite u toku sa vremenskim prilikama"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Možda će vam se dopasti i"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitnes"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vreme"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predloženo za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Vidžeti <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> sa desne strane, pretraga i opcije sa leve strane"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# prečica}one{# prečica}few{# prečice}other{# prečica}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Konverzacije"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pravljenje beležaka"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodaj"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Dodajte vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Da biste pronašli informacije bez otvaranja aplikacija, možete da dodate vidžete na početni ekran"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da biste promenili podešavanja vidžeta"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privatni prostor"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Neka privatne aplikacije budu zaključane i sakrivene"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da biste podesili ili otvorili"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Podešavanja privatnog prostora"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Zaključaj/otključaj privatni prostor"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index c978425..b6e30de 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Дадзенае спалучэнне праграм не падтрымліваецца на гэтай прыладзе"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Каб выкарыстоўваць гэта спалучэнне праграм, раскладзіце прыладу"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Націсніце і ўтрымлівайце віджэт для перамяшчэння."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Дакраніцеся двойчы і ўтрымлівайце, каб перамясціць віджэт або выкарыстоўваць спецыяльныя дзеянні."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Шырына: %1$d, вышыня: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\": шырыня – %2$d, вышыня – %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Утрымліваючы віджэт націснутым, перамяшчайце яго па галоўным экране"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Дадаць на галоўны экран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" дададзены на галоўны экран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Прапановы"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Праграмы першай неабходнасці"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Навіны для вас"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Асноўнае"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Навіны і часопісы"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зона адпачынку"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Вашы фітнэс-мэты"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Прагноз надвор\'я"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Іншыя рэкамендацыі"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забавы"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Сацыяльныя сеткі"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здароўе і фітнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Надвор\'е"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Рэкамендавана для вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Віджэты праграмы \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" справа, пошук і параметры злева"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджэт}one{# віджэт}few{# віджэты}many{# віджэтаў}other{# віджэта}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ярлык}one{# ярлык}few{# ярлыкі}many{# ярлыкоў}other{# ярлыка}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Працоўныя"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Размовы"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Стварэнне нататак"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Дадаць"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Дадаць віджэт \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Карысная інфармацыя ў вас пад рукой"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Каб не адкрываць праграмы для прагляду патрэбнай інфармацыі, дадайце віджэты на галоўны экран"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Націсніце, каб змяніць налады віджэта"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Фільтр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не ўдалося: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Прыватная вобласць"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Схавайце прыватныя праграмы ў асобную прастору і закрыйце доступ да яе"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Націсніце, каб наладзіць або адкрыць"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Прыватная"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Налады прыватнай вобласці"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Заблакіраваць (разблакіраваць) прыватную вобласць"</string>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 769c538..b9b6b60 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Тази двойка приложения не се поддържа на устройството"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Отворете устройството, за да използвате тази двойка приложения"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Докоснете и задръжте за преместване на приспособление"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Докоснете двукратно и задръжте за преместване на приспособление или използвайте персонал. действия."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина %1$d и височина %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> приспособление"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Приспособлението „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ е широко %2$d и високо %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Докоснете приспособлението и го задръжте, за да го местите на началния екран"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Добавяне към началния екран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Приспособлението <xliff:g id="WIDGET_NAME">%1$s</xliff:g> е добавено към началния екран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предложения"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Основните за деня ви"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Новини за вас"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Приспособления, които трябва да изпробвате"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новини и списания"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зоната ви за разпускане"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Постигнете фитнес целите си"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Бъдете една крачка напред с прогнозата за времето"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Може също да харесате"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Развлечения"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Социални мрежи"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здраве и фитнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Времето"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Предложено за вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Приспособленията за <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> са отдясно, търсенето и опциите – отляво"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# приспособление}other{# приспособления}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# пряк път}other{# преки пътя}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Служебни"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Разговори"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Водене на бележки"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Добавяне"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Добавяне на приспособлението „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Лесен достъп до полезна информация"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"За да получавате информация, без да отваряте приложенията, можете да добавите приспособления към началния екран"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Докоснете, за да промените настройките на приспособлението"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтър"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Неуспешно: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Лично пространство"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Заключване и скриване на частните приложения"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Докоснете за настройване или отваряне"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Лично"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Настройки за личното пространство"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Заключване/отключване на личното пространство"</string>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index cc6a8aa..64b0ba2 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"এই ডিভাইসে এই অ্যাপ পেয়ারটি কাজ করে না"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"এই অ্যাপ পেয়ার ব্যবহার করতে ডিভাইস আনফোল্ড করুন"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"কোনও উইজেট সরাতে সেটি টাচ করে ধরে রাখুন।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"একটি উইজেট সরাতে বা কাস্টম অ্যাকশন ব্যবহার করতে ডবল ট্যাপ করে ধরে রাখুন।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%2$d উচ্চতা অনুযায়ী %1$d প্রস্থ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>টি উইজেট"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> উইজেট, %2$d প্রস্থ ও %3$d উচ্চতা"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"হোম স্ক্রিনের যেকোনও জায়গায় নিয়ে যেতে, উইজেট টাচ করে ধরে থাকুন"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"হোম স্ক্রিনে যোগ করুন"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> উইজেট হোম স্ক্রিনে যোগ করা হয়েছে"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"সাজেশন"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"আপনার নিত্য প্রয়োজনীয় জিনিস"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"আপনার জন্য খবর"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"প্রয়োজনীয় জিনিস"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"খবর ও ম্যাগাজিন"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"আপনার চিল জোন"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"আপনার ফিটনেস সংক্রান্ত লক্ষ্যে পৌঁছান"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"আবহাওয়া সম্পর্কে আগেই খবর পান"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"আপনার এগুলিও পছন্দ হতে পারে"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"বিনোদন"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"সোশ্যাল"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"স্বাস্থ্য ও ফিটনেস"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"আবহাওয়া"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"আপনার জন্য সাজেস্ট করা হয়েছে"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> উইজেট ডানদিকে, সার্চ ও বিকল্প বাঁদিকে রয়েছে"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{#টি উইজেট}one{#টি উইজেট}other{#টি উইজেট}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{#টি শর্টকাট}one{#টি শর্টকাট}other{#টি শর্টকাট}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"অফিস"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"কথোপকথন"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"নোট নেওয়া"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"যোগ করুন"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> উইজেট যোগ করুন"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"সহজেই দরকারি তথ্য পান"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"অ্যাপ না খুলেই তথ্য পাওয়ার জন্য, হোম স্ক্রিনে উইজেট যোগ করতে পারবেন"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"উইজেট সেটিংস পরিবর্তন করতে ট্যাপ করুন"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ফিল্টার"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"কাজটি করা যায়নি: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ব্যক্তিগত স্পেস"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ব্যক্তিগত অ্যাপ লক করে লুকিয়ে রাখুন"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"সেট-আপ করতে বা খুলতে ট্যাপ করুন"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ব্যক্তিগত"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ব্যক্তিগত স্পেসের সেটিংস"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ব্যক্তিগত স্পেস লক/আনলক করুন"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 50f7a2e..d0d4ce6 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Par aplikacija nije podržan na uređaju"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Otklopite uređaj da koristite ovaj par aplikacija"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacija nije dostupan"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite da pomjerite vidžet."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite da pomjerite vidžet ili da koristite prilagođene radnje."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, visina %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, širina %2$d, visina %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dodirnite i zadržite vidžet da ga pomjerate po početnom ekranu"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na početni ekran"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Vidžet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> je dodan na početni ekran"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Prijedlozi"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Svakodnevni osnovni vidžeti"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Vijesti za vas"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovne aplikacije"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Vijesti i časopisi"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša zona opuštanja"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Postignite svoje ciljeve fitnesa"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Ne dajte da vas uhvati oluja"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Možda vam se svidi i ovo"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitnes"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vrijeme"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predloženo za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Vidžeti aplikacije <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> su na desnoj, a pretraživanje i opcije na lijevoj strani"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidžet}one{# vidžet}few{# vidžeta}other{# vidžeta}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# prečica}one{# prečica}few{# prečice}other{# prečica}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pisanje bilješki"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodaj"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Dodavanje vidžeta <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Da dobijete informacije bez otvaranja aplikacija, možete dodati vidžete na početni ekran"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da promijenite postavke vidžeta"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrirajte"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privatan prostor"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Ostavite privatne aplikacije zaključane i sakrivene"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da postavite ili otvorite"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Postavke privatnog prostora"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Zaključavanje/otključavanje privatnog prostora"</string>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 6825237..5d54f2e 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Aquesta parella d\'aplicacions no s\'admet en aquest dispositiu"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Desplega el dispositiu per utilitzar aquesta parella d\'aplicacions"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Fes doble toc i mantén premut per moure un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Fes doble toc i mantén premut per moure un widget o per utilitzar accions personalitzades."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d d\'amplada per %2$d d\'alçada"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d d\'amplada per %3$d d\'alçària"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén premut el widget per moure\'l per la pantalla d\'inici"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Afegeix a la pantalla d\'inici"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"El widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> s\'ha afegit a la pantalla d\'inici"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggeriments"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Els teus essencials per al dia a dia"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Notícies per a tu"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essencials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícies i revistes"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"La teva zona de relax"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Assoleix els teus objectius de fitnes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Que no et sorprengui el temps"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"També et pot agradar"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entreteniment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salut i fitnes"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Temps"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggeriments personalitzats"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la dreta, cerca i opcions a l\'esquerra"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# drecera}other{# dreceres}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Treball"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Converses"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Presa de notes"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Afegeix"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Afegeix el widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informació útil a l\'abast de la mà"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Per obtenir informació sense obrir les aplicacions, pots afegir widgets a la pantalla d\'inici"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toca per canviar la configuració del widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtra"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espai privat"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mantén les aplicacions privades bloquejades i amagades"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toca per configurar o obrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configuració d\'Espai privat"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloqueja o desbloqueja Espai privat"</string>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 27cd9e5..5d93636 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Tento pár aplikací není na tomto zařízení podporován"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Pokud chcete použít tento pár aplikací, rozložte zařízení"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Widget přesunete klepnutím a podržením."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a podržením přesunete widget, případně použijte vlastní akce."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"šířka %1$d, výška %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, šířka %2$d, výška %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pokud chcete widgetem pohybovat po ploše, podržte ho"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Přidat na plochu"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> byl přidán na plochu"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Vaše každodenní nezbytnosti"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Zprávy pro vás"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Nezbytnosti"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Zprávy a časopisy"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaše klidová zóna"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Dosažení kondičních cílů"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Mějte přehled o počasí"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Také by se vám mohlo líbit"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zábava"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociální sítě"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdraví a fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Počasí"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Návrhy pro vás"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgety <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vpravo, vyhledávání a možnosti vlevo"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ # widget}few{# widgety}many{# widgetu}other{# widgetů}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# zkratka}few{# zkratky}many{# zkratky}other{# zkratek}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Práce"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Konverzace"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Psaní poznámek"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Přidat"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Přidat widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Užitečné informace na dosah"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Pokud chcete mít informace k dispozici bez otevírání aplikací, můžete si na plochu přidat widgety"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Klepnutím změníte nastavení widgetu"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtr"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Selhalo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Soukromý prostor"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mějte soukromé aplikace uzamknuté a skryté"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Klepnutím nastavíte nebo otevřete"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Soukromé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Nastavení soukromého prostoru"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Zamknout/odemknout soukromý prostor"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 57053e6..3260fb5 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Denne appsammenknytning understøttes ikke på enheden"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Fold enheden ud for at bruge denne appsammenknytning"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Hold en widget nede for at flytte den."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryk to gange, og hold en widget nede for at flytte den eller bruge tilpassede handlinger."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i bredden og %2$d i højden"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widgetten <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-widget, %2$d i bredden og %3$d i højden"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Hold widgetten nede for at flytte den rundt på startskærmen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Føj til startskærm"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widgetten <xliff:g id="WIDGET_NAME">%1$s</xliff:g> blev føjet til startskærmen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Dine vigtige apps"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Nyheder til dig"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Vigtige ting"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Aviser og blade"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Dit afslapningshjørne"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Nå dine fitnessmål"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Vær på forkant med vejret"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Du kan måske også lide"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underholdning"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialt"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sundhed og fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vejr"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Forslag til dig"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-widgets til højre, søgning og valgmuligheder til venstre"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# genvej}one{# genvej}other{# genveje}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Arbejde"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Samtaler"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Notetagning"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Tilføj"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Tilføj <xliff:g id="WIDGET_NAME">%1$s</xliff:g>-widget"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Nyttige oplysninger lige ved hånden"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Hvis du vil have oplysninger uden at åbne apps, kan du føje widgets til din startskærm"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tryk for at ændre widgetindstillinger"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Mislykket: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privat område"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Hold private apps låste og skjulte"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tryk for at konfigurere eller åbne"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Indstillinger for privat rum"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lås/oplås det private område"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 8dcb567..78e20b6 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Dieses App-Paar wird auf diesem Gerät nicht unterstützt"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Gerät aufklappen, um dieses App-Paar zu verwenden"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Zum Verschieben des Widgets berühren und halten"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Doppeltippen und halten, um ein Widget zu bewegen oder benutzerdefinierte Aktionen zu nutzen."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breit und %2$d hoch"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“, %2$d breit und %3$d hoch"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Wenn du das Widget auf dem Startbildschirm verschieben möchtest, halte es gedrückt"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Zum Startbildschirm hinzufügen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-Widget zum Startbildschirm hinzugefügt"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Vorschläge"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Deine täglichen Essentials"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Neuigkeiten für dich"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Must-haves"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nachrichten und Zeitschriften"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zum Entspannen"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Erreiche deine Fitnessziele"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Dem Wetter einen Schritt voraus"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Das könnte dir auch gefallen"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Unterhaltung"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Soziale Netzwerke"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gesundheit und Fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Wetter"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Vorschläge für dich"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-Widgets rechts, Suche und Optionen links"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# Widget}other{# Widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# Verknüpfung}other{# Verknüpfungen}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Geschäftlich"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Unterhaltungen"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Notizen"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Hinzufügen"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Widget „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ hinzufügen"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Praktische Informationen – immer zur Hand"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Wenn du Informationen erhalten möchtest, ohne Apps zu öffnen, kannst du deinem Startbildschirm Widgets hinzufügen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tippen, um die Widget-Einstellungen zu ändern"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Fehler: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privates Profil"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Hier kannst du deine privaten Apps verbergen und sperren"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Zum Einrichten oder Öffnen tippen"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Einstellungen für privaten Bereich"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Privaten Bereich sperren/entsperren"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index d868040..f2d8a15 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Αυτό το ζεύγος εφαρμογών δεν υποστηρίζεται σε αυτή τη συσκευή"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Ξεδιπλώστε τη συσκευή για να χρησιμοποιήσετε αυτό το ζεύγος εφαρμογών"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Πατήστε παρατετ. για μετακίνηση γραφ. στοιχείου."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Πατήστε δύο φορές παρατεταμένα για μετακίνηση γραφικού στοιχείου ή χρήση προσαρμοσμένων ενεργειών."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Πλάτος %1$d επί ύψος %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Γραφικό στοιχείο <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Γραφικό στοιχείο <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d πλάτος επί %3$d ύψος"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Αγγίξτε παρατεταμένα το γραφικό στοιχείο για να το μετακινήσετε στην αρχική οθόνη"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Προσθήκη στην αρχική οθόνη"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Το γραφικό στοιχείο <xliff:g id="WIDGET_NAME">%1$s</xliff:g> προστέθηκε στην αρχική οθόνη."</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Προτάσεις"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Τα καθημερινά απαραίτητα"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Ειδήσεις για εσάς"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Απαραίτητα"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Ειδήσεις και περιοδικά"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ο δικός σας τρόπος χαλάρωσης"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Επιτύχετε τους στόχους που έχετε θέσει για τη φυσική σας κατάσταση"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Ετοιμαστείτε για κάθε καιρό"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Μπορεί να σας αρέσουν επίσης"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Ψυχαγωγία"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Κοινωνικά δίκτυα"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Υγεία και φυσική κατάσταση"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Καιρός"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Προτεινόμενα για εσάς"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Γραφικά στοιχεία <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> στα δεξιά, αναζήτηση και επιλογές στα αριστερά"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# γραφικό στοιχείο}other{# γραφικά στοιχεία}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# συντόμευση}other{# συντομεύσεις}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Εργασίας"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Συζητήσεις"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Δημιουργία σημειώσεων"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Προσθήκη"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Προσθήκη του γραφικού στοιχείου <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Χρήσιμες πληροφορίες στη διάθεσή σας"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Για να λάβετε πληροφορίες χωρίς να ανοίξετε εφαρμογές, μπορείτε να προσθέσετε γραφικά στοιχεία στην αρχική οθόνη."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Πατήστε για αλλαγή των ρυθμίσεων του γραφικού στοιχείου"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Φίλτρο"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Αποτυχία: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Ιδιωτικός χώρος"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Διατηρήστε τις ιδιωτικές εφαρμογές κλειδωμένες και κρυφές"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Πάτημα για ρύθμιση ή άνοιγμα"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Ιδιωτικό"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Ρυθμίσεις Ιδιωτικού χώρου"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Κλείδωμα/Ξεκλείδωμα Ιδιωτικού χώρου"</string>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index cee4d2a..7061889 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Unfold device to use this app pair"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget, %2$d wide by %3$d high"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch and hold the widget to move it around the home screen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Add to home screen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to home screen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Your daily essentials"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"News for you"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Reach your fitness goals"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Stay ahead of the weather"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"You might also like"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Add"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Add <xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Private space"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Keep private apps locked and hidden"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lock/Unlock Private Space"</string>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 87cd9eb..ec69ea8 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Unfold device to use this app pair"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"App pair isn\'t available"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap and hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget, %2$d wide by %3$d high"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch and hold the widget to move it around the home screen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Add to home screen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to home screen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Your Daily Essentials"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"News For You"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News &amp; magazines"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your Chill Zone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Reach Your Fitness Goals"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Stay Ahead of the Weather"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"You Might Also Like"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health &amp; fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Add"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Add <xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Private space"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Keep private apps locked and hidden"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lock/Unlock Private Space"</string>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index cee4d2a..7061889 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Unfold device to use this app pair"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget, %2$d wide by %3$d high"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch and hold the widget to move it around the home screen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Add to home screen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to home screen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Your daily essentials"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"News for you"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Reach your fitness goals"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Stay ahead of the weather"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"You might also like"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Add"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Add <xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Private space"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Keep private apps locked and hidden"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lock/Unlock Private Space"</string>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index cee4d2a..7061889 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"This app pair isn\'t supported on this device"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Unfold device to use this app pair"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Touch and hold to move a widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Double-tap &amp; hold to move a widget or use custom actions."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d wide by %2$d high"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget, %2$d wide by %3$d high"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Touch and hold the widget to move it around the home screen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Add to home screen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget added to home screen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Your daily essentials"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"News for you"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"News and magazines"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Your chill zone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Reach your fitness goals"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Stay ahead of the weather"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"You might also like"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Health and fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weather"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggested for you"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgets on right, search and options on left"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}other{# shortcuts}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Work"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Note-taking"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Add"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Add <xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Useful info at your fingertips"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"To get info without opening apps, you can add widgets to your home screen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tap to change widget settings"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Failed: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Private space"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Keep private apps locked and hidden"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tap to set up or open"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space Settings"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lock/Unlock Private Space"</string>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index ae84841..476ffda 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="APP1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ | ‎‏‎‎‏‏‎<xliff:g id="APP2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‎‎This app pair isn\'t supported on this device‎‏‎‎‏‎"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‏‏‎‏‎‎Unfold device to use this app pair‎‏‎‎‏‎"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎App pair isn\'t available‎‏‎‎‏‎"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎Touch &amp; hold to move a widget.‎‏‎‎‏‎"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎Double-tap &amp; hold to move a widget or use custom actions.‎‏‎‎‏‎"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎%1$d × %2$d‎‏‎‎‏‎"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎%1$d wide by %2$d high‎‏‎‎‏‎"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="WIDGET_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widget‎‏‎‎‏‎"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="WIDGET_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widget, %2$d wide by %3$d high‎‏‎‎‏‎"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎Touch &amp; hold the widget to move it around the home screen‎‏‎‎‏‎"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎Add to home screen‎‏‎‎‏‎"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="WIDGET_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widget added to home screen‎‏‎‎‏‎"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‎‎Suggestions‎‏‎‎‏‎"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎Your Daily Essentials‎‏‎‎‏‎"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎News For You‎‏‎‎‏‎"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎Essentials‎‏‎‎‏‎"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎News &amp; magazines‎‏‎‎‏‎"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‏‎Your Chill Zone‎‏‎‎‏‎"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‏‎Reach Your Fitness Goals‎‏‎‎‏‎"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎Stay Ahead of the Weather‎‏‎‎‏‎"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎You Might Also Like‎‏‎‎‏‎"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‎Entertainment‎‏‎‎‏‎"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‎Social‎‏‎‎‏‎"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‏‏‎‎‎Health &amp; fitness‎‏‎‎‏‎"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎Weather‎‏‎‎‏‎"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎Suggested for you‎‏‎‎‏‎"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widgets on right, search and options on left‎‏‎‎‏‎"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎# widget‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎# widgets‎‏‎‎‏‎}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎# shortcut‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎# shortcuts‎‏‎‎‏‎}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎Work‎‏‎‎‏‎"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎Conversations‎‏‎‎‏‎"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎Note-taking‎‏‎‎‏‎"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‎‏‏‎Add‎‏‎‎‏‎"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‎Add ‎‏‎‎‏‏‎<xliff:g id="WIDGET_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ widget‎‏‎‎‏‎"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‏‎Useful info at your fingertips‎‏‎‎‏‎"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎To get info without opening apps, you can add widgets to your home screen‎‏‎‎‏‎"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‎‏‎Tap to change widget settings‎‏‎‎‏‎"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‎‎‎‎‎Filter‎‏‎‎‏‎"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎Failed: ‎‏‎‎‏‏‎<xliff:g id="WHAT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="private_space_label" msgid="2359721649407947001">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎‎‏‎Private space‎‏‎‎‏‎"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎Keep private apps locked and hidden‎‏‎‎‏‎"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎Tap to set up or open‎‏‎‎‏‎"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‎Private‎‏‎‎‏‎"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‏‎Private Space Settings‎‏‎‎‏‎"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‎Lock/Unlock Private Space‎‏‎‎‏‎"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index dbb109b..012609e 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"No se admite esta vinculación de apps en este dispositivo"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Abre el dispositivo para usar esta vinculación de apps"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén presionado para mover un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Presiona dos veces y mantén presionado para mover un widget o usar acciones personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d de ancho por %3$d de alto"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén presionado el widget para moverlo por la pantalla principal"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Agregar a pantalla principal"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Se agregó el widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a la pantalla principal"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Tus esenciales diarios"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Noticias para ti"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Imprescindibles"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias y revistas"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona de descanso"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Logra tus objetivos de fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Mantente al tanto del clima"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Puede que también te guste"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimiento"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salud y bienestar"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Clima"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerencias para ti"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la derecha, búsqueda y opciones a la izquierda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# acceso directo}other{# accesos directos}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Tomar notas"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Agregar"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Agregar widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Información útil a tu alcance"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Para recibir información de apps sin abrirlas, puedes agregar widgets a la pantalla principal"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Presiona para cambiar la configuración del widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtro"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espacio privado"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mantén las apps privadas bloqueadas y ocultas"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Presiona para configurar o abrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configuración de Espacio privado"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloquear o desbloquear Espacio privado"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index a9be411..0b0cb41 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"El dispositivo no admite esta aplicación emparejada"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Despliega el dispositivo para usar esta aplicación emparejada"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén pulsado un widget para moverlo"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dos veces y mantén pulsado un widget para moverlo o usar acciones personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de ancho por %2$d de alto"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget de <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d de ancho por %3$d de alto"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén pulsado el widget para moverlo por la pantalla de inicio"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Añadir a pantalla de inicio"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> añadido a la pantalla de inicio"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugerencias"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Lo esencial para el día a día"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Noticias para ti"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Imprescindibles"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias y revistas"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Tu zona de descanso"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Logra tus objetivos de actividad física"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Infórmate sobre el tiempo"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"También te puede interesar"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimiento"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salud y actividad física"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"El tiempo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerencias para ti"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a la derecha, búsqueda y opciones a la izquierda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# acceso directo}other{# accesos directos}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabajo"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversaciones"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Toma de notas"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Añadir"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Añadir widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Información útil al alcance de la mano"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Para ver información sin abrir una aplicación, puedes añadir widgets a la pantalla de inicio"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toca para cambiar los ajustes del widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtro"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Se ha producido un error: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espacio privado"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Bloquea y oculta tus aplicaciones privadas"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toca para configurarlo o abrirlo"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Ajustes del espacio privado"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloquear/Desbloquear espacio privado"</string>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 830abf0..212b672 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"See rakendusepaar ei ole selles seadmes toetatud"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Selle rakendusepaari kasutamiseks voltige seade lahti"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidina teisaldamiseks puudutage ja hoidke all."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Vidina teisaldamiseks või kohandatud toimingute kasutamiseks topeltpuudutage ja hoidke all."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <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_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>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Kasulikud vidinad"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Uudised teile"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Alustalad"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Uudised ja ajakirjad"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Teie lõõgastumiskoht"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Saavutage oma treeningueesmärgid"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Olge ilmateatega kursis"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Teile võivad meeldida ka need"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Meelelahutus"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Suhtlus"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Tervis ja vormisolek"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ilm"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Teile soovitatud"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Teenuse <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidinad paremal, otsing ja valikud vasakul"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# vidin}other{# vidinat}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# otsetee}other{# otseteed}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Töö"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Vestlused"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Märkmete tegemine"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Lisa"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Lisa vidin <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Kasulik teave on teie käeulatuses"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Teabe saamiseks rakendusi avamata võite oma avakuvale lisada vidinaid"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Puudutage vidina seadete muutmiseks"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Nurjus: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privaatne ruum"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Hoidke privaatsed rakendused lukustatud ja peidetuna"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Seadistamiseks või avamiseks puudutage"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privaatne"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privaatse ruumi seaded"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Privaatse ruumi lukustamine/avamine"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 16ee5d7..8ffbea6 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Aplikazio pare hori ez da onartzen gailu honetan"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Zabaldu gailua aplikazio pare hau erabiltzeko"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Eduki sakatuta widget bat mugitzeko."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Sakatu birritan eta eduki sakatuta widget bat mugitzeko edo ekintza pertsonalizatuak erabiltzeko."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d zabal eta %2$d luze"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta, %2$d zabal eta %3$d altu"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Widgeta orri nagusian zehar mugitzeko, eduki ezazu sakatuta"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Gehitu orri nagusian"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta orri nagusian gehitu da"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iradokizunak"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Eguneroko funtsezkoak"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Zuretzako albisteak"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Oinarrizkoak"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Albisteak eta aldizkariak"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Lasaitzeko gunea"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Erdietsi zure fitness-helburuak"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Hartu aurrea eguraldiari"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Gustatuko zaizkizulakoan"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Aisia"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sare sozialak"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Osasuna eta ongizatea"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Eguraldia"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Zuri iradokiak"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> zerbitzuaren widgetak eskuinean, bilaketa eta aukerak ezkerrean"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# lasterbide}other{# lasterbide}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Lanekoak"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Elkarrizketak"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Oharrak idazteko"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Gehitu"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Gehitu <xliff:g id="WIDGET_NAME">%1$s</xliff:g> widgeta"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informazio erabilgarria beti eskura"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Aplikaziorik ireki beharrik gabe informazioa zuzenean jasotzeko, gehitu widgetak orri nagusian"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Sakatu hau widgeten ezarpenak aldatzeko"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Iragazi"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Huts egin du: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Eremu pribatua"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mantendu aplikazio pribatuak blokeatuta eta ezkutatuta"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Sakatu konfiguratzeko edo irekitzeko"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Pribatua"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Eremu pribatuaren ezarpenak"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Blokeatu/Desblokeatu eremu pribatua"</string>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index feaf724..848ebee 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"از این جفت برنامه در این دستگاه پشتیبانی نمی‌شود"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"برای استفاده از این جفت برنامه، دستگاه را باز کنید"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"جفت برنامه دردسترس نیست"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"برای جابه‌جا کردن ابزارک، لمس کنید و نگه دارید."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"برای جابه‌جا کردن ابزارک یا استفاده از کنش‌های سفارشی، دوضربه بزنید و نگه دارید."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏%1$d عرض در %2$d طول"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ابزارک <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"‏ابزارک <xliff:g id="WIDGET_NAME">%1$s</xliff:g>، %2$d عرض در %3$d ارتفاع"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ابزارک را لمس کنید و نگه دارید تا بتوانید آن را در صفحه اصلی حرکت دهید"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"افزودن به صفحه اصلی"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"ابزارک <xliff:g id="WIDGET_NAME">%1$s</xliff:g> به صفحه اصلی اضافه شد"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"پیشنهادها"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ملزومات روزانه"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"اخبار برای شما"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ضروریات"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"اخبار و مجله"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"منطقه آرامش شما"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"دستیابی به اهداف تناسب اندام"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"آب‌وهوا را پیش‌بینی کنید"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"شاید این را هم بپسندید"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"سرگرمی"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"اجتماعی"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"سلامتی و تناسب اندام"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"آب‌وهوا"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"پیشنهادشده برای شما"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ابزارک‌های <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> در سمت چپ، جستجو و گزینه‌ها در سمت راست"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{‏# ابزارک}one{‏# ابزارک}other{‏# ابزارک}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{‏# میان‌بر}one{‏# میان‌بر}other{‏# میان‌بر}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"کار"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"مکالمه‌ها"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"یادداشت‌برداری"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"افزودن"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"افزودن ابزارک <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"دسترسی آسان به اطلاعات سودمند"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"با افزودن ابزارک‌ها به صفحه اصلی می‌توانید اطلاعات را بدون باز کردن برنامه‌ها دریافت کنید"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"برای تغییر تنظیمات ابزارک، ضربه بزنید"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"فیلتر"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ناموفق بود: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"فضای خصوصی"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"برنامه‌های خصوصی قفل و پنهان نگه داشته می‌شود"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"برای راه‌اندازی یا باز کردن، ضربه بزنید"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"خصوصی"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"تنظیمات «فضای خصوصی»"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"قفل/ باز کردن «فضای خصوصی»"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 3198a03..e55c32f 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Sovellusparia ei tueta tällä laitteella"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Avaa taitettu laite, niin voit käyttää sovellusparia"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Kosketa pitkään, niin voit siirtää widgetiä."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Kaksoisnapauta ja paina pitkään, niin voit siirtää widgetiä tai käyttää muokattuja toimintoja."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Leveys: %1$d, korkeus: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, leveys %2$d ja korkeus %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Voit siirtää widgetiä aloitusnäytöllä koskettamalla sitä pitkään"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Lisää aloitusnäytölle"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget lisätty aloitusnäytölle: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ehdotukset"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Tärkeät asiat päivään"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Uutisia sinulle"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Kaikki tarvittava"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Uutiset ja aikakauslehdet"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ota rennosti"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Saavuta kuntoilutavoitteet"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Pysy ajan tasalla säästä"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Saatat pitää myös näistä"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Viihde"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Some"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Terveys ja kuntoilu"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Sää"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sinulle ehdotetut"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widgetit oikealla, haku ja vaihtoehdot vasemmalla"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetiä}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# pikakuvake}other{# pikakuvaketta}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Työ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Keskustelut"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Muistiinpanojen tekeminen"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Lisää"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Lisää widget: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Hyödyllisiä tietoja käden ulottuvilla"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Jos haluat nähdä tietoja avaamatta sovelluksia, voit lisätä aloitusnäytölle widgetejä"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Napauta, niin voit muuttaa widgetin asetuksia"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Suodatin"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Epäonnistui: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Yksityinen tila"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Pidä yksityiset sovellukset lukittuna ja piilossa"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Ota käyttöön tai avaa napauttamalla"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Yksityinen"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Yksityisen tilan asetukset"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lukitse yksityinen tila / avaa sen lukitus"</string>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 4d7c443..7578aea 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Cette paire d\'applications n\'est pas prise en charge sur cet appareil"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Déplier l\'appareil pour utiliser cette paire d\'applications"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Maintenez le doigt sur un widget pour le déplacer."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Touchez 2x un widget et maintenez le doigt dessus pour le déplacer ou utiliser des actions personnalisées."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur sur %2$d de hauteur"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d de largeur sur %3$d de hauteur"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Maintenez le doigt sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Ajouter à l\'écran d\'accueil"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Le widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a été ajouté à l\'écran d\'accueil"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Vos indispensables au quotidien"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Actualités personnalisées"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentiels"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Actualités et magazines"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zone de divertissement"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Objectifs de mise en forme"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"À l\'affût de la météo"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Autres recommandations"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertissement"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Médias sociaux"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Santé et mise en forme"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Météo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suggestions personnalisées"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à droite, recherche et options à gauche"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# raccourci}one{# raccourci}other{# raccourcis}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Professionnels"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Prise de note"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Ajouter"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Ajoutez le widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Renseignements utiles à portée de main"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Pour obtenir des informations sans ouvrir d\'applications, vous pouvez ajouter des widgets à votre écran d\'accueil"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Touchez pour modifier les paramètres du widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrer"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espace privé"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Verrouiller et cacher les applications privées"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toucher pour configurer ou ouvrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Paramètres de l\'Espace privé"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Verrouiller/Déverrouiller l\'Espace privé"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f680305..435d3d3 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Cette paire d\'applications n\'est pas prise en charge sur cet appareil"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Dépliez l\'appareil pour utiliser cette paire d\'applications"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Appuyez de manière prolongée sur un widget pour le déplacer."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Appuyez deux fois et maintenez la pression pour déplacer widget ou utiliser actions personnalisées."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largeur et %2$d de hauteur"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d de large par %3$d de haut"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Appuyez de manière prolongée sur le widget pour le déplacer sur l\'écran d\'accueil"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Ajouter à l\'écran d\'accueil"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ajouté à l\'écran d\'accueil"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggestions"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Vos indispensables du jour"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Actualités personnalisées"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Les bases"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Actualités et magazines"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Votre espace détente"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Atteignez vos objectifs forme"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Soyez au fait de la météo"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Découvrez également"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertissement"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Réseaux sociaux"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Santé et bien-être"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Météo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Recommandations"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à droite, recherche et options à gauche"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# raccourci}one{# raccourci}other{# raccourcis}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Professionnels"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversations"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Prise de notes"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Ajouter"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Ajoutez un widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Infos utiles à portée de main"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Pour obtenir des infos sans ouvrir d\'applis, vous pouvez ajouter des widgets à votre écran d\'accueil"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Appuyez pour modifier les paramètres du widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtre"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Échec : <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espace privé"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Gardez les applications privées verrouillées et masquées."</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Appuyer pour ouvrir ou configurer"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Paramètres d\'Espace privé"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Verrouiller/Déverrouiller Espace privé"</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 2339265..180a786 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"O dispositivo non admite este emparellamento de aplicacións"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Desprega o dispositivo para usar este emparellamento de aplicacións"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén premido un widget para movelo."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largo por %2$d de alto"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>: %2$d de largo por %3$d de alto"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Mantén premido o widget para movelo pola pantalla de inicio"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Engadir á pantalla de inicio"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Engadiuse o widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> á pantalla de inicio"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suxestións"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Indispensables para o día a día"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Novidades para ti"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Esenciais"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noticias e revistas"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Reláxate"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Acada os teus obxectivos para estar en forma"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Adiántate á meteoroloxía"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Tamén che pode interesar…"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretemento"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociais"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e forma física"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"O tempo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Suxestións personalizadas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> á dereita, busca e opcións á esquerda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# atallo}other{# atallos}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Widgets do traballo"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Toma de notas"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Engadir"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Engadir o widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Información útil ao teu alcance"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Se queres obter información sen abrir as aplicacións, podes engadir widgets á pantalla de inicio"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toca para cambiar a configuración do widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtra"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Erro: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espazo privado"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Manter bloqueadas e ocultas as aplicacións privadas"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toca para configuralo ou abrilo"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configuración do espazo privado"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloquear ou desbloquear o espazo privado"</string>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index ec6d994..931c38a 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"આ ડિવાઇસ પર, આ ઍપની જોડીને સપોર્ટ આપવામાં આવતો નથી"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"આ ઍપની જોડીનો ઉપયોગ કરવા માટે, ડિવાઇસને અનફોલ્ડ કરો"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"ઍપની જોડી ઉપલબ્ધ નથી"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"વિજેટ ખસેડવા ટચ કરીને થોડી વાર દબાવી રાખો."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"વિજેટ ખસેડવા બે વાર ટૅપ કરીને દબાવી રાખો અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરો."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d પહોળાઈ X %2$d ઊંચાઈ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ, %2$d પહોળું x %3$d ઊંચું"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"વિજેટને હોમ સ્ક્રીનની આજુબાજુ ખસેડવા માટે, તેને ટચ કરીને થોડીવાર દબાવી રાખો"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"હોમ સ્ક્રીનમાં ઉમેરો"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"હોમ સ્ક્રીન પર <xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ ઉમેર્યુ"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"સૂચનો"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"તમારી દૈનિક આવશ્યકતાઓ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"તમારા માટે સમાચાર"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"આવશ્યક"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ન્યૂઝ અને સામાયિકો"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"તમારો આરામદાયક ઝોન"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"તમારા ફિટનેસ લક્ષ્યો પૂરા કરો"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"હવામાન વિશે અપ ટૂ ડેટ રહો"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"કદાચ તમને આ પણ પસંદ હોય"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"મનોરંજન"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"સામાજિક"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"આરોગ્ય અને ફિટનેસ"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"હવામાન"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"તમારા માટે સૂચવેલી સેવાઓ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>ની વિજેટ જમણે, શોધ અને વિકલ્પો ડાબે"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# વિજેટ}one{# વિજેટ}other{# વિજેટ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# શૉર્ટકટ}one{# શૉર્ટકટ}other{# શૉર્ટકટ}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ઑફિસ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"વાતચીતો"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"નોંધ લેવી"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ઉમેરો"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> વિજેટ ઉમેરો"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ઉપયોગી માહિતી તમારી આંગળીના ટેરવે"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ઍપને ખોલ્યા વિના માહિતી મેળવવા માટે, તમે તમારી હોમ સ્ક્રીનમાં વિજેટ ઉમેરી શકો છો"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"વિજેટના સેટિંગ બદલવા માટે ટૅપ કરો"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ફિલ્ટર કરો"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"નિષ્ફળ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ખાનગી સ્પેસ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ખાનગી ઍપને લૉક કરેલી અને છુપાવેલી રાખો"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"સેટઅપ કરવા કે ખોલવા માટે ટૅપ કરો"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ખાનગી"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ખાનગી સ્પેસના સેટિંગ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ખાનગી સ્પેસને લૉક/અનલૉક કરો"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 8636ed1..6d83820 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन, इस डिवाइस पर काम नहीं कर सकते"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"साथ में इस्तेमाल किए जा सकने वाले ये ऐप्लिकेशन इस्तेमाल करने के लिए डिवाइस को अनफ़ोल्ड करें"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"साथ में इस्तेमाल किए जा सकने वाले ऐप्लिकेशन की सुविधा उपलब्ध नहीं है"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उसे दबाकर रखें."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"किसी विजेट को एक से दूसरी जगह ले जाने के लिए, उस पर दो बार टैप करके दबाकर रखें या पसंद के मुताबिक कार्रवाइयां इस्तेमाल करें."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d चौड़ाई गुणा %2$d ऊंचाई"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट. यह %2$d चौड़ा और %3$d लंबा है"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"विजेट को होम स्क्रीन पर इधर-उधर ले जाने के लिए, उसे दबाकर रखें"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"होम स्क्रीन पर जोड़ें"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट को होम स्क्रीन पर जोड़ा गया"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझाव"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"रोज़ाना इस्तेमाल होने वाले ज़रूरी ऐप्लिकेशन"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"आपके लिए खबरें"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ज़रूरी ऐप्लिकेशन"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"खबरों और पत्रिकाओं वाले ऐप्लिकेशन"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"आपके मनोरंजन के लिए"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"फ़िटनेस के लक्ष्य हासिल करें"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"मौसम की अप-टू-डेट जानकारी पाएं"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"शायद आपको ये भी पसंद आएं"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरंजन वाले ऐप्लिकेशन"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोशल"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"हेल्थ और फ़िटनेस वाले ऐप्लिकेशन"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"मौसम"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"आपके लिए सुझाए गए ऐप्लिकेशन"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> के विजेट दाईं ओर, खोज का विजेट और अन्य विकल्प बाईं ओर"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}one{# विजेट}other{# विजेट}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# शॉर्टकट}one{# शॉर्टकट}other{# शॉर्टकट}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"वर्क विजेट"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"बातचीत"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"नोट बनाने से जुड़े विजेट"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"जोड़ें"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट जोड़ें"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"काम की जानकारी आसानी से पाएं"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ऐप्लिकेशन को खोले बिना उनकी जानकारी पाने के लिए, होम स्क्रीन पर विजेट जोड़े जा सकते हैं"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"विजेट की सेटिंग में बदलाव करने के लिए टैप करें"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"फ़िल्टर"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"पूरा नहीं हुआ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"प्राइवेट स्पेस"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"निजी ऐप्लिकेशन को लॉक करके और छिपाकर रखें"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"सेट अप करने या खोलने के लिए टैप करें"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"निजी"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"प्राइवेट स्पेस सेटिंग"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"प्राइवेट स्पेस को लॉक करें/अनलॉक करें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 9db31ac..e860ea9 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Taj par aplikacija nije podržan na ovom uređaju"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Otvorite uređaj da biste upotrebljavali ovaj par aplikacija"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacija nije dostupan"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dodirnite i zadržite da biste premjestili widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvaput dodirnite i zadržite pritisak da biste premjestili widget ili upotrijebite prilagođene radnje"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d širine i %2$d visine"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, širine %2$d, visine %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dodirnite i zadržite widget da biste ga pomicali po početnom zaslonu"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na početni zaslon"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> dodan je na početni zaslon"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Prijedlozi"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Vaše dnevne potrepštine"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Vijesti za vas"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Osnovno"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Vijesti i časopisi"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša zona za opuštanje"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Postignite svoje ciljeve u fitnesu"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Budite korak ispred vremenskih prilika"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Možda će vam se svidjeti i ovo"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zabava"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Društvene mreže"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravlje i fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vrijeme"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Prijedlozi za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> –widgeti zdesna, pretraživanje i opcije slijeva"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}few{# widgeta}other{# widgeta}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# prečac}one{# prečac}few{# prečaca}other{# prečaca}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Posao"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Razgovori"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pisanje bilježaka"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodaj"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Dodaj widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Korisne informacije nadohvat ruke"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Da biste dobili informacije bez otvaranja aplikacija, možete dodati widgete na početni zaslon"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dodirnite da biste promijenili postavke widgeta"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrirajte"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Nije uspjelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privatni prostor"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Neka privatne aplikacije ostanu zaključane i skrivene"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Dodirnite da biste postavili ili otvorili"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Postavke privatnog prostora"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Zaključavanje/otključavanje privatnog prostora"</string>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index db8f961..69031fe 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ezt az alkalmazáspárt nem támogatja az eszköz"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Hajtsa ki az eszközt az alkalmazáspár használatához"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tartsa lenyomva a modult az áthelyezéshez."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Modul áthelyezéséhez koppintson duplán, tartsa nyomva az ujját, vagy használjon egyéni műveleteket."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d széles és %2$d magas"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul – %2$d széles, %3$d magas"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tartsa lenyomva a modult a kezdőképernyőn való mozgatáshoz"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Hozzáadás a kezdőképernyőhöz"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul hozzáadva a kezdőképernyőhöz"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Javaslatok"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Legfontosabb napi dolgok"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Hírek Önnek"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Kihagyhatatlanok"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Hírlapok és folyóiratok"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Az Ön relaxáló zónája"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Elérheti kitűzött erőnléti céljait"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Mindig friss időjárás-információk"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Lehet, hogy ez is tetszeni fog"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Szórakozás"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Közösségi"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Egészség és fitnesz"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Időjárás"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Neked javasolt"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"A <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-modulok a jobb, a kereső és a beállítások pedig a bal oldalon találhatók"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# modul}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# gyorsparancs}other{# gyorsparancs}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Munka"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Beszélgetések"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Jegyzetelés"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Hozzáadás"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> modul hozzáadása"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Hasznos információk egy koppintásnyira"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Ha az alkalmazások megnyitása nélkül szeretne információhoz jutni, felvehet modulokat a kezdőképernyőre"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ide koppintva módosíthatja a modulbeállításokat"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Szűrő"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Sikertelen: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privát terület"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Privát alkalmazások zárolásának és rejtve tartásának fenntartása"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Koppintson a beállításhoz vagy a megnyitáshoz"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privát"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privát terület beállításai"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Privát terület zárolása/zárolásának feloldása"</string>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 71b9ce5..8d78f1c 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Հավելվածների զույգը չի աջակցվում այս սարքում"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Բացեք սարքը՝ այս հավելվածների զույգն օգտագործելու համար"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Հպեք և պահեք՝ վիջեթ տեղափոխելու համար։"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Կրկնակի հպեք և պահեք՝ վիջեթ տեղափոխելու համար, կամ օգտվեք հատուկ գործողություններից։"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Լայնությունը՝ %1$d, բարձրությունը՝ %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> վիջեթ"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> վիջեթ, լայնությունը՝ %2$d, բարձրությունը՝ %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Հպեք վիջեթին և պահեք՝ հիմնական էկրան տեղափոխելու համար"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Ավելացնել հիմնական էկրանին"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> վիջեթն ավելացվել է հիմնական էկրանին"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Առաջարկներ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Ամենաանհրաժեշտը յուրաքանչյուր օրվա համար"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Նորություններ ձեզ համար"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Հիմնական"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Նորություններ և ամսագրեր"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ձեր հանգստի գոտին"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Հասեք ձեր ֆիթնես նպատակներին"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Եղեք տեղեկացված եղանակի մասին"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Ձեզ կարող է դուր գալ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Զվարճանք"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Սոցցանցեր"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Առողջություն և ֆիթնես"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Եղանակ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Առաջարկում ենք"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"«<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>» հավելվածի վիջեթներն աջ կողմում են, իսկ որոնման դաշտը և կարգավորումները՝ ձախ կողմում"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# վիջեթ}one{# վիջեթ}other{# վիջեթ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# դյուրանցում}one{# դյուրանցում}other{# դյուրանցում}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Աշխատանքային"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Զրույցներ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Նշումների ստեղծում"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Ավելացնել"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Ավելացնել <xliff:g id="WIDGET_NAME">%1$s</xliff:g> վիջեթը"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Բոլոր կարևոր տեղեկությունները՝ ձեռքի տակ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Ավելացրեք վիջեթներ ձեր հիմնական էկրանին, որպեսզի տեղեկություններ ստանաք՝ առանց հավելվածները բացելու։"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Հպեք՝ վիջեթի կարգավորումները փոփոխելու համար"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Զտեք"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Չհաջողվեց կատարել գործողությունը (<xliff:g id="WHAT">%1$s</xliff:g>)"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Անձնական տարածք"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Անձնական հավելվածները պահեք կողպված և թաքցված"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Հպեք կարգավորելու կամ բացելու համար"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Մասնավոր"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Անձնական տարածքի կարգավորումներ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Կողպել/ապակողպել մասնավոր տարածքը"</string>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 0fdae96..092995c 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Pasangan aplikasi ini tidak didukung di perangkat ini"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Bentangkan perangkat untuk menggunakan pasangan aplikasi ini"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Pasangan aplikasi tidak tersedia"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Sentuh lama untuk memindahkan widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketuk dua kali &amp; tahan untuk memindahkan widget atau gunakan tindakan khusus."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"lebar %1$d x tinggi %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, lebar %2$d dan tinggi %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Sentuh lama widget untuk memindah-mindahkannya di layar utama"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Tambahkan ke layar utama"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan ke layar utama"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Saran"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Kebutuhan Harian Anda"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Berita untuk Anda"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Wajib Coba"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Berita &amp; majalah"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona Nyaman Anda"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Capai Target Kebugaran Anda"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Tetap Waspada Menghadapi Cuaca"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Anda Mungkin Juga Suka"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hiburan"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kesehatan &amp; kebugaran"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Cuaca"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Saran untuk Anda"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> di bagian kanan, penelusuran dan opsi di bagian kiri"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# pintasan}other{# pintasan}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Kerja"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Percakapan"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pembuatan catatan"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Tambahkan"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Tambahkan widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Info bermanfaat mudah dilihat"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Untuk mendapatkan info tanpa membuka aplikasi, Anda dapat menambahkan widget ke layar utama"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ketuk untuk mengubah setelan widget"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Ruang pribadi"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Kunci dan sembunyikan aplikasi pribadi"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Ketuk untuk menyiapkan atau membuka"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Pribadi"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Setelan Ruang Pribadi"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Kunci/Buka Kunci Ruang Pribadi"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 51c2e52..73a7d64 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Þetta forritapar er ekki stutt í þessu tæki"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Opnaðu tæki til að nota þetta forritapar"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Forritapar er ekki í boði"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Haltu fingri á græju til að færa hana."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ýttu tvisvar og haltu fingri á græju til að færa hana eða notaðu sérsniðnar aðgerðir."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d á breidd og %2$d á hæð"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Græjan <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Græjan <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d breið og %3$d há"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Haltu fingri á græjunni til að hreyfa hana um heimaskjáinn"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Bæta á heimaskjá"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> græju bætt við heimaskjá"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Tillögur"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Daglegar nauðsynjar"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Fréttir fyrir þig"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Það nauðsynlegasta"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Fréttir og tímarit"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Slakaðu á"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Náðu hreyfingarmarkmiðunum þínum"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Vertu einu skrefi á undan veðrinu"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Þú gætir einnig haft áhuga á"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Afþreying"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Samfélag"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Heilsa og líkamsrækt"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Veður"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Tillögur fyrir þig"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-græjur til hægri, leit og valkostir til vinstri"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# græja}one{# græja}other{# græjur}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# flýtileið}one{# flýtileið}other{# flýtileiðir}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Vinna"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Samtöl"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Glósugerð"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Bæta við"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Bæta græjunni <xliff:g id="WIDGET_NAME">%1$s</xliff:g> við"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Gagnlegar upplýsingar innan seilingar"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Þú getur bætt við græjum á heimaskjáinn til að fá upplýsingar án þess að opna forrit"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ýttu til að breyta græjustillingum"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Sía"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Mistókst: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Einkarými"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Haltu einkaforritum læstum og földum"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Ýttu til að setja upp eða opna"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Lokað"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Stillingar einkarýmis"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Læsa leynirými/taka leynirými úr lás"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 0c76ba9..8cffb25 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Questa coppia di app non è supportata su questo dispositivo"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Apri il dispositivo per usare questa coppia di app"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tocca e tieni premuto per spostare un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tocca due volte e tieni premuto per spostare un widget o per usare le azioni personalizzate."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d di larghezza per %2$d di altezza"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d di larghezza per %3$d di altezza"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tocca e tieni premuto il widget per spostarlo nella schermata Home"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Aggiungi alla schermata Home"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> aggiunto alla schermata Home"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggerimenti"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"L\'essenziale ogni giorno"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Notizie per te"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenziali"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notizie e riviste"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Il tuo angolo di tranquillità"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Raggiungi i tuoi obiettivi di fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Non perderti le previsioni meteo"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Ti potrebbero anche piacere"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Intrattenimento"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salute e fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Consigliati per te"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget di <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> a destra, ricerca e opzioni a sinistra"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# scorciatoia}other{# scorciatoie}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Lavoro"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversazioni"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Aggiunta di note"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Aggiungi"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Aggiungi widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informazioni utili a portata di mano"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Per ricevere informazioni senza aprire le app, puoi aggiungere dei widget alla schermata Home"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tocca per modificare le impostazioni del widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtra"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Operazione non riuscita: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Spazio privato"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mantieni le app private bloccate e nascoste"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tocca per configurare o aprire"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privato"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Impostazioni dello Spazio privato"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Blocca/sblocca Spazio privato"</string>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 461a25e..0d67af5 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"צמד האפליקציות הזה לא נתמך במכשיר הזה"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"צריך לפתוח את המכשיר כדי להשתמש בצמד האפליקציות הזה"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"להעברת ווידג\'ט למקום אחר לוחצים עליו לחיצה ארוכה."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"כדי להעביר ווידג\'ט למקום אחר או להשתמש בפעולות מותאמות אישית, יש ללחוץ פעמיים ולא להרפות."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏רוחב %1$d על גובה %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"‏ווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, רוחב: %2$d, אורך: %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"לוחצים לחיצה ארוכה על הווידג\'ט כדי להזיז אותו במסך הבית"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"הוספה למסך הבית"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"הווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g> נוסף למסך הבית"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"הצעות"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"הפריטים היומיומיים שלך"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"חדשות בשבילך"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"האפליקציות שחייבים להכיר"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"חדשות וכתבי עת"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"המקום שלך לרגיעה"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"השגת יעדי הכושר שלך"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"התעדכנות במזג האוויר"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"אולי יעניין אותך גם"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"בידור"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"רשתות חברתיות"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"בריאות וכושר"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"מזג אוויר"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"הצעות בשבילך"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"‫<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ווידג\'טים מימין, חיפוש ואפשרויות משמאל"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ווידג\'ט אחד}one{# ווידג\'טים}two{# ווידג\'טים}other{# ווידג\'טים}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{קיצור דרך אחד}one{# קיצורי דרך}two{# קיצורי דרך}other{# קיצורי דרך}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"עבודה"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"שיחות"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"כתיבת הערות"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"הוספה"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"הוספת הווידג\'ט <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"קבלת מידע שימושי בהקשה"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"רוצה לקבל מידע בלי לפתוח אפליקציות? אפשר להוסיף ווידג\'טים למסך הבית"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"אפשר לשנות את הגדרות הווידג\'ט בהקשה"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"סינון"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"הפעולה נכשלה: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"מרחב פרטי"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"נעילה והסתרה של אפליקציות פרטיות"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"אפשר להקיש כדי להגדיר או לפתוח"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"פרטי"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"הגדרות המרחב הפרטי"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"נעילה או ביטול הנעילה של המרחב הפרטי"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 5b3e221..50f5ddf 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"このデバイスは、このアプリのペア設定に対応していません"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"このアプリのペア設定を使用するには、デバイスを開いてください"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"長押ししてウィジェットを移動させます。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ウィジェットをダブルタップして長押ししながら移動するか、カスタム操作を使用してください。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$dx%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"幅 %1$d、高さ %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ウィジェット"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>ウィジェット、幅%2$d、高さ%3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ウィジェットを押し続けると、ホーム画面上に移動できます"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ホーム画面に追加"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」ウィジェットをホーム画面に追加しました"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"候補"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"生活必需品"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"あなたへのおすすめニュース"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"基本"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ニュース&雑誌"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"休憩エリア"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"フィットネスの目標を達成"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"天気予報"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"あなたへのおすすめ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"エンタメ"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ソーシャル"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康&フィットネス"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天気"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"おすすめ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> のウィジェットは右側に、検索とオプションは左側にあります"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 件のウィジェット}other{# 件のウィジェット}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 件のショートカット}other{# 件のショートカット}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"仕事用"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"会話"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"メモ"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"追加"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>ウィジェットを追加"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ウィジェットで情報を得る"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ホーム画面にウィジェットを追加すると、アプリを開かずに情報を入手できます"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"タップしてウィジェットの設定を変更する"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"フィルタ"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"失敗: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"プライベート スペース"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"プライベート アプリをロック / 非表示状態に保つ"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"設定したり開いたりするにはタップしてください"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"プライベート"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"プライベート スペースの設定"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"プライベート スペースをロック / ロック解除する"</string>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index ae3b1e6..a3c3d87 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ამ მოწყობილობაზე აღნიშნული აპთა წყვილი არ არის მხარდაჭერილი"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"გაშალეთ მოწყობილობა ამ აპთა წყვილის გამოსაყენებლად"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ორმაგი შეხებით აირჩიეთ და გეჭიროთ ვიჯეტის გადასაადგილებლად ან მორგებული მოქმედებების გამოსაყენებლად."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"სიგრძე: %1$d, სიგანე: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტი"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტი, სიგანე: %2$d, სიმაღლე: %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ხანგრძლივად შეეხეთ ვიჯეტს მთავარ ეკრანზე მის გადასაადგილებლად"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"მთავარ ეკრანზე დამატება"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტი დამატებულია მთავარ ეკრანზე"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"შეთავაზებები"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"თქვენი ყოველდღიური საჭირო აპები"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"News თქვენთვის"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"უმნიშვნელოვანესები"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ახალი ამბები და ჟურნალები"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"განტვირთვის ადგილი"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"მიაღწიეთ ფიტნეს-მიზნებს"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"მიიღეთ ინფორმაცია წინასწარ ამინდის შესახებ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ასევე შეიძლება მოგეწონოთ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"გართობა"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"სოციალური"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ჯანმრთელობა და ფიტნესი"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ამინდი"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"თქვენთვის შემოთავაზებული"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ვიჯეტები მდებარეობს მარჯვნივ, ძებნა და პარამეტრები — მარცხნივ"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ვიჯეტი}other{# ვიჯეტი}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# მალსახმობი}other{# მალსახმობი}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"სამსახური"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"მიმოწერები"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"ჩანიშვნა"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"დამატება"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ვიჯეტის დამატება"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ადვილად მისაწვდომი სასარგებლო ინფორმაცია"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"იმისთვის, რომ ინფორმაცია აპების გაუხსნელად მიიღოთ, შეგიძლიათ, მთავარ ეკრანზე ვიჯეტები დაამატოთ"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"შეეხეთ ვიჯეტის პარამეტრების შესაცვლელად"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ფილტრი"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ვერ მოხერხდა: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"პირადი სივრცე"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"პირადი აპების ჩაკეტვა და დამალვა"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"დასაყენებლად ან გასახსნელად შეეხეთ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"პირადი"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"პირადი სივრცის პარამეტრები"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"პირადი სივრცის ჩაკეტვა/განბლოკვა"</string>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 7038483..ff030e8 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Бұл құрылғы қолданбаларды жұптау функциясын қолдамайды."</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Қолданбаларды жұптау функциясын пайдалану үшін құрылғыны ашыңыз."</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетті жылжыту үшін басып тұрыңыз."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетті жылжыту үшін екі рет түртіңіз де, ұстап тұрыңыз немесе арнаулы әрекеттерді пайдаланыңыз."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ені: %1$d, биіктігі: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджеті"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Виджет: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>. Ені %2$d, биіктігі %3$d."</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Негізгі экран бойынша жылжыту үшін виджетті басып ұстаңыз."</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Негізгі экранға қосу"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджеті негізгі экранға енгізілді."</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ұсыныстар"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Күнделікті маңызды виджеттеріңіз"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Сізге арналған жаңалықтар"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Ең қажетті"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Газеттер мен журналдар"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Жанға жайлы жер"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Денені шынықтыру бойынша қойған мақсаттарыңызға жетіңіз"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Ауа райын алдын ала біліп отырыңыз"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Сізге мыналар да ұнауы мүмкін"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Ойын-сауық"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Әлеуметтік"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Денсаулық және фитнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ауа райы"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Сізге ұсынылғандар"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виджеттері оң жақта, іздеу мен опциялар сол жақта"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# таңбаша}other{# таңбаша}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жұмыс виджеттері"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Әңгімелер"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Ескертпе жазу"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Қосу"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Виджет (<xliff:g id="WIDGET_NAME">%1$s</xliff:g>) қосу"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Саусақпен түртсеңіз болғаны – пайдалы ақпарат көз алдыңызда"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Қолданбаларды ашпай-ақ ақпарат алу үшін негізгі экранға тиісті виджеттерді қосыңыз."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Виджет параметрлерін өзгерту үшін түртіңіз."</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Сүзгі"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Қате шықты: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Жеке бөлме"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Құпия кеңістіктегі қолданбаларды құлыптаулы және жасырын күйде қалдырыңыз."</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Реттеу немесе ашу үшін түртіңіз"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Жеке"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Жеке бөлме параметрлері"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Жеке бөлмені құлыптау/оның құлпын ашу"</string>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 1297dee..243f9f4 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"មិនអាចប្រើគូកម្មវិធីនេះនៅលើឧបករណ៍នេះបានទេ"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"លាឧបករណ៍ ដើម្បីប្រើគូកម្មវិធីនេះ"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"មិនអាចប្រើគូកម្មវិធីបានទេ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ចុចឱ្យជាប់​ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក​។"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ចុចពីរដង រួចសង្កត់ឱ្យជាប់ ដើម្បីផ្លាស់ទី​ធាតុក្រាហ្វិក ឬប្រើ​សកម្មភាព​តាមបំណង​។"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ទទឺង %1$d គុណនឹងកម្ពស់ %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ធាតុ​ក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"ធាតុ​ក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ទទឹង %2$d គុណនឹងកម្ពស់ %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ចុចលើធាតុក្រាហ្វិកឱ្យជាប់ ដើម្បីផ្លាស់ទីវាជុំវិញអេក្រង់ដើម"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"បញ្ចូល​ទៅក្នុង​អេក្រង់​ដើម"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"បានបញ្ចូល​ធាតុក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ទៅ​អេក្រង់ដើម"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ការណែនាំ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"វត្ថុចាំបាច់ប្រចាំថ្ងៃរបស់អ្នក"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ព័ត៌មាន​សម្រាប់​អ្នក"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"សំខាន់"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ព័ត៌មាន និង​ទស្សនាវដ្ដី"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"តំបន់បន្ធូរ​អារម្មណ៍របស់អ្នក"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"សម្រេច​គោលដៅ​ហាត់ប្រាណ​របស់អ្នក"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"ទទួលបានដំណឹងជាមុនអំពីអាកាសធាតុ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"អ្នក​ក៏​អាច​នឹង​ចូលចិត្ត"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"កម្សាន្ត"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"សង្គម"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"សុខភាព និង​សម្បទា"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"អាកាសធាតុ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ណែនាំជូនអ្នក"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ធាតុក្រាហ្វិក <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> នៅខាងស្ដាំ ការស្វែងរក និងជម្រើសនៅខាងឆ្វេង"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ធាតុ​ក្រាហ្វិក #}other{ធាតុ​ក្រាហ្វិក #}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ផ្លូវកាត់ #}other{ផ្លូវកាត់ #}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ការងារ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"ការសន្ទនា"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"ការកត់ត្រា"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"បញ្ចូល"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"បញ្ចូលធាតុ​ក្រាហ្វិក <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ទទួលបាន​ព័ត៌មានដែលមានប្រយោជន៍​យ៉ាងងាយស្រួល"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ដើម្បីទទួលបាន​ព័ត៌មាន​ដោយមិនចាំបាច់​បើកកម្មវិធី អ្នកអាចបញ្ចូលធាតុ​ក្រាហ្វិកទៅក្នុង​អេក្រង់ដើម​របស់អ្នក"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ចុចដើម្បីប្ដូរការកំណត់ធាតុ​ក្រាហ្វិក"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"តម្រង"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"បានបរាជ័យ៖ <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"បន្ទប់​ឯកជន"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"រក្សាកម្មវិធីឯកជនឱ្យនៅជាប់សោ និងលាក់"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ចុចដើម្បីរៀបចំ ឬបើក"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ឯកជន"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ការកំណត់ Private Space"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ចាក់សោ/ដោះសោ Private Space"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index fa9a332..62864cb 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ಈ ಆ್ಯಪ್ ಜೋಡಿಯು ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ಈ ಆ್ಯಪ್ ಜೋಡಿಯನ್ನು ಬಳಸಲು ಸಾಧನವನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ವಿಜೆಟ್ ಸರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ವಿಜೆಟ್ ಸರಿಸಲು ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಲು ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ಅಗಲ ಮತ್ತು %2$d ಎತ್ತರ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ವಿಜೆಟ್"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ವಿಜೆಟ್, %2$d ಅಗಲ ಮತ್ತು %3$d ಎತ್ತರ"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ಹೋಮ್ ಸ್ಕ್ರೀನ್ ಸುತ್ತ ವಿಜೆಟ್ ಅನ್ನು ಸರಿಸಲು, ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ಗೆ ಸೇರಿಸಿ"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"ಹೋಮ್‌ಸ್ಕ್ರೀನ್‌ಗೆ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ವಿಜೆಟ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ಸಲಹೆಗಳು"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ನಿಮ್ಮ ದೈನಂದಿನ ಎಸೆನ್ಶಿಯಲ್‌ಗಳು"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ನಿಮಗಾಗಿ ಸುದ್ದಿ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ಅಗತ್ಯತೆಗಳು"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ಸುದ್ದಿ ಮತ್ತು ನಿಯತಕಾಲಿಕೆಗಳು"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ನೀವು ವಿಶ್ರಾಂತಿ ಪಡೆಯುವ ಸ್ಥಳ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ನಿಮ್ಮ ಫಿಟ್‌ನೆಸ್ ಗುರಿಗಳನ್ನು ಸಾಧಿಸಿ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"ಹವಾಮಾನದ ಕುರಿತು ಮುಂಚೆಯೇ ಅಪ್‌ಡೇಟ್‌ ಆಗಿರಿ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ನಿಮಗೆ ಇವು ಕೂಡ ಇಷ್ಟವಾಗಬಹುದು"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ಮನರಂಜನೆ"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ಸಾಮಾಜಿಕ"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ಆರೋಗ್ಯ ಮತ್ತು ಫಿಟ್‌ನೆಸ್"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ಹವಾಮಾನ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ನಿಮಗಾಗಿ ಸೂಚಿಸಲಾಗಿರುವುದು"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ಬಲಭಾಗದಲ್ಲಿ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ವಿಜೆಟ್‌ಗಳು, ಎಡಭಾಗದಲ್ಲಿ ಹುಡುಕಾಟ ಮತ್ತು ಆಯ್ಕೆಗಳು"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ವಿಜೆಟ್}one{# ವಿಜೆಟ್‌ಗಳು}other{# ವಿಜೆಟ್‌ಗಳು}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ಶಾರ್ಟ್‌ಕಟ್}one{# ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು}other{# ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ಕೆಲಸ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"ಸಂಭಾಷಣೆಗಳು"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"ಟಿಪ್ಪಣಿ ತೆಗೆದುಕೊಳ್ಳುವುದು"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ಸೇರಿಸಿ"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ವಿಜೆಟ್ ಸೇರಿಸಿ"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ನಿಮ್ಮ ಬೆರಳ ತುದಿಯಲ್ಲಿ ಉಪಯುಕ್ತ ಮಾಹಿತಿ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ಆ್ಯಪ್‌ಗಳನ್ನು ತೆರೆಯದೆಯೇ ಮಾಹಿತಿಯನ್ನು ಪಡೆಯಲು, ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನೀವು ವಿಜೆಟ್‌ಗಳನ್ನು ಸೇರಿಸಬಹುದು"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ವಿಜೆಟ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ಫಿಲ್ಟರ್‌"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ವಿಫಲವಾಗಿದೆ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ಖಾಸಗಿ ಸ್ಪೇಸ್"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ಖಾಸಗಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಲಾಕ್ ಮಾಡಿ ಮತ್ತು ಮರೆಮಾಡಿ"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ಸೆಟಪ್ ಮಾಡಲು ಅಥವಾ ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ಖಾಸಗಿ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ಖಾಸಗಿ ಸ್ಪೇಸ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ಖಾಸಗಿ ಸ್ಪೇಸ್ ಅನ್ನು ಲಾಕ್/ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 5c1e854..f97acf1 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"이 앱 페어링은 이 기기에서 지원되지 않습니다"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"이 앱 페어링을 사용하려면 기기를 펼치세요"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"길게 터치하여 위젯을 이동하세요."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"두 번 탭한 다음 길게 터치하여 위젯을 이동하거나 맞춤 작업을 사용하세요."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"너비 %1$d, 높이 %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"위젯 <xliff:g id="WIDGET_NAME">%1$s</xliff:g>개"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> 위젯, 너비는 %2$d, 높이는 %3$d입니다"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"홈 화면에서 위젯을 이동하려면 길게 터치하세요."</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"홈 화면에 추가"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> 위젯이 홈 화면에 추가됨"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"추천"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"매일 사용하는 항목"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"추천 뉴스"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"필수"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"뉴스 및 잡지"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"휴식 공간"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"피트니스 목표 달성"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"사전에 날씨 확인"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"좋아할 만한 항목"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"엔터테인먼트"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"소셜"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"건강 및 피트니스"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"날씨"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"추천"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"오른쪽에 <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> 위젯, 왼쪽에 검색 및 옵션"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{위젯 #개}other{위젯 #개}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{바로가기 #개}other{바로가기 #개}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"직장 위젯"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"대화"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"메모"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"추가"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> 위젯 추가"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"빠르게 유용한 정보 확인"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"앱을 열지 않고 정보를 확인하려면 홈 화면에 위젯을 추가하세요."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"탭하여 위젯 설정 변경"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"필터"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"실패: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"비공개 스페이스"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"비공개 앱을 잠그고 숨겨진 상태로 유지"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"탭하여 설정 또는 열기"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"비공개"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"비공개 스페이스 설정"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"비공개 스페이스 잠금/잠금 해제"</string>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 4c73a20..f908299 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Бул эки колдонмону бул түзмөктө бир маалда пайдаланууга болбойт"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Бул эки колдонмону бир маалда пайдалануу үчүн түзмөктү ачыңыз"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Эки колдонмону бир маалда пайдаланууга болбойт"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетти кое бербей басып туруп жылдырыңыз."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетти жылдыруу үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Туурасы: %1$d, бийиктиги: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджети"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджети, кеңдиги %2$d жана бийиктиги %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Башкы экранга жылдыруу үчүн виджетти коё бербей басып туруңуз"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Башкы экранга кошуу"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджети башкы экранга кошулду"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Сунуштар"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Күнүмдүк керектелүүчү нерселер"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Сиз үчүн жаңылыктар"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Эң зарыл параметрлер"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Жаңылыктар жана журналдар"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Чер жазуу"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Фитнес максаттарыңызга жетиңиз"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Аба ырайы тууралуу маалымат"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Төмөнкүлөр да жагышы мүмкүн"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Көңүл ачуу"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Коомдук тармактар"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Ден соолук жана дене-бойду чыңдоо"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Аба ырайы"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Сизге сунушталат"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виджеттери оң, ал эми издөө жана параметрлер сол жакта"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ыкчам баскыч}other{# ыкчам баскыч}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Жумуш"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Сүйлөшүүлөр"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Эскертме жазуу"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Кошуу"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджетин кошуу"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Керектүү маалымат манжаңыздын учунда"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Бир нерсе билүү үчүн колдонмолорду улам ачып убара болбостон, башкы экранга виджеттерди кошуп коюңуз."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Виджеттин параметрлерин өзгөртүү үчүн таптап коюңуз"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Чыпкалоо"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Аткарылган жок: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Жеке мейкиндик"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Жеке колдонмолорду кулпулап жана жашырып коюңуз"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Тууралоо же ачуу үчүн таптап коюңуз"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Жеке"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Жеке мейкиндиктин параметрлери"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Жеке мейкиндикти кулпулоо/кулпусун ачуу"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 0ff2d4e..c215bc8 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ການຈັບຄູ່ແອັບນີ້ບໍ່ຮອງຮັບຢູ່ອຸປະກອນນີ້"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ກາງອຸປະກອນອອກເພື່ອໃຊ້ການຈັບຄູ່ແອັບນີ້"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"ການຈັບຄູ່ແອັບບໍ່ມີໃຫ້"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ແຕະຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຍ້າຍວິດເຈັດ ຫຼື ໃຊ້ຄຳສັ່ງກຳນົດເອງ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ກວ້າງ %1$d ຄູນສູງ %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"ວິດເຈັດ <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"ວິດເຈັດ <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, ກວ້າງ %2$d ສູງ %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ແຕະໃສ່ວິດເຈັດຄ້າງໄວ້ເພື່ອຍ້າຍມັນໄປມາຢູ່ໂຮມສະກຣີນ"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ເພີ່ມໃສ່ໂຮມສະກຣີນ"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"ເພີ່ມວິດເຈັດ <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ໃສ່ໂຮມສະກຣີນແລ້ວ"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ການແນະນຳ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ສິ່ງຈຳເປັນໃນຊີວິດປະຈຳວັນຂອງທ່ານ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ຂ່າວສຳລັບທ່ານ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ສິ່ງຈຳເປັນ"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ຂ່າວ ແລະ ວາລະສານ"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ພື້ນທີ່ພັກຜ່ອນຂອງທ່ານ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ບັນລຸເປົ້າໝາຍການອອກກຳລັງກາຍຂອງທ່ານ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"ຮູ້ສະພາບອາກາດລ່ວງໜ້າ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ທ່ານອາດຈະມັກ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ຄວາມບັນເທີງ"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ສັງຄົມ"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ສຸຂະພາບ ແລະ ການອອກກຳລັງກາຍ"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ສະພາບອາກາດ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ແນະນຳສຳລັບທ່ານ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ວິດເຈັດ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ຢູ່ທາງຂວາ, ການຊອກຫາ ແລະ ຕົວເລືອກຢູ່ທາງຊ້າຍ"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ວິດເຈັດ}other{# ວິດເຈັດ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ທາງລັດ}other{# ທາງລັດ}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ວຽກ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"ການສົນທະນາ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"ການຈົດບັນທຶກ"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ເພີ່ມ"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"ເພີ່ມວິດເຈັດ <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ຂໍ້ມູນທີ່ເປັນປະໂຫຍດຢູ່ປາຍນິ້ວຂອງທ່ານ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ເພື່ອຮັບຂໍ້ມູນໂດຍບໍ່ຕ້ອງເປີດແອັບ, ທ່ານສາມາດເພີ່ມວິດເຈັດໃສ່ໂຮມສະກຣີນຂອງທ່ານໄດ້"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ແຕະເພື່ອປ່ຽນການຕັ້ງຄ່າວິດເຈັດ"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ກັ່ນຕອງ"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ບໍ່ສຳເລັດ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ພື້ນທີ່ສ່ວນຕົວ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ລັອກ ແລະ ເຊື່ອງແອັບສ່ວນຕົວໄວ້"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ແຕະເພື່ອຕັ້ງຄ່າ ຫຼື ເປີດ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ສ່ວນຕົວ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ການຕັ້ງຄ່າພື້ນທີ່ສ່ວນຕົວ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ລັອກ/ປົດລັອກພື້ນທີ່ສ່ວນຕົວ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index ef81b96..1dcb559 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ši programų pora šiame įrenginyje nepalaikoma"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Atlenkite įrenginį, kad galėtumėte naudoti šią programų porą."</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Dukart pal. ir palaik., kad perkeltumėte valdiklį."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dukart palieskite ir palaikykite, kad perkeltumėte valdiklį ar naudotumėte tinkintus veiksmus."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plotis ir %2$d aukštis"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> valdiklis"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Valdiklis: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>; %2$d pločio ir %3$d aukščio"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Paliesdami ir palaikydami valdiklį galite judėti pagrindiniame ekrane"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Pridėti prie pagrindinio ekrano"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Valdiklis „<xliff:g id="WIDGET_NAME">%1$s</xliff:g>“ pridėtas prie pagrindinio ekrano"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Pasiūlymai"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Tai, ko jums reikia kasdien"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Naujienos jums"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Būtiniausi"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Naujienos ir žurnalai"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jūsų atsipalaidavimo zona"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Pasiekite mankštos tikslus"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Visada žinokite, kokie bus orai"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Jums taip pat gali patikti"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Pramogos"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialiniai tinklai"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sveikata ir kūno rengyba"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Orai"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Siūloma jums"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> valdikliai dešinėje, paieška ir parinktys kairėje"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# valdiklis}one{# valdiklis}few{# valdikliai}many{# valdiklio}other{# valdiklių}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# spartusis klavišas}one{# spartusis klavišas}few{# spartieji klavišai}many{# sparčiojo klavišo}other{# sparčiųjų klavišų}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Darbas"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Pokalbiai"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Užrašų kūrimas"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Pridėti"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Pridėti valdiklį: <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Lengvai pasiekiama naudinga informacija"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Jei norite gauti informacijos neatidarę programų, galite pridėti valdiklių pagrindiniame ekrane"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Palieskite, kad pakeistumėte valdiklio nustatymus"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtruoti"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Nepavyko: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privati erdvė"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Privačių programų užrakinimas ir slėpimas"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Palieskite, kad nustatytumėte arba atidarytumėte"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privatus"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privačios erdvės nustatymai"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Užrakinti ir (arba) atrakinti privačią erdvę"</string>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index d04afa1..e2b1031 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Šis lietotņu pāris netiek atbalstīts šajā ierīcē"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Atveriet ierīci, lai izmantotu šo lietotņu pāri"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Lai pārvietotu logrīku, pieskarieties un turiet."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Lai pārvietotu logrīku, uz tā veiciet dubultskārienu un turiet. Varat arī veikt pielāgotas darbības."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d plats un %2$d augsts"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Logrīks <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Logrīks <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d plats un %3$d augsts"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pieskarieties logrīkam un turiet to, lai to pārvietotu pa sākuma ekrānu."</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Pievienot sākuma ekrānam"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Logrīks “<xliff:g id="WIDGET_NAME">%1$s</xliff:g>” ir pievienots sākuma ekrānam"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Ieteikumi"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Jums ikdienā vajadzīgais"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Ziņas jums"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Produktivitātei"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Ziņas un žurnāli"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Jūsu atpūtas stūrītis"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Sasniedziet fitnesa mērķus"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Neļaujiet laikapstākļiem jūs pārsteigt"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Jums varētu patikt arī…"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Izklaide"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociālie tīkli"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Veselība un fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Laikapstākļi"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Ieteikumi jums"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Pa labi logrīki <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>, pa kreisi meklēšana un iespējas"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# logrīks}zero{# logrīku}one{# logrīks}other{# logrīki}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# saīsne}zero{# saīšņu}one{# saīsne}other{# saīsnes}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Darba"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Sarunas"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Piezīmju pierakstīšana"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Pievienot"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Pievienot logrīku <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Ērta piekļuve noderīgai informācijai"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Lai iegūtu informāciju, neatverot lietotnes, varat pievienot sākuma ekrānam logrīkus"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Pieskarieties, lai mainītu logrīka iestatījumus."</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrs"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Neizdevās: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privātā telpa"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Paslēpiet privātās lietotnes un bloķējiet piekļuvi tām"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Pieskarieties, lai iestatītu vai atvērtu"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privātā mape"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Privātās mapes iestatījumi"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloķēt/atbloķēt privāto mapi"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 6a4dd26..0accd7f 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Паров апликации не е поддржан на уредов"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Отворете го уредот за да го користите паров апликации"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Допрете и задржете за да преместите виџет."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Допрете двапати и задржете за да преместите виџет или користете приспособени дејства."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d широк на %2$d висок"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, ширина од %2$d со висина од %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Допрете го и задржете го виџетот за да го движите наоколу на почетниот екран"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Додај на почетниот екран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Виџетот <xliff:g id="WIDGET_NAME">%1$s</xliff:g> е додаден на почетниот екран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Вашите секојдневни неопходности"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Вести за вас"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Неопходни"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Вести и списанија"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Вашата зона за релаксација"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Достигнете ги целите за фитнес"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Бидете во тек со временската прогноза"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Можеби ќе ви се допадне и"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забава"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Друштвени"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здравје и фитнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Време"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Препорачано за вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> виџети оддесно, „Пребарување“ и „Опции“ одлево"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}other{# виџети}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# кратенка}one{# кратенка}other{# кратенки}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Работни"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Разговори"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Фаќање белешки"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Додај"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Додај го виџетот <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Корисни информации на дофат на прстите"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"За да добивате информации без да ги отворате апликациите, може да додадете виџети на почетниот екран"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Допрете за да ги промените поставките за виџетот"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтер"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не успеа: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Приватен простор"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Чувајте ги приватните апликации заклучени и скриени"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Допрете за да поставите или отворите"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Приватен"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Поставки за „Приватен простор“"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Заклучување/отклучување на „Приватен простор“"</string>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 3952b22..e3b6e6b 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ഈ ഉപകരണത്തിൽ ഈ ആപ്പ് ജോടിക്ക് പിന്തുണയില്ല"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ഈ ആപ്പ് ജോടി ഉപയോഗിക്കാൻ ഉപകരണം അൺഫോൾഡ് ചെയ്യുക"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"ആപ്പ് ജോടി ലഭ്യമല്ല"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"വിജറ്റ് നീക്കാൻ സ്‌പർശിച്ച് പിടിക്കുക."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"വിജറ്റ് നീക്കാൻ ഡബിൾ ടാപ്പ് ചെയ്യൂ, ഹോൾഡ് ചെയ്യൂ അല്ലെങ്കിൽ ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കൂ."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d വീതിയും %2$d ഉയരവും"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ്"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ്, %2$d വീതി %3$d ഉയരം"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ഹോം സ്‌ക്രീനിന് ചുറ്റും വിജറ്റ് നീക്കാൻ അതിൽ സ്‌പർശിച്ച് പിടിക്കുക"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ഹോം സ്‌ക്രീനിലേക്ക് ചേർക്കുക"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ് ഹോം സ്‌ക്രീനിലേക്ക് ചേർത്തു"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"നിർദ്ദേശങ്ങൾ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ഓരോ ദിവസവും ആവശ്യമായവ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"നിങ്ങൾക്കായുള്ള വാർത്ത"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ആവശ്യമായവ"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"വാർത്തകളും മാസികകളും"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"നിങ്ങൾക്ക് സുഖപ്രദമായ സ്ഥലം"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ശാരീരികക്ഷമതയുമായി ബന്ധപ്പെട്ട ലക്ഷ്യങ്ങൾ കൈവരിക്കൂ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"കാലാവസ്ഥ മുൻകൂട്ടി മനസ്സിലാക്കുക"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"നിങ്ങൾക്ക് ഇനിപ്പറയുന്നവ ഇഷ്ടമായേക്കാം"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"വിനോദം"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"സാമൂഹികം"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ആരോഗ്യവും ശാരീരികക്ഷമതയും"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"കാലാവസ്ഥ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"നിങ്ങൾക്കായി നിർദ്ദേശിച്ചവ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"വലതുവശത്ത് <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> വിജറ്റുകളും ഇടതുവശത്ത് തിരയൽ, ഓപ്ഷനുകൾ എന്നിവയും"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# വിജറ്റ്}other{# വിജറ്റുകൾ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# കുറുക്കുവഴി}other{# കുറുക്കുവഴികൾ}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ജോലി"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"സംഭാഷണങ്ങൾ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"കുറിപ്പ് രേഖപ്പെടുത്തൽ"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ചേർക്കുക"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> വിജറ്റ് ചേർക്കുക"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ഉപകാരപ്രദമായ വിവരങ്ങൾ നിങ്ങളുടെ വിരൽത്തുമ്പിൽ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ആപ്പുകൾ തുറക്കാതെ വിവരങ്ങൾ ലഭിക്കാൻ, നിങ്ങൾക്ക് ഹോം സ്ക്രീനിലേക്ക് വിജറ്റുകൾ ചേർക്കാം"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"വിജറ്റ് ക്രമീകരണം മാറ്റാൻ ടാപ്പ് ചെയ്യുക"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ഫിൽട്ടർ ചെയ്യുക"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"പരാജയപ്പെട്ടു: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"സ്വകാര്യ സ്പേസ്"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"സ്വകാര്യ ആപ്പുകൾ ലോക്ക് ചെയ്ത് മറയ്‌ക്കുക"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"സജ്ജീകരിക്കാനോ തുറക്കാനോ ടാപ്പ് ചെയ്യുക"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"സ്വകാര്യം"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"സ്വകാര്യ സ്‌പേസ് ക്രമീകരണം"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"സ്വകാര്യ സ്‌പേസ് ലോക്ക് ചെയ്യുക/അൺലോക്ക് ചെയ്യുക"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 7a73041..cc4af0e 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Энэ апп хослуулалтыг уг төхөөрөмж дээр дэмждэггүй"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Энэ апп хослуулалтыг ашиглахын тулд төхөөрөмжийг дэлгэнэ үү"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Виджетийг зөөх бол хүрээд, удаан дарна уу."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Виджетийг зөөх эсвэл захиалгат үйлдлийг ашиглахын тулд хоёр товшоод, удаан дарна уу."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d өргөн %2$d өндөр"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> жижиг хэрэгсэл"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджет, %3$d-н өндрийг харьцах нь %2$d-н өргөн"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Виджетийг үндсэн нүүрний эргэн тойронд зөөхийн тулд түүнд хүрээд, удаан дарна уу"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Үндсэн нүүрэнд нэмэх"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджетийг үндсэн нүүрэнд нэмсэн"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Зөвлөмжүүд"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Таны өдөр тутмын хэрэгцээт зүйлс"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Танд зориулсан мэдээ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Зайлшгүй хэрэгтэй"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Мэдээ, сэтгүүлүүд"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Таны амралтын бүс"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Фитнесийн зорилгодоо хүрээрэй"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Цаг агаарын урьдчилсан мэдээлэлтэй байгаарай"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Танд таалагдаж магадгүй"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Энтертэйнмент"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Сошиал"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Эрүүл мэнд, фитнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Цаг агаар"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Танд санал болгосон"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Баруун талд <xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-н виджет, зүүн талд хайлт болон сонгуултууд байна"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}other{# виджет}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# товчлол}other{# товчлол}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Ажил"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Харилцан яриа"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Тэмдэглэл хөтлөх"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Нэмэх"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виджетийг нэмэх"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Хэрэгтэй мэдээллээ хурууныхаа үзүүрээр аваарай"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Аппуудыг нээлгүйгээр мэдээлэл авахын тулд та үндсэн нүүрэндээ виджетүүд нэмэх боломжтой"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Жижиг хэрэгслийн тохиргоог өөрчлөхийн тулд товшино уу"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Шүүлтүүр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Амжилтгүй болсон: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Хувийн орон зай"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Хувийн аппуудыг түгжээтэй бөгөөд нуугдсан байлгана уу"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Тохируулах эсвэл нээхийн тулд товших"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Хувийн"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Private Space-н тохиргоо"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Private Space-г түгжих/түгжээг тайлах"</string>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index bf83246..5eec969 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"या ॲपची जोडीला या डिव्हाइसवर सपोर्ट नाही"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ही ॲपची जोडी वापरण्यासाठी डिव्हाइस अनफोल्ड करा"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"विजेट हलवण्यासाठी स्पर्श करा आणि धरून ठेवा."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"विजेट हलवण्यासाठी किंवा कस्टम कृती वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d रूंद बाय %2$d उंच"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट, %2$d रुंदी आणि %3$d उंची"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"होम स्क्रीनवर हलवण्यासाठी विजेटला स्पर्श करून धरून ठेवा"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"होम स्क्रीनवर जोडा"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> हे विजेट तुमच्या होम स्क्रीनवर जोडले आहे"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सूचना"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"तुमच्या दररोजच्या आवश्यक गोष्टी"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"तुमच्यासाठी बातम्या"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"आवश्यक गोष्टी"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"बातम्‍या आणि मासिके"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"तुमचा आरामदायक झोन"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"तुमची फिटनेस ध्येये गाठा"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"हवामानासंबंधित बातम्या आगामी मिळवा"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"तुम्हाला हेदेखील आवडू शकते"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरंजन"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोशल"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"आरोग्य आणि फिटनेस"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"हवामान"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"तुमच्यासाठी सुचवलेले"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"उजवीकडे <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> विजेट, डावीकडे शोध आणि पर्याय"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# विजेट}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# शॉर्टकट}other{# शॉर्टकट}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ऑफिस"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"संभाषणे"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"टिपा घेणे"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"जोडा"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट जोडा"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"तुमच्यासाठी सहज उपलब्ध असलेली माहिती"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ॲप्स न उघडता माहिती मिळवण्यासाठी, तुम्ही तुमच्या होम स्क्रीनवर विजेट जोडू शकता"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"विजेट सेटिंग्ज बदलण्यासाठी टॅप करा"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"फिल्टर"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"हे करता आले नाही: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"खाजगी स्पेस"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"खाजगी अ‍ॅप्स लॉक करून आणि लपवून ठेवा"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"सेट करण्यासाठी किंवा उघडण्यासाठी टॅप करा"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"खाजगी"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"खाजगी स्पेस ची सेटिंग्ज"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"खाजगी स्पेस लॉक/अनलॉक करा"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 0f3d20d..68a9238 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Gandingan apl ini tidak disokong pada peranti ini"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Buka lipatan peranti untuk menggunakan gandingan apl ini"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Gandingan apl tidak tersedia"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Sentuh &amp; tahan untuk menggerakkan widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ketik dua kali &amp; tahan untuk menggerakkan widget atau menggunakan tindakan tersuai."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Lebar %1$d kali tinggi %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, lebar %2$d kali tinggi %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Sentuh &amp; tahan widget untuk menggerakkan widget di sekitar skrin utama"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Tambahkan pada skrin utama"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ditambahkan pada skrin utama"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Cadangan"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Keperluan Harian Anda"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Berita Untuk Anda"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Apl Asas"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Berita &amp; majalah"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zon Santai Anda"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Capai Matlamat Kecergasan Anda"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Ketahui Perkembangan Terkini Cuaca"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Anda Mungkin Turut Menyukai"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hiburan"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosial"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kesihatan &amp; kecergasan"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Cuaca"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Dicadangkan untuk anda"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widget <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> pada sebelah kanan, carian dan pilihan pada sebelah kiri"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# pintasan}other{# pintasan}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Tempat kerja"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Perbualan"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pengambilan nota"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Tambah"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Tambahkan widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Maklumat berguna di hujung jari anda"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Untuk mendapatkan maklumat tanpa membuka apl, anda boleh menambahkan widget pada skrin utama anda"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Ketik untuk menukar tetapan widget"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Tapis"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Gagal: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Ruang privasi"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Kunci dan sembunyikan apl peribadi"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Ketik untuk menyediakan atau membuka"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Peribadi"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Tetapan Ruang Peribadi"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Kunci/Buka kunci Ruang Peribadi"</string>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 00041fc..6a06d0d 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ဤအက်ပ်တွဲချိတ်ခြင်းကို ဤစက်တွင် ပံ့ပိုးမထားပါ"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ဤအက်ပ်တွဲချိတ်ခြင်းကို သုံးရန် စက်ကိုဖြန့်ပါ"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ဝိဂျက်ကို ရွှေ့ရန် တို့ပြီး ဖိထားပါ။"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ဝိဂျက်ကို ရွှေ့ရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"အလျား %1$d နှင့် အမြင့် %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်၊ အကျယ် %2$d နှင့် အမြင့် %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ဝိဂျက်ကို တို့ထိ၍ ဖိထားပြီး ပင်မစာမျက်နှာပေါ်တွင် နေရာအမျိုးမျိုးသို့ ရွှေ့နိုင်သည်"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ပင်မစာမျက်နှာတွင် ထည့်ရန်"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်ကို ပင်မစာမျက်နှာတွင် ထည့်လိုက်ပြီ"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"အကြံပြုချက်"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"သင်၏ နေ့စဉ်မရှိမဖြစ်များ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"သင့်အတွက် သတင်းများ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"မရှိမဖြစ်များ"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"သတင်းနှင့် မဂ္ဂဇင်းများ"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"သင်အနားယူသောနေရာ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"သင့်ကြံ့ခိုင်ရေးပန်းတိုင်ဆီ သွားရန်"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"မိုးလေဝသကို ကြိုတင်ကာကွယ်ရန်"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"သင်နှစ်သက်နိုင်သောအရာများ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ဖျော်ဖြေရေး"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"လူမှုရေး"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ကျန်းမာကြံ့ခိုင်ရေး"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"မိုးလေဝသ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"သင့်အတွက် အကြံပြုထားသည်များ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ဝိဂျက်များသည် ညာဘက်တွင်ရှိပြီး ရှာဖွေမှုနှင့် ရွေးစရာများသည် ဘယ်ဘက်တွင်ရှိသည်"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{ဝိဂျက် # ခု}other{ဝိဂျက် # ခု}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ဖြတ်လမ်းလင့်ခ် # ခု}other{ဖြတ်လမ်းလင့်ခ် # ခု}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"အလုပ်"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"စကားဝိုင်းများ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"မှတ်စုလိုက်ခြင်း"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ထည့်ရန်"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ဝိဂျက်ထည့်ရန်"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"အသုံးဝင်သော အချက်အလက်များကို အလွယ်တကူ ရယူလိုက်ပါ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"အက်ပ်မဖွင့်ဘဲ အချက်အလက်များရယူရန် ပင်မစာမျက်နှာတွင် ဝိဂျက်များ ထည့်နိုင်သည်"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ဝိဂျက် ဆက်တင်များကို ပြောင်းရန် တို့ပါ"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"စစ်ထုတ်ရန်"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"မအောင်မြင်ပါ− <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"သီးသန့်ချတ်ခန်း"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"သီးသန့်အက်ပ်များကို လော့ခ်ချပြီး ဖျောက်ထားပါ"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"စနစ်ထည့်သွင်းရန် (သို့) ဖွင့်ရန် တို့ပါ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"သီးသန့်"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"သီးသန့်ချတ်ခန်း ဆက်တင်များ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"သီးသန့်ချတ်ခန်း လော့ခ်ချ/ဖွင့်ရန်"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 72ac454..5a19b9b 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Denne apptilkoblingen støttes ikke på denne enheten"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Åpne enheten for å bruke denne apptilkoblingen"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Trykk og hold for å flytte en modul."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dobbelttrykk og hold inne for å flytte en modul eller bruke tilpassede handlinger."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bredde x %2$d høyde"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modul"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modulen, %2$d bred og %3$d høy"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Trykk og hold på modulen for å bevege den rundt på startskjermen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Legg til på startskjermen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modulen er lagt til på startskjermen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Forslag"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Viktige apper for dagliglivet"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Nyheter for deg"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Uunnværlige spill"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nyheter og tidsskrifter"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Avslappingssonen din"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Nå treningsmålene dine"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Hold deg i forkant av været"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Kanskje du også liker"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underholdning"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosialt"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kropp og helse"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Været"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Foreslått for deg"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> moduler til høyre, søk og alternativer til venstre"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# modul}other{# moduler}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# snarvei}other{# snarveier}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Jobb"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Samtaler"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Notatskriving"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Legg til"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Legg til <xliff:g id="WIDGET_NAME">%1$s</xliff:g>-modulen"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Lett tilgjengelig nyttig informasjon"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"For å se informasjon uten å åpne apper kan du legge til moduler på startskjermen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Trykk for å endre modulinnstillinger"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Mislyktes: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privat område"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Hold private apper låst og skjult"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Trykk for å konfigurere eller åpne"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Innstillinger for Private Space"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lås / lås opp Private Space"</string>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 9a8ade5..8e06879 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"यस डिभाइसमा यो एप पेयर प्रयोग गर्न मिल्दैन"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"यो एप पेयर प्रयोग गर्न डिभाइस अनफोल्ड गर्नुहोस्"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"एप पेयर उपलब्ध छैन"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"कुनै विजेट सार्न डबल ट्याप गरेर छोइराख्नुहोस्।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"कुनै विजेट सार्न वा आफ्नो रोजाइका कारबाही प्रयोग गर्न डबल ट्याप गरेर छोइराख्नुहोस्।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d चौडाइ गुणा %2$d उचाइ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट, %2$d चौडाइ र %3$d उचाइ"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"विजेटलाई होम स्क्रिनमा यताउता सार्न त्यसमा टच एन्ड होल्ड गर्नुहोस्"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"होम स्क्रिनमा राख्नुहोस्"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"होम स्क्रिनमा <xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट हालियो"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"सुझावहरू"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"तपाईंलाई दैनिक आवश्यक पर्ने एपहरू"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"तपाईंका निम्ति सिफारिस गरिएका समाचार"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"अत्यावश्यक कुराहरू"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"समाचार तथा पत्रपत्रिकाहरू"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"तपाईंको Chill Zone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"आफूले तय गरेको तन्दुरुस्तीको लक्ष्यमा पुग्नुहोस्"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"मौसमको पूर्वानुमान प्राप्त गर्नुहोस्"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"तपाईंलाई निम्न कुराहरू पनि मन पर्न सक्छन्"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"मनोरञ्जन"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"सोसल मिडिया"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"स्वास्थ्य तथा तन्दुरुस्ती"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"मौसम"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"तपाईंका लागि सिफारिस गरिएका"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"दायाँ भागमा <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> विजेटहरू, बायाँ भागमा खोज र विकल्पहरू"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# विजेट}other{# वटा विजेट}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# सर्टकट}other{# वटा सर्टकट}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"कामसम्बन्धी"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"वार्तालापहरू"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"नोट लेख्ने कार्य"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"हाल्नुहोस्"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> विजेट हाल्नुहोस्"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"उपयोगी जानकारी सजिलै प्राप्त गर्नुहोस्"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"एपहरू नखोलिकनै जानकारी प्राप्त गर्न तपाईं आफ्नो होम स्क्रिनमा विजेटहरू हाल्न सक्नुहुन्छ"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"विजेटका सेटिङ बदल्न ट्याप गर्नुहोस्"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"फिल्टर"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"कार्य पूरा गर्न सकिएन: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"निजी स्पेस"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"निजी एपहरू लक गरिराख्नुहोस् र लुकाइराख्नुहोस्"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"सेटअप गर्न वा खोल्न ट्याप गर्नुहोस्"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"निजी"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"निजी स्पेससम्बन्धी सेटिङ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"निजी स्पेस लक/अनलक गर्नुहोस्"</string>
diff --git a/res/values-night-v31/colors.xml b/res/values-night-v31/colors.xml
index e462ae0..d23f4d1 100644
--- a/res/values-night-v31/colors.xml
+++ b/res/values-night-v31/colors.xml
@@ -46,6 +46,10 @@
         @android:color/system_neutral2_200</color>
     <color name="widget_picker_collapse_handle_color_dark">
         @android:color/system_neutral2_700</color>
+    <color name="widget_picker_add_button_background_color_dark">
+        @android:color/system_accent1_200</color>
+    <color name="widget_picker_add_button_text_color_dark">
+        @android:color/system_accent1_800</color>
 
     <color name="work_fab_bg_color">
         @android:color/system_accent1_200</color>
diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml
index d41eb7e..613c2e9 100644
--- a/res/values-night/styles.xml
+++ b/res/values-night/styles.xml
@@ -22,4 +22,10 @@
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
         <item name="android:windowTranslucentStatus">true</item>
     </style>
+
+    <style name="WidgetPickerActivityTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
+        <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="pageIndicatorDotColor">@color/page_indicator_dot_color_dark</item>
+    </style>
 </resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 19600a0..d64e6c3 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Dit app-paar wordt niet ondersteund op dit apparaat"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Vouw het apparaat open om dit app-paar te gebruiken"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tik en houd vast om een widget te verplaatsen."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dubbeltik en houd vast om een widget te verplaatsen of aangepaste acties te gebruiken."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d breed en %2$d hoog"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d breed bij %3$d hoog"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Houd je vinger op de widget om deze te verplaatsen op het startscherm"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Toevoegen aan startscherm"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> toegevoegd aan startscherm"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Suggesties"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Je dagelijkse essentials"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Nieuws voor jou"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nieuws en tijdschriften"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Je chillzone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Behaal je fitnessdoelen"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Blijf het weer een stap voor"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Misschien ook interessant"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociaal"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Gezondheid en fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Weer"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Voorgesteld voor jou"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>-widgets aan de rechterkant, zoeken en opties aan de linkerkant"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# snelkoppeling}other{# snelkoppelingen}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Werk"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Gesprekken"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Aantekeningen maken"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Toevoegen"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> toevoegen"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Nuttige informatie binnen handbereik"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Als je informatie wilt krijgen zonder apps te openen, kun je widgets toevoegen aan je startscherm"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tik om de widgetinstellingen te wijzigen"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filteren"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Mislukt: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privéruimte"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Houd privé-apps vergrendeld en verborgen"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tik om in te stellen of te openen"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privé"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Instellingen voor privéruimte"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Privéruimte vergrendelen/ontgrendelen"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 44a85ca..9cecf07 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ଏହି ଆପ ପେୟାର ଏ ଡିଭାଇସରେ ସମର୍ଥିତ ନୁହେଁ"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ଏହି ଆପ ପେୟାରକୁ ବ୍ୟବହାର କରିବା ପାଇଁ ଡିଭାଇସକୁ ଅନଫୋଲ୍ଡ କରନ୍ତୁ"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"ଆପ ପେୟାର ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ଓସାର ଓ %2$d ଉଚ୍ଚ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ୱିଜେଟ୍"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ୱିଜେଟ, %2$d ଓସାର %3$d ଉଚ୍ଚ"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ହୋମ ସ୍କ୍ରିନର ଆଖପାଖରେ ୱିଜେଟକୁ ମୁଭ କରିବା ପାଇଁ ଏହାକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ହୋମ ସ୍କ୍ରିନରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>ର ୱିଜେଟ ହୋମ ସ୍କ୍ରିନରେ ଯୋଡ଼ାଗଲା"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ପରାମର୍ଶଗୁଡ଼ିକ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ଆପଣଙ୍କ ଦୈନନ୍ଦିନ ଅତ୍ୟାବଶ୍ୟକୀୟ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ଆପଣଙ୍କ ପାଇଁ ନ୍ୟୁଜ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ଅତ୍ୟାବଶ୍ୟକୀୟ"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ନ୍ୟୁଜ ଓ ମେଗାଜିନ"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ଆପଣଙ୍କ ଚିଲ ଜୋନ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ଆପଣଙ୍କ ଫିଟନେସ ଲକ୍ଷ୍ୟରେ ପହଞ୍ଚନ୍ତୁ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"ପାଣିପାଗ ବିଷୟରେ ଆଗୁଆ ସୂଚନା ପାଆନ୍ତୁ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ଆପଣ ମଧ୍ୟ ପସନ୍ଦ କରିପାରନ୍ତି"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ମନୋରଞ୍ଜନ"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ସୋସିଆଲ"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ସ୍ୱାସ୍ଥ୍ୟ ଓ ଫିଟନେସ"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ପାଣିପାଗ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ଆପଣଙ୍କ ପାଇଁ ପ୍ରସ୍ତାବିତ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"ଡାହାଣରେ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ୱିଜେଟଗୁଡ଼ିକ ଅଛି, ବାମରେ ସର୍ଚ୍ଚ ଓ ବିକଳ୍ପଗୁଡ଼ିକ ଅଛି"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ୱିଜେଟ}other{# ୱିଜେଟ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{#ଟି ସର୍ଟକଟ୍}other{#ଟି ସର୍ଟକଟ୍}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ୱାର୍କ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"ନୋଟ-ଟେକିଂ"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ଯୋଗ କରନ୍ତୁ"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ୱିଜେଟ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ଉପଯୋଗୀ ସୂଚନା ଆପଣଙ୍କ ପାଖରେ ସହଜରେ ଉପଲବ୍ଧ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ଆପ୍ସକୁ ନଖୋଲି ସୂଚନା ପାଇବା ପାଇଁ, ଆପଣ ଆପଣଙ୍କ ହୋମ ସ୍କ୍ରିନରେ ୱିଜେଟଗୁଡ଼ିକୁ ଯୋଗ କରିପାରିବେ"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ୱିଜେଟ ସେଟିଂସ ପରିବର୍ତ୍ତନ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ଫିଲ୍ଟର୍"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ବିଫଳ ହୋଇଛି: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ପ୍ରାଇଭେଟ ସ୍ପେସ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ପ୍ରାଇଭେଟ ଆପ୍ସକୁ ଲକ ଏବଂ ଲୁକ୍କାୟିତ ରଖନ୍ତୁ"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ସେଟ ଅପ କରିବା କିମ୍ବା ଖୋଲିବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ପ୍ରାଇଭେଟ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ପ୍ରାଇଭେଟ ସ୍ପେସ ସେଟିଂସ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ପ୍ରାଇଭେଟ ସ୍ପେସକୁ ଲକ/ଅନଲକ କରନ୍ତୁ"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 7ed539f..17f16f1 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਦਾ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਸਮਰਥਨ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ਇਸ ਐਪ ਜੋੜਾਬੱਧ ਨੂੰ ਵਰਤਣ ਲਈ ਡੀਵਾਈਸ ਨੂੰ ਅਣਫੋਲਡ ਕਰੋ"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ਕਿਸੇ ਵਿਜੇਟ ਨੂੰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ਵਿਜੇਟ ਲਿਜਾਉਣ ਲਈ ਜਾਂ ਵਿਉਂਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰਕੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ਚੌੜਾਈ ਅਤੇ %2$d ਲੰਬਾਈ"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ, ਇਹ %2$d ਚੌੜਾ ਅਤੇ %3$d ਲੰਬਾ ਹੈ"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ਵਿਜੇਟ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਇੱਧਰ-ਉੱਧਰ ਲਿਜਾਉਣ ਲਈ ਸਪਰਸ਼ ਕਰ ਕੇ ਦਬਾਈ ਰੱਖੋ"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"ਸੁਝਾਅ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ਤੁਹਾਡੇ ਰੋਜ਼ਾਨਾ ਦੀਆਂ ਲੋੜੀਂਦੀਆਂ ਚੀਜ਼ਾਂ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ਤੁਹਾਡੇ ਲਈ ਖਬਰਾਂ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"ਲੋੜੀਂਦੀਆਂ"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ਖਬਰਾਂ ਅਤੇ ਰਸਾਲੇ"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ਤੁਹਾਡੇ ਲਈ ਸਕੂਨਮਈ ਖੇਤਰ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ਆਪਣੇ ਫਿੱਟਨੈੱਸ ਸੰਬੰਧੀ ਟੀਚੇ ਹਾਸਲ ਕਰੋ"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"ਮੌਸਮ ਬਾਰੇ ਅੱਪ-ਟੂ-ਡੇਟ ਰਹੋ"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ਸ਼ਾਇਦ ਤੁਸੀਂ ਇਹ ਵੀ ਪਸੰਦ ਕਰੋ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ਮਨੋਰੰਜਨ"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"ਸੋਸ਼ਲ"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ਸਿਹਤ ਅਤੇ ਫਿੱਟਨੈੱਸ"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"ਮੌਸਮ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ਤੁਹਾਡੇ ਲਈ ਸੁਝਾਅ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ਵਿਜੇਟ ਸੱਜੇ ਪਾਸੇ ਹਨ, ਖੋਜ ਵਿਜੇਟ ਅਤੇ ਹੋਰ ਵਿਕਲਪ ਖੱਬੇ ਪਾਸੇ ਹਨ"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ਵਿਜੇਟ}one{# ਵਿਜੇਟ}other{# ਵਿਜੇਟ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ਸ਼ਾਰਟਕੱਟ}one{# ਸ਼ਾਰਟਕੱਟ}other{# ਸ਼ਾਰਟਕੱਟ}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ਕਾਰਜ-ਸਥਾਨ"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"ਗੱਲਾਂਬਾਤਾਂ"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"ਨੋਟ ਬਣਾਉਣਾ"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"ਸ਼ਾਮਲ ਕਰੋ"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ਮਹੱਤਵਪੂਰਨ ਜਾਣਕਾਰੀ ਤੁਰੰਤ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ਐਪਾਂ ਨੂੰ ਖੋਲ੍ਹੇ ਬਿਨਾਂ ਜਾਣਕਾਰੀ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ, ਤੁਸੀਂ ਆਪਣੀ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਵਿਜੇਟ ਸ਼ਾਮਲ ਕਰ ਸਕਦੇ ਹੋ"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ਵਿਜੇਟ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ਫਿਲਟਰ"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ਇਹ ਕਾਰਵਾਈ ਅਸਫਲ ਹੋਈ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ਨਿੱਜੀ ਸਪੇਸ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ਨਿੱਜੀ ਐਪਾਂ ਨੂੰ ਲਾਕ ਕਰ ਕੇ ਅਦਿੱਖ ਰੱਖੋ"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"ਸੈੱਟਅੱਪ ਕਰਨ ਜਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ਨਿੱਜੀ"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ਨਿੱਜੀ ਸਪੇਸ ਸੰਬੰਧੀ ਸੈਟਿੰਗਾਂ"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ਨਿੱਜੀ ਸਪੇਸ ਨੂੰ ਲਾਕ/ਅਣਲਾਕ ਕਰੋ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index d67df82..18642d7 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ta para aplikacji nie jest obsługiwana na tym urządzeniu"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Otwórz urządzenie, aby użyć tej pary aplikacji"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Para aplikacji jest niedostępna"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Naciśnij i przytrzymaj, aby przenieść widżet."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Naciśnij dwukrotnie i przytrzymaj, aby przenieść widżet lub użyć działań niestandardowych."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Szerokość %1$d, wysokość %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d (szerokość), %3$d (wysokość)"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Aby poruszać widżetem po ekranie głównym, kliknij go i przytrzymaj"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj do ekranu głównego"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g> został dodany do ekranu głównego"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestie"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Niezbędne na co dzień"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Wiadomości dla Ciebie"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Niezbędne"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Wiadomości i czasopisma"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Strefa relaksu"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Zadbaj o swoją formę"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Nie daj się zaskoczyć pogodzie"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"To też może Cię zainteresować"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Rozrywka"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Społecznościowe"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdrowie i fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Pogoda"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Proponowane dla Ciebie"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widżety (<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>) po prawej, wyszukiwanie i opcje po lewej"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widżet}few{# widżety}many{# widżetów}other{# widżetu}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# skrót}few{# skróty}many{# skrótów}other{# skrótu}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Służbowe"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Rozmowy"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Notatki"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodaj"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Dodaj widżet <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Użyteczne informacje w zasięgu ręki"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Możesz dodać widżety do ekranu głównego, aby uzyskiwać informacje bez otwierania aplikacji"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Kliknij, aby zmienić ustawienia widżetu"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtruj"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Niepowodzenie: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Obszar prywatny"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Pozostaw aplikacje prywatne zablokowane i ukryte"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Kliknij, aby skonfigurować lub otworzyć"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Prywatne"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Ustawienia obszaru prywatnego"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Zablokuj/odblokuj obszar prywatny"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 2eb3567..fc70150 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Este par de apps não é suportado neste dispositivo"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Abra o dispositivo para usar este par de apps"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"O par de apps não está disponível"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque sem soltar para mover um widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes sem soltar para mover um widget ou utilizar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d de largura por %3$d de altura"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Toque sem soltar no widget para o mover no ecrã principal"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Adicionar ao ecrã principal"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> adicionado ao ecrã principal"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Os seus essenciais do dia a dia"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Notícias para si"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenciais"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícias e revistas"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"A sua zona de relaxamento"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Atingir os seus objetivos de fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Ficar a par da meteorologia"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Também poderá gostar de"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimento"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Redes sociais"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteorologia"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerido para si"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets de <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à direita, pesquisa e opções à esquerda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# atalho}other{# atalhos}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabalho"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Tomar notas"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Adicionar"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Adicione o widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informações úteis à sua disposição"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Para obter informações sem abrir apps, pode adicionar widgets ao seu ecrã principal"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toque para alterar as definições do widget"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrar"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Falhou: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espaço privado"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mantém as apps privadas bloqueadas e ocultas"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tocar para configurar ou abrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Definições do espaço privado"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloquear/desbloquear espaço privado"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 10111aa..0391efe 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Este Par de apps não está disponível no dispositivo"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Abra o dispositivo para usar este Par de apps"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Toque e pressione para mover um widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toque duas vezes e mantenha a tela pressionada para mover um widget ou usar ações personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d de largura por %2$d de altura"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>: %2$d de largura por %3$d de altura"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Toque no widget e o pressione para definir a posição dele na tela inicial"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Adicionar à tela inicial"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g> adicionado à tela inicial"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestões"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Seus itens diários essenciais"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Notícias para você"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essenciais"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Notícias e revistas"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Sua zona de relaxamento"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Alcance seus objetivos fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Fique por dentro da previsão do tempo"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Você também pode gostar de"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entretenimento"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Saúde e bem-estar"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Clima"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugestões para você"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgets da <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> à direita, pesquisa e opções à esquerda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# widgets}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# atalho}one{# atalho}other{# atalhos}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabalho"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversas"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Anotações"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Adicionar"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Adicionar o widget <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informações úteis ao seu alcance"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Para acessar informações sem precisar abrir os apps, adicione widgets à sua tela inicial"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Toque para mudar as configurações do widget"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrar"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Falha: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Espaço particular"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mantenha apps particulares bloqueados e ocultos"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Toque para configurar ou abrir"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Particular"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Configurações do Espaço particular"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Bloquear/desbloquear o Espaço particular"</string>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 9eab793..07f3cf4 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Perechea de aplicații nu este acceptată pe acest dispozitiv"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Deschide dispozitivul ca să folosești această pereche de aplicații"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Atinge și ține apăsat pentru a muta un widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Atinge de două ori și ține apăsat pentru a muta un widget sau folosește acțiuni personalizate."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d lățime și %2$d înălțime"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d lățime x %3$d înălțime"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Atinge lung widgetul pentru a-l muta pe ecranul de pornire"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Adaugă pe ecranul de pornire"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g> a fost adăugat pe ecranul de pornire"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugestii"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Instrumente esențiale de zi cu zi"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Știri pentru tine"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Esențiale"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Știri și reviste"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona de relaxare"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Atinge-ți obiectivele de fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Fii la curent cu prognoza meteo"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"S-ar putea să îți placă și"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Divertisment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Rețele sociale"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sănătate și fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Meteo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugerate pentru tine"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgeturi pentru <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> în dreapta, căutare și opțiuni în stânga"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}few{# widgeturi}other{# de widgeturi}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# comandă rapidă}few{# comenzi rapide}other{# de comenzi rapide}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Serviciu"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Conversații"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Luare de notițe"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Adaugă"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Adaugă widgetul <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informații utile la îndemâna ta"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Pentru a primi informații fără să deschizi aplicațiile, poți adăuga widgeturi pe ecranul de pornire"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Atinge ca să schimbi setările pentru widgeturi"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtru"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Eșuare: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Spațiu privat"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Păstrează aplicațiile private blocate și ascunse"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Atinge pentru a configura sau a deschide"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Setări spațiu privat"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Blochează / deblochează spațiul privat"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 0b42966..ee1caef 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Одновременно использовать эти два приложения на устройстве нельзя."</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Чтобы одновременно использовать эти два приложения, разложите устройство."</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Одновременное использование двух приложений недоступно"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Чтобы переместить виджет, нажмите на него и удерживайте"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Чтобы использовать специальные действия или перенести виджет, нажмите на него дважды и удерживайте."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d x %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина %1$d, высота %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\", ширина: %2$d, высота: %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Нажмите на виджет и удерживайте его, чтобы переместить в нужное место на главном экране."</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Добавить на главный экран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\" добавлен на главный экран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Подсказки"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Самое важное"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Новости для вас"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Главное"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новости и журналы"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Развлечение и общение"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Ваши фитнес-цели"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Прогноз погоды"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Другие рекомендации"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Развлечения"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Общение"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здоровье и спорт"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Погода"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Рекомендации"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Виджеты приложения \"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>\" находятся справа, а панель поиска и настройки – слева"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виджет}one{# виджет}few{# виджета}many{# виджетов}other{# виджета}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ярлык}one{# ярлык}few{# ярлыка}many{# ярлыков}other{# ярлыка}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Рабочие виджеты"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Разговоры"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Создание заметок"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Добавить"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Добавить виджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Вся нужная информация перед глазами"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Чтобы не открывать приложения каждый раз, когда нужна информация, добавьте виджеты на главный экран."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Нажмите, чтобы изменить настройки виджета"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Фильтр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не удалось выполнить действие (<xliff:g id="WHAT">%1$s</xliff:g>)."</string>
     <string name="private_space_label" msgid="2359721649407947001">"Личное пространство"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Приложения в личном пространстве скрыты и доступны только вам"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Нажмите, чтобы настроить или открыть"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Доступно только вам"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Настройки личного пространства"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Блокировка и разблокировка личного пространства"</string>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index ad5d158..25cc880 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"මෙම යෙදුම් යුගලය මෙම උපාංගයෙහි සහාය නොදක්වයි"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"මෙම යෙදුම් යුගලය භාවිතා කිරීමට උපාංගය දිගහරින්න"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"විජට් එකක් ගෙන යාමට ස්පර්ශ කර අල්ලා ගෙන සිටින්න."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"විජට් එකක් ගෙන යාමට හෝ අභිරුචි ක්‍රියා භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"පළල %1$d උස %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට්ටුව"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට්ටුව, %2$d පළල සහ උස %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"විජට් එක මුල් පිටු තිරය වටා ගෙන යාමට විජට් එක ස්පර්ශ කර අල්ලාගෙන සිටින්න"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"මුල් තිරය වෙත එක් කරන්න"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට්ටුව මුල් පිටු තිරය වෙත එක් කරන ලදි"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"යෝජනා"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"ඔබේ දෛනික අත්‍යවශ්‍යාංග"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ඔබ වෙනුවෙන් පුවත්"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"අත්‍යවශ්‍යාංග"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"පුවත් සහ සඟරා"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"ඔබේ නිවුණු කලාපය"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ඔබේ යෝග්‍යතා ඉලක්ක ළඟා කර ගන්න"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"කාලගුණයට ඉදිරියෙන් සිටින්න"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"ඔබ මේවාට ද කැමති විය හැක"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"විනෝදාස්වාදය"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"සමාජයීය"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"සෞඛ්‍යය සහ යෝග්‍යතාව"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"කාලගුණ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"ඔබ සඳහා යෝජිත"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"දකුණේ <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> විජට්, වමේ සෙවීම සහ විකල්ප"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{විජට් #}one{විජට් #}other{විජට් #}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{කෙටි මං #}one{කෙටි මං #}other{කෙටි මං #}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"කාර්යාලය"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"සංවාද"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"සටහන් කර ගැනීම"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"එක් කරන්න"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> විජට්ටුව එක් කරන්න"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"ප්‍රයෝජනවත් තොරතුරු ඔබගේ ඇඟිලි තුඩු අග"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"යෙදුම් විවෘත නොකර තොරතුරු ලබා ගැනීම සඳහා, ඔබට ඔබගේ මුල් තිරයට විජට් එක් කළ හැකිය"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"විජට් සැකසීම් වෙනස් කිරීමට තට්ටු කරන්න"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"පෙරහන"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"අසාර්ථකයි: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"පෞද්ගලික ඉඩ"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"පෞද්ගලික යෙදුම් අගුලු දමා සඟවා තබා ගන්න"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"පිහිටුවීමට හෝ විවෘත කිරීමට තට්ටු කරන්න"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"පෞද්ගලික"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"පෞද්ගලික අවකාශ සැකසීම්"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"පෞද්ගලික අවකාශය අගුළු දමන්න/අගුළු හරින්න"</string>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index f1bf7eb..cf87cf8 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Tento pár aplikácií nie je v tomto zariadení podporovaný"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Ak chcete používať tento pár aplikácií, rozložte zariadenie"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Pár aplikácií nie je k dispozícii"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Pridržaním presuňte miniaplikáciu."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvojitým klepnutím a pridržaním presuňte miniaplikáciu alebo použite vlastné akcie."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"šírka %1$d, výška %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d na šírku, %3$d na výšku"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pridržaním môžete miniaplikáciu posúvať po ploche"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Pridať na plochu"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Na plochu bola pridaná miniaplikácia <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Návrhy"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Vaše každodenné základné položky"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Vaše správy"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Všetko dôležité"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Noviny a časopisy"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaša komfortná zóna"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Dosiahnite svoje kondičné ciele"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Získavajte informácie o počasí v predstihu"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Mohlo by sa vám páčiť"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Zábava"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sociálne siete"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravie a kondícia"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Počasie"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Navrhnuté pre vás"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Miniaplikácie <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vpravo, vyhľadávanie a možnosti vľavo"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikácia}few{# miniaplikácie}many{# widgets}other{# miniaplikácií}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# odkaz}few{# odkazy}many{# shortcuts}other{# odkazov}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Práca"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Konverzácie"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Zapisovanie poznámok"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Pridať"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Pridať miniaplikáciu <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Užitočné informácie poruke"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Ak chcete získavať informácie bez otvárania aplikácií, môžete si na plochu pridať miniaplikácie"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Klepnutím zmeňte nastavenia miniaplikácie"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtrujte"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Zlyhalo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Súkromný priestor"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Ponechajte súkromné aplikácie uzamknuté a skryté"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Klepnutím nastavte alebo otvorte"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Súkromné"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Nastavenia súkromného priestoru"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Súkromný priestor zamykania a odomykania"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 9472e44..8693ea2 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ta par aplikacij ni podprt v tej napravi"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Razprite napravo, če želite uporabljati ta par aplikacij"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Par aplikacij ni na voljo"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Pridržite pripomoček, da ga premaknete."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Dvakrat se dotaknite pripomočka in ga pridržite, da ga premaknete, ali pa uporabite dejanja po meri."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Širina %1$d, višina %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Pripomoček <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Pripomoček »<xliff:g id="WIDGET_NAME">%1$s</xliff:g>«, širina: %2$d, višina: %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Dotaknite se pripomočka in ga pridržite, če ga želite premikati po začetnem zaslonu."</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Dodaj na začetni zaslon"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Pripomoček »<xliff:g id="WIDGET_NAME">%1$s</xliff:g>« je dodan na začetni zaslon."</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Predlogi"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Vaše dnevne potrebščine"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Novice za vas"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Nepogrešljivo"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Novice in revije"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Vaš kotiček za sprostitev"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Dosegajte cilje glede telesne pripravljenosti"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Bodite na tekočem z vremenom"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Morda vam bo všeč tudi"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Razvedrilo"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Družbeno"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Zdravje in fitnes"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Vreme"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Predlagano za vas"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Pripomočki <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> na desni, iskanje in možnosti na levi"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# pripomoček}one{# pripomoček}two{# pripomočka}few{# pripomočki}other{# pripomočkov}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# bližnjica}one{# bližnjica}two{# bližnjici}few{# bližnjice}other{# bližnjic}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Služba"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Pogovori"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Ustvarjanje zapiskov"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Dodaj"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Dodajanje pripomočka »<xliff:g id="WIDGET_NAME">%1$s</xliff:g>«"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Koristne informacije na dosegu prstov"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Če si želite podatke ogledati brez odpiranja aplikacij, lahko na začetni zaslon dodate pripomočke."</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Dotaknite se, če želite spremeniti nastavitve pripomočka."</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtriranje"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Ni uspelo: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Zasebni prostor"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Naj vaše zasebne aplikacije ostanejo zaklenjene in skrite"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Dotaknite se, da nastavite ali odprete"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Zasebno"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Nastavitve zasebnega prostora"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Zaklepanje/odklepanje zasebnega prostora"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index bfc6fb3..7643c4a 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ky çift aplikacionesh nuk mbështetet në këtë pajisje"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Shpalose pajisjen për të përdorur këtë çift aplikacionesh"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Prek dhe mbaj shtypur një miniaplikacion për ta zhvendosur."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Trokit dy herë dhe mbaje shtypur një miniapliikacion për ta zhvendosur atë ose për të përdorur veprimet e personalizuara."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d i gjerë me %2$d i lartë"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> miniaplikacion"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Miniaplikacioni <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, me gjerësi %2$d dhe lartësi %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Prek dhe mbaj të shtypur miniaplikacionin për ta lëvizur atë nëpër ekranin bazë"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Shto në ekranin bazë"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Miniaplikacioni <xliff:g id="WIDGET_NAME">%1$s</xliff:g> u shtua në ekranin bazë"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Sugjerime"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Aplikacionet thelbësore të përditshme"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Lajme për ty"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Thelbësoret"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Lajme dhe revista"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Zona jote e qetësisë"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Realizo objektivat e stërvitjes"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Qëndro i informuar për motin"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Gjithashtu mund të të pëlqejë"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Argëtim"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Rrjetet sociale"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Shëndet dhe fitnes"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Moti"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sugjeruar për ty"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Miniaplikacionet e <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> në të djathtë, kërkimi dhe opsionet në të majtë"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# miniaplikacion}other{# miniaplikacione}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shkurtore}other{# shkurtore}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Puna"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Bisedat"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Mbajtja e shënimeve"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Shto"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Shto miniaplikacionin <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Informacione të dobishme në majë të gishtave të tu"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Për të marrë informacione pa i hapur aplikacionet, mund të shtosh miniaplikacione në ekranin bazë"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Trokit për të ndryshuar cilësimet e miniaplikacionit"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtro"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Dështoi: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Hapësira private"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Mbaji të kyçura dhe të fshehura aplikacionet private"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Trokit për të konfiguruar ose për të hapur"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Private"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Cilësimet e \"Hapësirës private\""</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Kyç/Shkyç \"Hapësirën private\""</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 03eb603..9535dc0 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Овај пар апликација није подржан на овом уређају"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Отворите уређај да бисте користили овај пар апликација"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Пар апликација није доступан"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Додирните и задржите ради померања виџета."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двапут додирните и задржите да бисте померали виџет или користите прилагођене радње."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d×%2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"ширина од %1$d и висина од %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виџет"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> виџет, ширина %2$d и висина %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Додирните и задржите виџет да бисте га померали по почетном екрану"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Додај на почетни екран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Додали сте виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g> на почетни екран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Предлози"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Основни виџети за сваки дан"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Вести за вас"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Неопходне апликације"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новости и часописи"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Зона за опуштање"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Остварите фитнес циљеве"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Будите у току са временским приликама"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Можда ће вам се допасти и"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Забава"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Друштвене мреже"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здравље и фитнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Време"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Предложено за вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Виџети <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> са десне стране, претрага и опције са леве стране"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# виџет}one{# виџет}few{# виџета}other{# виџета}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# пречица}one{# пречица}few{# пречице}other{# пречица}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Посао"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Конверзације"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Прављење бележака"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Додај"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Додајте виџет <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Корисне информације надохват руке"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Да бисте пронашли информације без отварања апликација, можете да додате виџете на почетни екран"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Додирните да бисте променили подешавања виџета"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Филтер"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Није успело: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Приватни простор"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Нека приватне апликације буду закључане и сакривене"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Додирните да бисте подесили или отворили"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Приватно"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Подешавања приватног простора"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Закључај/откључај приватни простор"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index dab8407..fd34dee 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"De här apparna som ska användas tillsammans stöds inte på den här enheten"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Vik upp enheten för att använda de här apparna som ska användas tillsammans"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Tryck länge för att flytta en widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Tryck snabbt två gånger och håll kvar för att flytta en widget eller använda anpassade åtgärder."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d bred gånger %2$d hög"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Widget för <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widgeten <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d i bredd och %3$d i höjd"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Tryck länge på widgeten om du vill flytta den på startskärmen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Lägg till på startskärmen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Widget för <xliff:g id="WIDGET_NAME">%1$s</xliff:g> har lagts till på startskärmen"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Förslag"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Det viktigaste i vardagen"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Nyheter för dig"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Favoriter"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Nyheter och tidskrifter"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Koppla av"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Nå dina träningsmål"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Håll koll på vädret"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Andra appar du kanske gillar"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Underhållning"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Socialt"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Hälsa och träning"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Väder"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Våra förslag"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Widgetar för <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> till höger, sökning och alternativ till vänster"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widgetar}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# genväg}other{# genvägar}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Arbete"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Konversationer"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Anteckna"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Lägg till"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Lägg till widgeten <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Användbar information nära till hands"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Om du vill ha information utan att öppna appar kan du lägga till widgetar på startskärmen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Tryck för att ändra inställningarna för widgeten"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Misslyckades: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Privat rum"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Håll privata appar låsta och dolda"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Tryck för att ställa in eller öppna"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Privat"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Inställningar för privat rum"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Lås eller lås upp ditt privata rum"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 193c92e..8d74b83 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Jozi hii ya programu haitumiki kwenye kifaa hiki"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Fungua kifaa ili utumie jozi hii ya programu"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Kipengele cha jozi ya programu hakipatikani"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Gusa na ushikilie ili usogeze wijeti."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Gusa mara mbili na ushikilie ili usogeze wijeti au utumie vitendo maalum."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Upana wa %1$d na kimo cha %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, upana wa %2$d kwa urefu wa %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Gusa na ushikilie wijeti ili uisogeze kwenye skrini ya kwanza"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Weka kwenye skrini ya kwanza"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Umeongeza wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g> kwenye skrini ya kwanza"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mapendekezo"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Hati Zako Muhimu za Kila Siku"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Habari Kwa Ajili Yako"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Habari na magazeti"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Mahali Pako pa Kupumzika"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Fikia Malengo Yako ya Siha"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Pata Taarifa kuhusu Hali ya Hewa"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Huenda Pia Ukapenda"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Burudani"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mitandao jamii"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Afya na siha"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hali ya Hewa"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Unayopendekezewa"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Wijeti za <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ziko upande wa kulia, utafutaji na chaguo ziko upande wa kushoto"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{Wijeti #}other{Wijeti #}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{Njia # ya mkato}other{Njia # za mkato}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Kazini"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Mazungumzo"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Kuandika madokezo"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Weka"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Weka wijeti ya <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Maelezo muhimu, popote ulipo"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Ili upate maelezo bila kufungua programu, unaweza kuweka wijeti kwenye skrini yako ya kwanza"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Gusa ili ubadilishe mipangilio ya wijeti"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Kichujio"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Hitilafu: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Nafasi ya faragha"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Funga na ufiche programu za faragha"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Gusa ili uweke mipangilio au ufungue"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Faragha"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Mipangilio ya Nafasi ya Faragha"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Funga/Fungua Nafasi ya Faragha"</string>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 3c79588..27aba6b 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -37,6 +37,7 @@
 
 <!-- Widget picker-->
     <dimen name="widget_list_horizontal_margin">30dp</dimen>
+    <dimen name="widget_cell_horizontal_padding">16dp</dimen>
 
     <!--  Folder spaces  -->
     <dimen name="folder_footer_horiz_padding">24dp</dimen>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 2f79f40..6baa6b1 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"இந்தச் சாதனத்தில் இந்த ஆப்ஸ் ஜோடி ஆதரிக்கப்படவில்லை"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"இந்த ஆப்ஸ் ஜோடியைப் பயன்படுத்த சாதனத்தை விரியுங்கள்"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"விட்ஜெட்டை நகர்த்தத் தொட்டுப் பிடிக்கவும்."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"விட்ஜெட்டை நகர்த்த இருமுறை தட்டிப் பிடிக்கவும் அல்லது பிரத்தியேகச் செயல்களைப் பயன்படுத்தவும்."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d அகலத்திற்கு %2$d உயரம்"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட்"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட், %2$d அகலம் மற்றும் %3$d உயரம்"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"முகப்புத் திரையைச் சுற்றி விட்ஜெட்டை நகர்த்த அதைத் தொட்டுப் பிடியுங்கள்"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"முகப்புத் திரையில் சேர்"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட் முகப்புத் திரையில் சேர்க்கப்பட்டது"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"பரிந்துரைகள்"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"உங்கள் தினசரி அத்தியாவசியத் தேவைகள்"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"உங்களுக்கான செய்திகள்"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"அத்தியாவசியமானவை"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"செய்திகள் &amp; பத்திரிக்கைகள்"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"உங்கள் மனதுக்கு இதமானவை"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"உடற்பயிற்சி இலக்குகளை அடையுங்கள்"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"வானிலை குறித்து முன்கூட்டியே அறிந்திருங்கள்"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"நீங்கள் இவற்றையும் விரும்பக்கூடும்"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"பொழுதுபோக்கு"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"சமூகம்"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ஆரோக்கியம் &amp; உடற்பயிற்சி"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"வானிலை"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"உங்களுக்கான பரிந்துரைகள்"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> விட்ஜெட்கள் வலதுபுறத்தில் உள்ளன, தேடல் மற்றும் விருப்பங்கள் இடதுபுறத்தில் உள்ளன"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# விட்ஜெட்}other{# விட்ஜெட்டுகள்}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ஷார்ட்கட்}other{# ஷார்ட்கட்கள்}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"பணி"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"உரையாடல்கள்"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"குறிப்பெடுத்தல்"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"சேர்"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> விட்ஜெட்டைச் சேர்க்கும்"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"விரல்நுனியில் பயனுள்ள தகவல்களைப் பெறுங்கள்"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"முகப்புத் திரையில் விட்ஜெட்டுகளைச் சேர்த்து ஆப்ஸைத் திறக்காமலேயே தகவல்களைப் பெறலாம்"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"விட்ஜெட் அமைப்புகளை மாற்றத் தட்டவும்"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"வடிப்பான்"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"தோல்வி: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"தனிப்பட்ட சேமிப்பிடம்"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"தனிப்பட்ட ஆப்ஸை லாக் செய்தும் மறைத்தும் வைக்கலாம்"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"அமைக்கவோ திறக்கவோ தட்டுங்கள்"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"தனிப்பட்டது"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"தனிப்பட்ட சேமிப்பிட அமைப்புகள்"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"தனிப்பட்ட சேமிப்பிடத்தை லாக்/அன்லாக் செய்யும்"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 5f104e2..daa90fa 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ఈ పరికరంలో ఈ యాప్ పెయిర్ సపోర్ట్ చేయదు"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ఈ యాప్ పెయిర్‌ను ఉపయోగించడానికి పరికరాన్ని అన్‌ఫోల్డ్ చేయండి"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"యాప్ పెయిర్ అందుబాటులో లేదు"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"విడ్జెట్‌ను తరలించడానికి తాకి &amp; నొక్కి ఉంచండి."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"విడ్జెట్‌ను తరలించడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కండి &amp; హోల్డ్ చేయి."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d వెడల్పు X %2$d ఎత్తు"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్, %2$d వెడల్పు %3$d ఎత్తు ఉండాలి"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"విడ్జెట్‌ను మొదటి స్క్రీన్‌లో తిప్పడానికి దాన్ని తాకి, &amp; నొక్కి పట్టుకోండి"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"మొదటి స్క్రీన్‌కు జోడించండి"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"మొదటి స్క్రీన్‌కు <xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్ జోడించబడింది"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"సూచనలు"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"మీ రోజువారీ అవసరాలు"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"మీ కోసం వార్తలు"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Essentials"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"వార్తలు &amp; మ్యాగజైన్లు"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"మీరు ప్రశాంతంగా ఉండే ప్రదేశం"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"ఫిట్‌నెస్ లక్ష్యాలను చేరుకోండి"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"వాతావరణాన్ని ముందుగానే తెలుసుకోండి"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"మీరు వీటిని కూడా ఇష్టపడవచ్చు"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"వినోదం"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"సామాజికం"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"ఆరోగ్యం &amp; ఫిట్‌నెస్"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"వాతావరణం"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"మీ కోసం సూచించినవి"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"కుడి వైపున <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> విడ్జెట్‌లు, ఎడమ వైపున సెర్చ్, ఇతర ఆప్షన్‌లు"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# విడ్జెట్}other{# విడ్జెట్‌లు}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# షార్ట్‌కట్}other{# షార్ట్‌కట్‌లు}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"ఆఫీస్"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"సంభాషణలు"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"నోట్-టేకింగ్"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"జోడించండి"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> విడ్జెట్‌ను జోడించండి"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"మీ చేతివేళ్ల మీద ఉపయోగకరమైన సమాచారం"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"యాప్‌లను తెరవకుండా సమాచారాన్ని పొందడానికి, మీరు మీ మొదటి స్క్రీన్‌కు విడ్జెట్‌లను జోడించవచ్చు"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"విడ్జెట్ సెట్టింగ్‌లను మార్చడానికి ట్యాప్ చేయండి"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ఫిల్టర్ చేయి"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"విఫలమైంది: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"ప్రైవేట్ స్పేస్"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ప్రైవేట్ యాప్‌లను లాక్ చేసి దాచి ఉంచండి"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"సెటప్ చేయడానికి లేదా తెరవడానికి ట్యాప్ చేయండి"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ప్రైవేట్"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"ప్రైవేట్ స్పేస్ సెట్టింగ్‌లు"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ప్రైవేట్ స్పేస్‌ను లాక్/అన్‌లాక్ చేయండి"</string>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 256c77a..efcd36f 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ไม่รองรับคู่แอปนี้ในอุปกรณ์เครื่องนี้"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"กางอุปกรณ์เพื่อใช้คู่แอปนี้"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"การจับคู่อุปกรณ์ไม่พร้อมให้บริการ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"แตะค้างไว้เพื่อย้ายวิดเจ็ต"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"แตะสองครั้งค้างไว้เพื่อย้ายวิดเจ็ตหรือใช้การดำเนินการที่กำหนดเอง"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"กว้าง %1$d x สูง %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"วิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"วิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, กว้าง %2$d สูง %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"แตะวิดเจ็ตค้างไว้เพื่อย้ายไปรอบๆ หน้าจอหลัก"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"เพิ่มลงในหน้าจอหลัก"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"เพิ่มวิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g> ลงในหน้าจอหลักแล้ว"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"คำแนะนำ"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"สิ่งจำเป็นในชีวิตประจำวันของคุณ"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"ข่าวสารสำหรับคุณ"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"รายการที่ห้ามพลาด"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"ข่าวสารและนิตยสาร"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"พื้นที่สบายๆ ของคุณ"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"บรรลุเป้าหมายการออกกำลังกาย"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"รู้สภาพอากาศล่วงหน้า"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"คุณอาจชอบ"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"ความบันเทิง"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"โซเชียล"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"สุขภาพและการออกกำลังกาย"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"สภาพอากาศ"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"แนะนำให้คุณ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"วิดเจ็ต<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>ทางด้านขวา การค้นหาและตัวเลือกทางด้านซ้าย"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{วิดเจ็ต # รายการ}other{วิดเจ็ต # รายการ}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{ทางลัด # รายการ}other{ทางลัด # รายการ}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"งาน"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"การสนทนา"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"การจดบันทึก"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"เพิ่ม"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"เพิ่มวิดเจ็ต <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"เข้าถึงข้อมูลที่เป็นประโยชน์ได้จากปลายนิ้ว"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"หากต้องการรับข้อมูลโดยไม่เปิดแอป ให้เพิ่มวิดเจ็ตลงในหน้าจอหลัก"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"แตะเพื่อเปลี่ยนการตั้งค่าวิดเจ็ต"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"ตัวกรอง"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ไม่สำเร็จ: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"พื้นที่ส่วนตัว"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"ล็อกและซ่อนแอปส่วนตัวไว้"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"แตะเพื่อตั้งค่าหรือเปิด"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"ส่วนตัว"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"การตั้งค่าพื้นที่ส่วนตัว"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"ล็อก/ปลดล็อกพื้นที่ส่วนตัว"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 16c9cb8..27c2dd8 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Hindi sinusuportahan sa device na ito ang pares ng app na ito"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"I-unfold ang device para magamit ang pares ng app na ito"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"Hindi available ang pares ng app"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Pindutin nang matagal para ilipat ang widget."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"I-double tap at pindutin nang matagal para ilipat ang widget o gumamit ng mga custom na pagkilos."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ang lapad at %2$d ang taas"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Widget na <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, %2$d ang lapad at %3$d ang taas"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Pindutin nang matagal ang widget para ilipat-lipat ito sa home screen"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Idagdag sa home screen"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Idinagdag sa home screen ang widget na <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Mga Suhestyon"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Ang Pang-araw-araw Mong Mga Essential"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Balita para sa Iyo"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Mga essential"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Balita at mga magazine"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ang Iyong Chill Zone"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Makamit ang Iyong Mga Layunin sa Fitness"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Manatiling Handa sa Lagay ng Panahon"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Baka Magustuhan Mo Rin"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Entertainment"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Social"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Kalusugan at fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Lagay ng panahon"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Iminumungkahi para sa iyo"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Mga widget ng <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> sa kanan, paghahanap at mga opsyon sa kaliwa"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}one{# widget}other{# na widget}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# shortcut}one{# shortcut}other{# na shortcut}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Trabaho"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Mga Pag-uusap"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Pagtatala"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Idagdag"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Idagdag ang widget na <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Abot-kamay na mahalagang impormasyon"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Para makakuha ng impormasyon nang hindi nagbubukas ng mga app, puwede kang magdagdag ng mga widget sa iyong home screen"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"I-tap para baguhin ang mga setting ng widget"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filter"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Hindi nagawa: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Pribadong space"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Panatilihing naka-lock at nakatago ang mga pribadong app"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"I-tap para i-set up o buksan"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Pribado"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Mga Setting ng Pribadong Space"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"I-lock/I-unlock ang Pribadong Space"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 7633940..b4743d6 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Bu uygulama çifti bu cihazda desteklenmiyor"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Bu uygulama çiftini kullanmak için katlanmış durumda olan cihazı açın"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Widget\'ı taşımak için dokunup basılı tutun."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Widget\'ı taşımak veya özel işlemleri kullanmak için iki kez dokunup basılı tutun."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"genişlik: %1$d, yükseklik: %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı, %2$d genişlik x %3$d yükseklik"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Ana ekranda taşımak için widget\'a dokunup basılı tutun"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Ana ekrana ekle"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı ana ekrana eklendi"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Öneriler"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Günlük Gerekenler"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Size özel haberler"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Kaçırmamanız gerekenler"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Haberler ve dergiler"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Huzur alanınız"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Fitness hedeflerinize ulaşın"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Havanın durumu sizi şaşırtmasın"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Şunları da beğenebilirsiniz"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Eğlence"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Sosyal"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sağlık ve fitness"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Hava durumu"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sizin için önerilenler"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> widget\'ları sağda, arama ve seçenekler solda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# widget}other{# widget}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# kısayol}other{# kısayol}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"İş"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Görüşmeler"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Not alma"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Ekle"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> widget\'ı ekle"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Faydalı bilgiler parmaklarınızın ucunda"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Uygulama açmadan bilgi almak için ana ekranınıza widget ekleyebilirsiniz"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Widget ayarlarını değiştirmek için dokunun"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Filtre"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Başarısız: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Gizli alan"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Özel uygulamaları kilitli ve gizli tutun"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Kurmak veya açmak için dokunun"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Gizli"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Gizli Alan Ayarları"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Gizli Alanı Kilitleyin/Kilidini Açın"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 7f56e1b..d09e51b 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Ці два додатки не можна одночасно використовувати на цьому пристрої"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Розкладіть пристрій, щоб одночасно використовувати ці два додатки"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Натисніть і втримуйте, щоб перемістити віджет."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Двічі натисніть і втримуйте віджет, щоб перемістити його або виконати інші дії."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Ширина – %1$d, висота – %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Віджет <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Віджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\", ширина: %2$d, висота: %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Натисніть і втримуйте віджет, щоб перемістити його в потрібне місце на головному екрані"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Додати на головний екран"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Віджет <xliff:g id="WIDGET_NAME">%1$s</xliff:g> додано на головний екран"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Пропозиції"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Найнеобхідніше на кожен день"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Новини для вас"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Основне для роботи"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Новини й журнали"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Ваша зона розваг"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Досягайте своїх фітнес-цілей"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Завчасно дізнавайтеся про зміни погоди"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Вам також може сподобатися"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Розваги"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Соціальні мережі"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Здоров’я і фітнес"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Погода"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Пропозиції для вас"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>: віджети праворуч, пошук і опції ліворуч"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# віджет}one{# віджет}few{# віджети}many{# віджетів}other{# віджета}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ярлик}one{# ярлик}few{# ярлики}many{# ярликів}other{# ярлика}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Робочі"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Розмови"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Створення нотаток"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Додати"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Додати віджет \"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>\""</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Корисна інформація завжди під рукою"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Щоб отримувати інформацію, не відкриваючи додатки, ви можете додати на головний екран віджети"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Натисніть, щоб змінити налаштування віджета"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Фільтр"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Не вдалося <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Приватний простір"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Зберігайте приватні додатки в прихованому й заблокованому сховищі"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Натисніть, щоб налаштувати або відкрити"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Приватні"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Налаштування приватного простору"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Заблокувати/розблокувати приватний простір"</string>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index c945bab..50334a0 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -33,21 +33,25 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"ایپس کا یہ جوڑا اس آلے پر تعاون یافتہ نہیں ہے"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"ایپس کے اس جوڑے کا استعمال کرنے کیلئے آلے کو اَن فولڈ کریں"</string>
+    <string name="app_pair_not_available" msgid="3556767440808032031">"ایپ کا جوڑا دستیاب نہیں ہے"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ویجیٹ منتقل کرنے کے لیے ٹچ کریں اور پکڑ کر رکھیں۔"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ویجیٹ کو منتقل کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کے لیے دوبار تھپتھپائیں اور پکڑ کر رکھیں۔"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"‏%1$d چوڑا اور ‎%2$d اونچا"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"‏<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ، ‏%2$d چوڑا اور ‏%3$d اونچا ہے"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"ویجیٹ کو ہوم اسکرین کے چاروں طرف منتقل کرنے کے لیے اسے ٹچ کریں اور دبائے رکھیں"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"ہوم اسکرین میں شامل کریں"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ کو ہوم اسکرین میں شامل کیا گیا"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"تجاویز"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"آپ کے روز مرہ کے لوازمات"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"آپ کے لیے خبریں"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"لوازمات"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"خبریں اور میگزینز"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"آپ کا آرام دہ زون"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"اپنی تندرستی کے مقاصد حاصل کریں"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"موسم سے باخبر رہیں"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"آپ کو یہ بھی پسند آ سکتا ہے"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"تفریح"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"سماجی"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"صحت اور تندرستی"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"موسم"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"آپ کے لیے تجویز کردہ"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> دائیں طرف وجیٹس، بائیں طرف تلاش اور اختیارات"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ویجیٹ}other{# ویجیٹس}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# شارٹ کٹ}other{# شارٹ کٹس}}"</string>
@@ -61,6 +65,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"دفتری ویجیٹس"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"گفتگوئیں"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"نوٹ لکھنا"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"شامل کریں"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ویجیٹ شامل کریں"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"مفید معلومات کو آسانی سے حاصل کریں"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"ایپس کو کھولے بغیر معلومات حاصل کرنے کے لیے آپ اپنی ہوم اسکرین پر ویجیٹس شامل کر سکتے ہیں"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"ویجیٹ ترتیبات تبدیل کرنے کے لیے تھپتھپائیں"</string>
@@ -183,7 +189,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"فلٹر"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"ناکام ہو گيا: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"نجی اسپیس"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"نجی ایپس کو مقفل اور پوشیدہ رکھیں"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"سیٹ اپ کرنے یا کھولنے کے لیے تھپتھپائیں"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"نجی"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"نجی اسپیس کی ترتیبات"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"نجی اسپیس کو مقفل کریں/غیر مقفل کریں"</string>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 4fbacb7..795a495 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Bu ilova jufti ushbu qurilmada ishlamaydi"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Bu ilova juftidan foydalanish uchun qurilmani oching"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Vidjetni bosib turgan holatda suring."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Eni %1$d, bo‘yi %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> ta vidjet"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidjeti, eniga: %2$d, boʻyiga: %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Bosh ekranda surish uchun vidjet ustiga bosib turing"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Bosh ekranga chiqarish"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidjeti bosh ekranga qoʻshildi"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Takliflar"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Kunlik muhim vazifalaringiz"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Siz uchun yangiliklar"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Asosiy ilovalar"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Gazeta va jurnallar"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Sokin hududingiz"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Fitness maqsadlaringizga erishing"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Doim ob-havodan oldinda yuring"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Sizga yoqishi mumkin"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Hordiq"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Ijtimoiy"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Salomatlik va sport"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Ob-havo"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Sizga tavsiya etiladi"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"<xliff:g id="SELECTED_HEADER">%1$s</xliff:g> vidjetlari oʻngda, qidiruv va sozlamalar chapda"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# ta vidjet}other{# ta vidjet}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# ta yorliq}other{# ta yorliq}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Ish"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Suhbatlar"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Qayd olish"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Chiqarish"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g> vidjetini chiqarish"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Barcha kerakli axborot doim yoningizda"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Kerakli ilovalarni ochmasdan turib ulardan axborot olish uchun vidjetlarni bosh ekranga chiqaring"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Vidjet sozlamalarini oʻzgartirish uchun bosing"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Saralash"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Xato: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Shaxsiy xona"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Maxfiy ilovalar qulflangan va yashirin saqlansin"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Sozlash yoki ochish uchun bosing"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Yopiq"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Shaxsiy xona sozlamalari"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Shaxsiy xonani ochish/qulflash"</string>
diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml
index e2f610e..fa87221 100644
--- a/res/values-v31/colors.xml
+++ b/res/values-v31/colors.xml
@@ -47,8 +47,8 @@
 
     <color name="wallpaper_popup_scrim">@android:color/system_neutral1_900</color>
 
-    <color name="folder_pagination_color_light">@android:color/system_accent1_600</color>
-    <color name="folder_pagination_color_dark">@android:color/system_accent1_200</color>
+    <color name="page_indicator_dot_color_light">@android:color/system_accent1_600</color>
+    <color name="page_indicator_dot_color_dark">@android:color/system_accent1_200</color>
 
     <color name="home_settings_header_accent">@android:color/system_accent1_600</color>
     <color name="home_settings_header_collapsed">@android:color/system_neutral1_100</color>
@@ -97,6 +97,10 @@
         @android:color/system_neutral2_700</color>
     <color name="widget_picker_collapse_handle_color_light">
         @android:color/system_neutral2_200</color>
+    <color name="widget_picker_add_button_background_color_light">
+        @android:color/system_accent1_600</color>
+    <color name="widget_picker_add_button_text_color_light">
+        @android:color/system_accent1_0</color>
 
     <color name="work_fab_bg_color">
         @android:color/system_accent1_200</color>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 290adac..99bf064 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Cặp ứng dụng này không hoạt động được trên thiết bị này"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Hãy mở thiết bị để dùng cặp ứng dụng này"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Chạm và giữ để di chuyển một tiện ích."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Nhấn đúp và giữ để di chuyển một tiện ích hoặc sử dụng các thao tác tùy chỉnh."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"Rộng %1$d x cao %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g>, rộng %2$d x cao %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Chạm và giữ tiện ích để di chuyển tiện ích đó xung quanh màn hình chính"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Thêm vào màn hình chính"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Đã thêm tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g> vào màn hình chính"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Nội dung đề xuất"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Các tiện ích thiết yếu hằng ngày của bạn"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Tin tức cho bạn"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Các tiện ích thiết yếu"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Tin tức và tạp chí"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Giai điệu thư giãn của bạn"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Đạt được mục tiêu tập thể dục"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Luôn nắm bắt tình hình thời tiết"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Có thể bạn cũng thích"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Giải trí"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Mạng xã hội"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Sức khoẻ và thể chất"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Thời tiết"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Đề xuất cho bạn"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Tiện ích <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> ở bên phải, công cụ tìm kiếm và tuỳ chọn ở bên trái"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# tiện ích}other{# tiện ích}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# lối tắt}other{# lối tắt}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Công việc"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Cuộc trò chuyện"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Ghi chú"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Thêm"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Thêm tiện ích <xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Thông tin hữu ích ngay trong tầm tay bạn"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Để nhận thông tin mà không cần mở các ứng dụng, bạn có thể thêm tiện ích vào màn hình chính"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Nhấn để thay đổi chế độ cài đặt tiện ích"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Bộ lọc"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Không thực hiện được thao tác: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Không gian riêng tư"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Luôn khoá và ẩn các ứng dụng riêng tư"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Nhấn để thiết lập hoặc mở"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Riêng tư"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Cài đặt không gian riêng tư"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Khoá/mở khoá không gian riêng tư"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 4c95167..2b4abe1 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"在该设备上无法使用此应用对"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"展开设备即可使用此应用组合"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"轻触并按住即可移动微件。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"点按两次并按住微件即可移动该微件或使用自定义操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"宽 %1$d,高 %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件,宽 %2$d,高 %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"轻触并按住此微件即可在主屏幕上随意移动"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"添加到主屏幕"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已将“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件添加到主屏幕"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建议"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"您的日常必需品"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"更多相关新闻"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必备"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新闻与杂志"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"您的休闲区"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"达成您的健身目标"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"天气早知道"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"您可能还会喜欢"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娱乐"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社交"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康与健身"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天气"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"为您推荐"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右边是<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>微件,左边是搜索功能和选项"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 个微件}other{# 个微件}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 个快捷方式}other{# 个快捷方式}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"对话"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"记事"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"添加"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"添加“<xliff:g id="WIDGET_NAME">%1$s</xliff:g>”微件"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"实用信息触手可及"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"要想不打开应用就能获取信息,您可以将相应微件添加到主屏幕"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"点按即可更改微件设置"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"过滤器"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"失败:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"私密空间"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"让专用应用保持锁定状态并隐藏"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"点按即可设置或打开"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"私密"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"私密空间设置"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"锁定/解锁私密空间"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index ff71ad2..a48ca7e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"此裝置不支援此應用程式配對"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"打開裝置即可使用此應用程式配對"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"輕觸並按住即可移動小工具。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"㩒兩下之後㩒住,就可以郁小工具或者用自訂操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d 闊,%2$d 高"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"<xliff:g id="WIDGET_NAME">%1$s</xliff:g>小工具,闊 %2$d,高 %3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"按住小工具即可移到主畫面的任何位置"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"加去主畫面"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已經將「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具加咗去主畫面"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"你的日常必需品"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"你的專屬新聞"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"必備之選"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新聞和雜誌"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"放鬆專區"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"向健身目標邁進"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"隨時掌握天氣資料"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"相關推薦"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娛樂"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社交"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康和健身"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天氣"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"為你推薦"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右邊係「<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>」小工具,左邊係搜尋功能同選項"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 個小工具}other{# 個小工具}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 個捷徑}other{# 個捷徑}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"對話"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"做筆記"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"新增"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"加<xliff:g id="WIDGET_NAME">%1$s</xliff:g>小工具"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"實用資訊,唾手可得"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"只要將小工具新增至主畫面,就可以直接查看資料,無需開啟應用程式"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"輕按即可變更小工具設定"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"篩選器"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"操作失敗:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"私人空間"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"讓私人應用程式保持鎖定及隱藏"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"輕按即可設定或開啟"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"私人"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"「私人空間」設定"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"鎖定/解鎖「私人空間」"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 451efc7..66e504c 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"這部裝置不支援這組應用程式配對"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"展開裝置即可使用這組應用程式配對"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"按住即可移動小工具。"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"輕觸兩下並按住即可移動小工具或使用自訂操作。"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"寬度為 %1$d,高度為 %2$d"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具 (寬 %2$d,高 %3$d)"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"按住小工具即可拖曳到主畫面的任何位置"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"新增至主畫面"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"已將「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具新增到主畫面"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"建議"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"生活好幫手"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"你的專屬新聞"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"常用項目"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"新聞與雜誌"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"放鬆專區"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"達成健身目標"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"隨時掌握天氣資訊"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"你可能也會喜歡的內容"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"娛樂"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"社群"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"健康與塑身"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"天氣"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"個人化建議"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"右邊是「<xliff:g id="SELECTED_HEADER">%1$s</xliff:g>」小工具,左邊是搜尋功能和選項"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{# 項小工具}other{# 項小工具}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{# 個捷徑}other{# 個捷徑}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"工作"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"對話"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"做筆記"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"新增"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"新增「<xliff:g id="WIDGET_NAME">%1$s</xliff:g>」小工具"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"實用資訊隨手可得"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"只要將小工具新增到主畫面,就可以直接查看資訊,不必開啟應用程式"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"輕觸即可變更小工具設定"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"篩選器"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"失敗:<xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"私人空間"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"讓私人應用程式保持鎖定及隱藏的狀態"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"輕觸即可設定或開啟"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"私人"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"私人空間設定"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"鎖定/取消鎖定私人空間"</string>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 8388bb7..9a90e1e 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -33,21 +33,26 @@
     <string name="app_pair_default_title" msgid="4045241727446873529">"<xliff:g id="APP1">%1$s</xliff:g> | <xliff:g id="APP2">%2$s</xliff:g>"</string>
     <string name="app_pair_unlaunchable_at_screen_size" msgid="3446551575502685376">"Lokhu kubhanqwa kwe-app akusekelwa kule divayisi"</string>
     <string name="app_pair_needs_unfold" msgid="4588897528143807002">"Vula idivayisi ukuze usebenzise lokhu kubhanqwa kwe-app"</string>
+    <!-- no translation found for app_pair_not_available (3556767440808032031) -->
+    <skip />
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Thinta uphinde ubambe ukuze uhambise iwijethi."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Thepha kabili uphinde ubambe ukuze uhambise iwijethi noma usebenzise izindlela ezingokwezifiso."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
     <string name="widget_accessible_dims_format" msgid="3640149169885301790">"%1$d ububanzi ngokungu-%2$d ukuya phezulu"</string>
     <string name="widget_preview_context_description" msgid="9045841361655787574">"Iwijethi elingu-<xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
+    <string name="widget_preview_name_and_dims_content_description" msgid="8489038126122831595">"Iwijethi ye-<xliff:g id="WIDGET_NAME">%1$s</xliff:g>, ububanzi obungu-%2$d ngokuphakama okungu-%3$d"</string>
     <string name="add_item_request_drag_hint" msgid="8730547755622776606">"Thinta uphinde ubambe iwijethi ukuyihambisa kusikrini sasekhaya"</string>
     <string name="add_to_home_screen" msgid="9168649446635919791">"Faka kusikrini sasekhaya"</string>
     <string name="added_to_home_screen_accessibility_text" msgid="4451545765448884415">"Iwijethi ye-<xliff:g id="WIDGET_NAME">%1$s</xliff:g> yengezwe kusikrini sasekhaya"</string>
     <string name="suggested_widgets_header_title" msgid="1844314680798145222">"Iziphakamiso"</string>
-    <string name="productivity_widget_recommendation_category_label" msgid="1722113555721820766">"Okusemqoka kwakho kwansuku zonke"</string>
-    <string name="news_widget_recommendation_category_label" msgid="3908242346768119070">"Izindaba Zakho"</string>
+    <string name="productivity_widget_recommendation_category_label" msgid="3811812719618323750">"Okusemqoka"</string>
+    <string name="news_widget_recommendation_category_label" msgid="6756167867113741310">"Izindaba nomagazini"</string>
     <string name="social_and_entertainment_widget_recommendation_category_label" msgid="2923840997302308191">"Indawo Ozipholela Kuyo"</string>
-    <string name="fitness_widget_recommendation_category_label" msgid="2657652999128882431">"Finyelela Imigomo Yakho Yokufaneleka"</string>
-    <string name="weather_widget_recommendation_category_label" msgid="6712678763480668598">"Hlale Wazi Ngesimo Sezulu"</string>
-    <string name="others_widget_recommendation_category_label" msgid="897876078077284733">"Ungase Futhi Uthande"</string>
+    <string name="entertainment_widget_recommendation_category_label" msgid="3973107268630717874">"Okokozijabulisa"</string>
+    <string name="social_widget_recommendation_category_label" msgid="689147679536384717">"Okomphakathi"</string>
+    <string name="fitness_widget_recommendation_category_label" msgid="2756483898236585324">"Ezempilo nokufaneleka"</string>
+    <string name="weather_widget_recommendation_category_label" msgid="3059715991930798039">"Isimo sezulu"</string>
+    <string name="others_widget_recommendation_category_label" msgid="5555987036267226245">"Okuphakanyiselwe wena"</string>
     <string name="widget_picker_right_pane_accessibility_title" msgid="1673313931455067502">"Amawijethi okuthi <xliff:g id="SELECTED_HEADER">%1$s</xliff:g> kwesokudla, ukusesha nokukhethwayo kwesobunxele"</string>
     <string name="widgets_count" msgid="6467746476364652096">"{count,plural, =1{iwijethi #}one{amawijethi #}other{amawijethi #}}"</string>
     <string name="shortcuts_count" msgid="8471715556199592381">"{count,plural, =1{isinqamuleli #}one{izinqamuleli #}other{izinqamuleli #}}"</string>
@@ -61,6 +66,8 @@
     <string name="widgets_full_sheet_work_tab" msgid="3767150027110633765">"Umsebenzi"</string>
     <string name="widget_category_conversations" msgid="8894438636213590446">"Izingxoxo"</string>
     <string name="widget_category_note_taking" msgid="3469689394504266039">"Ukuthatha amanothi"</string>
+    <string name="widget_add_button_label" msgid="2761267068711937179">"Engeza"</string>
+    <string name="widget_add_button_content_description" msgid="1810530016360039643">"Engeza iwijethi ye-<xliff:g id="WIDGET_NAME">%1$s</xliff:g>"</string>
     <string name="widget_education_header" msgid="4874760613775913787">"Ulwazi oluwusizo phambi nje kwakho"</string>
     <string name="widget_education_content" msgid="1731667670753497052">"Ukuze uthole ulwazi ngaphandle kokuvula ama-app, ungakwazi ukwengeza amawijethi kusikrini sakho sasekhaya"</string>
     <string name="reconfigurable_widget_education_tip" msgid="6336962690888067057">"Thepha ukuze ushintshe amasethingi ewijethi"</string>
@@ -183,7 +190,7 @@
     <string name="developer_options_filter_hint" msgid="5896817443635989056">"Hlunga"</string>
     <string name="remote_action_failed" msgid="1383965239183576790">"Yehlulekile: <xliff:g id="WHAT">%1$s</xliff:g>"</string>
     <string name="private_space_label" msgid="2359721649407947001">"Isikhala esiyimfihlo"</string>
-    <string name="private_space_secondary_label" msgid="611902414159280263">"Gcina ama-app angasese ekhiyiwe futhi efihliwe"</string>
+    <string name="private_space_secondary_label" msgid="9203933341714508907">"Thepha ukuze usethe noma uvule"</string>
     <string name="ps_container_title" msgid="4391796149519594205">"Okuyimfihlo"</string>
     <string name="ps_container_settings" msgid="6059734123353320479">"Amasethingi Esikhala Esiyimfihlo"</string>
     <string name="ps_container_lock_unlock_button" msgid="7605602332253423755">"Khiya/Vula Isikhala Esiyimfihlo"</string>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 4a0b5e8..b3a25c0 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -43,14 +43,16 @@
     <attr name="popupNotificationDotColor" format="color" />
     <attr name="notificationDotColor" format="color" />
     <attr name="focusOutlineColor" format="color" />
+    <attr name="focusInnerOutlineColor" format="color" />
 
-    <attr name="folderPaginationColor" format="color" />
+    <attr name="pageIndicatorDotColor" format="color" />
     <attr name="folderPreviewColor" format="color" />
     <attr name="folderBackgroundColor" format="color" />
     <attr name="folderIconRadius" format="float" />
     <attr name="folderIconBorderColor" format="color" />
     <attr name="folderTextColor" format="color" />
     <attr name="folderHintTextColor" format="color" />
+    <attr name="appPairSurfaceInFolder" format="color" />
     <attr name="isFolderDarkText" format="boolean" />
     <attr name="workspaceAccentColor" format="color" />
     <attr name="workspaceSurfaceColor" format="color" />
@@ -72,6 +74,8 @@
     <attr name="widgetPickerSelectedTabTextColor" format="color"/>
     <attr name="widgetPickerUnselectedTabTextColor" format="color"/>
     <attr name="widgetPickerCollapseHandleColor" format="color"/>
+    <attr name="widgetPickerAddButtonBackgroundColor" format="color"/>
+    <attr name="widgetPickerAddButtonTextColor" format="color"/>
 
     <!-- BubbleTextView specific attributes. -->
     <declare-styleable name="BubbleTextView">
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 6a484d7..a620eb0 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -73,8 +73,8 @@
     <color name="folder_preview_light">#7FCFFF</color>
     <color name="folder_preview_dark">#1E1F20</color>
 
-    <color name="folder_pagination_color_light">#0B57D0</color>
-    <color name="folder_pagination_color_dark">#A8C7FA</color>
+    <color name="pagination_indicator_dot_color_light">#0B57D0</color>
+    <color name="pagination_indicator_dot_color_dark">#A8C7FA</color>
 
     <color name="text_color_primary_dark">#FFFFFFFF</color>
     <color name="text_color_secondary_dark">#FFFFFFFF</color>
@@ -113,6 +113,8 @@
     <color name="widget_picker_selected_tab_text_color_light">#FFFFFF</color>
     <color name="widget_picker_unselected_tab_text_color_light">#444746</color>
     <color name="widget_picker_collapse_handle_color_light">#C4C7C5</color>
+    <color name="widget_picker_add_button_background_color_light">#0B57D0</color>
+    <color name="widget_picker_add_button_text_color_light">#0B57D0</color>
 
     <color name="widget_picker_primary_surface_color_dark">#1F2020</color>
     <color name="widget_picker_secondary_surface_color_dark">#393939</color>
@@ -128,6 +130,8 @@
     <color name="widget_picker_selected_tab_text_color_dark">#2D312F</color>
     <color name="widget_picker_unselected_tab_text_color_dark">#C4C7C5</color>
     <color name="widget_picker_collapse_handle_color_dark">#444746</color>
+    <color name="widget_picker_add_button_background_color_dark">#062E6F</color>
+    <color name="widget_picker_add_button_text_color_dark">#FFFFFF</color>
 
     <color name="material_color_on_secondary_fixed_variant">#3F4759</color>
     <color name="material_color_on_tertiary_fixed_variant">#583E5B</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index 21d6024..f820e76 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -17,38 +17,23 @@
     <!-- Miscellaneous -->
     <bool name="config_largeHeap">false</bool>
 
-    <integer name="extracted_color_gradient_alpha">153</integer>
-
     <!-- A string pointer to the original app name string. This allows derived projects to
      easily override the app name without providing all translations -->
     <string name="derived_app_name" translatable="false">@string/app_name</string>
 
-    <!-- String representing the intent for search on the apps market. To specify a query, add
-    q=<query> to the data to the intent -->
-    <string name="market_search_intent" translatable="false">market://search?c=apps</string>
-
     <!-- String representing the intent to delete a package.-->
     <string name="delete_package_intent" translatable="false">#Intent;action=android.intent.action.DELETE;launchFlags=0x10800000;end</string>
 
     <!-- String representing the fragment class for settings activity.-->
     <string name="settings_fragment_name" translatable="false">com.android.launcher3.settings.SettingsActivity$LauncherSettingsFragment</string>
 
-    <!-- DragController -->
-    <item type="id" name="drag_event_parity" />
-
     <!-- AllApps & Launcher transitions -->
-    <!-- The duration of the animation from search hint to text entry -->
-    <integer name="config_searchHintAnimationDuration">50</integer>
-
     <!-- The duration of the PagedView page snap animation -->
     <integer name="config_pageSnapAnimationDuration">750</integer>
 
     <!-- The duration of the PagedView page snap animation -->
     <integer name="config_keyboardTaskFocusSnapAnimationDuration">750</integer>
 
-    <!-- View tag key used to store SpringAnimation data. -->
-    <item type="id" name="spring_animation_tag" />
-
     <!-- View tag key used to determine if we should fade in the child views.. -->
     <string name="popup_container_iterate_children" translatable="false">popup_container_iterate_children</string>
 
@@ -91,74 +76,34 @@
     <string name="taskbar_model_callbacks_factory_class" translatable="false"></string>
     <string name="taskbar_view_callbacks_factory_class" translatable="false"></string>
     <string name="launcher_restore_event_logger_class" translatable="false"></string>
-
-    <!-- View ID to use for QSB widget -->
-    <item type="id" name="qsb_widget" />
-
-    <!-- View ID used by cell layout to jail its content -->
-    <item type="id" name="cell_layout_jail_id" />
-
-    <!-- View IDs to store item highlight information -->
-    <item type="id" name="view_unhighlight_background" />
-
-    <!-- view ID used to restore work tab state -->
-    <item type="id" name="work_tab_state_id" />
-
-    <!-- Menu id for feature flags -->
-    <item type="id" name="menu_apply_flags" />
+    <!--  Used for determining category of a widget presented in widget recommendations. -->
+    <string name="widget_recommendation_category_provider_class" translatable="false"></string>
+    <string name="api_wrapper_class" translatable="false"></string>
 
     <!-- Default packages -->
     <string name="wallpaper_picker_package" translatable="false"></string>
     <string name="local_colors_extraction_class" translatable="false"></string>
     <string name="search_session_manager_class" translatable="false"></string>
 
-    <!-- Accessibility actions -->
-    <item type="id" name="action_remove" />
-    <item type="id" name="action_uninstall" />
-    <item type="id" name="action_reconfigure" />
-    <item type="id" name="action_add_to_workspace" />
-    <item type="id" name="action_move" />
-    <item type="id" name="action_move_to_workspace" />
-    <item type="id" name="action_move_screen_backwards" />
-    <item type="id" name="action_move_screen_forwards" />
-    <item type="id" name="action_resize" />
-    <item type="id" name="action_deep_shortcuts" />
-    <item type="id" name="action_remote_action_shortcut" />
-    <item type="id" name="action_dismiss_prediction" />
-    <item type="id" name="action_pin_prediction"/>
-
-    <!-- QSB IDs. DO not change -->
-    <item type="id" name="search_container_workspace" />
-    <item type="id" name="search_container_all_apps" />
-    <item type="id" name="search_container_hotseat" />
 
     <!-- Scalable Grid configuration -->
     <!-- This is a float because it is converted to dp later in DeviceProfile -->
     <dimen name="hotseat_bar_bottom_space_default">48</dimen>
     <dimen name="hotseat_qsb_space_default">0</dimen>
 
-    <!-- Recents -->
-    <item type="id" name="overview_panel"/>
-
     <!-- Whether to enable background preloading of task thumbnails. -->
     <bool name="config_enableTaskSnapshotPreloading">true</bool>
 
     <!-- Configuration resources -->
-    <item name="all_apps_spring_damping_ratio" type="dimen" format="float">0.75</item>
-    <item name="all_apps_spring_stiffness" type="dimen" format="float">600</item>
-
     <item name="dismiss_task_trans_y_damping_ratio" type="dimen" format="float">0.73</item>
     <item name="dismiss_task_trans_y_stiffness" type="dimen" format="float">800</item>
 
-    <item name="dismiss_task_trans_x_damping_ratio" type="dimen" format="float">0.73</item>
-    <item name="dismiss_task_trans_x_stiffness" type="dimen" format="float">800</item>
-
-    <item name="horizontal_spring_damping_ratio" type="dimen" format="float">0.8</item>
-    <item name="horizontal_spring_stiffness" type="dimen" format="float">250</item>
-
     <item name="swipe_up_rect_scale_damping_ratio" type="dimen" format="float">0.75</item>
     <item name="swipe_up_rect_scale_stiffness" type="dimen" format="float">200</item>
     <item name="swipe_up_rect_scale_higher_stiffness" type="dimen" format="float">400</item>
+    <!-- Flag: enableScalingRevealHomeAnimation() -->
+    <item name="swipe_up_rect_scale_damping_ratio_v2" type="dimen" format="float">0.8</item>
+    <item name="swipe_up_rect_scale_stiffness_v2" type="dimen" format="float">650</item>
 
     <item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item>
 
@@ -166,6 +111,11 @@
 
     <item name="swipe_up_rect_xy_damping_ratio" type="dimen" format="float">0.8</item>
     <item name="swipe_up_rect_xy_stiffness" type="dimen" format="float">200</item>
+    <!-- Flag: enableScalingRevealHomeAnimation() -->
+    <item name="swipe_up_rect_x_damping_ratio" type="dimen" format="float">0.965</item>
+    <item name="swipe_up_rect_x_stiffness" type="dimen" format="float">300</item>
+    <item name="swipe_up_rect_y_damping_ratio" type="dimen" format="float">0.95</item>
+    <item name="swipe_up_rect_y_stiffness" type="dimen" format="float">190</item>
 
     <!-- Taskbar -->
     <!-- This is a float because it is converted to dp later in DeviceProfile -->
@@ -190,6 +140,12 @@
     <dimen name="swipe_up_fling_min_visible_change">18dp</dimen>
     <dimen name="swipe_up_max_workspace_trans_y">-60dp</dimen>
     <dimen name="swipe_up_max_velocity">7.619dp</dimen>
+    <!-- Flag: enableScalingRevealHomeAnimation() -->
+    <item name="swipe_up_min_velocity_x_px_per_s" type="dimen" format="integer">300</item>
+    <item name="swipe_up_max_velocity_x_px_per_s" type="dimen" format="integer">500</item>
+    <item name="swipe_up_min_velocity_y_px_per_s" type="dimen" format="integer">2000</item>
+    <item name="swipe_up_max_velocity_y_px_per_s" type="dimen" format="integer">5000</item>
+    <item name="swipe_up_max_velocity_fall_off_factor" type="dimen" format="float">1.4</item>
 
     <array name="dynamic_resources">
         <item>@dimen/swipe_up_scale_start</item>
@@ -203,9 +159,6 @@
     <!-- Widget component names to be included in fitness category of widget suggestions. -->
     <string-array name="fitness_recommendations"></string-array>
 
-    <!-- Name of the class used to generate colors from the wallpaper colors. Must be implementing the LauncherAppWidgetHostView.ColorGenerator interface. -->
-    <string name="color_generator_class" translatable="false"/>
-
     <!-- Swipe back to home related -->
     <dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
     <dimen name="swipe_back_window_corner_radius">40dp</dimen>
@@ -261,9 +214,6 @@
     <!--  Used for custom widgets  -->
     <array name="custom_widget_providers"/>
 
-    <!--  Used for determining category of a widget presented in widget recommendations. -->
-    <string name="widget_recommendation_category_provider_class" translatable="false"></string>
-
     <!-- Embed parameters -->
     <dimen name="activity_split_ratio"  format="float">0.5</dimen>
     <integer name="min_width_split">720</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a912e2d..a056e81 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -22,7 +22,7 @@
     <dimen name="dynamic_grid_edge_margin">10.77dp</dimen>
     <dimen name="dynamic_grid_left_right_margin">8dp</dimen>
     <!-- Minimum amount of next page visible in spring loaded mode -->
-    <dimen name="dynamic_grid_spring_loaded_min_next_space_visible">24dp</dimen>
+    <dimen name="dynamic_grid_spring_loaded_min_next_space_visible">48dp</dimen>
 
     <dimen name="dynamic_grid_cell_border_spacing">16dp</dimen>
     <dimen name="cell_layout_padding">10.77dp</dimen>
@@ -176,10 +176,13 @@
 
     <!-- Widget tray -->
     <dimen name="widget_cell_vertical_padding">8dp</dimen>
-    <dimen name="widget_cell_horizontal_padding">16dp</dimen>
+    <dimen name="widget_cell_horizontal_padding">8dp</dimen>
     <dimen name="widget_cell_font_size">14sp</dimen>
     <dimen name="widget_cell_app_icon_size">24dp</dimen>
     <dimen name="widget_cell_app_icon_padding">8dp</dimen>
+    <dimen name="widget_cell_add_button_height">48dp</dimen>
+    <dimen name="widget_cell_add_button_start_padding">8dp</dimen>
+    <dimen name="widget_cell_add_button_end_padding">16dp</dimen>
 
     <dimen name="widget_tabs_button_horizontal_padding">4dp</dimen>
     <dimen name="widget_tabs_horizontal_padding">16dp</dimen>
@@ -187,7 +190,6 @@
     <dimen name="widget_picker_landscape_tablet_left_right_margin">117dp</dimen>
     <dimen name="widget_picker_two_panels_left_right_margin">0dp</dimen>
     <dimen name="widget_recommendations_table_vertical_padding">8dp</dimen>
-    <dimen name="widget_recommendations_table_horizontal_padding">16dp</dimen>
     <!-- Bottom margin for the search and recommended widgets container without work profile -->
     <dimen name="search_and_recommended_widgets_container_bottom_margin">16dp</dimen>
     <!-- Bottom margin for the search and recommended widgets container with work profile -->
@@ -198,7 +200,8 @@
 
     <dimen name="widget_list_header_view_vertical_padding">20dp</dimen>
     <dimen name="widget_list_entry_spacing">2dp</dimen>
-    <dimen name="widget_list_horizontal_margin">16dp</dimen>
+    <!-- Less margin on sides to let widgets table width be close to the workspace width. -->
+    <dimen name="widget_list_horizontal_margin">11dp</dimen>
     <!-- Margin applied to the recycler view with search bar & the list of widget apps below it. -->
     <dimen name="widget_list_left_pane_horizontal_margin">0dp</dimen>
     <dimen name="widget_list_horizontal_margin_two_pane">24dp</dimen>
@@ -273,7 +276,6 @@
 
     <!-- Sizes for managed profile badges -->
     <dimen name="profile_badge_size">24dp</dimen>
-    <dimen name="profile_badge_margin">5dp</dimen>
     <dimen name="profile_badge_minimum_top">2dp</dimen>
 
     <!-- Shadows and outlines -->
@@ -396,7 +398,7 @@
     <dimen name="transient_taskbar_clamped_offset_bound">0dp</dimen>
     <dimen name="taskbar_icon_spacing">0dp</dimen>
     <dimen name="taskbar_nav_buttons_size">0dp</dimen>
-    <dimen name="taskbar_contextual_button_margin">0dp</dimen>
+    <dimen name="taskbar_contextual_button_suw_margin">0dp</dimen>
     <dimen name="taskbar_hotseat_nav_spacing">0dp</dimen>
     <dimen name="taskbar_button_margin_default">0dp</dimen>
     <dimen name="taskbar_button_space_inbetween">0dp</dimen>
@@ -445,9 +447,15 @@
     <dimen name="split_instructions_bottom_margin_phone_landscape">24dp</dimen>
     <dimen name="split_instructions_bottom_margin_phone_portrait">60dp</dimen>
     <dimen name="split_instructions_start_margin_cancel">8dp</dimen>
+    <dimen name="split_divider_handle_region_width">96dp</dimen>
+    <dimen name="split_divider_handle_region_height">48dp</dimen>
 
     <dimen name="focus_outline_radius">16dp</dimen>
-    <dimen name="focus_outline_stroke_width">3dp</dimen>
+    <dimen name="focus_inner_outline_radius">14dp</dimen>
+    <dimen name="focus_outline_stroke_width">2dp</dimen>
+    <!-- -4dp for double stroke focus outlines, -2dp for padding between outline and widget,
+    make it negative to outset the rect and leave space for drawing focus outline and padding -->
+    <dimen name="focus_rect_widget_outsets">-6dp</dimen>
 
     <!-- Workspace grid visualization parameters -->
     <dimen name="grid_visualization_rounding_radius">16dp</dimen>
@@ -484,12 +492,13 @@
     <dimen name="ps_header_image_height">48dp</dimen>
     <dimen name="ps_header_text_height">24dp</dimen>
     <dimen name="ps_header_layout_margin">16dp</dimen>
-    <dimen name="ps_header_settings_icon_margin_end">8dp</dimen>
+    <dimen name="ps_header_settings_icon_margin_end">4dp</dimen>
     <dimen name="ps_header_text_size">16sp</dimen>
     <dimen name="ps_button_height">40dp</dimen>
     <dimen name="ps_button_width">40dp</dimen>
     <dimen name="ps_lock_button_width">89dp</dimen>
     <dimen name="ps_app_divider_padding">16dp</dimen>
+    <dimen name="ps_extra_bottom_padding">16dp</dimen>
     <dimen name="ps_lock_corner_radius">20dp</dimen>
     <dimen name="ps_lock_icon_size">20dp</dimen>
     <dimen name="ps_lock_icon_margin_top">10dp</dimen>
diff --git a/res/values/id.xml b/res/values/id.xml
index 198496f..7bb9396 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -23,6 +23,40 @@
     <item type="id" name="split_topLeft_appInfo" />
     <item type="id" name="split_bottomRight_appInfo" />
 
+    <!-- Accessibility actions -->
+    <item type="id" name="action_remove" />
+    <item type="id" name="action_uninstall" />
+    <item type="id" name="action_reconfigure" />
+    <item type="id" name="action_add_to_workspace" />
+    <item type="id" name="action_move" />
+    <item type="id" name="action_move_to_workspace" />
+    <item type="id" name="action_move_screen_backwards" />
+    <item type="id" name="action_move_screen_forwards" />
+    <item type="id" name="action_resize" />
+    <item type="id" name="action_deep_shortcuts" />
+    <item type="id" name="action_remote_action_shortcut" />
+    <item type="id" name="action_dismiss_prediction" />
+    <item type="id" name="action_pin_prediction"/>
+
+    <!-- QSB IDs. DO not change -->
+    <item type="id" name="search_container_workspace" />
+    <item type="id" name="search_container_all_apps" />
+    <item type="id" name="search_container_hotseat" />
+
+    <!-- View ID to use for QSB widget -->
+    <item type="id" name="qsb_widget" />
+
+    <!-- View ID used by cell layout to jail its content -->
+    <item type="id" name="cell_layout_jail_id" />
+
+    <!-- View IDs to store item highlight information -->
+    <item type="id" name="view_unhighlight_background" />
+
+    <!-- view ID used to restore work tab state -->
+    <item type="id" name="work_tab_state_id" />
+
+    <!-- Menu id for feature flags -->
+    <item type="id" name="menu_apply_flags" />
 
     <!--  Do not change, must be kept in sync with sysui navbar button IDs for tests!  -->
     <item type="id" name="home" />
@@ -40,6 +74,7 @@
     <item type="id" name="cache_entry_tag_id" />
 
     <item type="id" name="saved_clip_children_tag_id" />
+    <item type="id" name="saved_clip_to_padding_tag_id" />
 
     <item type="id" name="saved_floating_widget_foreground" />
     <item type="id" name="saved_floating_widget_background" />
@@ -52,4 +87,13 @@
     <item type="id" name="ps_settings_button" />
     <item type="id" name="ps_transition_image" />
 
+    <!-- Recents -->
+    <item type="id" name="overview_panel"/>
+
+    <!-- DragController -->
+    <item type="id" name="drag_event_parity" />
+
+    <!-- View tag key used to store SpringAnimation data. -->
+    <item type="id" name="spring_animation_tag" />
+
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index aaef15b..e1c7d64 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -50,6 +50,8 @@
     <string name="app_pair_unlaunchable_at_screen_size">This app pair isn\'t supported on this device</string>
     <!-- Displayed when an app pair can't launch at this screen size, but user can unfold device to restore functionality [CHAR_LIMIT=none] -->
     <string name="app_pair_needs_unfold">Unfold device to use this app pair</string>
+    <!-- Displayed when user selects a shortcut for an app pair that is currently not available [CHAR_LIMIT=none]-->
+    <string name="app_pair_not_available">App pair isn\'t available</string>
 
     <!-- Widgets -->
     <!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
@@ -64,6 +66,12 @@
     <!-- Spoken text for a screen reader. The placeholder text is the widget name.
          [CHAR_LIMIT=none]-->
     <string name="widget_preview_context_description"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget</string>
+    <!-- Spoken text for a screen reader. The first placeholder text is the widget name, the
+         remaining placeholders are for the widget dimensions.
+         [CHAR_LIMIT=none]-->
+    <string name="widget_preview_name_and_dims_content_description">
+        <xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget, %2$d wide by %3$d high
+    </string>
     <!-- Message to tell the user to press and hold a widget/icon to add it to the home screen.
          [CHAR LIMIT=NONE]  -->
     <string name="add_item_request_drag_hint">Touch &amp; hold the widget to move it around the home screen</string>
@@ -75,12 +83,14 @@
     <!-- Widget suggestions header title in the full widgets picker for large screen devices
     in landscape mode. [CHAR_LIMIT=50] -->
     <string name="suggested_widgets_header_title">Suggestions</string>
-    <string name="productivity_widget_recommendation_category_label">Your Daily Essentials</string>
-    <string name="news_widget_recommendation_category_label">News For You</string>
+    <string name="productivity_widget_recommendation_category_label">Essentials</string>
+    <string name="news_widget_recommendation_category_label">News &amp; magazines</string>
     <string name="social_and_entertainment_widget_recommendation_category_label">Your Chill Zone</string>
-    <string name="fitness_widget_recommendation_category_label">Reach Your Fitness Goals</string>
-    <string name="weather_widget_recommendation_category_label">Stay Ahead of the Weather</string>
-    <string name="others_widget_recommendation_category_label">You Might Also Like</string>
+    <string name="entertainment_widget_recommendation_category_label">Entertainment</string>
+    <string name="social_widget_recommendation_category_label">Social</string>
+    <string name="fitness_widget_recommendation_category_label">Health &amp; fitness</string>
+    <string name="weather_widget_recommendation_category_label">Weather</string>
+    <string name="others_widget_recommendation_category_label">Suggested for you</string>
     <!-- accessibilityPaneTitle for the right pane when showing suggested widgets. -->
     <string name="widget_picker_right_pane_accessibility_title"><xliff:g id="selected_header" example="Calendar">%1$s</xliff:g> widgets on right, search and options on left</string>
     <!-- Label for showing the number of widgets an app has in the full widgets picker.
@@ -123,6 +133,12 @@
     <!-- A widget category label for grouping widgets related to note taking. [CHAR_LIMIT=30] -->
     <string name="widget_category_note_taking">Note-taking</string>
 
+    <!-- Text on the button that adds a widget to the home screen. [CHAR_LIMIT=15] -->
+    <string name="widget_add_button_label">Add</string>
+    <!-- Accessibility content description for the button that adds a widget to the home screen. The
+         placeholder text is the widget name. [CHAR_LIMIT=none] -->
+    <string name="widget_add_button_content_description">Add <xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget</string>
+
     <!-- Title of a dialog. This dialog lets a user know how they can use widgets on their phone.
          [CHAR_LIMIT=NONE] -->
     <string name="widget_education_header">Useful info at your fingertips</string>
@@ -435,6 +451,8 @@
     <string name="work_profile_edu_work_apps">Work apps are badged and visible to your IT admin</string>
     <!-- Action label to finish work profile edu-->
     <string name="work_profile_edu_accept">Got it</string>
+    <!-- Info icon unicode for alpha scroller when work edu card is present -->
+    <string name="work_profile_edu_section" translatable="false">\u24D8</string>
 
     <!--- heading shown when user opens work apps tab while work apps are paused -->
     <string name="work_apps_paused_title">Work apps are paused</string>
@@ -464,7 +482,7 @@
     <!-- Private space tile label -->
     <string name="private_space_label">Private space</string>
     <!-- Private space tile secondary label -->
-    <string name="private_space_secondary_label">Keep private apps locked and hidden</string>
+    <string name="private_space_secondary_label">Tap to set up or open</string>
     <!-- Title for Private Space Container shown at the bottom of all apps drawer -->
     <string name="ps_container_title">Private</string>
     <!-- Description for Private Space Settings button -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 401155d..00b962e 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -52,14 +52,16 @@
         <item name="workspaceAmbientShadowColor">#40000000</item>
         <item name="workspaceKeyShadowColor">#89000000</item>
         <item name="widgetsTheme">@style/WidgetContainerTheme</item>
-        <item name="focusOutlineColor">@color/material_color_on_secondary_container</item>
-        <item name="folderPaginationColor">@color/folder_pagination_color_light</item>
+        <item name="pageIndicatorDotColor">@color/page_indicator_dot_color_light</item>
+        <item name="focusOutlineColor">@color/material_color_secondary_fixed</item>
+        <item name="focusInnerOutlineColor">@color/material_color_on_secondary_fixed_variant</item>
         <item name="folderPreviewColor">@color/folder_preview_light</item>
         <item name="folderBackgroundColor">@color/folder_background_light</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
         <item name="isFolderDarkText">true</item>
         <item name="folderTextColor">@color/folder_text_color_light</item>
         <item name="folderHintTextColor">@color/folder_hint_text_color_light</item>
+        <item name="appPairSurfaceInFolder">@color/material_color_surface_container_lowest</item>
         <item name="loadingIconColor">#CCFFFFFF</item>
         <item name="iconOnlyShortcutColor">?android:attr/textColorSecondary</item>
         <item name="eduHalfSheetBGColor">?android:attr/colorAccent</item>
@@ -164,13 +166,14 @@
         <item name="popupShadeThird">@color/popup_shade_third_dark</item>
         <item name="notificationDotColor">@color/notification_dot_color_dark</item>
         <item name="widgetsTheme">@style/WidgetContainerTheme.Dark</item>
-        <item name="folderPaginationColor">@color/folder_pagination_color_dark</item>
+        <item name="pageIndicatorDotColor">@color/page_indicator_dot_color_dark</item>
         <item name="folderPreviewColor">@color/folder_preview_dark</item>
         <item name="folderBackgroundColor">@color/folder_background_dark</item>
         <item name="folderIconBorderColor">?android:attr/colorPrimary</item>
         <item name="isFolderDarkText">false</item>
         <item name="folderTextColor">@color/folder_text_color_dark</item>
         <item name="folderHintTextColor">@color/folder_hint_text_color_dark</item>
+        <item name="appPairSurfaceInFolder">@color/material_color_surface_container_lowest</item>
         <item name="isMainColorDark">true</item>
         <item name="loadingIconColor">#99FFFFFF</item>
         <item name="iconOnlyShortcutColor">#B3FFFFFF</item>
@@ -261,6 +264,10 @@
             @color/widget_picker_unselected_tab_text_color_light</item>
         <item name="widgetPickerCollapseHandleColor">
             @color/widget_picker_collapse_handle_color_light</item>
+        <item name="widgetPickerAddButtonBackgroundColor">
+            @color/widget_picker_add_button_background_color_light</item>
+        <item name="widgetPickerAddButtonTextColor">
+            @color/widget_picker_add_button_text_color_light</item>
     </style>
     <style name="WidgetContainerTheme.Dark" parent="AppTheme.Dark">
         <item name="android:colorEdgeEffect">?android:attr/textColorSecondary</item>
@@ -292,6 +299,10 @@
             @color/widget_picker_unselected_tab_text_color_dark</item>
         <item name="widgetPickerCollapseHandleColor">
             @color/widget_picker_collapse_handle_color_dark</item>
+        <item name="widgetPickerAddButtonBackgroundColor">
+            @color/widget_picker_add_button_background_color_dark</item>
+        <item name="widgetPickerAddButtonTextColor">
+            @color/widget_picker_add_button_text_color_dark</item>
     </style>
 
     <style name="FastScrollerPopup" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
diff --git a/settings.gradle b/settings.gradle
deleted file mode 100644
index ce13bfb..0000000
--- a/settings.gradle
+++ /dev/null
@@ -1,5 +0,0 @@
-include ':IconLoader'
-project(':IconLoader').projectDir = new File(rootDir, 'iconloaderlib')
-
-include ':SharedLibWrapper'
-project(':SharedLibWrapper').projectDir = new File(rootDir, 'SharedLibWrapper')
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index e7b88dc..4ccf3db 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -278,18 +278,7 @@
 
     public static void closeOpenViews(ActivityContext activity, boolean animate,
             @FloatingViewType int type) {
-        BaseDragLayer dragLayer = activity.getDragLayer();
-        // Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
-        // and will be one of the last views.
-        for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
-            View child = dragLayer.getChildAt(i);
-            if (child instanceof AbstractFloatingView) {
-                AbstractFloatingView abs = (AbstractFloatingView) child;
-                if (abs.isOfType(type)) {
-                    abs.close(animate);
-                }
-            }
-        }
+        new AbstractFloatingViewHelper().closeOpenViews(activity, animate, type);
     }
 
     public static void closeAllOpenViews(ActivityContext activity, boolean animate) {
diff --git a/src/com/android/launcher3/AbstractFloatingViewHelper.kt b/src/com/android/launcher3/AbstractFloatingViewHelper.kt
new file mode 100644
index 0000000..0bfbc6e
--- /dev/null
+++ b/src/com/android/launcher3/AbstractFloatingViewHelper.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import com.android.launcher3.AbstractFloatingView.FloatingViewType
+import com.android.launcher3.views.ActivityContext
+
+/**
+ * Helper class for manaing AbstractFloatingViews which shows a floating UI on top of the launcher
+ * UI.
+ */
+class AbstractFloatingViewHelper {
+    fun closeOpenViews(activity: ActivityContext, animate: Boolean, @FloatingViewType type: Int) {
+        val dragLayer = activity.getDragLayer()
+        // Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
+        // and will be one of the last views.
+        for (i in dragLayer.getChildCount() - 1 downTo 0) {
+            val child = dragLayer.getChildAt(i)
+            if (child is AbstractFloatingView && child.isOfType(type)) {
+                child.close(animate)
+            }
+        }
+    }
+}
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 4a277f0..b46d7e2 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -46,6 +46,7 @@
 import com.android.launcher3.views.ArrowTipView;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.widget.PendingAppWidgetHostView;
 import com.android.launcher3.widget.util.WidgetSizes;
 
 import java.util.ArrayList;
@@ -200,6 +201,10 @@
     }
 
     public static void showForWidget(LauncherAppWidgetHostView widget, CellLayout cellLayout) {
+        // If widget is not added to view hierarchy, we cannot show resize frame at correct location
+        if (widget.getParent() == null) {
+            return;
+        }
         Launcher launcher = Launcher.getLauncher(cellLayout.getContext());
         AbstractFloatingView.closeAllOpenViews(launcher);
 
@@ -470,8 +475,11 @@
             mLastDirectionVector[1] = mDirectionVector[1];
         }
 
-        if (mCellLayout.createAreaForResize(cellX, cellY, spanX, spanY, mWidgetView,
-                mDirectionVector, onDismiss)) {
+        // We don't want to evaluate resize if a widget was pending config activity and was already
+        // occupying a space on the screen. This otherwise will cause reorder algorithm evaluate a
+        // different location for the widget and cause a jump.
+        if (!(mWidgetView instanceof PendingAppWidgetHostView) && mCellLayout.createAreaForResize(
+                cellX, cellY, spanX, spanY, mWidgetView, mDirectionVector, onDismiss)) {
             if (mStateAnnouncer != null && (lp.cellHSpan != spanX || lp.cellVSpan != spanY) ) {
                 mStateAnnouncer.announce(
                         mLauncher.getString(R.string.widget_resized, spanX, spanY));
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index c7cdfa8..cf86528 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -52,7 +52,7 @@
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.qsb.QsbContainerView;
 import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.Partner;
 import com.android.launcher3.util.Thunk;
@@ -203,7 +203,7 @@
         mIdp = LauncherAppState.getIDP(context);
         mRowCount = mIdp.numRows;
         mColumnCount = mIdp.numColumns;
-        mActivityOverride = ApiWrapper.getActivityOverrides(context);
+        mActivityOverride = ApiWrapper.INSTANCE.get(context).getActivityOverrides();
     }
 
     /**
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 1c2ed43..cf93a79 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -111,8 +111,6 @@
         return false;
     }
 
-    public abstract <T extends View> T getOverviewPanel();
-
     public abstract View getRootView();
 
     public void returnToHomescreen() {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 4ca20d6..83236d1 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -237,7 +237,7 @@
             defaultIconSize = getResources().getDimensionPixelSize(
                     R.dimen.search_row_small_icon_size);
         } else if (mDisplay == DISPLAY_TASKBAR) {
-            defaultIconSize = mDeviceProfile.iconSizePx;
+            defaultIconSize = mDeviceProfile.taskbarIconSize;
         } else {
             // widget_selection or shortcut_popup
             defaultIconSize = mDeviceProfile.iconSizePx;
@@ -911,7 +911,8 @@
     /** Applies the given progress level to the this icon's progress bar. */
     @Nullable
     public PreloadIconDrawable applyProgressLevel() {
-        if (!(getTag() instanceof ItemInfoWithIcon)) {
+        if (!(getTag() instanceof ItemInfoWithIcon)
+                || ((ItemInfoWithIcon) getTag()).isInactiveArchive()) {
             return null;
         }
 
@@ -968,6 +969,7 @@
         return info.isDisabled() || info.isPendingDownload();
     }
 
+
     public void applyDotState(ItemInfo itemInfo, boolean animate) {
         if (mIcon instanceof FastBitmapDrawable) {
             boolean wasDotted = mDotInfo != null;
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index f96d59e..6cb33a8 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -18,6 +18,7 @@
 
 import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Flags.enableOverviewIconMenu;
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.InvariantDeviceProfile.INDEX_DEFAULT;
 import static com.android.launcher3.InvariantDeviceProfile.INDEX_LANDSCAPE;
 import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_LANDSCAPE;
@@ -62,13 +63,13 @@
 import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType;
 import com.android.launcher3.responsive.ResponsiveSpec.DimensionType;
 import com.android.launcher3.responsive.ResponsiveSpecsProvider;
-import com.android.launcher3.uioverrides.ApiWrapper;
 import com.android.launcher3.util.CellContentDimensions;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.IconSizeSteps;
 import com.android.launcher3.util.ResourceHelper;
 import com.android.launcher3.util.WindowBounds;
+import com.android.launcher3.util.window.WindowManagerProxy;
 
 import java.io.PrintWriter;
 import java.util.Locale;
@@ -101,6 +102,7 @@
     public final boolean transposeLayoutWithOrientation;
     public final boolean isMultiDisplay;
     public final boolean isTwoPanels;
+    public boolean isPredictiveBackSwipe;
     public final boolean isQsbInline;
 
     // Device properties in current orientation
@@ -348,7 +350,8 @@
         isTablet = info.isTablet(windowBounds);
         isPhone = !isTablet;
         isTwoPanels = isTablet && isMultiDisplay;
-        isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS;
+        isTaskbarPresent = isTablet
+                && WindowManagerProxy.INSTANCE.get(context).isTaskbarDrawnInProcess();
 
         // Some more constants.
         context = getContext(context, info, isVerticalBarLayout() || (isTablet && isLandscape)
@@ -436,7 +439,11 @@
             if (isMultiDisplay && !ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH.get()) {
                 // TODO(b/259893832): Revert to use maxWallpaperScale to calculate bottomSheetDepth
                 // when screen recorder bug is fixed.
-                bottomSheetDepth = 1f;
+                if (enableScalingRevealHomeAnimation()) {
+                    bottomSheetDepth = 0.3f;
+                } else {
+                    bottomSheetDepth = 1f;
+                }
             } else {
                 // The goal is to set wallpaper to zoom at workspaceContentScale when in AllApps.
                 // When depth is 0, wallpaper zoom is set to maxWallpaperScale.
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 42d4d50..bc36336 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -72,6 +72,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 public class InvariantDeviceProfile {
@@ -358,6 +359,15 @@
         return displayOption.grid.name;
     }
 
+    /**
+     * @deprecated This is a temporary solution because on the backup and restore case we modify the
+     * IDP, this resets it. b/332974074
+     */
+    @Deprecated
+    public void reset(Context context) {
+        initGrid(context, getCurrentGridName(context));
+    }
+
     @VisibleForTesting
     public static String getDefaultGridName(Context context) {
         return new InvariantDeviceProfile().initGrid(context, null);
@@ -578,6 +588,45 @@
     }
 
     /**
+     * Returns the GridOption associated to the given file name or null if the fileName is not
+     * supported.
+     * Ej, launcher.db -> "normal grid", launcher_4_by_4.db -> "practical grid"
+     */
+    public GridOption getGridOptionFromFileName(Context context, String fileName) {
+        return parseAllGridOptions(context).stream()
+                .filter(gridOption -> Objects.equals(gridOption.dbFile, fileName))
+                .findFirst()
+                .orElse(null);
+    }
+
+    /**
+     * Returns the name of the given size on the current device or empty string if the size is not
+     * supported. Ej. 4x4 -> normal, 5x4 -> practical, etc.
+     * (Note: the name of the grid can be different for the same grid size depending of
+     * the values of the InvariantDeviceProfile)
+     *
+     */
+    public String getGridNameFromSize(Context context, Point size) {
+        return parseAllGridOptions(context).stream()
+                .filter(gridOption -> gridOption.numColumns == size.x
+                        && gridOption.numRows == size.y)
+                .map(gridOption -> gridOption.name)
+                .findFirst()
+                .orElse("");
+    }
+
+    /**
+     * Returns the grid option for the given gridName on the current device (Note: the gridOption
+     * be different for the same gridName depending on the values of the InvariantDeviceProfile).
+     */
+    public GridOption getGridOptionFromName(Context context, String gridName) {
+        return parseAllGridOptions(context).stream()
+                .filter(gridOption -> Objects.equals(gridOption.name, gridName))
+                .findFirst()
+                .orElse(null);
+    }
+
+    /**
      * @return all the grid options that can be shown on the device
      */
     public List<GridOption> parseAllGridOptions(Context context) {
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 24ef3d0..d2d5ba9 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -261,6 +261,7 @@
 import com.android.launcher3.widget.custom.CustomWidgetManager;
 import com.android.launcher3.widget.model.WidgetsListBaseEntry;
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
+import com.android.launcher3.widget.util.WidgetSizes;
 import com.android.systemui.plugins.LauncherOverlayPlugin;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.shared.LauncherOverlayManager;
@@ -662,6 +663,11 @@
         // #5 state handler
         return new OnBackAnimationCallback() {
             @Override
+            public void onBackStarted(BackEvent backEvent) {
+                Launcher.this.onBackStarted();
+            }
+
+            @Override
             public void onBackInvoked() {
                 onStateBack();
             }
@@ -674,7 +680,7 @@
 
             @Override
             public void onBackCancelled() {
-                mStateManager.getState().onBackCancelled(Launcher.this);
+                Launcher.this.onBackCancelled();
             }
         };
     }
@@ -837,7 +843,7 @@
                 announceForAccessibility(R.string.item_added_to_workspace);
                 break;
             case REQUEST_CREATE_APPWIDGET:
-                completeAddAppWidget(appWidgetId, info, null, null, false, null);
+                completeAddAppWidget(appWidgetId, info, null, null, false, true, null);
                 break;
             case REQUEST_RECONFIGURE_APPWIDGET:
                 getStatsLogManager().logger().withItemInfo(info).log(LAUNCHER_WIDGET_RECONFIGURED);
@@ -1035,7 +1041,7 @@
                             requestArgs.getWidgetHandler().getProviderInfo(this));
             boundWidget = layout;
             onCompleteRunnable = () -> {
-                completeAddAppWidget(appWidgetId, requestArgs, layout, null, false, null);
+                completeAddAppWidget(appWidgetId, requestArgs, layout, null, false, true, null);
                 if (!isInState(EDIT_MODE)) {
                     mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
                 }
@@ -1466,7 +1472,8 @@
     @Thunk
     void completeAddAppWidget(int appWidgetId, ItemInfo itemInfo,
             @Nullable AppWidgetHostView hostView, LauncherAppWidgetProviderInfo appWidgetInfo,
-            boolean showPendingWidget, @Nullable Bitmap widgetPreviewBitmap) {
+            boolean showPendingWidget, boolean updateWidgetSize,
+            @Nullable Bitmap widgetPreviewBitmap) {
 
         if (appWidgetInfo == null) {
             appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId,
@@ -1491,11 +1498,10 @@
         if (showPendingWidget) {
             launcherInfo.restoreStatus = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
             PendingAppWidgetHostView pendingAppWidgetHostView = new PendingAppWidgetHostView(
-                    this, mAppWidgetHolder, launcherInfo, appWidgetInfo);
-            pendingAppWidgetHostView.setPreviewBitmap(widgetPreviewBitmap);
+                    this, mAppWidgetHolder, launcherInfo, appWidgetInfo, widgetPreviewBitmap);
             hostView = pendingAppWidgetHostView;
         } else if (hostView instanceof PendingAppWidgetHostView) {
-            ((PendingAppWidgetHostView) hostView).setPreviewBitmap(null);
+            ((PendingAppWidgetHostView) hostView).setPreviewBitmapAndUpdateBackground(null);
             // User has selected a widget config and exited the config activity, we can trigger
             // re-inflation of PendingAppWidgetHostView to replace it with
             // LauncherAppWidgetHostView in workspace.
@@ -1508,8 +1514,14 @@
                     reInflatedHostView,
                     (LauncherAppWidgetInfo) reInflatedHostView.getTag(),
                     presenterPos);
+            // We always update widget size after re-inflating PendingAppWidgetHostView
+            WidgetSizes.updateWidgetSizeRanges(
+                    reInflatedHostView, this, itemInfo.spanX, itemInfo.spanY);
             return;
         }
+        if (updateWidgetSize) {
+            WidgetSizes.updateWidgetSizeRanges(hostView, this, itemInfo.spanX, itemInfo.spanY);
+        }
         if (itemInfo instanceof PendingAddWidgetInfo) {
             launcherInfo.sourceContainer = ((PendingAddWidgetInfo) itemInfo).sourceContainer;
         } else if (itemInfo instanceof PendingRequestArgs) {
@@ -1539,7 +1551,13 @@
             LauncherAppWidgetInfo launcherInfo,
             CellPos presenterPos) {
         CellLayout cellLayout = getCellLayout(launcherInfo.container, presenterPos.screenId);
-        if (mStateManager.getState() == NORMAL) {
+        // We should wait until launcher is not animating to show resize frame so that
+        // {@link View#hasIdentityMatrix()} returns true (no scale effect) from CellLayout and
+        // Workspace (they are widget's parent view). Otherwise widget's
+        // {@link View#getLocationInWindow(int[])} will set skewed location, causing resize
+        // frame not showing at skewed location in
+        // {@link AppWidgetResizeFrame#snapToWidget(boolean)}.
+        if (mStateManager.getState() == NORMAL && !mStateManager.isInTransition()) {
             AppWidgetResizeFrame.showForWidget(launcherHostView, cellLayout);
         } else {
             mStateManager.addStateListener(new StateManager.StateListener<LauncherState>() {
@@ -1635,9 +1653,10 @@
         } else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) {
             showAllAppsFromIntent(alreadyOnHome);
         } else if (INTENT_ACTION_ALL_APPS_TOGGLE.equals(intent.getAction())) {
-            toggleAllAppsFromIntent(alreadyOnHome);
+            toggleAllAppsSearch(alreadyOnHome);
         } else if (Intent.ACTION_SHOW_WORK_APPS.equals(intent.getAction())) {
-            showAllAppsWorkTabFromIntent(alreadyOnHome);
+            showAllAppsWithSelectedTabFromIntent(alreadyOnHome,
+                    ActivityAllAppsContainerView.AdapterHolder.WORK);
         }
 
         TraceHelper.INSTANCE.endSection();
@@ -1648,7 +1667,12 @@
         // Overridden
     }
 
-    protected void toggleAllAppsFromIntent(boolean alreadyOnHome) {
+    /** Toggles Launcher All Apps with keyboard ready for search. */
+    public void toggleAllAppsSearch() {
+        toggleAllAppsSearch(/* alreadyOnHome= */ true);
+    }
+
+    protected void toggleAllAppsSearch(boolean alreadyOnHome) {
         if (getStateManager().isInStableState(ALL_APPS)) {
             getStateManager().goToState(NORMAL, alreadyOnHome);
         } else {
@@ -1669,13 +1693,19 @@
     }
 
     protected void showAllAppsFromIntent(boolean alreadyOnHome) {
-        AbstractFloatingView.closeAllOpenViews(this);
-        getStateManager().goToState(ALL_APPS, alreadyOnHome);
+        showAllAppsWithSelectedTabFromIntent(alreadyOnHome,
+                ActivityAllAppsContainerView.AdapterHolder.MAIN);
     }
 
-    private void showAllAppsWorkTabFromIntent(boolean alreadyOnHome) {
-        showAllAppsFromIntent(alreadyOnHome);
-        mAppsView.switchToTab(ActivityAllAppsContainerView.AdapterHolder.WORK);
+    private void showAllAppsWithSelectedTabFromIntent(boolean alreadyOnHome, int tab) {
+        AbstractFloatingView.closeAllOpenViews(this);
+        getStateManager().goToState(ALL_APPS, alreadyOnHome);
+        if (mAppsView.isSearching()) {
+            mAppsView.reset(alreadyOnHome);
+        }
+        if (mAppsView.getCurrentPage() != tab) {
+            mAppsView.switchToTab(tab);
+        }
     }
 
     /**
@@ -1830,7 +1860,9 @@
         if (isActivityStarted) {
             DragView dropView = getDragLayer().clearAnimatedView();
             if (dropView != null && dropView.containsAppWidgetHostView()) {
-                widgetPreviewBitmap = getBitmapFromView(dropView.getContentView());
+                // Extracting Bitmap from dropView instead of its content view produces the correct
+                // bitmap.
+                widgetPreviewBitmap = getBitmapFromView(dropView);
             }
         }
 
@@ -1839,7 +1871,7 @@
                 : () -> mStateManager.goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
         completeAddAppWidget(appWidgetId, info, boundWidget,
                 addFlowHandler.getProviderInfo(this), addFlowHandler.needsConfigure(),
-                widgetPreviewBitmap);
+                false, widgetPreviewBitmap);
         mWorkspace.removeExtraEmptyScreenDelayed(delay, false, onComplete);
     }
 
@@ -2057,8 +2089,16 @@
         getOnBackAnimationCallback().onBackInvoked();
     }
 
+    protected void onBackStarted() {
+        mStateManager.getState().onBackStarted(this);
+    }
+
     protected void onStateBack() {
-        mStateManager.getState().onBackPressed(this);
+        mStateManager.getState().onBackInvoked(this);
+    }
+
+    protected void onBackCancelled() {
+        mStateManager.getState().onBackCancelled(this);
     }
 
     protected void onScreenOnChanged(boolean isOn) {
@@ -2367,7 +2407,8 @@
      * Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
      * animation.
      *
-     * @param preferredItemId The id of the preferred item to match to if it exists.
+     * @param preferredItemId The id of the preferred item to match to if it exists,
+     *                        or ItemInfo#NO_MATCHING_ID if you want to not match by item id
      * @param packageName The package name of the app to match.
      * @param user The user of the app to match.
      * @param supportsAllAppsState If true and we are in All Apps state, looks for view in All Apps.
@@ -2644,6 +2685,7 @@
 
         mModel.dumpState(prefix, fd, writer, args);
         mOverlayManager.dump(prefix, writer);
+        ACTIVITY_TRACKER.dump(prefix, writer);
     }
 
     /**
@@ -2731,7 +2773,7 @@
 
     private void updateDisallowBack() {
         if (Flags.enableDesktopWindowingMode()) {
-            // Do not disable back in launcher when prototype behavior is enabled
+            // TODO(b/330183377) disable back in launcher when when we productionize
             return;
         }
         LauncherRootView rv = getRootView();
@@ -2851,8 +2893,8 @@
      * Returns {@code true} if there are visible tasks with windowing mode set to
      * {@link android.app.WindowConfiguration#WINDOWING_MODE_FREEFORM}
      */
-    public boolean areFreeformTasksVisible() {
-        return false; // Base launcher does not track freeform tasks
+    public boolean areDesktopTasksVisible() {
+        return false; // Base launcher does not track desktop tasks
     }
 
     // Getters and Setters
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index be01d63..7fdfd72 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -47,12 +47,12 @@
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.AddWorkspaceItemsTask;
 import com.android.launcher3.model.AllAppsList;
+import com.android.launcher3.model.BaseLauncherBinder;
 import com.android.launcher3.model.BaseModelUpdateTask;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.CacheDataUpdatedTask;
 import com.android.launcher3.model.ItemInstallQueue;
-import com.android.launcher3.model.LauncherBinder;
 import com.android.launcher3.model.LoaderTask;
 import com.android.launcher3.model.ModelDbController;
 import com.android.launcher3.model.ModelDelegate;
@@ -365,7 +365,7 @@
                     MAIN_EXECUTOR.execute(cb::clearPendingBinds);
                 }
 
-                LauncherBinder launcherBinder = new LauncherBinder(
+                BaseLauncherBinder launcherBinder = new BaseLauncherBinder(
                         mApp, mBgDataModel, mBgAllAppsList, callbacksList);
                 if (bindDirectly) {
                     // Divide the set of loaded items into those that we are binding synchronously,
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index b0a644b..875c407 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -20,7 +20,6 @@
 import android.content.SharedPreferences
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener
 import android.util.Log
-import android.view.ViewConfiguration
 import androidx.annotation.VisibleForTesting
 import com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN
 import com.android.launcher3.LauncherFiles.DEVICE_PREFERENCES_KEY
@@ -298,59 +297,9 @@
         @JvmField
         val ICON_STATE =
             nonRestorableItem("pref_icon_shape_path", "", EncryptionType.MOVE_TO_DEVICE_PROTECTED)
+
         @JvmField
-        val ALL_APPS_OVERVIEW_THRESHOLD =
-            nonRestorableItem(
-                "pref_all_apps_overview_threshold",
-                180,
-                EncryptionType.MOVE_TO_DEVICE_PROTECTED
-            )
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE =
-            nonRestorableItem("LPNH_SLOP_PERCENTAGE", 100, EncryptionType.MOVE_TO_DEVICE_PROTECTED)
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_TIMEOUT_MS =
-            nonRestorableItem(
-                "LPNH_TIMEOUT_MS",
-                ViewConfiguration.getLongPressTimeout(),
-                EncryptionType.MOVE_TO_DEVICE_PROTECTED
-            )
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT =
-            nonRestorableItem(
-                "LPNH_HAPTIC_HINT_START_SCALE_PERCENT",
-                0,
-                EncryptionType.MOVE_TO_DEVICE_PROTECTED
-            )
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT =
-            nonRestorableItem(
-                "LPNH_HAPTIC_HINT_END_SCALE_PERCENT",
-                100,
-                EncryptionType.MOVE_TO_DEVICE_PROTECTED
-            )
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT =
-            nonRestorableItem(
-                "LPNH_HAPTIC_HINT_SCALE_EXPONENT",
-                1,
-                EncryptionType.MOVE_TO_DEVICE_PROTECTED
-            )
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS =
-            nonRestorableItem(
-                "LPNH_HAPTIC_HINT_ITERATIONS",
-                50,
-                EncryptionType.MOVE_TO_DEVICE_PROTECTED
-            )
-        @JvmField
-        val LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_DELAY =
-            nonRestorableItem("LPNH_HAPTIC_HINT_DELAY", 0, EncryptionType.MOVE_TO_DEVICE_PROTECTED)
-        @JvmField
-        val PRIVATE_SPACE_APPS =
-            nonRestorableItem("pref_private_space_apps", 0, EncryptionType.MOVE_TO_DEVICE_PROTECTED)
-        @JvmField val ENABLE_TWOLINE_ALLAPPS_TOGGLE =
-                backedUpItem("pref_enable_two_line_toggle", false)
+        val ENABLE_TWOLINE_ALLAPPS_TOGGLE = backedUpItem("pref_enable_two_line_toggle", false)
         @JvmField
         val THEMED_ICONS =
             backedUpItem(Themes.KEY_THEMED_ICONS, false, EncryptionType.MOVE_TO_DEVICE_PROTECTED)
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 34ebaf2..84b8ba1 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -139,6 +139,11 @@
         public static final int ITEM_TYPE_SEARCH_ACTION = 9;
 
         /**
+         * Private space install app button.
+         */
+        public static final int ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON = 11;
+
+        /**
          * The custom icon bitmap.
          * <P>Type: BLOB</P>
          */
@@ -206,6 +211,8 @@
                 case ITEM_TYPE_TASK: return "TASK";
                 case ITEM_TYPE_QSB: return "QSB";
                 case ITEM_TYPE_APP_PAIR: return "APP_PAIR";
+                case ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON:
+                    return "PRIVATE_SPACE_INSTALL_APP_BUTTON";
                 default: return String.valueOf(type);
             }
         }
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 6e66c14..3bdd863 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -424,20 +424,29 @@
         return TestProtocol.stateOrdinalToString(ordinal);
     }
 
-    public void onBackPressed(Launcher launcher) {
+    /** Called when predictive back gesture is started. */
+    public void onBackStarted(Launcher launcher) {}
+
+    /**
+     * Called when back action is invoked. This can happen when:
+     * 1. back button is pressed in 3-button navigation.
+     * 2. when back is committed during back swiped (predictive or non-predictive).
+     * 3. when we programmatically perform back action.
+     */
+    public void onBackInvoked(Launcher launcher) {
         if (this != NORMAL) {
             StateManager<LauncherState> lsm = launcher.getStateManager();
             LauncherState lastState = lsm.getLastState();
-            lsm.goToState(lastState, forEndCallback(this::onBackPressCompleted));
+            lsm.goToState(lastState, forEndCallback(this::onBackAnimationCompleted));
         }
     }
 
     /**
-     * To be called if back press is completed in a launcher state.
+     * To be called if back animation is completed in a launcher state.
      *
-     * @param success whether back press animation was successful or canceled.
+     * @param success whether back animation was successful or canceled.
      */
-    protected void onBackPressCompleted(boolean success) {
+    protected void onBackAnimationCompleted(boolean success) {
         // Do nothing. To be overridden by child class.
     }
 
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 1fede56..1c23644 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -826,7 +826,9 @@
                 // or right edge for RTL.
                 final int pageScroll =
                         mIsRtl ? childPrimaryEnd - scrollOffsetEnd : childStart - scrollOffsetStart;
-                if (outPageScrolls[i] != pageScroll) {
+                // If there's more than one panel, only update scroll on leftmost panel.
+                if (outPageScrolls[i] != pageScroll
+                        && (panelCount <= 1 || i == getLeftmostVisiblePageForIndex(i))) {
                     pageScrollChanged = true;
                     outPageScrolls[i] = pageScroll;
                 }
@@ -842,7 +844,7 @@
 
         if (panelCount > 1) {
             for (int i = 0; i < childCount; i++) {
-                // In case we have multiple panels, always use left most panel's page scroll for all
+                // In case we have multiple panels, always use leftmost panel's page scroll for all
                 // panels on the screen.
                 int adjustedScroll = outPageScrolls[getLeftmostVisiblePageForIndex(i)];
                 if (outPageScrolls[i] != adjustedScroll) {
diff --git a/src/com/android/launcher3/UtilitiesKt.kt b/src/com/android/launcher3/UtilitiesKt.kt
new file mode 100644
index 0000000..a207d57
--- /dev/null
+++ b/src/com/android/launcher3/UtilitiesKt.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewParent
+
+object UtilitiesKt {
+
+    /**
+     * Modify [ViewGroup]'s attribute with type [T]. The overridden attribute is saved by calling
+     * [View.setTag] and can be later restored by [View.getTag].
+     *
+     * @param <T> type of [ViewGroup] attribute. For example, [T] is [Boolean] if modifying
+     *   [ViewGroup.setClipChildren]
+     */
+    abstract class ViewGroupAttrModifier<T>(
+        private val targetAttrValue: T,
+        private val tagKey: Int
+    ) {
+        /**
+         * If [targetAttrValue] is different from existing view attribute returned from
+         * [getAttribute], this method will save existing attribute by calling [ViewGroup.setTag].
+         * Then call [setAttribute] to set attribute with [targetAttrValue].
+         */
+        fun saveAndChangeAttribute(viewGroup: ViewGroup) {
+            val oldAttrValue = getAttribute(viewGroup)
+            if (oldAttrValue !== targetAttrValue) {
+                viewGroup.setTag(tagKey, oldAttrValue)
+                setAttribute(viewGroup, targetAttrValue)
+            }
+        }
+
+        /** Restore saved attribute in [saveAndChangeAttribute] by calling [ViewGroup.getTag]. */
+        @Suppress("UNCHECKED_CAST")
+        fun restoreAttribute(viewGroup: ViewGroup) {
+            val oldAttrValue: T = viewGroup.getTag(tagKey) as T ?: return
+            setAttribute(viewGroup, oldAttrValue)
+            viewGroup.setTag(tagKey, null)
+        }
+
+        /** Subclass will override this method to decide how to get [ViewGroup] attribute. */
+        abstract fun getAttribute(viewGroup: ViewGroup): T
+
+        /** Subclass will override this method to decide how to set [ViewGroup] attribute. */
+        abstract fun setAttribute(viewGroup: ViewGroup, attr: T)
+    }
+
+    /** [ViewGroupAttrModifier] to call [ViewGroup.setClipChildren] to false. */
+    @JvmField
+    val CLIP_CHILDREN_FALSE_MODIFIER: ViewGroupAttrModifier<Boolean> =
+        object : ViewGroupAttrModifier<Boolean>(false, R.id.saved_clip_children_tag_id) {
+            override fun getAttribute(viewGroup: ViewGroup): Boolean {
+                return viewGroup.clipChildren
+            }
+
+            override fun setAttribute(viewGroup: ViewGroup, clipChildren: Boolean) {
+                viewGroup.clipChildren = clipChildren
+            }
+        }
+
+    /** [ViewGroupAttrModifier] to call [ViewGroup.setClipToPadding] to false. */
+    @JvmField
+    val CLIP_TO_PADDING_FALSE_MODIFIER: ViewGroupAttrModifier<Boolean> =
+        object : ViewGroupAttrModifier<Boolean>(false, R.id.saved_clip_to_padding_tag_id) {
+            override fun getAttribute(viewGroup: ViewGroup): Boolean {
+                return viewGroup.clipToPadding
+            }
+
+            override fun setAttribute(viewGroup: ViewGroup, clipToPadding: Boolean) {
+                viewGroup.clipToPadding = clipToPadding
+            }
+        }
+
+    /**
+     * Recursively call [ViewGroupAttrModifier.saveAndChangeAttribute] from [View] to its parent
+     * (direct or indirect) inclusive.
+     *
+     * [ViewGroupAttrModifier.saveAndChangeAttribute] will save the existing attribute value on each
+     * view with [View.setTag], which can be restored in [restoreAttributesOnViewTree].
+     *
+     * Note that if parent is null or not a parent of the view, this method will be applied all the
+     * way to root view.
+     *
+     * @param v child view
+     * @param parent direct or indirect parent of child view
+     * @param modifiers list of [ViewGroupAttrModifier] to modify view attribute
+     */
+    @JvmStatic
+    fun modifyAttributesOnViewTree(
+        v: View?,
+        parent: ViewParent?,
+        vararg modifiers: ViewGroupAttrModifier<*>
+    ) {
+        if (v == null) {
+            return
+        }
+        if (v is ViewGroup) {
+            for (modifier in modifiers) {
+                modifier.saveAndChangeAttribute(v)
+            }
+        }
+        if (v === parent) {
+            return
+        }
+        if (v.parent is View) {
+            modifyAttributesOnViewTree(v.parent as View, parent, *modifiers)
+        }
+    }
+
+    /**
+     * Recursively call [ViewGroupAttrModifier.restoreAttribute]} to restore view attributes
+     * previously saved in [ViewGroupAttrModifier.saveAndChangeAttribute] on view to its parent
+     * (direct or indirect) inclusive.
+     *
+     * Note that if parent is null or not a parent of the view, this method will be applied all the
+     * way to root view.
+     *
+     * @param v child view
+     * @param parent direct or indirect parent of child view
+     * @param modifiers list of [ViewGroupAttrModifier] to restore view attributes
+     */
+    @JvmStatic
+    fun restoreAttributesOnViewTree(
+        v: View?,
+        parent: ViewParent?,
+        vararg modifiers: ViewGroupAttrModifier<*>
+    ) {
+        if (v == null) {
+            return
+        }
+        if (v is ViewGroup) {
+            for (modifier in modifiers) {
+                modifier.restoreAttribute(v)
+            }
+        }
+        if (v === parent) {
+            return
+        }
+        if (v.parent is View) {
+            restoreAttributesOnViewTree(v.parent as View, parent, *modifiers)
+        }
+    }
+}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index e80156c..0fc3211 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.BubbleTextView.DISPLAY_FOLDER;
 import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
 import static com.android.launcher3.LauncherState.ALL_APPS;
@@ -73,6 +74,7 @@
 import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
 import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.apppairs.AppPairIcon;
 import com.android.launcher3.celllayout.CellInfo;
 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
 import com.android.launcher3.celllayout.CellPosMapper;
@@ -241,6 +243,8 @@
     public static final int REORDER_TIMEOUT = 650;
     protected final Alarm mReorderAlarm = new Alarm();
     private PreviewBackground mFolderCreateBg;
+    /** The underlying view that we are dragging something over. */
+    private View mDragOverView = null;
     private FolderIcon mDragOverFolderIcon = null;
     private boolean mCreateUserFolderOnDrop = false;
     private boolean mAddToExistingFolderOnDrop = false;
@@ -2381,6 +2385,11 @@
         if (mFolderCreateBg != null) {
             mFolderCreateBg.animateToRest();
         }
+
+        if (mDragOverView instanceof AppPairIcon api) {
+            api.getIconDrawableArea().onTemporaryContainerChange(null);
+            mDragOverView = null;
+        }
     }
 
     private void cleanupAddToFolder() {
@@ -2656,32 +2665,36 @@
             return;
         }
 
-        final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
+        mDragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
         ItemInfo info = dragObject.dragInfo;
-        boolean userFolderPending = willCreateUserFolder(info, dragOverView, false);
+        boolean userFolderPending = willCreateUserFolder(info, mDragOverView, false);
         if (mDragMode == DRAG_MODE_NONE && userFolderPending) {
 
             mFolderCreateBg = new PreviewBackground();
             mFolderCreateBg.setup(mLauncher, mLauncher, null,
-                    dragOverView.getMeasuredWidth(), dragOverView.getPaddingTop());
+                    mDragOverView.getMeasuredWidth(), mDragOverView.getPaddingTop());
 
             // The full preview background should appear behind the icon
             mFolderCreateBg.isClipping = false;
 
+            if (mDragOverView instanceof AppPairIcon api) {
+                api.getIconDrawableArea().onTemporaryContainerChange(DISPLAY_FOLDER);
+            }
+
             mFolderCreateBg.animateToAccept(mDragTargetLayout, mTargetCell[0], mTargetCell[1]);
             mDragTargetLayout.clearDragOutlines();
             setDragMode(DRAG_MODE_CREATE_FOLDER);
 
             if (dragObject.stateAnnouncer != null) {
                 dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
-                        .getDescriptionForDropOver(dragOverView, getContext()));
+                        .getDescriptionForDropOver(mDragOverView, getContext()));
             }
             return;
         }
 
-        boolean willAddToFolder = willAddToExistingUserFolder(info, dragOverView);
+        boolean willAddToFolder = willAddToExistingUserFolder(info, mDragOverView);
         if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
-            mDragOverFolderIcon = ((FolderIcon) dragOverView);
+            mDragOverFolderIcon = ((FolderIcon) mDragOverView);
             mDragOverFolderIcon.onDragEnter(info);
             if (mDragTargetLayout != null) {
                 mDragTargetLayout.clearDragOutlines();
@@ -2690,7 +2703,7 @@
 
             if (dragObject.stateAnnouncer != null) {
                 dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
-                        .getDescriptionForDropOver(dragOverView, getContext()));
+                        .getDescriptionForDropOver(mDragOverView, getContext()));
             }
             return;
         }
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 785074b..9792300 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -57,6 +57,7 @@
 import com.android.launcher3.views.OptionsPopupView;
 import com.android.launcher3.views.OptionsPopupView.OptionItem;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.PendingAddWidgetInfo;
 import com.android.launcher3.widget.util.WidgetSizes;
 
 import java.util.ArrayList;
@@ -417,10 +418,21 @@
                 announceConfirmation(R.string.item_added_to_workspace);
             } else if (item instanceof PendingAddItemInfo) {
                 PendingAddItemInfo info = (PendingAddItemInfo) item;
+                if (info instanceof PendingAddWidgetInfo widgetInfo
+                        && widgetInfo.bindOptions == null) {
+                    widgetInfo.bindOptions = widgetInfo.getDefaultSizeOptions(mContext);
+                }
                 Workspace<?> workspace = mContext.getWorkspace();
-                workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
-                mContext.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
-                        screenId, coordinates, info.spanX, info.spanY);
+                workspace.post(() -> {
+                    workspace.snapToPage(workspace.getPageIndexForScreenId(screenId));
+                    workspace.setOnPageTransitionEndCallback(() -> {
+                        mContext.addPendingItem(info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
+                                screenId, coordinates, info.spanX, info.spanY);
+                        if (finishCallback != null) {
+                            finishCallback.accept(/* success= */ true);
+                        }
+                    });
+                });
             } else if (item instanceof WorkspaceItemInfo) {
                 WorkspaceItemInfo info = ((WorkspaceItemInfo) item).clone();
                 mContext.getModelWriter().addItemToDatabase(info,
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index 6acfcd0..c255eb5 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.Flags.enableExpandingPauseWorkButton;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
 import static com.android.launcher3.config.FeatureFlags.ALL_APPS_GONE_VISIBILITY;
@@ -70,7 +71,6 @@
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.Flags;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.R;
@@ -86,6 +86,7 @@
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.recyclerview.AllAppsRecyclerViewPool;
 import com.android.launcher3.util.ItemInfoMatcher;
+import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ActivityContext;
 import com.android.launcher3.views.BaseDragLayer;
@@ -97,6 +98,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Optional;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
 
@@ -127,7 +129,6 @@
     public static final float PULL_MULTIPLIER = .02f;
     public static final float FLING_VELOCITY_MULTIPLIER = 1200f;
     protected static final String BUNDLE_KEY_CURRENT_PAGE = "launcher.allapps.current_page";
-    private static final int SCROLL_TO_BOTTOM_DURATION = 500;
     private static final long DEFAULT_SEARCH_TRANSITION_DURATION_MS = 300;
     // Render the header protection at all times to debug clipping issues.
     private static final boolean DEBUG_HEADER_PROTECTION = false;
@@ -158,6 +159,7 @@
             };
     private final Paint mNavBarScrimPaint;
     private final int mHeaderProtectionColor;
+    private final int mPrivateSpaceBottomExtraSpace;
     private final Path mTmpPath = new Path();
     private final RectF mTmpRectF = new RectF();
     protected AllAppsPagedView mViewPager;
@@ -189,10 +191,9 @@
     private float mBottomSheetAlpha = 1f;
     private boolean mForceBottomSheetVisible;
     private int mTabsProtectionAlpha;
+    private float mTotalHeaderProtectionHeight;
     @Nullable private AllAppsTransitionController mAllAppsTransitionController;
 
-    private PrivateSpaceHeaderViewController mPrivateSpaceHeaderViewController;
-
     public ActivityAllAppsContainerView(Context context) {
         this(context, null);
     }
@@ -221,6 +222,8 @@
                 this,
                 mActivityContext.getStatsLogManager(),
                 UserCache.INSTANCE.get(mActivityContext));
+        mPrivateSpaceBottomExtraSpace = context.getResources().getDimensionPixelSize(
+                R.dimen.ps_extra_bottom_padding);
         mAH = Arrays.asList(null, null, null);
         mNavBarScrimPaint = new Paint();
         mNavBarScrimPaint.setColor(Themes.getNavBarScrimColor(mActivityContext));
@@ -260,10 +263,6 @@
      */
     protected void initContent() {
         mMainAdapterProvider = mSearchUiDelegate.createMainAdapterProvider();
-        if (Flags.enablePrivateSpace()) {
-            mPrivateSpaceHeaderViewController =
-                    new PrivateSpaceHeaderViewController(this, mPrivateProfileManager);
-        }
 
         mAH.set(AdapterHolder.MAIN, new AdapterHolder(AdapterHolder.MAIN,
                 new AlphabeticalAppsList<>(mActivityContext,
@@ -397,7 +396,7 @@
         mAllAppsTransitionController = allAppsTransitionController;
     }
 
-    private void animateToSearchState(boolean goingToSearch, long durationMs) {
+    void animateToSearchState(boolean goingToSearch, long durationMs) {
         if (!mSearchTransitionController.isRunning() && goingToSearch == isSearching()) {
             return;
         }
@@ -498,9 +497,9 @@
     }
 
     /**
-     * Exits search and returns to A-Z apps list. Scroll to the bottom.
+     * Exits search and returns to A-Z apps list. Scroll to the private space header.
      */
-    public void resetAndScrollToBottom() {
+    public void resetAndScrollToPrivateSpaceHeader() {
         if (mTouchHandler != null) {
             mTouchHandler.endFastScrolling();
         }
@@ -517,7 +516,13 @@
             // Switch to the main tab
             switchToTab(ActivityAllAppsContainerView.AdapterHolder.MAIN);
             // Scroll to bottom
-            getActiveRecyclerView().scrollToBottomWithMotion(SCROLL_TO_BOTTOM_DURATION);
+            if (mPrivateProfileManager != null) {
+                mPrivateProfileManager.scrollForHeaderToBeVisibleInContainer(
+                        getActiveAppsRecyclerView(),
+                        getPersonalAppList().getAdapterItems(),
+                        mPrivateProfileManager.getPsHeaderHeight(),
+                        mActivityContext.getDeviceProfile().allAppsCellHeightPx);
+            }
         });
     }
 
@@ -905,7 +910,7 @@
 
     protected BaseAllAppsAdapter<T> createAdapter(AlphabeticalAppsList<T> appsList) {
         return new AllAppsGridAdapter<>(mActivityContext, getLayoutInflater(), appsList,
-                mMainAdapterProvider, mPrivateSpaceHeaderViewController);
+                mMainAdapterProvider);
     }
 
     // TODO(b/216683257): Remove when Taskbar All Apps supports search.
@@ -1367,12 +1372,25 @@
         invalidateHeader();
     }
 
+    /**
+     * Set {@link Animator.AnimatorListener} on {@link mAllAppsTransitionController} to observe
+     * animation of backing out of all apps search view to all apps view.
+     */
+    public void setAllAppsSearchBackAnimatorListener(Animator.AnimatorListener listener) {
+        Preconditions.assertNotNull(mAllAppsTransitionController);
+        if (mAllAppsTransitionController == null) {
+            return;
+        }
+        mAllAppsTransitionController.setAllAppsSearchBackAnimationListener(listener);
+    }
+
     public void setScrimView(ScrimView scrimView) {
         mScrimView = scrimView;
     }
 
     @Override
-    public void drawOnScrimWithScale(Canvas canvas, float scale) {
+    public void drawOnScrimWithScaleAndBottomOffset(
+            Canvas canvas, float scale, @Px int bottomOffsetPx) {
         final View panel = mBottomSheetBackground;
         final boolean hasBottomSheet = panel.getVisibility() == VISIBLE;
         final float translationY = ((View) panel.getParent()).getTranslationY();
@@ -1384,6 +1402,7 @@
         final float topWithScale = topNoScale + verticalScaleOffset;
         final float leftWithScale = panel.getLeft() + horizontalScaleOffset;
         final float rightWithScale = panel.getRight() - horizontalScaleOffset;
+        final float bottomWithOffset = panel.getBottom() + bottomOffsetPx;
         // Draw full background panel for tablets.
         if (hasBottomSheet) {
             mHeaderPaint.setColor(mBottomSheetBackgroundColor);
@@ -1393,7 +1412,7 @@
                     leftWithScale,
                     topWithScale,
                     rightWithScale,
-                    panel.getBottom());
+                    bottomWithOffset);
             mTmpPath.reset();
             mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW);
             canvas.drawPath(mTmpPath, mHeaderPaint);
@@ -1429,9 +1448,11 @@
                 mTmpPath.reset();
                 mTmpPath.addRoundRect(mTmpRectF, mBottomSheetCornerRadii, Direction.CW);
                 canvas.drawPath(mTmpPath, mHeaderPaint);
+                mTotalHeaderProtectionHeight = headerBottomWithScaleOnTablet;
             }
         } else {
             canvas.drawRect(0, 0, canvas.getWidth(), headerBottomWithScaleOnPhone, mHeaderPaint);
+            mTotalHeaderProtectionHeight = headerBottomWithScaleOnPhone;
         }
 
         // If tab exist (such as work profile), extend header with tab height
@@ -1461,10 +1482,19 @@
                     right,
                     tabBottomWithScale,
                     mHeaderPaint);
+            mTotalHeaderProtectionHeight = tabBottomWithScale;
         }
     }
 
     /**
+     * The height of the header protection is dynamically calculated during the time of drawing the
+     * header.
+     */
+    float getHeaderProtectionHeight() {
+        return mTotalHeaderProtectionHeight;
+    }
+
+    /**
      * redraws header protection
      */
     public void invalidateHeader() {
@@ -1552,6 +1582,14 @@
                 int bottomOffset = 0;
                 if (isWork() && mWorkManager.getWorkModeSwitch() != null) {
                     bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight();
+                } else if (isMain() && mPrivateProfileManager != null) {
+                    Optional<AdapterItem> privateSpaceHeaderItem = mAppsList.getAdapterItems()
+                            .stream()
+                            .filter(item -> item.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER)
+                            .findFirst();
+                    if (privateSpaceHeaderItem.isPresent()) {
+                        bottomOffset = mPrivateSpaceBottomExtraSpace;
+                    }
                 }
                 if (isSearchBarFloating()) {
                     bottomOffset += mSearchContainer.getHeight();
@@ -1568,5 +1606,9 @@
         private boolean isSearch() {
             return mType == SEARCH;
         }
+
+        private boolean isMain() {
+            return mType == MAIN;
+        }
     }
 }
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 5f002b5..df383bf 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -73,9 +73,8 @@
 
 
     public AllAppsGridAdapter(T activityContext, LayoutInflater inflater,
-            AlphabeticalAppsList apps, SearchAdapterProvider<?> adapterProvider,
-            PrivateSpaceHeaderViewController privateSpaceHeaderViewController) {
-        super(activityContext, inflater, apps, adapterProvider, privateSpaceHeaderViewController);
+            AlphabeticalAppsList apps, SearchAdapterProvider<?> adapterProvider) {
+        super(activityContext, inflater, apps, adapterProvider);
         mGridLayoutMgr = new AppsGridLayoutManager(mActivityContext);
         mGridLayoutMgr.setSpanSizeLookup(new GridSpanSizer());
         setAppsPerRow(activityContext.getDeviceProfile().numShownAllAppsColumns);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index e2c5795..564daf1 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -24,6 +24,9 @@
 import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.UtilitiesKt.CLIP_CHILDREN_FALSE_MODIFIER;
+import static com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree;
+import static com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_BOTTOM_SHEET_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
@@ -38,8 +41,6 @@
 import android.util.FloatProperty;
 import android.view.HapticFeedbackConstants;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
 import android.view.animation.Interpolator;
 
 import androidx.annotation.FloatRange;
@@ -167,6 +168,8 @@
     private final AnimatedFloat mAllAppScale = new AnimatedFloat(this::onScaleProgressChanged);
     private final int mNavScrimFlag;
 
+    @Nullable private Animator.AnimatorListener mAllAppsSearchBackAnimationListener;
+
     private boolean mIsVerticalLayout;
 
     // Animation in this class is controlled by a single variable {@link mProgress}.
@@ -280,8 +283,7 @@
             return;
         }
 
-        float deceleratedProgress =
-                Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(backProgress);
+        float deceleratedProgress = Interpolators.BACK_GESTURE.getInterpolation(backProgress);
         float scaleProgress = ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE
                 + (1 - ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE)
                 * (1 - deceleratedProgress);
@@ -295,9 +297,6 @@
         mLauncher.getScrimView().setScrimHeaderScale(scaleProgress);
 
         AllAppsRecyclerView rv = mLauncher.getAppsView().getActiveRecyclerView();
-        if (rv != null && rv.getScrollbar() != null) {
-            rv.getScrollbar().setVisibility(scaleProgress < 1f ? View.INVISIBLE : View.VISIBLE);
-        }
 
         // Disable view clipping from all apps' RecyclerView up to all apps view during scale
         // animation, and vice versa. The goal is to display extra roll(s) app icons (rendered in
@@ -306,18 +305,34 @@
         if (hasScaleEffect != mHasScaleEffect) {
             mHasScaleEffect = hasScaleEffect;
             if (mHasScaleEffect) {
-                setClipChildrenOnViewTree(rv, mLauncher.getAppsView(), false);
+                modifyAttributesOnViewTree(rv, mLauncher.getAppsView(),
+                        CLIP_CHILDREN_FALSE_MODIFIER);
             } else {
-                restoreClipChildrenOnViewTree(rv, mLauncher.getAppsView());
+                restoreAttributesOnViewTree(rv, mLauncher.getAppsView(),
+                        CLIP_CHILDREN_FALSE_MODIFIER);
             }
         }
     }
 
-    /** Animate all apps view to 1f scale. */
+    /** Set {@link Animator.AnimatorListener} for scaling all apps scale to 1 animation. */
+    public void setAllAppsSearchBackAnimationListener(Animator.AnimatorListener listener) {
+        mAllAppsSearchBackAnimationListener = listener;
+    }
+
+    /**
+     * Animate all apps view to 1f scale. This is called when backing (exiting) from all apps
+     * search view to all apps view.
+     */
     public void animateAllAppsToNoScale() {
-        mAllAppScale.animateToValue(1f)
-                .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS)
-                .start();
+        if (mAllAppScale.isAnimating()) {
+            return;
+        }
+        Animator animator = mAllAppScale.animateToValue(1f)
+                .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS);
+        if (mAllAppsSearchBackAnimationListener != null) {
+            animator.addListener(mAllAppsSearchBackAnimationListener);
+        }
+        animator.start();
     }
 
     /**
@@ -423,79 +438,6 @@
     }
 
     /**
-     * Recursively call {@link ViewGroup#setClipChildren(boolean)} from {@link View} to ts parent
-     * (direct or indirect) inclusive. This method will also save the old clipChildren value on each
-     * view with {@link View#setTag(int, Object)}, which can be restored in
-     * {@link #restoreClipChildrenOnViewTree(View, ViewParent)}.
-     *
-     * Note that if parent is null or not a parent of the view, this method will be applied all the
-     * way to root view.
-     *
-     * @param v child view
-     * @param parent direct or indirect parent of child view
-     * @param clipChildren whether we should clip children
-     */
-    private static void setClipChildrenOnViewTree(
-            @Nullable View v,
-            @Nullable ViewParent parent,
-            boolean clipChildren) {
-        if (v == null) {
-            return;
-        }
-
-        if (v instanceof ViewGroup) {
-            ViewGroup viewGroup = (ViewGroup) v;
-            boolean oldClipChildren = viewGroup.getClipChildren();
-            if (oldClipChildren != clipChildren) {
-                v.setTag(R.id.saved_clip_children_tag_id, oldClipChildren);
-                viewGroup.setClipChildren(clipChildren);
-            }
-        }
-
-        if (v == parent) {
-            return;
-        }
-
-        if (v.getParent() instanceof View) {
-            setClipChildrenOnViewTree((View) v.getParent(), parent, clipChildren);
-        }
-    }
-
-    /**
-     * Recursively call {@link ViewGroup#setClipChildren(boolean)} to restore clip children value
-     * set in {@link #setClipChildrenOnViewTree(View, ViewParent, boolean)} on view to its parent
-     * (direct or indirect) inclusive.
-     *
-     * Note that if parent is null or not a parent of the view, this method will be applied all the
-     * way to root view.
-     *
-     * @param v child view
-     * @param parent direct or indirect parent of child view
-     */
-    private static void restoreClipChildrenOnViewTree(
-            @Nullable View v, @Nullable ViewParent parent) {
-        if (v == null) {
-            return;
-        }
-        if (v instanceof ViewGroup) {
-            ViewGroup viewGroup = (ViewGroup) v;
-            Object viewTag = viewGroup.getTag(R.id.saved_clip_children_tag_id);
-            if (viewTag instanceof Boolean) {
-                viewGroup.setClipChildren((boolean) viewTag);
-                viewGroup.setTag(R.id.saved_clip_children_tag_id, null);
-            }
-        }
-
-        if (v == parent) {
-            return;
-        }
-
-        if (v.getParent() instanceof View) {
-            restoreClipChildrenOnViewTree((View) v.getParent(), parent);
-        }
-    }
-
-    /**
      * Updates the total scroll range but does not update the UI.
      */
     public void setShiftRange(float shiftRange) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index fba7537..4d4b8d2 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -18,6 +18,8 @@
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_LEFT;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_RIGHT;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_PREINSTALLED_APPS_COUNT;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_USER_INSTALLED_APPS_COUNT;
 
 import android.content.Context;
 
@@ -26,6 +28,7 @@
 import androidx.recyclerview.widget.DiffUtil;
 
 import com.android.launcher3.Flags;
+import com.android.launcher3.R;
 import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -203,7 +206,10 @@
      */
     @Override
     public void onAppsUpdated() {
-        if (mAllAppsStore == null) {
+        // Don't update apps when the private profile animations are running, otherwise the motion
+        // is canceled.
+        if (mAllAppsStore == null || (mPrivateProviderManager != null &&
+                mPrivateProviderManager.getAnimationRunning())) {
             return;
         }
         // Sort the list of apps
@@ -270,6 +276,12 @@
                 addApps = mWorkProviderManager.shouldShowWorkApps();
             }
             if (addApps) {
+                if (/* education card was added */ position == 1) {
+                    // Add work educard section with "info icon" at 0th position.
+                    mFastScrollerSections.add(new FastScrollSectionInfo(
+                            mActivityContext.getResources().getString(
+                                    R.string.work_profile_edu_section), 0));
+                }
                 position = addAppsWithSections(mApps, position);
             }
             if (Flags.enablePrivateSpace()) {
@@ -342,6 +354,20 @@
         Map<Boolean, List<AppInfo>> split = mPrivateApps.stream()
                 .collect(Collectors.partitioningBy(mPrivateProviderManager
                                 .splitIntoUserInstalledAndSystemApps()));
+
+        // TODO(b/329688630): switch to the pulled LayoutStaticSnapshot atom
+        mActivityContext
+                .getStatsLogManager()
+                .logger()
+                .withCardinality(split.get(true).size())
+                .log(LAUNCHER_PRIVATE_SPACE_USER_INSTALLED_APPS_COUNT);
+
+        mActivityContext
+                .getStatsLogManager()
+                .logger()
+                .withCardinality(split.get(false).size())
+                .log(LAUNCHER_PRIVATE_SPACE_PREINSTALLED_APPS_COUNT);
+
         // Add user installed apps
         position = addAppsWithSections(split.get(true), position);
         // Add system apps separator.
@@ -421,6 +447,10 @@
         return roundRegion;
     }
 
+    public PrivateProfileManager getPrivateProfileManager() {
+        return mPrivateProviderManager;
+    }
+
     private static class MyDiffCallback extends DiffUtil.Callback {
 
         private final List<AdapterItem> mOldList;
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index 5e5795d..3ba1eed 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -21,6 +21,7 @@
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_TOP_LEFT;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_TOP_RIGHT;
 import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
+import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED;
 
 import android.content.Context;
 import android.view.LayoutInflater;
@@ -40,7 +41,6 @@
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.views.ActivityContext;
 
@@ -169,16 +169,9 @@
     protected final OnClickListener mOnIconClickListener;
     protected final OnLongClickListener mOnIconLongClickListener;
     protected OnFocusChangeListener mIconFocusListener;
-    private final PrivateSpaceHeaderViewController mPrivateSpaceHeaderViewController;
 
     public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
             AlphabeticalAppsList<T> apps, SearchAdapterProvider<?> adapterProvider) {
-        this(activityContext, inflater, apps, adapterProvider, null);
-    }
-
-    public BaseAllAppsAdapter(T activityContext, LayoutInflater inflater,
-            AlphabeticalAppsList<T> apps, SearchAdapterProvider<?> adapterProvider,
-            PrivateSpaceHeaderViewController privateSpaceHeaderViewController) {
         mActivityContext = activityContext;
         mApps = apps;
         mLayoutInflater = inflater;
@@ -187,7 +180,6 @@
         mOnIconLongClickListener = mActivityContext.getAllAppsItemLongClickListener();
 
         mAdapterProvider = adapterProvider;
-        mPrivateSpaceHeaderViewController = privateSpaceHeaderViewController;
     }
 
     /** Checks if the passed viewType represents all apps divider. */
@@ -270,6 +262,17 @@
                 icon.reset();
                 icon.applyFromApplicationInfo(adapterItem.itemInfo);
                 icon.setOnFocusChangeListener(mIconFocusListener);
+                PrivateProfileManager privateProfileManager = mApps.getPrivateProfileManager();
+                // Set the alpha of the private space icon to 0 upon expanding the header so the
+                // alpha can animate -> 1.
+                if (icon.getAlpha() == 0 || icon.getAlpha() == 1) {
+                    icon.setAlpha(privateProfileManager != null
+                            && privateProfileManager.isPrivateSpaceItem(adapterItem)
+                            && privateProfileManager.getAnimationScrolling()
+                            && privateProfileManager.getAnimate()
+                            && privateProfileManager.getCurrentState() == STATE_ENABLED
+                            ? 0 : 1);
+                }
                 break;
             }
             case VIEW_TYPE_EMPTY_SEARCH: {
@@ -283,13 +286,10 @@
             case VIEW_TYPE_PRIVATE_SPACE_HEADER:
                 RelativeLayout psHeaderLayout = holder.itemView.findViewById(
                         R.id.ps_header_layout);
-                assert mPrivateSpaceHeaderViewController != null;
-                assert psHeaderLayout != null;
-                mPrivateSpaceHeaderViewController.addPrivateSpaceHeaderViewElements(psHeaderLayout);
+                mApps.getPrivateProfileManager().addPrivateSpaceHeaderViewElements(psHeaderLayout);
                 AdapterItem adapterItem = mApps.getAdapterItems().get(position);
                 int roundRegions = ROUND_TOP_LEFT | ROUND_TOP_RIGHT;
-                if (mPrivateSpaceHeaderViewController.getPrivateProfileManager().getCurrentState()
-                        == STATE_DISABLED) {
+                if (mApps.getPrivateProfileManager().getCurrentState() == STATE_DISABLED) {
                     roundRegions |= (ROUND_BOTTOM_LEFT | ROUND_BOTTOM_RIGHT);
                 }
                 adapterItem.decorationInfo =
diff --git a/src/com/android/launcher3/allapps/PrivateAppsSectionDecorator.java b/src/com/android/launcher3/allapps/PrivateAppsSectionDecorator.java
index 8712b84..18175b6 100644
--- a/src/com/android/launcher3/allapps/PrivateAppsSectionDecorator.java
+++ b/src/com/android/launcher3/allapps/PrivateAppsSectionDecorator.java
@@ -56,7 +56,7 @@
                                 new SectionDecorationHandler.UnionDecorationHandler(
                                         decorationHandler, parent.getPaddingLeft(),
                                         parent.getPaddingRight()));
-                unionHandler.addChild(decorationHandler, view, true /* applyBackground */);
+                unionHandler.addChild(decorationHandler, view);
                 deferredDecorations.put(PRIVATE_APP_SECTION, unionHandler);
             } else {
                 decorationHandler.onFocusDraw(c, view);
diff --git a/src/com/android/launcher3/allapps/PrivateProfileManager.java b/src/com/android/launcher3/allapps/PrivateProfileManager.java
index 1ebd49e..1def8a3 100644
--- a/src/com/android/launcher3/allapps/PrivateProfileManager.java
+++ b/src/com/android/launcher3/allapps/PrivateProfileManager.java
@@ -16,37 +16,67 @@
 
 package com.android.launcher3.allapps;
 
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ICON;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
 import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER;
 import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;
+import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP;
 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
 import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
-import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_PRIVATE_SPACE_INSTALL_APP;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 import static com.android.launcher3.util.SettingsCache.PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.LayoutTransition;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.LinearSmoothScroller;
+import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.BuildConfig;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
 import com.android.launcher3.R;
+import com.android.launcher3.anim.AnimatedPropertySetter;
+import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.PrivateSpaceInstallAppButtonInfo;
 import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.SettingsCache;
+import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.RecyclerViewFastScroller;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -59,18 +89,31 @@
  * logic in the Personal tab.
  */
 public class PrivateProfileManager extends UserProfileManager {
-
-    // TODO (b/324573634): Fix the intent string.
-    public static final Intent PRIVATE_SPACE_INTENT = new
-            Intent("com.android.settings.action.PRIVATE_SPACE_SETUP_FLOW");
-
+    private static final int EXPAND_COLLAPSE_DURATION = 800;
+    private static final int SETTINGS_OPACITY_DURATION = 160;
     private final ActivityAllAppsContainerView<?> mAllApps;
     private final Predicate<UserHandle> mPrivateProfileMatcher;
+    private final int mPsHeaderHeight;
+    private final RecyclerView.OnScrollListener mOnIdleScrollListener =
+            new RecyclerView.OnScrollListener() {
+        @Override
+        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
+            super.onScrollStateChanged(recyclerView, newState);
+            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                mAnimationScrolling = false;
+            }
+        }
+    };
     private Set<String> mPreInstalledSystemPackages = new HashSet<>();
     private Intent mAppInstallerIntent = new Intent();
     private PrivateAppsSectionDecorator mPrivateAppsSectionDecorator;
     private boolean mPrivateSpaceSettingsAvailable;
-    private Runnable mUnlockRunnable;
+    private boolean mIsAnimationRunning;
+    private boolean mAnimate;
+    private boolean mAnimationScrolling;
+    private Runnable mOnPSHeaderAdded;
+    @Nullable
+    private RelativeLayout mPSHeader;
 
     public PrivateProfileManager(UserManager userManager,
             ActivityAllAppsContainerView<?> allApps,
@@ -79,7 +122,11 @@
         super(userManager, statsLogManager, userCache);
         mAllApps = allApps;
         mPrivateProfileMatcher = (user) -> userCache.getUserInfo(user).isPrivate();
-        UI_HELPER_EXECUTOR.post(this::initializeInBackgroundThread);
+
+        Context appContext = allApps.getContext().getApplicationContext();
+        UI_HELPER_EXECUTOR.post(() -> initializeInBackgroundThread(appContext));
+        mPsHeaderHeight = mAllApps.getContext().getResources().getDimensionPixelSize(
+                R.dimen.ps_header_height);
     }
 
     /** Adds Private Space Header to the layout. */
@@ -105,13 +152,13 @@
                 context, com.android.launcher3.R.drawable.private_space_install_app_icon);
         BitmapInfo bitmapInfo = LauncherIcons.obtain(context).createIconBitmap(shortcut);
 
-        AppInfo itemInfo = new AppInfo();
+        PrivateSpaceInstallAppButtonInfo itemInfo = new PrivateSpaceInstallAppButtonInfo();
         itemInfo.title = context.getResources().getString(R.string.ps_add_button_label);
         itemInfo.intent = mAppInstallerIntent;
         itemInfo.bitmap = bitmapInfo;
         itemInfo.contentDescription = context.getResources().getString(
                 com.android.launcher3.R.string.ps_add_button_content_description);
-        itemInfo.runtimeStatusFlags |= FLAG_PRIVATE_SPACE_INSTALL_APP | FLAG_NOT_PINNABLE;
+        itemInfo.runtimeStatusFlags |= FLAG_NOT_PINNABLE;
 
         BaseAllAppsAdapter.AdapterItem item = new BaseAllAppsAdapter.AdapterItem(VIEW_TYPE_ICON);
         item.itemInfo = itemInfo;
@@ -124,45 +171,54 @@
 
     /**
      * Disables quiet mode for Private Space User Profile.
-     * The runnable passed will be executed in the {@link #reset()} method,
-     * when Launcher receives update about profile availability.
-     * The runnable passed is only executed once, and reset after execution.
+     * When called from search, a runnable is set and executed in the {@link #reset()} method, when
+     * Launcher receives update about profile availability.
+     * The runnable is only executed once, and reset after execution.
      * In case the method is called again, before the previously set runnable was executed,
      * the runnable will be updated.
      */
-    public void unlockPrivateProfile(Runnable runnable) {
-        enableQuietMode(false);
-        mUnlockRunnable = runnable;
+    public void unlockPrivateProfile() {
+        setQuietMode(false);
     }
 
     /** Enables quiet mode for Private Space User Profile. */
-    public void lockPrivateProfile() {
-        enableQuietMode(true);
+    void lockPrivateProfile() {
+        setQuietMode(true);
     }
 
     /** Whether private profile should be hidden on Launcher. */
     public boolean isPrivateSpaceHidden() {
         return getCurrentState() == STATE_DISABLED && SettingsCache.INSTANCE
-                    .get(mAllApps.mActivityContext).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0);
+                    .get(mAllApps.getContext()).getValue(PRIVATE_SPACE_HIDE_WHEN_LOCKED_URI, 0);
     }
 
-    /** Resets the current state of Private Profile, w.r.t. to Launcher. */
+    /**
+     * Resets the current state of Private Profile, w.r.t. to Launcher. The decorator should only
+     * be applied upon expand before animating. When collapsing, reset() will remove the decorator
+     * when animation is not running.
+     */
     public void reset() {
         int previousState = getCurrentState();
         boolean isEnabled = !mAllApps.getAppsStore()
                 .hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED);
         int updatedState = isEnabled ? STATE_ENABLED : STATE_DISABLED;
         setCurrentState(updatedState);
-        resetPrivateSpaceDecorator(updatedState);
-        if (transitioningFromLockedToUnlocked(previousState, updatedState)) {
-            applyUnlockRunnable();
+        if (mPSHeader != null) {
+            mPSHeader.setAlpha(1);
         }
+        if (transitioningFromLockedToUnlocked(previousState, updatedState)) {
+            postUnlock();
+        } else if (transitioningFromUnlockedToLocked(previousState, updatedState)){
+            executeLock();
+        }
+        resetPrivateSpaceDecorator(updatedState);
     }
 
     /** Opens the Private Space Settings Page. */
     public void openPrivateSpaceSettings() {
         if (mPrivateSpaceSettingsAvailable) {
-            mAllApps.getContext().startActivity(PRIVATE_SPACE_INTENT);
+            mAllApps.getContext().startActivity(
+                    ApiWrapper.INSTANCE.get(mAllApps.getContext()).getPrivateSpaceSettingsIntent());
         }
     }
 
@@ -185,34 +241,17 @@
      * This case should still be ok, as locking the Private Space container and unlocking it,
      * reloads the values, fixing the incorrect UI.
      */
-    private void initializeInBackgroundThread() {
+    private void initializeInBackgroundThread(Context appContext) {
         Preconditions.assertNonUiThread();
-        setPreInstalledSystemPackages();
-        setAppInstallerIntent();
-        initializePrivateSpaceSettingsState();
-    }
-
-    private void initializePrivateSpaceSettingsState() {
-        Preconditions.assertNonUiThread();
-        ResolveInfo resolveInfo = mAllApps.getContext().getPackageManager()
-                .resolveActivity(PRIVATE_SPACE_INTENT, PackageManager.MATCH_SYSTEM_ONLY);
-        setPrivateSpaceSettingsAvailable(resolveInfo != null);
-    }
-
-    private void setPreInstalledSystemPackages() {
-        Preconditions.assertNonUiThread();
-        if (getProfileUser() != null) {
-            mPreInstalledSystemPackages = new HashSet<>(ApiWrapper
-                    .getPreInstalledSystemPackages(mAllApps.getContext(), getProfileUser()));
+        ApiWrapper apiWrapper = ApiWrapper.INSTANCE.get(appContext);
+        UserHandle profileUser = getProfileUser();
+        if (profileUser != null) {
+            mPreInstalledSystemPackages = new HashSet<>(
+                    apiWrapper.getPreInstalledSystemPackages(profileUser));
+            mAppInstallerIntent = apiWrapper
+                    .getAppMarketActivityIntent(BuildConfig.APPLICATION_ID, profileUser);
         }
-    }
-
-    private void setAppInstallerIntent() {
-        Preconditions.assertNonUiThread();
-        if (getProfileUser() != null) {
-            mAppInstallerIntent = ApiWrapper.getAppMarketActivityIntent(mAllApps.getContext(),
-                    BuildConfig.APPLICATION_ID, getProfileUser());
-        }
+        setPrivateSpaceSettingsAvailable(apiWrapper.getPrivateSpaceSettingsIntent() != null);
     }
 
     @VisibleForTesting
@@ -235,29 +274,54 @@
             mainAdapterHolder.mRecyclerView.addItemDecoration(mPrivateAppsSectionDecorator);
         } else {
             // Remove Private Space Decorator from the Recycler view.
-            if (mPrivateAppsSectionDecorator != null) {
+            if (mPrivateAppsSectionDecorator != null && !mIsAnimationRunning) {
                 mainAdapterHolder.mRecyclerView.removeItemDecoration(mPrivateAppsSectionDecorator);
             }
         }
     }
 
-    /** Posts quiet mode enable/disable call for private profile. */
-    private void enableQuietMode(boolean enable) {
-        setQuietMode(enable);
+    @Override
+    public void setQuietMode(boolean enable) {
+        super.setQuietMode(enable);
+        mAnimate = true;
     }
 
-    void applyUnlockRunnable() {
-        if (mUnlockRunnable != null) {
-            // reset the runnable to prevent re-execution.
-            MAIN_EXECUTOR.post(mUnlockRunnable);
-            mUnlockRunnable = null;
+    /**
+     * Expand the private space after the app list has been added and updated from
+     * {@link AlphabeticalAppsList#onAppsUpdated()}
+     */
+    void postUnlock() {
+        if (mAllApps.isSearching()) {
+            MAIN_EXECUTOR.post(this::exitSearchAndExpand);
+        } else {
+            MAIN_EXECUTOR.post(this::expandPrivateSpace);
         }
     }
 
+    /** Collapses the private space before the app list has been updated. */
+    void executeLock() {
+        MAIN_EXECUTOR.execute(() -> updatePrivateStateAnimator(false));
+    }
+
+    void setAnimationRunning(boolean isAnimationRunning) {
+        if (!isAnimationRunning) {
+            mAnimate = false;
+        }
+        mIsAnimationRunning = isAnimationRunning;
+    }
+
+    boolean getAnimationRunning() {
+        return mIsAnimationRunning;
+    }
+
     private boolean transitioningFromLockedToUnlocked(int previousState, int updatedState) {
         return previousState == STATE_DISABLED && updatedState == STATE_ENABLED;
     }
 
+    private boolean transitioningFromUnlockedToLocked(int previousState, int updatedState) {
+        return previousState == STATE_ENABLED && updatedState == STATE_DISABLED;
+    }
+
     @Override
     public Predicate<UserHandle> getUserMatcher() {
         return mPrivateProfileMatcher;
@@ -272,4 +336,404 @@
                 && (appInfo.componentName == null
                 || !(mPreInstalledSystemPackages.contains(appInfo.componentName.getPackageName())));
     }
+
+    /** Add Private Space Header view elements based upon {@link UserProfileState} */
+    public void addPrivateSpaceHeaderViewElements(RelativeLayout parent) {
+        mPSHeader = parent;
+        if (mOnPSHeaderAdded != null) {
+            MAIN_EXECUTOR.execute(mOnPSHeaderAdded);
+            mOnPSHeaderAdded = null;
+        }
+        // Set the transition duration for the settings and lock button to animate.
+        ViewGroup settingAndLockGroup = mPSHeader.findViewById(R.id.settingsAndLockGroup);
+        if (mAnimate) {
+            enableLayoutTransition(settingAndLockGroup);
+        } else {
+            // Ensure any unwanted animations to not happen.
+            settingAndLockGroup.setLayoutTransition(null);
+        }
+
+        //Add quietMode image and action for lock/unlock button
+        ViewGroup lockButton = mPSHeader.findViewById(R.id.ps_lock_unlock_button);
+        assert lockButton != null;
+        addLockButton(lockButton);
+
+        //Trigger lock/unlock action from header.
+        addHeaderOnClickListener(mPSHeader);
+
+        //Add image and action for private space settings button
+        ImageButton settingsButton = mPSHeader.findViewById(R.id.ps_settings_button);
+        assert settingsButton != null;
+        addPrivateSpaceSettingsButton(settingsButton);
+
+        //Add image for private space transitioning view
+        ImageView transitionView = parent.findViewById(R.id.ps_transition_image);
+        assert transitionView != null;
+        addTransitionImage(transitionView);
+    }
+
+    /**
+     *  Adds the quietModeButton and attach onClickListener for the header to animate different
+     *  states when clicked.
+     */
+    private void addLockButton(ViewGroup lockButton) {
+        TextView lockText = lockButton.findViewById(R.id.lock_text);
+        switch (getCurrentState()) {
+            case STATE_ENABLED -> {
+                lockText.setVisibility(VISIBLE);
+                lockButton.setVisibility(VISIBLE);
+                lockButton.setOnClickListener(view -> lockingAction(/* lock */ true));
+            }
+            case STATE_DISABLED -> {
+                lockText.setVisibility(GONE);
+                lockButton.setVisibility(VISIBLE);
+                lockButton.setOnClickListener(view -> lockingAction(/* lock */ false));
+            }
+            default -> lockButton.setVisibility(GONE);
+        }
+    }
+
+    private void addHeaderOnClickListener(RelativeLayout header) {
+        if (getCurrentState() == STATE_DISABLED) {
+            header.setOnClickListener(view -> lockingAction(/* lock */ false));
+            header.setClickable(true);
+        } else {
+            header.setOnClickListener(null);
+            header.setClickable(false);
+        }
+    }
+
+    /** Sets the enablement of the profile when header or button is clicked. */
+    private void lockingAction(boolean lock) {
+        logEvents(lock ? LAUNCHER_PRIVATE_SPACE_LOCK_TAP : LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP);
+        if (lock) {
+            lockPrivateProfile();
+        } else {
+            unlockPrivateProfile();
+        }
+    }
+
+    private void addPrivateSpaceSettingsButton(ImageButton settingsButton) {
+        if (getCurrentState() == STATE_ENABLED
+                && isPrivateSpaceSettingsAvailable()) {
+            settingsButton.setVisibility(VISIBLE);
+            settingsButton.setAlpha(1f);
+            settingsButton.setOnClickListener(
+                    view -> {
+                        logEvents(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP);
+                        openPrivateSpaceSettings();
+                    });
+        } else {
+            settingsButton.setVisibility(GONE);
+        }
+    }
+
+    private void addTransitionImage(ImageView transitionImage) {
+        if (getCurrentState() == STATE_TRANSITION) {
+            transitionImage.setVisibility(VISIBLE);
+        } else {
+            transitionImage.setVisibility(GONE);
+        }
+    }
+
+    /** Finds the private space header to scroll to and set the private space icons to GONE. */
+    private void collapse() {
+        AllAppsRecyclerView allAppsRecyclerView = mAllApps.getActiveRecyclerView();
+        List<BaseAllAppsAdapter.AdapterItem> appListAdapterItems =
+                allAppsRecyclerView.getApps().getAdapterItems();
+        for (int i = appListAdapterItems.size() - 1; i > 0; i--) {
+            BaseAllAppsAdapter.AdapterItem currentItem = appListAdapterItems.get(i);
+            // Scroll to the private space header.
+            if (currentItem.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER) {
+                // Note: SmoothScroller is meant to be used once.
+                RecyclerView.SmoothScroller smoothScroller =
+                        new LinearSmoothScroller(mAllApps.getContext()) {
+                            @Override protected int getVerticalSnapPreference() {
+                                return LinearSmoothScroller.SNAP_TO_END;
+                            }
+                        };
+                smoothScroller.setTargetPosition(i);
+                RecyclerView.LayoutManager layoutManager = allAppsRecyclerView.getLayoutManager();
+                if (layoutManager != null) {
+                    startAnimationScroll(allAppsRecyclerView, layoutManager, smoothScroller);
+                    currentItem.decorationInfo = null;
+                }
+                break;
+            }
+            // Make the private space apps gone to "collapse".
+            if (isPrivateSpaceItem(currentItem)) {
+                RecyclerView.ViewHolder viewHolder =
+                        allAppsRecyclerView.findViewHolderForAdapterPosition(i);
+                if (viewHolder != null) {
+                    viewHolder.itemView.setVisibility(GONE);
+                    currentItem.decorationInfo = null;
+                }
+            }
+        }
+    }
+
+    /**
+     * Upon expanding, only scroll to the item position in the adapter that allows the header to be
+     * visible.
+     */
+    public int scrollForHeaderToBeVisibleInContainer(
+            AllAppsRecyclerView allAppsRecyclerView,
+            List<BaseAllAppsAdapter.AdapterItem> appListAdapterItems,
+            int psHeaderHeight,
+            int allAppsCellHeight) {
+        int rowToExpandToWithRespectToHeader = -1;
+        int itemToScrollTo = -1;
+        // Looks for the item in the app list to scroll to so that the header is visible.
+        for (int i = 0; i < appListAdapterItems.size(); i++) {
+            BaseAllAppsAdapter.AdapterItem currentItem = appListAdapterItems.get(i);
+            if (currentItem.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER) {
+                itemToScrollTo = i;
+                continue;
+            }
+            if (itemToScrollTo != -1) {
+                itemToScrollTo = i;
+                if (rowToExpandToWithRespectToHeader == -1) {
+                    rowToExpandToWithRespectToHeader = currentItem.rowIndex;
+                }
+                int rowToScrollTo =
+                        (int) Math.floor((double) (mAllApps.getHeight() - psHeaderHeight
+                                - mAllApps.getHeaderProtectionHeight()) / allAppsCellHeight);
+                int currentRowDistance = currentItem.rowIndex - rowToExpandToWithRespectToHeader;
+                // rowToScrollTo - 1 since the item to scroll to is 0 indexed.
+                if (currentRowDistance == rowToScrollTo - 1) {
+                    break;
+                }
+            }
+        }
+        if (itemToScrollTo != -1) {
+            // Note: SmoothScroller is meant to be used once.
+            RecyclerView.SmoothScroller smoothScroller =
+                    new LinearSmoothScroller(mAllApps.getContext()) {
+                        @Override protected int getVerticalSnapPreference() {
+                            return LinearSmoothScroller.SNAP_TO_ANY;
+                        }
+                    };
+            smoothScroller.setTargetPosition(itemToScrollTo);
+            RecyclerView.LayoutManager layoutManager = allAppsRecyclerView.getLayoutManager();
+            if (layoutManager != null) {
+                startAnimationScroll(allAppsRecyclerView, layoutManager, smoothScroller);
+            }
+        }
+        return itemToScrollTo;
+    }
+
+    /**
+     * Scrolls up to the private space header and animates the collapsing of the text.
+     */
+    private ValueAnimator animateCollapseAnimation() {
+        float from = 1;
+        float to = 0;
+        RecyclerViewFastScroller scrollBar = mAllApps.getActiveRecyclerView().getScrollbar();
+        ValueAnimator collapseAnim = ValueAnimator.ofFloat(from, to);
+        collapseAnim.setDuration(EXPAND_COLLAPSE_DURATION);
+        collapseAnim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                if (scrollBar != null) {
+                    scrollBar.setVisibility(INVISIBLE);
+                }
+                // Scroll up to header.
+                collapse();
+            }
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                if (scrollBar != null) {
+                    scrollBar.setThumbOffsetY(-1);
+                    scrollBar.setVisibility(VISIBLE);
+                }
+            }
+        });
+        return collapseAnim;
+    }
+
+    private ValueAnimator animateAlphaOfIcons(boolean isExpanding) {
+        float from = isExpanding ? 0 : 1;
+        float to = isExpanding ? 1 : 0;
+        AllAppsRecyclerView allAppsRecyclerView = mAllApps.getActiveRecyclerView();
+        List<BaseAllAppsAdapter.AdapterItem> allAppsAdapterItems =
+                mAllApps.getActiveRecyclerView().getApps().getAdapterItems();
+        ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
+        alphaAnim.setDuration(EXPAND_COLLAPSE_DURATION);
+        alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                float newAlpha = (float) valueAnimator.getAnimatedValue();
+                for (int i = 0; i < allAppsAdapterItems.size(); i++) {
+                    BaseAllAppsAdapter.AdapterItem currentItem = allAppsAdapterItems.get(i);
+                    if (isPrivateSpaceItem(currentItem) &&
+                            currentItem.viewType != VIEW_TYPE_PRIVATE_SPACE_HEADER) {
+                        RecyclerView.ViewHolder viewHolder =
+                                allAppsRecyclerView.findViewHolderForAdapterPosition(i);
+                        if (viewHolder != null) {
+                            viewHolder.itemView.setAlpha(newAlpha);
+                        }
+                    }
+                }
+            }
+        });
+        return alphaAnim;
+    }
+
+    /**
+     * Using PropertySetter{@link PropertySetter}, we can update the view's attributes within an
+     * animation. At the moment, collapsing, setting alpha changes, and animating the text is done
+     * here.
+     */
+    private void updatePrivateStateAnimator(boolean expand) {
+        if (mPSHeader == null) {
+            mOnPSHeaderAdded = () -> updatePrivateStateAnimator(expand);
+            setAnimationRunning(false);
+            return;
+        }
+        ViewGroup settingsAndLockGroup = mPSHeader.findViewById(R.id.settingsAndLockGroup);
+        ViewGroup lockButton = mPSHeader.findViewById(R.id.ps_lock_unlock_button);
+        if (settingsAndLockGroup.getLayoutTransition() == null) {
+            // Set a new transition if the current ViewGroup does not already contain one as each
+            // transition should only happen once when applied.
+            enableLayoutTransition(settingsAndLockGroup);
+        }
+        PropertySetter headerSetter = new AnimatedPropertySetter();
+        ImageButton settingsButton = mPSHeader.findViewById(R.id.ps_settings_button);
+        updateSettingsGearAlpha(settingsButton, expand, headerSetter);
+        AnimatorSet animatorSet = headerSetter.buildAnim();
+        animatorSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                // Animate the collapsing of the text at the same time while updating lock button.
+                lockButton.findViewById(R.id.lock_text).setVisibility(expand ? VISIBLE : GONE);
+                setAnimationRunning(true);
+            }
+        });
+        animatorSet.addListener(forEndCallback(() -> {
+            setAnimationRunning(false);
+            if (!expand) {
+                // Call onAppsUpdated() because it may be canceled when this animation occurs.
+                mAllApps.getPersonalAppList().onAppsUpdated();
+                if (isPrivateSpaceHidden()) {
+                    // TODO (b/325455879): Figure out if we can avoid this.
+                    mAllApps.getActiveRecyclerView().getAdapter().notifyDataSetChanged();
+                }
+            }
+        }));
+        if (expand) {
+            animatorSet.playTogether(animateAlphaOfIcons(true));
+        } else {
+            if (isPrivateSpaceHidden()) {
+                animatorSet.playSequentially(animateAlphaOfIcons(false),
+                        animateCollapseAnimation(), fadeOutHeaderAlpha());
+            } else {
+                animatorSet.playSequentially(animateAlphaOfIcons(false),
+                        animateCollapseAnimation());
+            }
+        }
+        animatorSet.setDuration(EXPAND_COLLAPSE_DURATION);
+        animatorSet.start();
+    }
+
+    /** Fades out the private space container. */
+    private ValueAnimator fadeOutHeaderAlpha() {
+        if (mPSHeader == null) {
+            return new ValueAnimator();
+        }
+        float from = 1;
+        float to = 0;
+        ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
+        alphaAnim.setDuration(EXPAND_COLLAPSE_DURATION);
+        alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                if (mPSHeader != null) {
+                    mPSHeader.setAlpha((float) valueAnimator.getAnimatedValue());
+                }
+            }
+        });
+        return alphaAnim;
+    }
+
+    /** Animates the layout changes when the text of the button becomes visible/gone. */
+    private void enableLayoutTransition(ViewGroup settingsAndLockGroup) {
+        LayoutTransition settingsAndLockTransition = new LayoutTransition();
+        settingsAndLockTransition.enableTransitionType(LayoutTransition.CHANGING);
+        settingsAndLockTransition.setDuration(EXPAND_COLLAPSE_DURATION);
+        settingsAndLockTransition.addTransitionListener(new LayoutTransition.TransitionListener() {
+            @Override
+            public void startTransition(LayoutTransition transition, ViewGroup viewGroup,
+                    View view, int i) {
+            }
+            @Override
+            public void endTransition(LayoutTransition transition, ViewGroup viewGroup,
+                    View view, int i) {
+                settingsAndLockGroup.setLayoutTransition(null);
+                mAnimate = false;
+            }
+        });
+        settingsAndLockGroup.setLayoutTransition(settingsAndLockTransition);
+    }
+
+    /** Change the settings gear alpha when expanded or collapsed. */
+    private void updateSettingsGearAlpha(ImageButton settingsButton, boolean expand,
+            PropertySetter setter) {
+        float toAlpha = expand ? 1 : 0;
+        setter.setFloat(settingsButton, VIEW_ALPHA, toAlpha, Interpolators.LINEAR)
+                .setDuration(SETTINGS_OPACITY_DURATION).setStartDelay(0);
+    }
+
+    void expandPrivateSpace() {
+        // If we are on main adapter view, we apply the PS Container expansion animation and
+        // scroll down to load the entire container, making animation visible.
+        ActivityAllAppsContainerView<?>.AdapterHolder mainAdapterHolder = mAllApps.mAH.get(MAIN);
+        List<BaseAllAppsAdapter.AdapterItem> adapterItems =
+                mainAdapterHolder.mAppsList.getAdapterItems();
+        if (Flags.enablePrivateSpace() && Flags.privateSpaceAnimation()
+                && mAllApps.isPersonalTab()) {
+            // Animate the text and settings icon.
+            DeviceProfile deviceProfile =
+                    ActivityContext.lookupContext(mAllApps.getContext()).getDeviceProfile();
+            scrollForHeaderToBeVisibleInContainer(mainAdapterHolder.mRecyclerView, adapterItems,
+                    getPsHeaderHeight(), deviceProfile.allAppsCellHeightPx);
+            updatePrivateStateAnimator(true);
+        }
+    }
+
+    private void exitSearchAndExpand() {
+        mAllApps.updateHeaderScroll(0);
+        // Animate to A-Z with 0 time to reset the animation with proper state management.
+        mAllApps.animateToSearchState(false, 0);
+        MAIN_EXECUTOR.post(() -> {
+            mAllApps.mSearchUiManager.resetSearch();
+            mAllApps.switchToTab(ActivityAllAppsContainerView.AdapterHolder.MAIN);
+            expandPrivateSpace();
+        });
+    }
+
+    /** Starts the smooth scroll with the provided smoothScroller and add idle listener. */
+    private void startAnimationScroll(AllAppsRecyclerView allAppsRecyclerView,
+            RecyclerView.LayoutManager layoutManager, RecyclerView.SmoothScroller smoothScroller) {
+        mAnimationScrolling = true;
+        layoutManager.startSmoothScroll(smoothScroller);
+        allAppsRecyclerView.removeOnScrollListener(mOnIdleScrollListener);
+        allAppsRecyclerView.addOnScrollListener(mOnIdleScrollListener);
+    }
+
+    boolean getAnimate() {
+        return mAnimate;
+    }
+
+    boolean getAnimationScrolling() {
+        return mAnimationScrolling;
+    }
+
+    int getPsHeaderHeight() {
+        return mPsHeaderHeight;
+    }
+
+    boolean isPrivateSpaceItem(BaseAllAppsAdapter.AdapterItem item) {
+        return item.decorationInfo != null;
+    }
 }
diff --git a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java b/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
deleted file mode 100644
index 6067454..0000000
--- a/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewController.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.allapps;
-
-import static android.view.View.GONE;
-import static android.view.View.INVISIBLE;
-import static android.view.View.VISIBLE;
-
-import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
-import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.MAIN;
-import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
-import static com.android.launcher3.allapps.PrivateProfileManager.STATE_DISABLED;
-import static com.android.launcher3.allapps.PrivateProfileManager.STATE_ENABLED;
-import static com.android.launcher3.allapps.PrivateProfileManager.STATE_TRANSITION;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_LOCK_TAP;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.LayoutTransition;
-import android.animation.ValueAnimator;
-import android.view.ViewGroup;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import androidx.recyclerview.widget.LinearSmoothScroller;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.app.animation.Interpolators;
-import com.android.launcher3.Flags;
-import com.android.launcher3.R;
-import com.android.launcher3.allapps.UserProfileManager.UserProfileState;
-import com.android.launcher3.anim.AnimatedPropertySetter;
-import com.android.launcher3.anim.PropertySetter;
-import com.android.launcher3.views.RecyclerViewFastScroller;
-
-import java.util.List;
-
-/**
- * Controller which returns views to be added to Private Space Header based upon
- * {@link UserProfileState}
- */
-public class PrivateSpaceHeaderViewController {
-    private static final int EXPAND_SCROLL_DURATION = 2000;
-    private static final int EXPAND_COLLAPSE_DURATION = 800;
-    private static final int SETTINGS_OPACITY_DURATION = 160;
-    private final ActivityAllAppsContainerView mAllApps;
-    private final PrivateProfileManager mPrivateProfileManager;
-
-    public PrivateSpaceHeaderViewController(ActivityAllAppsContainerView allApps,
-            PrivateProfileManager privateProfileManager) {
-        this.mAllApps = allApps;
-        this.mPrivateProfileManager = privateProfileManager;
-    }
-
-    /** Add Private Space Header view elements based upon {@link UserProfileState} */
-    public void addPrivateSpaceHeaderViewElements(RelativeLayout parent) {
-        // Set the transition duration for the settings and lock button to animate.
-        ViewGroup settingsAndLockGroup = parent.findViewById(R.id.settingsAndLockGroup);
-        LayoutTransition settingsAndLockTransition = settingsAndLockGroup.getLayoutTransition();
-        settingsAndLockTransition.enableTransitionType(LayoutTransition.CHANGING);
-        settingsAndLockTransition.setDuration(EXPAND_COLLAPSE_DURATION);
-
-        //Add quietMode image and action for lock/unlock button
-        ViewGroup lockButton =
-                parent.findViewById(R.id.ps_lock_unlock_button);
-        assert lockButton != null;
-        addLockButton(parent, lockButton);
-
-        //Trigger lock/unlock action from header.
-        addHeaderOnClickListener(parent);
-
-        //Add image and action for private space settings button
-        ImageButton settingsButton = parent.findViewById(R.id.ps_settings_button);
-        assert settingsButton != null;
-        addPrivateSpaceSettingsButton(settingsButton);
-
-        //Add image for private space transitioning view
-        ImageView transitionView = parent.findViewById(R.id.ps_transition_image);
-        assert transitionView != null;
-        addTransitionImage(transitionView);
-    }
-
-    /**
-     *  Adds the quietModeButton and attach onClickListener for the header to animate different
-     *  states when clicked.
-     */
-    private void addLockButton(ViewGroup psHeader, ViewGroup lockButton) {
-        TextView lockText = lockButton.findViewById(R.id.lock_text);
-        switch (mPrivateProfileManager.getCurrentState()) {
-            case STATE_ENABLED -> {
-                lockText.setVisibility(VISIBLE);
-                lockButton.setVisibility(VISIBLE);
-                lockButton.setOnClickListener(view -> lockAction(psHeader));
-            }
-            case STATE_DISABLED -> {
-                lockText.setVisibility(GONE);
-                lockButton.setVisibility(VISIBLE);
-                lockButton.setOnClickListener(view -> unlockAction(psHeader));
-            }
-            default -> lockButton.setVisibility(GONE);
-        }
-    }
-
-    private void addHeaderOnClickListener(RelativeLayout header) {
-        if (mPrivateProfileManager.getCurrentState() == STATE_DISABLED) {
-            header.setOnClickListener(view -> unlockAction(header));
-        } else {
-            header.setOnClickListener(null);
-        }
-    }
-
-    private void unlockAction(ViewGroup psHeader) {
-        mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP);
-        mPrivateProfileManager.unlockPrivateProfile((() -> onPrivateProfileUnlocked(psHeader)));
-    }
-
-    private void lockAction(ViewGroup psHeader) {
-        mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_LOCK_TAP);
-        if (Flags.enablePrivateSpace() && Flags.privateSpaceAnimation()) {
-            updatePrivateStateAnimator(false, psHeader);
-        } else {
-            mPrivateProfileManager.lockPrivateProfile();
-        }
-    }
-
-    private void addPrivateSpaceSettingsButton(ImageButton settingsButton) {
-        if (mPrivateProfileManager.getCurrentState() == STATE_ENABLED
-                && mPrivateProfileManager.isPrivateSpaceSettingsAvailable()) {
-            settingsButton.setVisibility(VISIBLE);
-            settingsButton.setAlpha(1f);
-            settingsButton.setOnClickListener(
-                    view -> {
-                        mPrivateProfileManager.logEvents(LAUNCHER_PRIVATE_SPACE_SETTINGS_TAP);
-                        mPrivateProfileManager.openPrivateSpaceSettings();
-                    });
-        } else {
-            settingsButton.setVisibility(GONE);
-        }
-    }
-
-    private void addTransitionImage(ImageView transitionImage) {
-        if (mPrivateProfileManager.getCurrentState() == STATE_TRANSITION) {
-            transitionImage.setVisibility(VISIBLE);
-        } else {
-            transitionImage.setVisibility(GONE);
-        }
-    }
-
-    private void onPrivateProfileUnlocked(ViewGroup header) {
-        // If we are on main adapter view, we apply the PS Container expansion animation and
-        // then scroll down to load the entire container, making animation visible.
-        ActivityAllAppsContainerView<?>.AdapterHolder mainAdapterHolder =
-                (ActivityAllAppsContainerView<?>.AdapterHolder) mAllApps.mAH.get(MAIN);
-        if (Flags.enablePrivateSpace() && Flags.privateSpaceAnimation()
-                && mAllApps.getActiveRecyclerView() == mainAdapterHolder.mRecyclerView) {
-            // Animate the text and settings icon.
-            updatePrivateStateAnimator(true, header);
-            mAllApps.getActiveRecyclerView().scrollToBottomWithMotion(EXPAND_SCROLL_DURATION);
-        }
-    }
-
-    /** Finds the private space header to scroll to and set the private space icons to GONE. */
-    private void collapse() {
-        AllAppsRecyclerView allAppsRecyclerView = mAllApps.getActiveRecyclerView();
-        for (int i = allAppsRecyclerView.getChildCount() - 1; i > 0; i--) {
-            int adapterPosition = allAppsRecyclerView.getChildAdapterPosition(
-                    allAppsRecyclerView.getChildAt(i));
-            List<BaseAllAppsAdapter.AdapterItem> allAppsAdapters = allAppsRecyclerView.getApps()
-                    .getAdapterItems();
-            if (adapterPosition < 0 || adapterPosition >= allAppsAdapters.size()) {
-                continue;
-            }
-            // Scroll to the private space header.
-            if (allAppsAdapters.get(adapterPosition).viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER) {
-                // Note: SmoothScroller is meant to be used once.
-                RecyclerView.SmoothScroller smoothScroller =
-                        new LinearSmoothScroller(mAllApps.getContext()) {
-                            @Override protected int getVerticalSnapPreference() {
-                                return LinearSmoothScroller.SNAP_TO_END;
-                            }
-                        };
-                smoothScroller.setTargetPosition(adapterPosition);
-                RecyclerView.LayoutManager layoutManager = allAppsRecyclerView.getLayoutManager();
-                if (layoutManager != null) {
-                    layoutManager.startSmoothScroll(smoothScroller);
-                }
-                break;
-            }
-            // Make the private space apps gone to "collapse".
-            if (allAppsAdapters.get(adapterPosition).decorationInfo != null) {
-                allAppsRecyclerView.getChildAt(i).setVisibility(GONE);
-            }
-        }
-    }
-
-    PrivateProfileManager getPrivateProfileManager() {
-        return mPrivateProfileManager;
-    }
-
-    /**
-     * Scrolls up to the private space header and animates the collapsing of the text.
-     */
-    private ValueAnimator animateCollapseAnimation(ViewGroup lockButton) {
-        float from = 1;
-        float to = 0;
-        RecyclerViewFastScroller scrollBar = mAllApps.getActiveRecyclerView().getScrollbar();
-        ValueAnimator collapseAnim = ValueAnimator.ofFloat(from, to);
-        collapseAnim.setDuration(EXPAND_COLLAPSE_DURATION);
-        collapseAnim.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                if (scrollBar != null) {
-                    scrollBar.setVisibility(INVISIBLE);
-                }
-                // scroll up
-                collapse();
-                // Animate the collapsing of the text.
-                lockButton.findViewById(R.id.lock_text).setVisibility(GONE);
-            }
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                super.onAnimationEnd(animation);
-                if (scrollBar != null) {
-                    scrollBar.setThumbOffsetY(-1);
-                    scrollBar.setVisibility(VISIBLE);
-                }
-                mPrivateProfileManager.lockPrivateProfile();
-            }
-        });
-        return collapseAnim;
-    }
-
-    /**
-     * Using PropertySetter{@link PropertySetter}, we can update the view's attributes within an
-     * animation. At the moment, collapsing, setting alpha changes, and animating the text is done
-     * here.
-     */
-    private void updatePrivateStateAnimator(boolean expand, ViewGroup psHeader) {
-        PropertySetter setter = new AnimatedPropertySetter();
-        ViewGroup lockButton = psHeader.findViewById(R.id.ps_lock_unlock_button);
-        ImageButton settingsButton = psHeader.findViewById(R.id.ps_settings_button);
-        updateSettingsGearAlpha(settingsButton, expand, setter);
-        AnimatorSet animatorSet = setter.buildAnim();
-        animatorSet.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationStart(Animator animation) {
-                // Animate the collapsing of the text at the same time while updating lock button.
-                lockButton.findViewById(R.id.lock_text).setVisibility(expand ? VISIBLE : GONE);
-            }
-        });
-        // Play the collapsing together of the stateAnimator to avoid being unable to scroll to the
-        // header. Otherwise the smooth scrolling will scroll higher when played with the state
-        // animator.
-        if (!expand) {
-            animatorSet.playTogether(animateCollapseAnimation(lockButton));
-        }
-        animatorSet.setDuration(EXPAND_COLLAPSE_DURATION);
-        animatorSet.start();
-     }
-
-    /** Change the settings gear alpha when expanded or collapsed. */
-     private void updateSettingsGearAlpha(ImageButton settingsButton, boolean expand,
-            PropertySetter setter) {
-        float toAlpha = expand ? 1 : 0;
-        setter.setFloat(settingsButton, VIEW_ALPHA, toAlpha, Interpolators.LINEAR)
-                .setDuration(SETTINGS_OPACITY_DURATION).setStartDelay(0);
-    }
-}
diff --git a/src/com/android/launcher3/allapps/SectionDecorationHandler.java b/src/com/android/launcher3/allapps/SectionDecorationHandler.java
index f79b82c..ac9b146 100644
--- a/src/com/android/launcher3/allapps/SectionDecorationHandler.java
+++ b/src/com/android/launcher3/allapps/SectionDecorationHandler.java
@@ -176,13 +176,10 @@
         /**
          * Expands decoration bounds to include child {@link PrivateAppsSectionDecorator}
          */
-        public void addChild(SectionDecorationHandler child, View view, boolean applyBackground) {
+        public void addChild(SectionDecorationHandler child, View view) {
             int scaledHeight = (int) (view.getHeight() * view.getScaleY());
             mBounds.union(view.getLeft(), view.getY(),
                     view.getRight(), view.getY() + scaledHeight);
-            if (applyBackground) {
-                applyBackground(view, mContext, null, false);
-            }
             mIsBottomRound |= child.mIsBottomRound;
             mIsBottomLeftRound |= child.mIsBottomLeftRound;
             mIsBottomRightRound |= child.mIsBottomRightRound;
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
index 1059097..5fe2f0c 100644
--- a/src/com/android/launcher3/allapps/WorkEduCard.java
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -103,6 +103,8 @@
             AllAppsRecyclerView rv = mActivityContext.getAppsView().mAH.get(
                     ActivityAllAppsContainerView.AdapterHolder.WORK).mRecyclerView;
             rv.getApps().getAdapterItems().remove(mPosition);
+            // Remove the educard fast scroll section.
+            rv.getApps().getFastScrollerSections().remove(0);
             rv.getAdapter().notifyItemRemoved(mPosition);
         }
     }
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index a54e52c..96998a3 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -73,7 +73,7 @@
      * Posts quite mode enable/disable call for work profile user
      */
     public void setWorkProfileEnabled(boolean enabled) {
-        setCurrentState(STATE_TRANSITION);
+        updateCurrentState(STATE_TRANSITION);
         setQuietMode(!enabled);
     }
 
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index f9d047b..ec45415 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -155,6 +155,7 @@
     public void reset() {
         mCallback.clearSearchResult();
         mInput.reset();
+        mInput.clearFocus();
         mQuery = null;
         mInput.removeOnFocusChangeListener(this);
     }
diff --git a/src/com/android/launcher3/apppairs/AppPairIcon.java b/src/com/android/launcher3/apppairs/AppPairIcon.java
index 8ce1c19..0e955ad 100644
--- a/src/com/android/launcher3/apppairs/AppPairIcon.java
+++ b/src/com/android/launcher3/apppairs/AppPairIcon.java
@@ -110,22 +110,42 @@
         // For some reason, app icons have setIncludeFontPadding(false) inside folders, so we set it
         // here to match that.
         icon.mAppPairName.setIncludeFontPadding(container != DISPLAY_FOLDER);
-        icon.mAppPairName.applyLabel(appPairInfo);
+        // Set title text and accessibility title text.
+        icon.updateTitleAndA11yTitle();
 
-        // Set up accessibility
-        icon.setContentDescription(icon.getAccessibilityTitle(appPairInfo));
         icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
 
         return icon;
     }
 
     /**
-     * Returns a formatted accessibility title for app pairs.
+     * Updates the title and a11y title of the app pair. Called on creation and when packages
+     * change, to reflect app name changes or user language changes.
      */
-    public String getAccessibilityTitle(AppPairInfo appPairInfo) {
-        CharSequence app1 = appPairInfo.getFirstApp().title;
-        CharSequence app2 = appPairInfo.getSecondApp().title;
-        return getContext().getString(R.string.app_pair_name_format, app1, app2);
+    public void updateTitleAndA11yTitle() {
+        updateTitleAndTextView();
+        updateAccessibilityTitle();
+    }
+
+    /**
+     * Updates AppPairInfo with a formatted app pair title, and sets it on the BubbleTextView.
+     */
+    public void updateTitleAndTextView() {
+        CharSequence newTitle = getInfo().generateTitle(getContext());
+        mAppPairName.setText(newTitle);
+    }
+
+    /**
+     * Updates the accessibility title with a formatted string template.
+     */
+    public void updateAccessibilityTitle() {
+        CharSequence app1 = getInfo().getFirstApp().title;
+        CharSequence app2 = getInfo().getSecondApp().title;
+        String a11yTitle = getContext().getString(R.string.app_pair_name_format, app1, app2);
+        setContentDescription(
+                getInfo().shouldDrawAsDisabled(getContext())
+                        ? getContext().getString(R.string.disabled_app_label, a11yTitle)
+                        : a11yTitle);
     }
 
     // Required for DraggableView
@@ -181,6 +201,10 @@
         return mIconGraphic;
     }
 
+    public int getContainer() {
+        return mContainer;
+    }
+
     /**
      * Ensures that both app icons in the pair are loaded in high resolution.
      */
@@ -196,6 +220,7 @@
         // If either of the app pair icons return true on the predicate (i.e. in the list of
         // updated apps), redraw the icon graphic (icon background and both icons).
         if (getInfo().anyMatch(itemCheck)) {
+            updateTitleAndA11yTitle();
             mIconGraphic.redraw();
         }
     }
diff --git a/src/com/android/launcher3/apppairs/AppPairIconBackground.java b/src/com/android/launcher3/apppairs/AppPairIconBackground.java
deleted file mode 100644
index 8b13789..0000000
--- a/src/com/android/launcher3/apppairs/AppPairIconBackground.java
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
index e2c2670..45dc013 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
+++ b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
@@ -20,6 +20,7 @@
 import com.android.launcher3.BubbleTextView.DISPLAY_FOLDER
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
+import com.android.launcher3.util.Themes
 import com.android.launcher3.views.ActivityContext
 
 class AppPairIconDrawingParams(val context: Context, container: Int) {
@@ -62,7 +63,7 @@
     // The app pair icon appears differently in portrait and landscape.
     var isLeftRightSplit: Boolean = true
     // The background paint color (based on container).
-    val bgColor: Int
+    var bgColor: Int = 0
 
     init {
         val activity: ActivityContext = ActivityContext.lookupContext(context)
@@ -77,7 +78,7 @@
         innerPadding = iconSize * INNER_PADDING_SCALE
         memberIconSize = iconSize * MEMBER_ICON_SCALE
         updateOrientation(dp)
-        bgColor = getBgColorForContainer(container)
+        updateBgColor(container)
     }
 
     /** Checks the device orientation and updates isLeftRightSplit accordingly. */
@@ -85,21 +86,13 @@
         isLeftRightSplit = dp.isLeftRightSplit
     }
 
-    private fun getBgColorForContainer(container: Int): Int {
-        val color: Int
+    fun updateBgColor(container: Int) {
         if (container == DISPLAY_FOLDER) {
-            val ta =
-                context.theme.obtainStyledAttributes(
-                    intArrayOf(R.attr.materialColorSurfaceContainerLowest)
-                )
-            color = ta.getColor(0, 0)
-            ta.recycle()
+            bgColor = Themes.getAttrColor(context, R.attr.appPairSurfaceInFolder)
         } else {
             val ta = context.theme.obtainStyledAttributes(R.styleable.FolderIconPreview)
-            color = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0)
+            bgColor = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0)
             ta.recycle()
         }
-
-        return color
     }
 }
diff --git a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
index 86ee0c0..7809102 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
+++ b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
@@ -26,7 +26,6 @@
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener
 import com.android.launcher3.icons.BitmapInfo
-import com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter
 import com.android.launcher3.model.data.AppPairInfo
 import com.android.launcher3.util.Themes
 import com.android.launcher3.views.ActivityContext
@@ -43,13 +42,7 @@
     private val TAG = "AppPairIconGraphic"
 
     companion object {
-        /**
-         * Composes a drawable for this icon, consisting of a background and 2 app icons. The app
-         * pair will draw as "disabled" if either of the following is true:
-         * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is
-         *    paused or can't be launched for some other reason).
-         * 2) One of the member apps can't be launched due to screen size requirements.
-         */
+        /** Composes a drawable for this icon, consisting of a background and 2 app icons. */
         @JvmStatic
         fun composeDrawable(
             appPairInfo: AppPairInfo,
@@ -62,21 +55,10 @@
             appIcon1.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt())
             appIcon2.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt())
 
-            val shouldDrawAsDisabled =
-                appPairInfo.isDisabled || !appPairInfo.isLaunchable(p.context)
-
-            // Set disabled status on icons.
-            appIcon1.setIsDisabled(shouldDrawAsDisabled)
-            appIcon2.setIsDisabled(shouldDrawAsDisabled)
-
             // Create icon drawable.
             val fullIconDrawable = AppPairIconDrawable(p, appIcon1, appIcon2)
             fullIconDrawable.setBounds(0, 0, p.iconSize, p.iconSize)
 
-            // Set disabled color filter on background paint.
-            fullIconDrawable.colorFilter =
-                if (shouldDrawAsDisabled) getDisabledColorFilter() else null
-
             return fullIconDrawable
         }
     }
@@ -119,6 +101,15 @@
     }
 
     /**
+     * When the icon is temporary moved to a different colored surface, update the background color.
+     * Calling this method with [null] reverts the icon back to its default color.
+     */
+    fun onTemporaryContainerChange(newContainer: Int?) {
+        drawParams.updateBgColor(newContainer ?: parentIcon.container)
+        redraw()
+    }
+
+    /**
      * Gets this icon graphic's visual bounds, with respect to the parent icon's coordinate system.
      */
     fun getIconBounds(outBounds: Rect) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 262b2a1..830e552 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -17,31 +17,16 @@
 package com.android.launcher3.config;
 
 import static com.android.launcher3.BuildConfig.WIDGET_ON_FIRST_SCREEN;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_DELAY;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE;
-import static com.android.launcher3.LauncherPrefs.LONG_PRESS_NAV_HANDLE_TIMEOUT_MS;
-import static com.android.launcher3.config.FeatureFlags.FlagState.DISABLED;
-import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
-import static com.android.launcher3.config.FeatureFlags.FlagState.TEAMFOOD;
-import static com.android.launcher3.uioverrides.flags.FlagsFactory.getDebugFlag;
-import static com.android.launcher3.uioverrides.flags.FlagsFactory.getReleaseFlag;
+import static com.android.launcher3.config.FeatureFlags.BooleanFlag.DISABLED;
+import static com.android.launcher3.config.FeatureFlags.BooleanFlag.ENABLED;
 import static com.android.wm.shell.Flags.enableTaskbarNavbarUnification;
 
 import android.content.res.Resources;
-import android.view.ViewConfiguration;
 
 import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.BuildConfig;
 import com.android.launcher3.Flags;
-import com.android.launcher3.uioverrides.flags.FlagsFactory;
-
-import java.util.function.Predicate;
-import java.util.function.ToIntFunction;
 
 /**
  * Defines a set of flags used to control various launcher behaviors.
@@ -50,11 +35,6 @@
  */
 public final class FeatureFlags {
 
-    @VisibleForTesting
-    public static Predicate<BooleanFlag> sBooleanReader = f -> f.mCurrentValue;
-    @VisibleForTesting
-    public static ToIntFunction<IntFlag> sIntReader = f -> f.mCurrentValue;
-
     private FeatureFlags() { }
 
     /**
@@ -130,28 +110,6 @@
             getDebugFlag(275132633, "ENABLE_ALL_APPS_FROM_OVERVIEW", DISABLED,
                     "Allow entering All Apps from Overview (e.g. long swipe up from app)");
 
-    public static final BooleanFlag CUSTOM_LPNH_THRESHOLDS =
-            getReleaseFlag(301680992, "CUSTOM_LPNH_THRESHOLDS", DISABLED,
-                    "Add dev options to customize the LPNH trigger slop and milliseconds");
-
-    public static final BooleanFlag ANIMATE_LPNH =
-            getReleaseFlag(308693847, "ANIMATE_LPNH", TEAMFOOD,
-                    "Animates navbar when long pressing");
-
-    public static final BooleanFlag SHRINK_NAV_HANDLE_ON_PRESS =
-            getReleaseFlag(314158312, "SHRINK_NAV_HANDLE_ON_PRESS", DISABLED,
-                    "Shrinks navbar when long pressing if ANIMATE_LPNH is enabled");
-
-    public static final IntFlag LPNH_SLOP_PERCENTAGE =
-            FlagsFactory.getIntFlag(301680992, "LPNH_SLOP_PERCENTAGE", 100,
-                    "Controls touch slop percentage for lpnh",
-                    LONG_PRESS_NAV_HANDLE_SLOP_PERCENTAGE);
-
-    public static final IntFlag LPNH_TIMEOUT_MS =
-            FlagsFactory.getIntFlag(301680992, "LPNH_TIMEOUT_MS",
-                    ViewConfiguration.getLongPressTimeout(),
-                    "Controls lpnh timeout in milliseconds", LONG_PRESS_NAV_HANDLE_TIMEOUT_MS);
-
     public static final BooleanFlag ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS = getReleaseFlag(
             270394468, "ENABLE_SHOW_KEYBOARD_OPTION_IN_ALL_APPS", ENABLED,
             "Enable option to show keyboard when going to all-apps");
@@ -177,11 +135,6 @@
             "SECONDARY_DRAG_N_DROP_TO_PIN", DISABLED,
             "Enable dragging and dropping to pin apps within secondary display");
 
-    // TODO(Block 7): Clean up flags
-    public static final BooleanFlag ENABLE_FORCED_MONO_ICON = getDebugFlag(270396209,
-            "ENABLE_FORCED_MONO_ICON", DISABLED,
-            "Enable the ability to generate monochromatic icons, if it is not provided by the app");
-
     // TODO(Block 8): Clean up flags
 
     // TODO(Block 9): Clean up flags
@@ -220,7 +173,7 @@
 
     // TODO(Block 14): Cleanup flags
     public static final BooleanFlag NOTIFY_CRASHES = getDebugFlag(270393108, "NOTIFY_CRASHES",
-            TEAMFOOD, "Sends a notification whenever launcher encounters an uncaught exception.");
+            DISABLED, "Sends a notification whenever launcher encounters an uncaught exception.");
 
     public static final boolean ENABLE_TASKBAR_NAVBAR_UNIFICATION =
             enableTaskbarNavbarUnification() && !isPhone();
@@ -287,53 +240,10 @@
             "INJECT_FALLBACK_APP_CORPUS_RESULTS", DISABLED,
             "Inject fallback app corpus result when AiAi fails to return it.");
 
-    public static final BooleanFlag ENABLE_LONG_PRESS_NAV_HANDLE =
-            getReleaseFlag(299682306, "ENABLE_LONG_PRESS_NAV_HANDLE", ENABLED,
-                    "Enables long pressing on the bottom bar nav handle to trigger events.");
-
-    public static final BooleanFlag ENABLE_SEARCH_HAPTIC_HINT =
-            getReleaseFlag(314005131, "ENABLE_SEARCH_HAPTIC_HINT", ENABLED,
-                    "Enables haptic hint while long pressing on the bottom bar nav handle.");
-
-    public static final BooleanFlag ENABLE_SEARCH_HAPTIC_COMMIT =
-            getReleaseFlag(314005577, "ENABLE_SEARCH_HAPTIC_COMMIT", ENABLED,
-                    "Enables haptic hint at end of long pressing on the bottom bar nav handle.");
-
-    public static final IntFlag LPNH_HAPTIC_HINT_START_SCALE_PERCENT =
-            FlagsFactory.getIntFlag(309972570,
-                    "LPNH_HAPTIC_HINT_START_SCALE_PERCENT", 0,
-                    "Haptic hint start scale.",
-                    LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_START_SCALE_PERCENT);
-
-    public static final IntFlag LPNH_HAPTIC_HINT_END_SCALE_PERCENT =
-            FlagsFactory.getIntFlag(309972570,
-                    "LPNH_HAPTIC_HINT_END_SCALE_PERCENT", 100,
-                    "Haptic hint end scale.", LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_END_SCALE_PERCENT);
-
-    public static final IntFlag LPNH_HAPTIC_HINT_SCALE_EXPONENT =
-            FlagsFactory.getIntFlag(309972570,
-                    "LPNH_HAPTIC_HINT_SCALE_EXPONENT", 1,
-                    "Haptic hint scale exponent.",
-                    LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_SCALE_EXPONENT);
-
-    public static final IntFlag LPNH_HAPTIC_HINT_ITERATIONS =
-            FlagsFactory.getIntFlag(309972570, "LPNH_HAPTIC_HINT_ITERATIONS",
-                    50,
-                    "Haptic hint number of iterations.",
-                    LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_ITERATIONS);
-
-    public static final BooleanFlag ENABLE_LPNH_DEEP_PRESS =
-            getReleaseFlag(310952290, "ENABLE_LPNH_DEEP_PRESS", ENABLED,
-                    "Long press of nav handle is instantly triggered if deep press is detected.");
-
-    public static final IntFlag LPNH_HAPTIC_HINT_DELAY =
-            FlagsFactory.getIntFlag(309972570, "LPNH_HAPTIC_HINT_DELAY", 0,
-                    "Delay before haptic hint starts.", LONG_PRESS_NAV_HANDLE_HAPTIC_HINT_DELAY);
-
     // TODO(Block 17): Clean up flags
     // Aconfig migration complete for ENABLE_TASKBAR_PINNING.
     private static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(296231746,
-            "ENABLE_TASKBAR_PINNING", TEAMFOOD,
+            "ENABLE_TASKBAR_PINNING", DISABLED,
             "Enables taskbar pinning to allow user to switch between transient and persistent "
                     + "taskbar flavors");
 
@@ -373,7 +283,7 @@
 
     // Aconfig migration complete for ENABLE_HOME_TRANSITION_LISTENER.
     public static final BooleanFlag ENABLE_HOME_TRANSITION_LISTENER = getDebugFlag(306053414,
-            "ENABLE_HOME_TRANSITION_LISTENER", TEAMFOOD,
+            "ENABLE_HOME_TRANSITION_LISTENER", DISABLED,
             "Enables launcher to listen to all transitions that include home activity.");
 
     public static boolean enableHomeTransitionListener() {
@@ -395,11 +305,6 @@
                     + "waiting for SystemUI and then merging the SystemUI progress whenever we "
                     + "start receiving the events");
 
-    // TODO(Block 24): Clean up flags
-    public static final BooleanFlag ENABLE_NEW_MIGRATION_LOGIC = getDebugFlag(270393455,
-            "ENABLE_NEW_MIGRATION_LOGIC", ENABLED,
-            "Enable the new grid migration logic, keeping pages when src < dest");
-
     // TODO(Block 25): Clean up flags
     public static final BooleanFlag ENABLE_NEW_GESTURE_NAV_TUTORIAL = getDebugFlag(270396257,
             "ENABLE_NEW_GESTURE_NAV_TUTORIAL", ENABLED,
@@ -473,7 +378,7 @@
     // Aconfig migration complete for ENABLE_RESPONSIVE_WORKSPACE.
     @VisibleForTesting
     public static final BooleanFlag ENABLE_RESPONSIVE_WORKSPACE = getDebugFlag(241386436,
-            "ENABLE_RESPONSIVE_WORKSPACE", TEAMFOOD,
+            "ENABLE_RESPONSIVE_WORKSPACE", DISABLED,
             "Enables new workspace grid calculations method.");
     public static boolean enableResponsiveWorkspace() {
         return ENABLE_RESPONSIVE_WORKSPACE.get() || Flags.enableResponsiveWorkspace();
@@ -487,51 +392,31 @@
             "ALL_APPS_GONE_VISIBILITY", ENABLED,
             "Set all apps container view's hidden visibility to GONE instead of INVISIBLE.");
 
-    // TODO(Block 34): Empty block
-    // Please only add flags to your assigned block. If you do not have a block:
-    // 1. Assign yourself this block
-    // 2. Add your flag to this block
-    // 3. Add a new empty block below this one
-    // 4. Move this comment to that new empty block
-    // This is all to prevent merge conflicts in the future and help keep track of who owns which
-    // flags.
-    // List of assigned blocks can be found: http://go/gnl-flags-block-directory
-
-    public static class BooleanFlag {
-
-        private final boolean mCurrentValue;
-
-        public BooleanFlag(boolean currentValue) {
-            mCurrentValue = currentValue;
-        }
-
-        public boolean get() {
-            return sBooleanReader.test(this);
-        }
+    public static BooleanFlag getDebugFlag(
+            int bugId, String key, BooleanFlag flagState, String description) {
+        return flagState;
     }
 
-    /**
-     * Class representing an integer flag
-     */
-    public static class IntFlag {
-
-        private final int mCurrentValue;
-
-        public IntFlag(int currentValue) {
-            mCurrentValue = currentValue;
-        }
-
-        public int get() {
-            return sIntReader.applyAsInt(this);
-        }
+    public static BooleanFlag getReleaseFlag(
+            int bugId, String key, BooleanFlag flagState, String description) {
+        return flagState;
     }
 
     /**
      * Enabled state for a flag
      */
-    public enum FlagState {
-        ENABLED,
-        DISABLED,
-        TEAMFOOD    // Enabled in team food
+    public enum BooleanFlag {
+        ENABLED(true),
+        DISABLED(false);
+
+        private final boolean mValue;
+
+        BooleanFlag(boolean value) {
+            mValue = value;
+        }
+
+        public boolean get() {
+            return mValue;
+        }
     }
 }
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 213c458..05fdcef 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -67,7 +67,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.pm.PinRequestHelper;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.SystemUiController;
 import com.android.launcher3.views.AbstractSlideInView;
@@ -258,8 +258,9 @@
                         .addCategory(Intent.CATEGORY_HOME)
                         .setPackage(getPackageName())
                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        Launcher.ACTIVITY_TRACKER.registerCallback(listener);
-        startActivity(homeIntent, ApiWrapper.createFadeOutAnimOptions(this).toBundle());
+        Launcher.ACTIVITY_TRACKER.registerCallback(listener, "AddItemActivity.onLongClick");
+        startActivity(homeIntent,
+                ApiWrapper.INSTANCE.get(this).createFadeOutAnimOptions().toBundle());
         logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_DRAGGED);
         mFinishOnPause = true;
         return false;
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 5c74108..dcc55e6 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -301,6 +301,8 @@
         mContent.setFolder(this);
 
         mPageIndicator = findViewById(R.id.folder_page_indicator);
+        mFooter = findViewById(R.id.folder_footer);
+        mFooterHeight = dp.folderFooterHeightPx;
         mFolderName = findViewById(R.id.folder_name);
         mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
         mFolderName.setOnBackKeyListener(this);
@@ -311,9 +313,10 @@
                 | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
                 | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
         mFolderName.forceDisableSuggestions(true);
-
-        mFooter = findViewById(R.id.folder_footer);
-        mFooterHeight = dp.folderFooterHeightPx;
+        mFolderName.setPadding(mFolderName.getPaddingLeft(),
+                (mFooterHeight - mFolderName.getLineHeight()) / 2,
+                mFolderName.getPaddingRight(),
+                (mFooterHeight - mFolderName.getLineHeight()) / 2);
 
         mKeyboardInsetAnimationCallback = new KeyboardInsetAnimationCallback(this);
         setWindowInsetsAnimationCallback(mKeyboardInsetAnimationCallback);
@@ -1440,6 +1443,11 @@
         updateTextViewFocus();
     }
 
+    @Override
+    public void onTitleChanged(CharSequence title) {
+        mFolderName.setText(title);
+    }
+
     /**
      * Utility methods to iterate over items of the view
      */
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 6b30b95..4d88b68 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -723,6 +723,7 @@
         requestLayout();
     }
 
+    @Override
     public void onTitleChanged(CharSequence title) {
         mFolderName.setText(title);
         setContentDescription(getAccessiblityTitle(title));
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 14d1700..6b3bb51 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -90,7 +90,6 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.uioverrides.PredictedAppIconInflater;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.DisplayController;
@@ -459,10 +458,10 @@
 
     private void inflateAndAddPredictedIcon(WorkspaceItemInfo info) {
         CellLayout screen = mWorkspaceScreens.get(info.screenId);
-        View view = PredictedAppIconInflater.inflate(mHomeElementInflater, screen, info);
-        if (view != null) {
-            addInScreenFromBind(view, info);
-        }
+        BubbleTextView icon = (BubbleTextView) mHomeElementInflater.inflate(
+                R.layout.predicted_app_icon, screen, false);
+        icon.applyFromWorkspaceItem(info);
+        addInScreenFromBind(icon, info);
     }
 
     private void dispatchVisibilityAggregated(View view, boolean isVisible) {
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 051fb6f..addd072 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -37,7 +37,6 @@
 import android.view.SurfaceControlViewHost;
 import android.view.SurfaceControlViewHost.SurfacePackage;
 import android.view.View;
-import android.view.WindowManager.LayoutParams;
 import android.view.animation.AccelerateDecelerateInterpolator;
 
 import androidx.annotation.NonNull;
@@ -51,10 +50,10 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.graphics.LauncherPreviewRenderer.PreviewContext;
+import com.android.launcher3.model.BaseLauncherBinder;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.GridSizeMigrationUtil;
-import com.android.launcher3.model.LauncherBinder;
 import com.android.launcher3.model.LoaderTask;
 import com.android.launcher3.model.ModelDbController;
 import com.android.launcher3.provider.LauncherDbUtils;
@@ -87,6 +86,7 @@
     private final int mHeight;
     private String mGridName;
 
+    private final int mDisplayId;
     private final Display mDisplay;
     private final WallpaperColors mWallpaperColors;
     private final RunnableList mOnDestroyCallbacks = new RunnableList();
@@ -110,8 +110,12 @@
         mHostToken = bundle.getBinder(KEY_HOST_TOKEN);
         mWidth = bundle.getInt(KEY_VIEW_WIDTH);
         mHeight = bundle.getInt(KEY_VIEW_HEIGHT);
+        mDisplayId = bundle.getInt(KEY_DISPLAY_ID);
         mDisplay = context.getSystemService(DisplayManager.class)
-                .getDisplay(bundle.getInt(KEY_DISPLAY_ID));
+                .getDisplay(mDisplayId);
+        if (mDisplay == null) {
+            throw new IllegalArgumentException("Display ID does not match any displays.");
+        }
 
         mSurfaceControlViewHost = MAIN_EXECUTOR.submit(() ->
                 new SurfaceControlViewHost(mContext, context.getSystemService(DisplayManager.class)
@@ -121,7 +125,7 @@
     }
 
     public int getDisplayId() {
-        return mDisplay.getDisplayId();
+        return mDisplayId;
     }
 
     public IBinder getHostToken() {
@@ -210,7 +214,6 @@
             return new ContextThemeWrapper(context,
                     Themes.getActivityThemeRes(context));
         }
-        context = context.createWindowContext(LayoutParams.TYPE_APPLICATION_OVERLAY, null);
         LocalColorExtractor.newInstance(context)
                 .applyColorsOverride(context, mWallpaperColors);
         return new ContextThemeWrapper(context,
@@ -241,7 +244,7 @@
                     /* bgAllAppsList= */ null,
                     bgModel,
                     LauncherAppState.getInstance(previewContext).getModel().getModelDelegate(),
-                    new LauncherBinder(LauncherAppState.getInstance(previewContext), bgModel,
+                    new BaseLauncherBinder(LauncherAppState.getInstance(previewContext), bgModel,
                             /* bgAllAppsList= */ null, new Callbacks[0])) {
 
                 @Override
diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java
index a15348b..513377a 100644
--- a/src/com/android/launcher3/icons/LauncherIcons.java
+++ b/src/com/android/launcher3/icons/LauncherIcons.java
@@ -16,14 +16,13 @@
 
 package com.android.launcher3.icons;
 
-import static com.android.launcher3.config.FeatureFlags.ENABLE_FORCED_MONO_ICON;
-
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
 
 import androidx.annotation.NonNull;
 
+import com.android.launcher3.Flags;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.graphics.LauncherPreviewRenderer;
@@ -103,7 +102,7 @@
     @Override
     protected Drawable getMonochromeDrawable(Drawable base) {
         Drawable mono = super.getMonochromeDrawable(base);
-        if (mono != null || !ENABLE_FORCED_MONO_ICON.get()) {
+        if (mono != null || !Flags.forceMonochromeAppIcons()) {
             return mono;
         }
         if (mMonochromeIconFactory == null) {
diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
index 1791539..f40eda6 100644
--- a/src/com/android/launcher3/icons/ShortcutCachingLogic.java
+++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.icons;
 
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -101,7 +101,7 @@
      * Launcher specific checks
      */
     public static Drawable getIcon(Context context, ShortcutInfo shortcutInfo, int density) {
-        if (GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return null;
         }
         try {
diff --git a/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
index 3e320bd..72dc63e 100644
--- a/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
+++ b/src/com/android/launcher3/keyboard/FocusIndicatorHelper.java
@@ -31,9 +31,11 @@
         implements OnFocusChangeListener {
 
     public FocusIndicatorHelper(View container) {
-        super(container, Flags.enableFocusOutline() ? Themes.getAttrColor(container.getContext(),
-                R.attr.focusOutlineColor)
-                : container.getResources().getColor(R.color.focused_background));
+        super(container,
+                Flags.enableFocusOutline() ? new int[]{Themes.getAttrColor(container.getContext(),
+                        R.attr.focusOutlineColor), Themes.getAttrColor(container.getContext(),
+                        R.attr.focusInnerOutlineColor)}
+                        : new int[]{container.getResources().getColor(R.color.focused_background)});
     }
 
     @Override
diff --git a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
index a8cd03b..456cde8 100644
--- a/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
+++ b/src/com/android/launcher3/keyboard/ItemFocusIndicatorHelper.java
@@ -74,7 +74,8 @@
     private static final Rect sTempRect2 = new Rect();
 
     private final View mContainer;
-    protected final Paint mPaint;
+    protected final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+    private final Paint mInnerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final int mMaxAlpha;
 
     private final Rect mDirtyRect = new Rect();
@@ -93,24 +94,31 @@
     private ObjectAnimator mCurrentAnimation;
     private float mAlpha;
     private float mRadius;
+    private float mInnerRadius;
 
-    public ItemFocusIndicatorHelper(View container, int color) {
+    public ItemFocusIndicatorHelper(View container, int... colors) {
         mContainer = container;
 
-        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-        mPaint.setColor(0xFF000000 | color);
-        if (Flags.enableFocusOutline()) {
+        mPaint.setColor(0xFF000000 | colors[0]);
+        if (Flags.enableFocusOutline() && colors.length > 1) {
             mPaint.setStyle(Paint.Style.STROKE);
             mPaint.setStrokeWidth(container.getResources().getDimensionPixelSize(
                     R.dimen.focus_outline_stroke_width));
             mRadius = container.getResources().getDimensionPixelSize(
                     R.dimen.focus_outline_radius);
+
+            mInnerPaint.setStyle(Paint.Style.STROKE);
+            mInnerPaint.setColor(0xFF000000 | colors[1]);
+            mInnerPaint.setStrokeWidth(container.getResources().getDimensionPixelSize(
+                    R.dimen.focus_outline_stroke_width));
+            mInnerRadius = container.getResources().getDimensionPixelSize(
+                    R.dimen.focus_inner_outline_radius);
         } else {
             mPaint.setStyle(Paint.Style.FILL);
             mRadius = container.getResources().getDimensionPixelSize(
                     R.dimen.grid_visualization_rounding_radius);
         }
-        mMaxAlpha = Color.alpha(color);
+        mMaxAlpha = Color.alpha(colors[0]);
 
         setAlpha(0);
         mShift = 0;
@@ -119,6 +127,7 @@
     protected void setAlpha(float alpha) {
         mAlpha = alpha;
         mPaint.setAlpha((int) (mAlpha * mMaxAlpha));
+        mInnerPaint.setAlpha((int) (mAlpha * mMaxAlpha));
     }
 
     @Override
@@ -147,11 +156,18 @@
         Rect newRect = getDrawRect();
         if (newRect != null) {
             if (Flags.enableFocusOutline()) {
-                // Stroke is drawn with half outside and half inside the view. Inset by half
-                // stroke width to move the whole stroke inside the view and avoid other views
-                // occluding it
-                int halfStrokeWidth = (int) mPaint.getStrokeWidth() / 2;
-                newRect.inset(halfStrokeWidth, halfStrokeWidth);
+                int strokeWidth = (int) mPaint.getStrokeWidth();
+                // Inset for inner outline. Stroke is drawn with half outside and half inside
+                // the view. Inset by half stroke width to move the whole stroke inside the view
+                // and avoid other views occluding it. Inset one more stroke width to leave space
+                // for outer outline.
+                newRect.inset((int) (strokeWidth * 1.5), (int) (strokeWidth * 1.5));
+                c.drawRoundRect((float) newRect.left, (float) newRect.top,
+                        (float) newRect.right, (float) newRect.bottom,
+                        mInnerRadius, mInnerRadius, mInnerPaint);
+
+                // Inset outward for drawing outer outline
+                newRect.inset(-strokeWidth, -strokeWidth);
             }
             mDirtyRect.set(newRect);
             c.drawRoundRect((float) mDirtyRect.left, (float) mDirtyRect.top,
diff --git a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
index f9bd343..4653bf1 100644
--- a/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
+++ b/src/com/android/launcher3/keyboard/ViewGroupFocusHelper.java
@@ -27,6 +27,7 @@
 public class ViewGroupFocusHelper extends FocusIndicatorHelper {
 
     private final View mContainer;
+    private static final Rect sTempRect = new Rect();
 
     public ViewGroupFocusHelper(View container) {
         super(container);
@@ -35,18 +36,22 @@
 
     @Override
     public void viewToRect(View v, Rect outRect) {
-        outRect.left = 0;
-        outRect.top = 0;
+        // Using FocusedRect here allows views to provide their custom rect for drawing outline,
+        // e.g. making the Rect bigger than the content to leave some padding between view and
+        // outline
+        v.getFocusedRect(sTempRect);
+        outRect.left = sTempRect.left;
+        outRect.top = sTempRect.top;
 
         computeLocationRelativeToContainer(v, outRect);
 
         // If a view is scaled, its position will also shift accordingly. For optimization, only
         // consider this for the last node.
-        outRect.left += (1 - v.getScaleX()) * v.getWidth() / 2;
-        outRect.top += (1 - v.getScaleY()) * v.getHeight() / 2;
+        outRect.left = (int) (outRect.left + (1 - v.getScaleX()) * sTempRect.width() / 2);
+        outRect.top = (int) (outRect.top + (1 - v.getScaleY()) * sTempRect.height() / 2);
 
-        outRect.right = outRect.left + (int) (v.getScaleX() * v.getWidth());
-        outRect.bottom = outRect.top + (int) (v.getScaleY() * v.getHeight());
+        outRect.right = outRect.left + (int) (v.getScaleX() * sTempRect.width());
+        outRect.bottom = outRect.top + (int) (v.getScaleY() * sTempRect.height());
     }
 
     private void computeLocationRelativeToContainer(View child, Rect outRect) {
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 5cb1540..441bbb5 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.view.View;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.slice.SliceItem;
 
@@ -53,11 +54,18 @@
     public static final int LAUNCHER_STATE_ALLAPPS = 4;
     public static final int LAUNCHER_STATE_UNCHANGED = 5;
 
+    @NonNull
+    protected final Context mContext;
+    @Nullable
+    protected final ActivityContext mActivityContext;
+
+    private KeyboardStateManager mKeyboardStateManager;
     private InstanceId mInstanceId;
 
-    protected @Nullable ActivityContext mActivityContext = null;
-    protected @Nullable Context mContext = null;
-    private KeyboardStateManager mKeyboardStateManager;
+    public StatsLogManager(@NonNull Context context) {
+        mContext = context;
+        mActivityContext = ActivityContext.lookupContextNoThrow(context);
+    }
 
     /**
      * Returns event enum based on the two state transition information when swipe
@@ -210,6 +218,9 @@
         @UiEvent(doc = "User tapped on free form icon on a task menu.")
         LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP(519),
 
+        @UiEvent(doc = "User tapped on desktop icon on a task menu.")
+        LAUNCHER_SYSTEM_SHORTCUT_DESKTOP_TAP(1706),
+
         @UiEvent(doc = "User tapped on pause app system shortcut.")
         LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP(521),
 
@@ -751,6 +762,15 @@
                 + " metric.")
         LAUNCHER_SPLIT_SELECTION_EXIT_INTERRUPTED(1612),
 
+        @UiEvent(doc = "User tapped add widget button in widget sheet.")
+        LAUNCHER_WIDGET_ADD_BUTTON_TAP(1622),
+
+        @UiEvent(doc = "Number of user installed Private profile apps, shown above separator line")
+        LAUNCHER_PRIVATE_SPACE_USER_INSTALLED_APPS_COUNT(1672),
+
+        @UiEvent(doc = "Number of preinstalled Private profile apps, shown under separator line")
+        LAUNCHER_PRIVATE_SPACE_PREINSTALLED_APPS_COUNT(1673)
+
         // ADD MORE
         ;
 
@@ -1185,10 +1205,7 @@
      * Creates a new instance of {@link StatsLogManager} based on provided context.
      */
     public static StatsLogManager newInstance(Context context) {
-        StatsLogManager manager = Overrides.getObject(StatsLogManager.class,
+        return Overrides.getObject(StatsLogManager.class,
                 context.getApplicationContext(), R.string.stats_log_manager_class);
-        manager.mActivityContext = ActivityContext.lookupContextNoThrow(context);
-        manager.mContext = context;
-        return manager;
     }
 }
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index fa2a1b0..41dbe4e 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.model;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.Flags.enableWorkspaceInflation;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
 import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
@@ -29,6 +30,8 @@
 import android.util.Pair;
 import android.view.View;
 
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel.CallbackTask;
@@ -41,6 +44,7 @@
 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.util.ComponentKey;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.ItemInflater;
@@ -48,10 +52,12 @@
 import com.android.launcher3.util.LooperIdleLock;
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.widget.model.WidgetsListBaseEntry;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -63,7 +69,7 @@
 /**
  * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
  */
-public abstract class BaseLauncherBinder {
+public class BaseLauncherBinder {
 
     protected static final String TAG = "LauncherBinder";
     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
@@ -79,8 +85,8 @@
     private int mMyBindingId;
 
     public BaseLauncherBinder(LauncherAppState app, BgDataModel dataModel,
-            AllAppsList allAppsList, Callbacks[] callbacksList, LooperExecutor uiExecutor) {
-        mUiExecutor = uiExecutor;
+            AllAppsList allAppsList, Callbacks[] callbacksList) {
+        mUiExecutor = MAIN_EXECUTOR;
         mApp = app;
         mBgDataModel = dataModel;
         mBgAllAppsList = allAppsList;
@@ -156,7 +162,16 @@
     /**
      * BindDeepShortcuts is abstract because it is a no-op for the go launcher.
      */
-    public abstract void bindDeepShortcuts();
+    public void bindDeepShortcuts() {
+        if (!WIDGETS_ENABLED) {
+            return;
+        }
+        final HashMap<ComponentKey, Integer> shortcutMapCopy;
+        synchronized (mBgDataModel) {
+            shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
+        }
+        executeCallbacksTask(c -> c.bindDeepShortcutMap(shortcutMapCopy), mUiExecutor);
+    }
 
     /**
      * Binds the all apps results from LoaderTask to the callbacks UX.
@@ -176,12 +191,24 @@
     /**
      * bindWidgets is abstract because it is a no-op for the go launcher.
      */
-    public abstract void bindWidgets();
+    public void bindWidgets() {
+        if (!WIDGETS_ENABLED) {
+            return;
+        }
+        final List<WidgetsListBaseEntry> widgets =
+                mBgDataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());
+        executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor);
+    }
 
     /**
      * bindWidgets is abstract because it is a no-op for the go launcher.
      */
-    public abstract void bindSmartspaceWidget();
+    public void bindSmartspaceWidget() {
+        if (!WIDGETS_ENABLED) {
+            return;
+        }
+        executeCallbacksTask(c -> c.bindSmartspaceWidget(), mUiExecutor);
+    }
 
     /**
      * Sorts the set of items by hotseat, workspace (spatially from top to bottom, left to right)
@@ -309,9 +336,16 @@
             // Bind workspace screens
             executeCallbacksTask(c -> c.bindScreens(mOrderedScreenIds), mUiExecutor);
 
+            ItemInflater inflater = mCallbacks.getItemInflater();
+
             // Load items on the current page.
-            bindItemsInChunks(currentWorkspaceItems, ITEMS_CHUNK, mUiExecutor);
-            bindItemsInChunks(currentAppWidgets, 1, mUiExecutor);
+            if (enableWorkspaceInflation() && inflater != null) {
+                inflateAsyncAndBind(currentWorkspaceItems, inflater, mUiExecutor);
+                inflateAsyncAndBind(currentAppWidgets, inflater, mUiExecutor);
+            } else {
+                bindItemsInChunks(currentWorkspaceItems, ITEMS_CHUNK, mUiExecutor);
+                bindItemsInChunks(currentAppWidgets, 1, mUiExecutor);
+            }
             if (!FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
                 mExtraItems.forEach(item ->
                         executeCallbacksTask(c -> c.bindExtraContainerItems(item), mUiExecutor));
@@ -322,18 +356,20 @@
 
             RunnableList onCompleteSignal = new RunnableList();
 
-            if (enableWorkspaceInflation()) {
+            if (enableWorkspaceInflation() && inflater != null) {
                 MODEL_EXECUTOR.execute(() ->  {
-                    setupPendingBind(otherWorkspaceItems, otherAppWidgets, currentScreenIds,
-                            pendingExecutor);
+                    inflateAsyncAndBind(otherWorkspaceItems, inflater, pendingExecutor);
+                    inflateAsyncAndBind(otherAppWidgets, inflater, pendingExecutor);
+                    setupPendingBind(currentScreenIds, pendingExecutor);
 
                     // Wait for the async inflation to complete and then notify the completion
                     // signal on UI thread.
                     MAIN_EXECUTOR.execute(onCompleteSignal::executeAllAndDestroy);
                 });
             } else {
-                setupPendingBind(
-                        otherWorkspaceItems, otherAppWidgets, currentScreenIds, pendingExecutor);
+                bindItemsInChunks(otherWorkspaceItems, ITEMS_CHUNK, pendingExecutor);
+                bindItemsInChunks(otherAppWidgets, 1, pendingExecutor);
+                setupPendingBind(currentScreenIds, pendingExecutor);
                 onCompleteSignal.executeAllAndDestroy();
             }
 
@@ -348,13 +384,8 @@
         }
 
         private void setupPendingBind(
-                List<ItemInfo> otherWorkspaceItems,
-                List<ItemInfo> otherAppWidgets,
                 IntSet currentScreenIds,
                 Executor pendingExecutor) {
-            bindItemsInChunks(otherWorkspaceItems, ITEMS_CHUNK, pendingExecutor);
-            bindItemsInChunks(otherAppWidgets, 1, pendingExecutor);
-
             StringCache cacheClone = mBgDataModel.stringCache.clone();
             executeCallbacksTask(c -> c.bindStringCache(cacheClone), pendingExecutor);
 
@@ -371,18 +402,11 @@
          * Tries to inflate the items asynchronously and bind. Returns true on success or false if
          * async-binding is not supported in this case.
          */
-        private boolean inflateAsyncAndBind(List<ItemInfo> items, Executor executor) {
-            if (!enableWorkspaceInflation()) {
-                return false;
-            }
-            ItemInflater inflater = mCallbacks.getItemInflater();
-            if (inflater == null) {
-                return false;
-            }
-
+        private void inflateAsyncAndBind(
+                List<ItemInfo> items, @NonNull ItemInflater inflater, Executor executor) {
             if (mMyBindingId != mBgDataModel.lastBindId) {
                 Log.d(TAG, "Too many consecutive reloads, skipping obsolete view inflation");
-                return true;
+                return;
             }
 
             ModelWriter writer = mApp.getModel()
@@ -390,15 +414,10 @@
             List<Pair<ItemInfo, View>> bindItems = items.stream().map(i ->
                     Pair.create(i, inflater.inflateItem(i, writer, null))).toList();
             executeCallbacksTask(c -> c.bindInflatedItems(bindItems), executor);
-            return true;
         }
 
-        private void bindItemsInChunks(List<ItemInfo> workspaceItems, int chunkCount,
-                Executor executor) {
-            if (inflateAsyncAndBind(workspaceItems, executor)) {
-                return;
-            }
-
+        private void bindItemsInChunks(
+                List<ItemInfo> workspaceItems, int chunkCount, Executor executor) {
             // Bind the workspace items
             int count = workspaceItems.size();
             for (int i = 0; i < count; i += chunkCount) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 886ae27..d5de4ce 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -18,9 +18,9 @@
 import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY;
 
 import static com.android.launcher3.BuildConfig.QSB_ON_FIRST_SCREEN;
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SMARTSPACE_REMOVAL;
 import static com.android.launcher3.config.FeatureFlags.shouldShowFirstPageWidget;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
 import static com.android.launcher3.shortcuts.ShortcutRequest.PINNED;
 
 import static java.util.stream.Collectors.groupingBy;
@@ -312,7 +312,7 @@
      * shortcuts and unpinning any extra shortcuts.
      */
     public synchronized void updateShortcutPinnedState(Context context, UserHandle user) {
-        if (GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return;
         }
 
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
index 1360510..88ca009 100644
--- a/src/com/android/launcher3/model/DatabaseHelper.java
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -333,7 +333,7 @@
             for (int widgetId : allWidgets) {
                 if (!validWidgets.contains(widgetId)) {
                     try {
-                        FileLog.d(TAG, "Deleting invalid widget " + widgetId);
+                        FileLog.d(TAG, "Deleting widget not found in db: appWidgetId=" + widgetId);
                         holder.deleteAppWidgetId(widgetId);
                         isAnyWidgetRemoved = true;
                     } catch (RuntimeException e) {
@@ -342,15 +342,17 @@
                 }
             }
             if (isAnyWidgetRemoved) {
-                final String allWidgetsIds = Arrays.stream(allWidgets).mapToObj(String::valueOf)
+                final String allLauncherHostWidgetIds = Arrays.stream(allWidgets)
+                        .mapToObj(String::valueOf)
                         .collect(Collectors.joining(",", "[", "]"));
-                final String validWidgetsIds = Arrays.stream(
+                final String allValidLauncherDbWidgetIds = Arrays.stream(
                                 validWidgets.getArray().toArray()).mapToObj(String::valueOf)
                         .collect(Collectors.joining(",", "[", "]"));
                 FileLog.d(TAG,
-                        "One or more widgets was removed. db_path=" + db.getPath()
-                                + " allWidgetsIds=" + allWidgetsIds
-                                + ", validWidgetsIds=" + validWidgetsIds);
+                        "One or more widgets was removed: "
+                                + " allLauncherHostWidgetIds=" + allLauncherHostWidgetIds
+                                + ", allValidLauncherDbWidgetIds=" + allValidLauncherDbWidgetIds
+                );
             }
         } finally {
             holder.destroy();
diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java
index f24d1d2..729b381 100644
--- a/src/com/android/launcher3/model/DeviceGridState.java
+++ b/src/com/android/launcher3/model/DeviceGridState.java
@@ -53,6 +53,13 @@
     private final @DeviceType int mDeviceType;
     private final String mDbFile;
 
+    public DeviceGridState(int columns, int row, int numHotseat, int deviceType, String dbFile) {
+        mGridSizeString = String.format(Locale.ENGLISH, "%d,%d", columns, row);
+        mNumHotseat = numHotseat;
+        mDeviceType = deviceType;
+        mDbFile = dbFile;
+    }
+
     public DeviceGridState(InvariantDeviceProfile idp) {
         mGridSizeString = String.format(Locale.ENGLISH, "%d,%d", idp.numColumns, idp.numRows);
         mNumHotseat = idp.numDatabaseHotseatIcons;
@@ -149,11 +156,11 @@
     }
 
     public Integer getColumns() {
-        return Integer.parseInt(String.valueOf(mGridSizeString.charAt(0)));
+        return Integer.parseInt(String.valueOf(mGridSizeString.split(",")[0]));
     }
 
     public Integer getRows() {
-        return Integer.parseInt(String.valueOf(mGridSizeString.charAt(2)));
+        return Integer.parseInt(String.valueOf(mGridSizeString.split(",")[1]));
     }
 
     @Override
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index af66431..f24a7c1 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -38,7 +38,9 @@
 import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
 
+import com.android.launcher3.Flags;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherSettings;
@@ -47,6 +49,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
+import com.android.launcher3.util.ContentWriter;
 import com.android.launcher3.util.GridOccupancy;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
@@ -94,6 +97,15 @@
         return needsToMigrate;
     }
 
+    @VisibleForTesting
+    public static List<DbEntry> readAllEntries(SQLiteDatabase db, String tableName,
+            Context context) {
+        DbReader dbReader = new DbReader(db, tableName, context, getValidPackages(context));
+        List<DbEntry> result = dbReader.loadAllWorkspaceEntries();
+        result.addAll(dbReader.loadHotseatEntries());
+        return result;
+    }
+
     /**
      * When migrating the grid, we copy the table
      * {@link LauncherSettings.Favorites#TABLE_NAME} from {@code source} into
@@ -105,15 +117,23 @@
      */
     public static boolean migrateGridIfNeeded(
             @NonNull Context context,
-            @NonNull InvariantDeviceProfile idp,
+            @NonNull DeviceGridState srcDeviceState,
+            @NonNull DeviceGridState destDeviceState,
             @NonNull DatabaseHelper target,
             @NonNull SQLiteDatabase source) {
-
-        DeviceGridState srcDeviceState = new DeviceGridState(context);
-        DeviceGridState destDeviceState = new DeviceGridState(idp);
         if (!needsToMigrate(srcDeviceState, destDeviceState)) {
             return true;
         }
+
+        if (Flags.enableGridMigrationFix()
+                && srcDeviceState.getColumns().equals(destDeviceState.getColumns())
+                && srcDeviceState.getRows() < destDeviceState.getRows()) {
+            // Only use this strategy when comparing the previous grid to the new grid and the
+            // columns are the same and the destination has more rows
+            copyTable(source, TABLE_NAME, target.getWritableDatabase(), TABLE_NAME, context);
+            destDeviceState.writeToPrefs(context);
+            return true;
+        }
         copyTable(source, TABLE_NAME, target.getWritableDatabase(), TMP_TABLE, context);
 
         HashSet<String> validPackages = getValidPackages(context);
@@ -204,19 +224,13 @@
             screens.add(screenId);
         }
 
-        boolean preservePages = false;
-        if (screens.isEmpty() && FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC.get()) {
-            preservePages = destDeviceState.compareTo(srcDeviceState) >= 0
-                    && destDeviceState.getColumns() - srcDeviceState.getColumns() <= 2;
-        }
-
         // Then we place the items on the screens
         for (int screenId : screens) {
             if (DEBUG) {
                 Log.d(TAG, "Migrating " + screenId);
             }
             solveGridPlacement(helper, srcReader,
-                    destReader, screenId, trgX, trgY, workspaceToBeAdded, false);
+                    destReader, screenId, trgX, trgY, workspaceToBeAdded);
             if (workspaceToBeAdded.isEmpty()) {
                 break;
             }
@@ -226,8 +240,8 @@
         // any of the screens, in this case we add them to new screens until all of them are placed.
         int screenId = destReader.mLastScreenId + 1;
         while (!workspaceToBeAdded.isEmpty()) {
-            solveGridPlacement(helper, srcReader,
-                    destReader, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
+            solveGridPlacement(helper, srcReader, destReader, screenId, trgX, trgY,
+                    workspaceToBeAdded);
             screenId++;
         }
 
@@ -329,7 +343,7 @@
     private static void solveGridPlacement(@NonNull final DatabaseHelper helper,
             @NonNull final DbReader srcReader, @NonNull final DbReader destReader,
             final int screenId, final int trgX, final int trgY,
-            @NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
+            @NonNull final List<DbEntry> sortedItemsToPlace) {
         final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
         final Point trg = new Point(trgX, trgY);
         final Point next = new Point(0, screenId == 0
@@ -347,8 +361,6 @@
         Iterator<DbEntry> iterator = sortedItemsToPlace.iterator();
         while (iterator.hasNext()) {
             final DbEntry entry = iterator.next();
-            if (matchingScreenIdOnly && entry.screenId < screenId) continue;
-            if (matchingScreenIdOnly && entry.screenId > screenId) break;
             if (entry.minSpanX > trgX || entry.minSpanY > trgY) {
                 iterator.remove();
                 continue;
@@ -416,7 +428,8 @@
         }
     }
 
-    protected static class DbReader {
+    @VisibleForTesting
+    public static class DbReader {
 
         private final SQLiteDatabase mDb;
         private final String mTableName;
@@ -427,7 +440,7 @@
         private final Map<Integer, ArrayList<DbEntry>> mWorkspaceEntriesByScreenId =
                 new ArrayMap<>();
 
-        DbReader(SQLiteDatabase db, String tableName, Context context,
+        public DbReader(SQLiteDatabase db, String tableName, Context context,
                 Set<String> validPackages) {
             mDb = db;
             mTableName = tableName;
@@ -656,12 +669,17 @@
         }
     }
 
-    protected static class DbEntry extends ItemInfo implements Comparable<DbEntry> {
+    public static class DbEntry extends ItemInfo implements Comparable<DbEntry> {
 
         private String mIntent;
         private String mProvider;
         private Map<String, Set<Integer>> mFolderItems = new HashMap<>();
 
+        /**
+         * Id of the specific widget.
+         */
+        public int appWidgetId = NO_ID;
+
         /** Comparator according to the reading order */
         @Override
         public int compareTo(DbEntry another) {
@@ -695,6 +713,18 @@
             values.put(LauncherSettings.Favorites.SPANY, spanY);
         }
 
+        @Override
+        public void writeToValues(@NonNull ContentWriter writer) {
+            super.writeToValues(writer);
+            writer.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
+        }
+
+        @Override
+        public void readFromValues(@NonNull ContentValues values) {
+            super.readFromValues(values);
+            appWidgetId = values.getAsInteger(LauncherSettings.Favorites.APPWIDGET_ID);
+        }
+
         /** This id is not used in the DB is only used while doing the migration and it identifies
          * an entry on each workspace. For example two calculator icons would have the same
          * migration id even thought they have different database ids.
@@ -705,7 +735,10 @@
                 case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR:
                     return getFolderMigrationId();
                 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
-                    return mProvider;
+                    // mProvider is the app the widget belongs to and appWidgetId it's the unique
+                    // is of the widget, we need both because if you remove a widget and then add it
+                    // again, then it can change and the WidgetProvider would not know the widget.
+                    return mProvider + appWidgetId;
                 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                     final String intentStr = cleanIntentString(mIntent);
                     try {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 3a23765..ac4c087 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -132,7 +132,7 @@
     private FirstScreenBroadcast mFirstScreenBroadcast;
 
     @NonNull
-    private final LauncherBinder mLauncherBinder;
+    private final BaseLauncherBinder mLauncherBinder;
 
     private final LauncherApps mLauncherApps;
     private final UserManager mUserManager;
@@ -153,13 +153,13 @@
     private String mDbName;
 
     public LoaderTask(@NonNull LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel bgModel,
-            ModelDelegate modelDelegate, @NonNull LauncherBinder launcherBinder) {
+            ModelDelegate modelDelegate, @NonNull BaseLauncherBinder launcherBinder) {
         this(app, bgAllAppsList, bgModel, modelDelegate, launcherBinder, new UserManagerState());
     }
 
     @VisibleForTesting
     LoaderTask(@NonNull LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel bgModel,
-            ModelDelegate modelDelegate, @NonNull LauncherBinder launcherBinder,
+            ModelDelegate modelDelegate, @NonNull BaseLauncherBinder launcherBinder,
             UserManagerState userManagerState) {
         mApp = app;
         mBgAllAppsList = bgAllAppsList;
diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java
index 64771bd..7e1d40d 100644
--- a/src/com/android/launcher3/model/ModelDbController.java
+++ b/src/com/android/launcher3/model/ModelDbController.java
@@ -312,8 +312,12 @@
         mOpenHelper = (mContext instanceof SandboxContext) ? oldHelper
                 : createDatabaseHelper(true /* forMigration */);
         try {
-            return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, idp, mOpenHelper,
-                   oldHelper.getWritableDatabase());
+            // This is the current grid we have, given by the mContext
+            DeviceGridState srcDeviceState = new DeviceGridState(mContext);
+            // This is the state we want to migrate to that is given by the idp
+            DeviceGridState destDeviceState = new DeviceGridState(idp);
+            return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, srcDeviceState,
+                    destDeviceState, mOpenHelper, oldHelper.getWritableDatabase());
         } catch (Exception e) {
             FileLog.e(TAG, "Failed to migrate grid", e);
             return false;
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 7e7bfb3..8360b14 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -45,28 +45,29 @@
             boolean isPrimaryInstance) {
         ModelDelegate delegate = Overrides.getObject(
                 ModelDelegate.class, context, R.string.model_delegate_class);
-        delegate.init(context, app, appsList, dataModel, isPrimaryInstance);
+        delegate.init(app, appsList, dataModel, isPrimaryInstance);
         return delegate;
     }
 
-    protected Context mContext;
+    protected final Context mContext;
     protected LauncherAppState mApp;
     protected AllAppsList mAppsList;
     protected BgDataModel mDataModel;
     protected boolean mIsPrimaryInstance;
 
-    public ModelDelegate() { }
+    public ModelDelegate(Context context) {
+        mContext = context;
+    }
 
     /**
      * Initializes the object with the given params.
      */
-    private void init(Context context, LauncherAppState app, AllAppsList appsList,
+    private void init(LauncherAppState app, AllAppsList appsList,
             BgDataModel dataModel, boolean isPrimaryInstance) {
         this.mApp = app;
         this.mAppsList = appsList;
         this.mDataModel = dataModel;
         this.mIsPrimaryInstance = isPrimaryInstance;
-        this.mContext = context;
     }
 
     /** Called periodically to validate and update any data */
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index e8767bf..1923065 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -48,7 +48,7 @@
 import com.android.launcher3.pm.PackageInstallInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.ItemInfoMatcher;
@@ -286,7 +286,7 @@
                             }
                             if (si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
                                 if (activities != null && !activities.isEmpty()) {
-                                    si.status = ApiWrapper
+                                    si.status = ApiWrapper.INSTANCE.get(context)
                                             .isNonResizeableActivity(activities.get(0))
                                             ? si.status | WorkspaceItemInfo.FLAG_NON_RESIZEABLE
                                             : si.status & ~WorkspaceItemInfo.FLAG_NON_RESIZEABLE;
diff --git a/src/com/android/launcher3/model/WidgetItem.java b/src/com/android/launcher3/model/WidgetItem.java
index 1dd58c3..3f88717 100644
--- a/src/com/android/launcher3/model/WidgetItem.java
+++ b/src/com/android/launcher3/model/WidgetItem.java
@@ -123,6 +123,7 @@
         if (!Flags.enableGeneratedPreviews() || generatedPreviews == null) {
             return false;
         }
-        return generatedPreviews.contains(widgetCategory);
+        return generatedPreviews.contains(widgetCategory)
+                && generatedPreviews.get(widgetCategory) != null;
     }
 }
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java
similarity index 96%
rename from src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
rename to src/com/android/launcher3/model/WidgetsModel.java
index 8b983fc..91ce5ea 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src/com/android/launcher3/model/WidgetsModel.java
@@ -3,6 +3,7 @@
 
 import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.pm.ShortcutConfigActivityInfo.queryList;
 import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
 
@@ -44,6 +45,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -59,10 +61,6 @@
  */
 public class WidgetsModel {
 
-    // True is the widget support is disabled.
-    public static final boolean GO_DISABLE_WIDGETS = false;
-    public static final boolean GO_DISABLE_NOTIFICATION_DOTS = false;
-
     private static final String TAG = "WidgetsModel";
     private static final boolean DEBUG = false;
 
@@ -79,6 +77,9 @@
     public synchronized ArrayList<WidgetsListBaseEntry> getFilteredWidgetsListForPicker(
             Context context,
             Predicate<WidgetItem> widgetItemFilter) {
+        if (!WIDGETS_ENABLED) {
+            return new ArrayList<>();
+        }
         ArrayList<WidgetsListBaseEntry> result = new ArrayList<>();
         AlphabeticIndexCompat indexer = new AlphabeticIndexCompat(context);
 
@@ -111,6 +112,9 @@
 
     /** Returns a mapping of packages to their widgets without static shortcuts. */
     public synchronized Map<PackageUserKey, List<WidgetItem>> getAllWidgetsWithoutShortcuts() {
+        if (!WIDGETS_ENABLED) {
+            return Collections.emptyMap();
+        }
         Map<PackageUserKey, List<WidgetItem>> packagesToWidgets = new HashMap<>();
         mWidgetsList.forEach((packageItemInfo, widgetsAndShortcuts) -> {
             List<WidgetItem> widgets = widgetsAndShortcuts.stream()
@@ -131,6 +135,9 @@
      */
     public List<ComponentWithLabelAndIcon> update(
             LauncherAppState app, @Nullable PackageUserKey packageUser) {
+        if (!WIDGETS_ENABLED) {
+            return Collections.emptyList();
+        }
         Preconditions.assertWorkerThread();
 
         Context context = app.getContext();
@@ -207,6 +214,9 @@
 
     public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
             LauncherAppState app) {
+        if (!WIDGETS_ENABLED) {
+            return;
+        }
         WidgetManagerHelper widgetManager = new WidgetManagerHelper(app.getContext());
         for (Entry<PackageItemInfo, List<WidgetItem>> entry : mWidgetsList.entrySet()) {
             if (packageNames.contains(entry.getKey().packageName)) {
@@ -231,6 +241,9 @@
 
     public WidgetItem getWidgetProviderInfoByProviderName(
             ComponentName providerName, UserHandle user) {
+        if (!WIDGETS_ENABLED) {
+            return null;
+        }
         List<WidgetItem> widgetsList = mWidgetsList.get(
                 new PackageItemInfo(providerName.getPackageName(), user));
         if (widgetsList == null) {
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index 1093753..ee45c0f 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -32,6 +32,7 @@
 import com.android.launcher3.LauncherSettings.Favorites
 import com.android.launcher3.Utilities
 import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError
+import com.android.launcher3.config.FeatureFlags
 import com.android.launcher3.logging.FileLog
 import com.android.launcher3.model.data.AppPairInfo
 import com.android.launcher3.model.data.FolderInfo
@@ -41,7 +42,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.pm.PackageInstallInfo
 import com.android.launcher3.shortcuts.ShortcutKey
-import com.android.launcher3.uioverrides.ApiWrapper
+import com.android.launcher3.util.ApiWrapper
 import com.android.launcher3.util.ComponentKey
 import com.android.launcher3.util.PackageManagerHelper
 import com.android.launcher3.util.PackageUserKey
@@ -325,7 +326,7 @@
             }
             val activityInfo = c.launcherActivityInfo
             if (activityInfo != null) {
-                if (ApiWrapper.isNonResizeableActivity(activityInfo)) {
+                if (ApiWrapper.INSTANCE.get(app.context).isNonResizeableActivity(activityInfo)) {
                     info.status = info.status or WorkspaceItemInfo.FLAG_NON_RESIZEABLE
                 }
                 info.setProgressLevel(
@@ -373,6 +374,12 @@
         // If we generated a placeholder Folder before this point, it may need to be replaced with
         // an app pair.
         if (c.itemType == Favorites.ITEM_TYPE_APP_PAIR && collection is FolderInfo) {
+            if (!FeatureFlags.enableAppPairs()) {
+                // If app pairs are not enabled, stop loading.
+                Log.e(TAG, "app pairs flag is off, did not load app pair")
+                return
+            }
+
             val folderInfo: FolderInfo = collection
             val newAppPair = AppPairInfo()
             // Move the placeholder's contents over to the new app pair.
@@ -428,14 +435,21 @@
         appWidgetInfo.restoreStatus = c.restoreFlag
         if (appWidgetInfo.spanX <= 0 || appWidgetInfo.spanY <= 0) {
             c.markDeleted(
-                "Widget has invalid size: ${appWidgetInfo.spanX}x${appWidgetInfo.spanY}",
+                "processWidget: Widget has invalid size: ${appWidgetInfo.spanX}x${appWidgetInfo.spanY}" +
+                    ", id=${c.id}," +
+                    ", appWidgetId=${c.appWidgetId}," +
+                    ", component=${component}",
                 RestoreError.INVALID_LOCATION
             )
             return
         }
         if (!c.isOnWorkspaceOrHotseat) {
             c.markDeleted(
-                "Widget found where container != CONTAINER_DESKTOP nor CONTAINER_HOTSEAT - ignoring!",
+                "processWidget: invalid Widget container != CONTAINER_DESKTOP nor CONTAINER_HOTSEAT." +
+                    " id=${c.id}," +
+                    ", appWidgetId=${c.appWidgetId}," +
+                    ", component=${component}," +
+                    ", container=${c.container}",
                 RestoreError.INVALID_LOCATION
             )
             return
@@ -446,7 +460,12 @@
         val inflationResult = widgetInflater.inflateAppWidget(appWidgetInfo)
         var shouldUpdate = inflationResult.isUpdate
         val lapi = inflationResult.widgetInfo
-
+        FileLog.d(
+            TAG,
+            "processWidget: id=${c.id}" +
+                ", appWidgetId=${c.appWidgetId}" +
+                ", inflationResult=$inflationResult"
+        )
         when (inflationResult.type) {
             WidgetInflater.TYPE_DELETE -> {
                 c.markDeleted(inflationResult.reason, inflationResult.restoreErrorType)
@@ -466,7 +485,11 @@
                 ) {
                     // Restore never started
                     c.markDeleted(
-                        "Unrestored widget removed: $component",
+                        "processWidget: Unrestored Pending widget removed:" +
+                            " id=${c.id}" +
+                            ", appWidgetId=${c.appWidgetId}" +
+                            ", component=${component}" +
+                            ", restoreFlag:=${c.restoreFlag}",
                         RestoreError.APP_NOT_INSTALLED
                     )
                     return
@@ -509,7 +532,10 @@
             if (appWidgetInfo.spanX < lapi.minSpanX || appWidgetInfo.spanY < lapi.minSpanY) {
                 FileLog.d(
                     TAG,
-                    "Widget ${lapi.component} minSizes not meet: span=${appWidgetInfo.spanX}x${appWidgetInfo.spanY} minSpan=${lapi.minSpanX}x${lapi.minSpanY}"
+                    " processWidget: Widget ${lapi.component} minSizes not met: span=${appWidgetInfo.spanX}x${appWidgetInfo.spanY} minSpan=${lapi.minSpanX}x${lapi.minSpanY}," +
+                        " id: ${c.id}," +
+                        " appWidgetId: ${c.appWidgetId}," +
+                        " component=${component}"
                 )
                 logWidgetInfo(app.invariantDeviceProfile, lapi)
             }
diff --git a/src/com/android/launcher3/model/data/AppPairInfo.kt b/src/com/android/launcher3/model/data/AppPairInfo.kt
index a56ee8e..fad365c 100644
--- a/src/com/android/launcher3/model/data/AppPairInfo.kt
+++ b/src/com/android/launcher3/model/data/AppPairInfo.kt
@@ -18,6 +18,7 @@
 
 import android.content.Context
 import com.android.launcher3.LauncherSettings
+import com.android.launcher3.R
 import com.android.launcher3.icons.IconCache
 import com.android.launcher3.logger.LauncherAtom
 import com.android.launcher3.views.ActivityContext
@@ -74,6 +75,31 @@
                 it.hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE)
             }
 
+    /** Fetches high-res icons for member apps if needed. */
+    fun fetchHiResIconsIfNeeded(iconCache: IconCache) {
+        getAppContents().stream().filter(ItemInfoWithIcon::usingLowResIcon).forEach { member ->
+            iconCache.getTitleAndIcon(member, false)
+        }
+    }
+
+    /**
+     * App pairs will draw as "disabled" if either of the following is true:
+     * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is paused
+     *    or can't be launched for some other reason).
+     * 2) One of the member apps can't be launched due to screen size requirements.
+     */
+    fun shouldDrawAsDisabled(context: Context): Boolean {
+        return isDisabled || !isLaunchable(context)
+    }
+
+    /** Generates a default title for the app pair and sets it. */
+    fun generateTitle(context: Context): CharSequence? {
+        val app1: CharSequence? = getFirstApp().title
+        val app2: CharSequence? = getSecondApp().title
+        title = context.getString(R.string.app_pair_default_title, app1, app2)
+        return title
+    }
+
     /** Generates an ItemInfo for logging. */
     override fun buildProto(cInfo: CollectionInfo?): LauncherAtom.ItemInfo {
         val appPairIcon = LauncherAtom.FolderIcon.newBuilder().setCardinality(contents.size)
@@ -84,11 +110,4 @@
             .setContainerInfo(getContainerInfo())
             .build()
     }
-
-    /** Fetches high-res icons for member apps if needed. */
-    fun fetchHiResIconsIfNeeded(iconCache: IconCache) {
-        getAppContents().stream().filter(ItemInfoWithIcon::usingLowResIcon).forEach { member ->
-            iconCache.getTitleAndIcon(member, false)
-        }
-    }
 }
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index 56996ef..18d2b85 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -213,6 +213,8 @@
         void onAdd(ItemInfo item, int rank);
         void onRemove(List<ItemInfo> item);
         void onItemsChanged(boolean animate);
+        void onTitleChanged(CharSequence title);
+
     }
 
     public boolean hasOption(int optionFlag) {
@@ -285,6 +287,10 @@
         if (modelWriter != null) {
             modelWriter.updateItemInDatabase(this);
         }
+
+        for (int i = 0; i < mListeners.size(); i++) {
+            mListeners.get(i).onTitleChanged(title);
+        }
     }
 
     /**
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 348a953..8c3efd7 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -94,6 +94,10 @@
      * {@link Favorites#ITEM_TYPE_APP_PAIR},
      * {@link Favorites#ITEM_TYPE_APPWIDGET} or
      * {@link Favorites#ITEM_TYPE_CUSTOM_APPWIDGET}.
+     * {@link Favorites#ITEM_TYPE_TASK}.
+     * {@link Favorites#ITEM_TYPE_QSB}.
+     * {@link Favorites#ITEM_TYPE_SEARCH_ACTION}.
+     * {@link Favorites#ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON}.
      */
     public int itemType;
 
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index f8878b6..3a74ff2 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -29,7 +29,7 @@
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 
 /**
  * Represents an ItemInfo which also holds an icon.
@@ -122,11 +122,6 @@
     public static final int FLAG_ARCHIVED = 1 << 14;
 
     /**
-     * Flag indicating it's the Private Space Install App icon.
-     */
-    public static final int FLAG_PRIVATE_SPACE_INSTALL_APP = 1 << 15;
-
-    /**
      * Status associated with the system state of the underlying item. This is calculated every
      * time a new info is created and not persisted on the disk.
      */
@@ -161,10 +156,6 @@
      * and its install session is active
      */
     public boolean isPendingDownload() {
-        if (isArchived()) {
-            return this.getProgressLevel() == 0
-                    && (this.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0;
-        }
         return getProgressLevel() == 0;
     }
 
@@ -178,6 +169,11 @@
         return (runtimeStatusFlags & FLAG_ARCHIVED) != 0;
     }
 
+    /** Returns true if the app is archived and doesn't have an active install session. */
+    public boolean isInactiveArchive() {
+        return isArchived() && (runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) == 0;
+    }
+
     /**
      * Indicates whether we're using a low res icon
      */
@@ -256,8 +252,8 @@
         String targetPackage = getTargetPackage();
 
         return targetPackage != null
-                ? ApiWrapper.getAppMarketActivityIntent(
-                context, targetPackage, Process.myUserHandle())
+                ? ApiWrapper.INSTANCE.get(context).getAppMarketActivityIntent(
+                        targetPackage, Process.myUserHandle())
                 : null;
     }
 
diff --git a/src/com/android/launcher3/model/data/PrivateSpaceInstallAppButtonInfo.java b/src/com/android/launcher3/model/data/PrivateSpaceInstallAppButtonInfo.java
new file mode 100644
index 0000000..1e7281d
--- /dev/null
+++ b/src/com/android/launcher3/model/data/PrivateSpaceInstallAppButtonInfo.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model.data;
+
+import com.android.launcher3.LauncherSettings;
+
+/**
+ * Represents the Private Space Install App button in AllAppsView.
+ */
+public class PrivateSpaceInstallAppButtonInfo extends AppInfo {
+
+    public PrivateSpaceInstallAppButtonInfo() {
+        itemType = LauncherSettings.Favorites.ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON;
+    }
+}
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 9917ad7..5ae7003 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -32,7 +32,7 @@
 import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.ContentWriter;
 
 import java.util.Arrays;
@@ -201,7 +201,7 @@
             runtimeStatusFlags &= ~FLAG_DISABLED_VERSION_LOWER;
         }
 
-        Person[] persons = ApiWrapper.getPersons(shortcutInfo);
+        Person[] persons = ApiWrapper.INSTANCE.get(context).getPersons(shortcutInfo);
         personKeys = persons.length == 0 ? Utilities.EMPTY_STRING_ARRAY
             : Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new);
     }
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 77effca..e44ea1d 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -153,7 +153,7 @@
 
         mPaginationPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
         mPaginationPaint.setStyle(Style.FILL);
-        mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.folderPaginationColor));
+        mPaginationPaint.setColor(Themes.getAttrColor(context, R.attr.pageIndicatorDotColor));
         mDotRadius = getResources().getDimension(R.dimen.page_indicator_dot_size) / 2;
         mCircleGap = DOT_GAP_FACTOR * mDotRadius;
         setOutlineProvider(new MyOutlineProver());
diff --git a/src/com/android/launcher3/pm/UserCache.java b/src/com/android/launcher3/pm/UserCache.java
index 032de31..185e0b5 100644
--- a/src/com/android/launcher3/pm/UserCache.java
+++ b/src/com/android/launcher3/pm/UserCache.java
@@ -17,7 +17,6 @@
 package com.android.launcher3.pm;
 
 import static com.android.launcher3.Utilities.ATLEAST_U;
-import static com.android.launcher3.uioverrides.ApiWrapper.queryAllUsers;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
 import android.content.Context;
@@ -34,6 +33,7 @@
 
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.UserBadgeDrawable;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.SafeCloseable;
@@ -119,7 +119,7 @@
 
     @WorkerThread
     private void updateCache() {
-        mUserToSerialMap = queryAllUsers(mContext);
+        mUserToSerialMap = ApiWrapper.INSTANCE.get(mContext).queryAllUsers();
     }
 
     /**
diff --git a/src/com/android/launcher3/popup/RemoteActionShortcut.java b/src/com/android/launcher3/popup/RemoteActionShortcut.java
index 688da49..0860ae5 100644
--- a/src/com/android/launcher3/popup/RemoteActionShortcut.java
+++ b/src/com/android/launcher3/popup/RemoteActionShortcut.java
@@ -33,22 +33,22 @@
 import android.widget.Toast;
 
 import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.views.ActivityContext;
 
 import java.lang.ref.WeakReference;
 
-public class RemoteActionShortcut extends SystemShortcut<BaseDraggingActivity> {
+public class RemoteActionShortcut<T extends Context & ActivityContext> extends SystemShortcut<T> {
     private static final String TAG = "RemoteActionShortcut";
     private static final boolean DEBUG = Utilities.IS_DEBUG_DEVICE;
 
     private final RemoteAction mAction;
 
     public RemoteActionShortcut(RemoteAction action,
-            BaseDraggingActivity activity, ItemInfo itemInfo, View originalView) {
-        super(0, R.id.action_remote_action_shortcut, activity, itemInfo, originalView);
+            T context, ItemInfo itemInfo, View originalView) {
+        super(0, R.id.action_remote_action_shortcut, context, itemInfo, originalView);
         mAction = action;
     }
 
@@ -80,7 +80,7 @@
         mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
                 .log(LAUNCHER_SYSTEM_SHORTCUT_PAUSE_TAP);
 
-        final WeakReference<BaseDraggingActivity> weakTarget = new WeakReference<>(mTarget);
+        final WeakReference<T> weakTarget = new WeakReference<>(mTarget);
         final String actionIdentity = mAction.getTitle() + ", "
                 + mItemInfo.getTargetComponent().getPackageName();
 
@@ -95,7 +95,7 @@
                             mItemInfo.getTargetComponent().getPackageName()),
                     (pendingIntent, intent, resultCode, resultData, resultExtras) -> {
                         if (DEBUG) Log.d(TAG, "Action is complete: " + actionIdentity);
-                        final BaseDraggingActivity target = weakTarget.get();
+                        final T target = weakTarget.get();
                         if (resultData != null && !resultData.isEmpty()) {
                             Log.e(TAG, "Remote action returned result: " + actionIdentity
                                     + " : " + resultData);
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 0af7e67..f56d732 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -22,6 +22,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.AbstractFloatingViewHelper;
 import com.android.launcher3.Flags;
 import com.android.launcher3.R;
 import com.android.launcher3.SecondaryDropTarget;
@@ -31,7 +32,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.InstantAppResolver;
 import com.android.launcher3.util.PackageManagerHelper;
@@ -61,23 +62,23 @@
     protected final ItemInfo mItemInfo;
     protected final View mOriginalView;
 
+    private final AbstractFloatingViewHelper mAbstractFloatingViewHelper;
+
     public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo,
             View originalView) {
+        this(iconResId, labelResId, target, itemInfo, originalView,
+                new AbstractFloatingViewHelper());
+    }
+
+    public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo,
+            View originalView, AbstractFloatingViewHelper abstractFloatingViewHelper) {
         mIconResId = iconResId;
         mLabelResId = labelResId;
         mAccessibilityActionId = labelResId;
         mTarget = target;
         mItemInfo = itemInfo;
         mOriginalView = originalView;
-    }
-
-    public SystemShortcut(SystemShortcut<T> other) {
-        mIconResId = other.mIconResId;
-        mLabelResId = other.mLabelResId;
-        mAccessibilityActionId = other.mAccessibilityActionId;
-        mTarget = other.mTarget;
-        mItemInfo = other.mItemInfo;
-        mOriginalView = other.mOriginalView;
+        mAbstractFloatingViewHelper = abstractFloatingViewHelper;
     }
 
     public void setIconAndLabelFor(View iconView, TextView labelView) {
@@ -178,7 +179,7 @@
 
         @Override
         public void onClick(View view) {
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             Rect sourceBounds = Utilities.getViewBounds(view);
             new PackageManagerHelper(view.getContext()).startDetailsActivityForInfo(
                     mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
@@ -259,10 +260,8 @@
         @Override
         public void onClick(View view) {
             Intent intent =
-                    ApiWrapper.getAppMarketActivityIntent(
-                            view.getContext(),
-                            mItemInfo.getTargetComponent().getPackageName(),
-                            mSpaceUser);
+                    ApiWrapper.INSTANCE.get(view.getContext()).getAppMarketActivityIntent(
+                            mItemInfo.getTargetComponent().getPackageName(), mSpaceUser);
             mTarget.startActivitySafely(view, intent, mItemInfo);
             AbstractFloatingView.closeAllOpenViews(mTarget);
             mTarget.getStatsLogManager()
@@ -303,9 +302,8 @@
 
         @Override
         public void onClick(View view) {
-            Intent intent = ApiWrapper.getAppMarketActivityIntent(view.getContext(),
-                    mItemInfo.getTargetComponent().getPackageName(),
-                    Process.myUserHandle());
+            Intent intent = ApiWrapper.INSTANCE.get(view.getContext()).getAppMarketActivityIntent(
+                    mItemInfo.getTargetComponent().getPackageName(), Process.myUserHandle());
             mTarget.startActivitySafely(view, intent, mItemInfo);
             AbstractFloatingView.closeAllOpenViews(mTarget);
         }
@@ -327,7 +325,7 @@
 
         @Override
         public void onClick(View view) {
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             mTarget.getStatsLogManager().logger()
                     .withItemInfo(mItemInfo)
                     .log(LAUNCHER_SYSTEM_SHORTCUT_DONT_SUGGEST_APP_TAP);
@@ -370,7 +368,7 @@
 
         @Override
         public void onClick(View view) {
-            dismissTaskMenuView(mTarget);
+            dismissTaskMenuView();
             SecondaryDropTarget.performUninstall(view.getContext(), mComponentName, mItemInfo);
             mTarget.getStatsLogManager()
                     .logger()
@@ -379,8 +377,8 @@
         }
     }
 
-    public static <T extends ActivityContext> void dismissTaskMenuView(T activity) {
-        AbstractFloatingView.closeOpenViews(activity, true,
+    protected void dismissTaskMenuView() {
+        mAbstractFloatingViewHelper.closeOpenViews(mTarget, true,
                 AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
     }
 }
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index 1f15947..b992a92 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -152,7 +152,12 @@
             }
 
             ShortcutInfo info = infoBuilder.build();
-            if (!PinRequestHelper.createRequestForShortcut(context, info).accept()) {
+            try {
+                if (!PinRequestHelper.createRequestForShortcut(context, info).accept()) {
+                    deletedShortcuts.add(lc.id);
+                    continue;
+                }
+            } catch (Exception e) {
                 deletedShortcuts.add(lc.id);
                 continue;
             }
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index 22bc13b..d702e51 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -18,6 +18,7 @@
 
 import static android.os.Process.myUserHandle;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.Flags.enableLauncherBrMetricsFixed;
 import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
 import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
@@ -50,8 +51,10 @@
 import androidx.annotation.VisibleForTesting;
 import androidx.annotation.WorkerThread;
 
+import com.android.launcher3.Flags;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherFiles;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.LauncherSettings.Favorites;
@@ -62,13 +65,12 @@
 import com.android.launcher3.model.DeviceGridState;
 import com.android.launcher3.model.LoaderTask;
 import com.android.launcher3.model.ModelDbController;
-import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.ContentWriter;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.LogConfig;
@@ -121,7 +123,51 @@
         // executed again.
         LauncherPrefs.get(context).removeSync(RESTORE_DEVICE);
 
-        idp.reinitializeAfterRestore(context);
+        if (Flags.enableNarrowGridRestore()) {
+            String oldPhoneFileName = idp.dbFile;
+            removeOldDBs(context, oldPhoneFileName);
+            // The idp before this contains data about the old phone, after this it becomes the idp
+            // of the current phone.
+            idp.reset(context);
+            trySettingPreviousGidAsCurrent(context, idp, oldPhoneFileName);
+        } else {
+            idp.reinitializeAfterRestore(context);
+        }
+    }
+
+    /**
+     * Try setting the gird used in the previous phone to the new one. If the current device doesn't
+     * support the previous grid option it will not be set.
+     */
+    private static void trySettingPreviousGidAsCurrent(Context context, InvariantDeviceProfile idp,
+            String oldPhoneDbFileName) {
+        InvariantDeviceProfile.GridOption gridOption = idp.getGridOptionFromFileName(context,
+                oldPhoneDbFileName);
+        if (gridOption != null) {
+            /*
+             * We do this because in some cases different devices have different names for grid
+             * options, in one device the grid option "normal" can be 4x4 while in other it
+             * could be "practical". Calling this changes the current device grid to the same
+             * we had in the other phone, in the case the current phone doesn't support the grid
+             * option we use the default and migrate the db to the default. Migration occurs on
+             * {@code GridSizeMigrationUtil#migrateGridIfNeeded}
+             */
+            idp.setCurrentGrid(context, gridOption.name);
+        }
+    }
+
+    /**
+     * Only keep the last database used on the previous device.
+     */
+    private static void removeOldDBs(Context context, String oldPhoneDbFileName) {
+        // At this point idp.dbFile contains the name of the dbFile from the previous phone
+        LauncherFiles.GRID_DB_FILES.stream()
+                .filter(dbName -> !dbName.equals(oldPhoneDbFileName))
+                .forEach(dbName -> {
+                    if (context.getDatabasePath(dbName).delete()) {
+                        FileLog.d(TAG, "Removed old grid db file: " + dbName);
+                    }
+                });
     }
 
     private static boolean performRestore(Context context, ModelDbController controller) {
@@ -385,7 +431,7 @@
     private void restoreAppWidgetIds(Context context, ModelDbController controller,
             LauncherRestoreEventLogger launcherRestoreEventLogger, int[] oldWidgetIds,
             int[] newWidgetIds, @NonNull AppWidgetHost host) {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             FileLog.e(TAG, "Skipping widget ID remap as widgets not supported");
             host.deleteHost();
             launcherRestoreEventLogger.logFavoritesItemsRestoreFailed(Favorites.ITEM_TYPE_APPWIDGET,
@@ -413,7 +459,7 @@
         logDatabaseWidgetInfo(controller);
 
         for (int i = 0; i < oldWidgetIds.length; i++) {
-            FileLog.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
+            FileLog.i(TAG, "migrating appWidgetId: " + oldWidgetIds[i] + " => " + newWidgetIds[i]);
 
             final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]);
             final int state;
@@ -514,9 +560,8 @@
 
     protected static void maybeOverrideShortcuts(Context context, ModelDbController controller,
             SQLiteDatabase db, long currentUser) {
-        Map<String, LauncherActivityInfo> activityOverrides = ApiWrapper.getActivityOverrides(
-                context);
-
+        Map<String, LauncherActivityInfo> activityOverrides =
+                ApiWrapper.INSTANCE.get(context).getActivityOverrides();
         if (activityOverrides == null || activityOverrides.isEmpty()) {
             return;
         }
diff --git a/src/com/android/launcher3/search/StringMatcherUtility.java b/src/com/android/launcher3/search/StringMatcherUtility.java
index 28fc4f0..7446314 100644
--- a/src/com/android/launcher3/search/StringMatcherUtility.java
+++ b/src/com/android/launcher3/search/StringMatcherUtility.java
@@ -18,6 +18,8 @@
 
 import android.text.TextUtils;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.util.IntArray;
 
 import java.text.Collator;
@@ -120,7 +122,11 @@
         /**
          * Returns true if {@param query} is a prefix of {@param target}
          */
-        public boolean matches(String query, String target) {
+        public boolean matches(@Nullable String query, @Nullable String target) {
+            // `mCollator.compare` requires non-null inputs, so return false earlier (not a match)
+            if (query == null || target == null) {
+                return false;
+            }
             switch (mCollator.compare(query, target)) {
                 case 0:
                     return true;
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 910b029..0299a23 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -200,11 +200,6 @@
     }
 
     @Override
-    public <T extends View> T getOverviewPanel() {
-        return null;
-    }
-
-    @Override
     public View getRootView() {
         return mDragLayer;
     }
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index a5f9c2a..c10d85e 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -52,7 +52,6 @@
 import com.android.launcher3.BuildConfig;
 import com.android.launcher3.LauncherFiles;
 import com.android.launcher3.R;
-import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.states.RotationHelper;
 import com.android.launcher3.uioverrides.flags.DeveloperOptionsUI;
 import com.android.launcher3.util.DisplayController;
@@ -238,7 +237,7 @@
         protected boolean initPreference(Preference preference) {
             switch (preference.getKey()) {
                 case NOTIFICATION_DOTS_PREFERENCE_KEY:
-                    return !WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS;
+                    return BuildConfig.NOTIFICATION_DOTS_ENABLED;
 
                 case ALLOW_ROTATION_PREFERENCE_KEY:
                     DisplayController.Info info =
diff --git a/src/com/android/launcher3/shortcuts/ShortcutRequest.java b/src/com/android/launcher3/shortcuts/ShortcutRequest.java
index 21efceb..015d54d 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutRequest.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutRequest.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.shortcuts;
 
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 
 import android.content.ComponentName;
 import android.content.Context;
@@ -47,7 +47,7 @@
             | ShortcutQuery.FLAG_MATCH_MANIFEST;
     public static final int PINNED = ShortcutQuery.FLAG_MATCH_PINNED;
 
-    private final ShortcutQuery mQuery = GO_DISABLE_WIDGETS ? null : new ShortcutQuery();
+    private final ShortcutQuery mQuery = !WIDGETS_ENABLED ? null : new ShortcutQuery();
 
     private final Context mContext;
     private final UserHandle mUserHandle;
@@ -74,7 +74,7 @@
      * @return A list of ShortcutInfo's associated with the given package.
      */
     public ShortcutRequest forPackage(String packageName, @Nullable List<String> shortcutIds) {
-        if (!GO_DISABLE_WIDGETS && packageName != null) {
+        if (WIDGETS_ENABLED && packageName != null) {
             mQuery.setPackage(packageName);
             mQuery.setShortcutIds(shortcutIds);
         }
@@ -82,7 +82,7 @@
     }
 
     public ShortcutRequest withContainer(@Nullable ComponentName activity) {
-        if (!GO_DISABLE_WIDGETS) {
+        if (WIDGETS_ENABLED) {
             if (activity == null) {
                 mFailed = true;
             } else {
@@ -93,7 +93,7 @@
     }
 
     public QueryResult query(int flags) {
-        if (GO_DISABLE_WIDGETS || mFailed) {
+        if (!WIDGETS_ENABLED || mFailed) {
             return QueryResult.DEFAULT;
         }
         mQuery.setQueryFlags(flags);
@@ -109,7 +109,7 @@
 
     public static class QueryResult extends ArrayList<ShortcutInfo> {
 
-        static final QueryResult DEFAULT = new QueryResult(GO_DISABLE_WIDGETS);
+        static final QueryResult DEFAULT = new QueryResult(!WIDGETS_ENABLED);
 
         private final boolean mWasSuccess;
 
diff --git a/src/com/android/launcher3/states/EditModeState.kt b/src/com/android/launcher3/states/EditModeState.kt
index aafaaa0..6ff47ae 100644
--- a/src/com/android/launcher3/states/EditModeState.kt
+++ b/src/com/android/launcher3/states/EditModeState.kt
@@ -16,6 +16,7 @@
 package com.android.launcher3.states
 
 import android.content.Context
+import com.android.launcher3.Flags.enableScalingRevealHomeAnimation
 import com.android.launcher3.Launcher
 import com.android.launcher3.LauncherState
 import com.android.launcher3.logging.StatsLogManager
@@ -25,6 +26,8 @@
 class EditModeState(id: Int) : LauncherState(id, StatsLogManager.LAUNCHER_STATE_HOME, STATE_FLAGS) {
 
     companion object {
+        const val DEPTH_15_PERCENT = 0.15f
+
         private val STATE_FLAGS =
             (FLAG_MULTI_PAGE or
                 FLAG_WORKSPACE_INACCESSIBLE or
@@ -40,7 +43,11 @@
     }
 
     override fun <T> getDepthUnchecked(context: T): Float where T : Context?, T : ActivityContext? {
-        return 0.5f
+        if (enableScalingRevealHomeAnimation()) {
+            return DEPTH_15_PERCENT
+        } else {
+            return 0.5f
+        }
     }
 
     override fun getWorkspaceScaleAndTranslation(launcher: Launcher): ScaleAndTranslation {
diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java
index 4cfced8..bf2fb30 100644
--- a/src/com/android/launcher3/states/HintState.java
+++ b/src/com/android/launcher3/states/HintState.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.states;
 
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 
 import android.content.Context;
@@ -34,6 +35,8 @@
     private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_DISABLE_RESTORE
             | FLAG_HAS_SYS_UI_SCRIM;
 
+    public static final float DEPTH_5_PERCENT = 0.05f;
+
     public HintState(int id) {
         this(id, LAUNCHER_STATE_HOME);
     }
@@ -49,7 +52,11 @@
 
     @Override
     protected float getDepthUnchecked(Context context) {
-        return 0.15f;
+        if (enableScalingRevealHomeAnimation()) {
+            return DEPTH_5_PERCENT;
+        } else {
+            return 0.15f;
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index 6950fb5..fdb37f0 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -35,6 +35,7 @@
 import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.BaseActivity;
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.util.DisplayController;
 
@@ -42,6 +43,7 @@
  * Utility class to manage launcher rotation
  */
 public class RotationHelper implements OnSharedPreferenceChangeListener,
+        DeviceProfile.OnDeviceProfileChangeListener,
         DisplayController.DisplayInfoChangeListener {
 
     public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
@@ -119,10 +121,24 @@
         }
     }
 
+    /**
+     * Listening to both onDisplayInfoChanged and onDeviceProfileChanged to reduce delay. While
+     * onDeviceProfileChanged is triggered earlier, it only receives callback when Launcher is in
+     * the foreground. When in the background, we can still rely on onDisplayInfoChanged to update,
+     * assuming that the delay is tolerable since it takes time to change to foreground.
+     */
     @Override
     public void onDisplayInfoChanged(Context context, DisplayController.Info info, int flags) {
+        onIgnoreAutoRotateChanged(info.isTablet(info.realBounds));
+    }
+
+    @Override
+    public void onDeviceProfileChanged(DeviceProfile dp) {
+        onIgnoreAutoRotateChanged(dp.isTablet);
+    }
+
+    private void onIgnoreAutoRotateChanged(boolean ignoreAutoRotateSettings) {
         if (mDestroyed) return;
-        boolean ignoreAutoRotateSettings = info.isTablet(info.realBounds);
         if (mIgnoreAutoRotateSettings != ignoreAutoRotateSettings) {
             setIgnoreAutoRotateSettings(ignoreAutoRotateSettings);
             notifyChange();
@@ -161,12 +177,14 @@
         DisplayController.Info info = displayController.getInfo();
         setIgnoreAutoRotateSettings(info.isTablet(info.realBounds));
         displayController.addChangeListener(this);
+        mActivity.addOnDeviceProfileChangeListener(this);
         notifyChange();
     }
 
     public void destroy() {
         if (mDestroyed) return;
         mDestroyed = true;
+        mActivity.removeOnDeviceProfileChangeListener(this);
         DisplayController.INSTANCE.get(mActivity).removeChangeListener(this);
         LauncherPrefs.get(mActivity).removeListener(this, ALLOW_ROTATION);
     }
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 3286afb..2e57ed8 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.states;
 
+import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 
 import android.content.Context;
@@ -33,6 +34,8 @@
             | FLAG_WORKSPACE_INACCESSIBLE | FLAG_DISABLE_RESTORE
             | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_WORKSPACE_HAS_BACKGROUNDS;
 
+    public static final float DEPTH_15_PERCENT = 0.15f;
+
     public SpringLoadedState(int id) {
         super(id, LAUNCHER_STATE_HOME, STATE_FLAGS);
     }
@@ -62,7 +65,11 @@
 
     @Override
     protected float getDepthUnchecked(Context context) {
-        return 0.5f;
+        if (enableScalingRevealHomeAnimation()) {
+            return DEPTH_15_PERCENT;
+        } else {
+            return 0.5f;
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 07df7af..d5c9b9f 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -19,43 +19,60 @@
 import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
 import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
+import static com.android.launcher3.config.FeatureFlags.enableAppPairs;
 import static com.android.launcher3.config.FeatureFlags.enableSplitContextually;
 import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
-import static com.android.launcher3.config.FeatureFlags.enableAppPairs;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
 import android.app.Activity;
+import android.app.Application;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Insets;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.os.Binder;
 import android.os.Bundle;
+import android.system.Os;
 import android.view.WindowInsets;
 
+import androidx.annotation.Keep;
 import androidx.annotation.Nullable;
 import androidx.core.view.WindowInsetsCompat;
 
+import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.R;
+import com.android.launcher3.ShortcutAndWidgetContainer;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.icons.ClockDrawableWrapper;
 import com.android.launcher3.testing.shared.HotseatCellCenterRequest;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.testing.shared.WorkspaceCellCenterRequest;
+import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
 import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.ResourceBasedOverride;
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+import java.util.WeakHashMap;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
@@ -69,6 +86,12 @@
                 context, R.string.test_information_handler_class);
     }
 
+    private static Collection<String> sEvents;
+    private static Application.ActivityLifecycleCallbacks sActivityLifecycleCallbacks;
+    private static final Set<Activity> sActivities =
+            Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));
+    private static int sActivitiesCreatedCount = 0;
+
     protected Context mContext;
     protected DeviceProfile mDeviceProfile;
     protected LauncherAppState mLauncherAppState;
@@ -78,6 +101,17 @@
         mDeviceProfile = InvariantDeviceProfile.INSTANCE.
                 get(context).getDeviceProfile(context);
         mLauncherAppState = LauncherAppState.getInstanceNoCreate();
+        if (sActivityLifecycleCallbacks == null) {
+            sActivityLifecycleCallbacks = new ActivityLifecycleCallbacksAdapter() {
+                @Override
+                public void onActivityCreated(Activity activity, Bundle bundle) {
+                    sActivities.add(activity);
+                    ++sActivitiesCreatedCount;
+                }
+            };
+            ((Application) context.getApplicationContext())
+                    .registerActivityLifecycleCallbacks(sActivityLifecycleCallbacks);
+        }
     }
 
     /**
@@ -183,7 +217,10 @@
             case TestProtocol.REQUEST_IS_TABLET:
                 response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, mDeviceProfile.isTablet);
                 return response;
-
+            case TestProtocol.REQUEST_IS_PREDICTIVE_BACK_SWIPE_ENABLED:
+                response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+                        mDeviceProfile.isPredictiveBackSwipe);
+                return response;
             case TestProtocol.REQUEST_ENABLE_TASKBAR_NAVBAR_UNIFICATION:
                 response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
                         ENABLE_TASKBAR_NAVBAR_UNIFICATION);
@@ -306,6 +343,127 @@
                 return response;
             }
 
+            case TestProtocol.REQUEST_APP_LIST_FREEZE_FLAGS: {
+                return getLauncherUIProperty(Bundle::putInt,
+                        l -> l.getAppsView().getAppsStore().getDeferUpdatesFlags());
+            }
+
+            case TestProtocol.REQUEST_ENABLE_DEBUG_TRACING:
+                TestProtocol.sDebugTracing = true;
+                ClockDrawableWrapper.sRunningInTest = true;
+                return response;
+
+            case TestProtocol.REQUEST_DISABLE_DEBUG_TRACING:
+                TestProtocol.sDebugTracing = false;
+                ClockDrawableWrapper.sRunningInTest = false;
+                return response;
+
+            case TestProtocol.REQUEST_PID: {
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, Os.getpid());
+                return response;
+            }
+
+            case TestProtocol.REQUEST_FORCE_GC: {
+                runGcAndFinalizersSync();
+                return response;
+            }
+
+            case TestProtocol.REQUEST_START_EVENT_LOGGING: {
+                sEvents = new ArrayList<>();
+                TestLogging.setEventConsumer(
+                        (sequence, event) -> {
+                            final Collection<String> events = sEvents;
+                            if (events != null) {
+                                synchronized (events) {
+                                    events.add(sequence + '/' + event);
+                                }
+                            }
+                        });
+                return response;
+            }
+
+            case TestProtocol.REQUEST_STOP_EVENT_LOGGING: {
+                TestLogging.setEventConsumer(null);
+                sEvents = null;
+                return response;
+            }
+
+            case TestProtocol.REQUEST_GET_TEST_EVENTS: {
+                if (sEvents == null) {
+                    // sEvents can be null if Launcher died and restarted after
+                    // REQUEST_START_EVENT_LOGGING.
+                    return response;
+                }
+
+                synchronized (sEvents) {
+                    response.putStringArrayList(
+                            TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents));
+                }
+                return response;
+            }
+
+            case TestProtocol.REQUEST_REINITIALIZE_DATA: {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    MODEL_EXECUTOR.execute(() -> {
+                        LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
+                        model.getModelDbController().createEmptyDB();
+                        MAIN_EXECUTOR.execute(model::forceReload);
+                    });
+                    return response;
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+
+            case TestProtocol.REQUEST_CLEAR_DATA: {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    MODEL_EXECUTOR.execute(() -> {
+                        LauncherModel model = LauncherAppState.getInstance(mContext).getModel();
+                        model.getModelDbController().createEmptyDB();
+                        model.getModelDbController().clearEmptyDbFlag();
+                        MAIN_EXECUTOR.execute(model::forceReload);
+                    });
+                    return response;
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+
+            case TestProtocol.REQUEST_HOTSEAT_ICON_NAMES: {
+                return getLauncherUIProperty(Bundle::putStringArrayList, l -> {
+                    ShortcutAndWidgetContainer hotseatIconsContainer =
+                            l.getHotseat().getShortcutsAndWidgets();
+                    ArrayList<String> hotseatIconNames = new ArrayList<>();
+
+                    for (int i = 0; i < hotseatIconsContainer.getChildCount(); i++) {
+                        // Use unchecked cast to catch changes in hotseat layout
+                        BubbleTextView icon = (BubbleTextView) hotseatIconsContainer.getChildAt(i);
+                        hotseatIconNames.add((String) icon.getText());
+                    }
+
+                    return hotseatIconNames;
+                });
+            }
+
+            case TestProtocol.REQUEST_GET_ACTIVITIES_CREATED_COUNT: {
+                response.putInt(TestProtocol.TEST_INFO_RESPONSE_FIELD, sActivitiesCreatedCount);
+                return response;
+            }
+
+            case TestProtocol.REQUEST_GET_ACTIVITIES: {
+                response.putStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+                        sActivities.stream().map(
+                                        a -> a.getClass().getSimpleName() + " ("
+                                                + (a.isDestroyed() ? "destroyed" : "current") + ")")
+                                .toArray(String[]::new));
+                return response;
+            }
+
+            case TestProtocol.REQUEST_MODEL_QUEUE_CLEARED:
+                return getFromExecutorSync(MODEL_EXECUTOR, Bundle::new);
+
             default:
                 return null;
         }
@@ -384,4 +542,38 @@
          */
         void set(Bundle b, String key, T value);
     }
+
+
+    private static void runGcAndFinalizersSync() {
+        Runtime.getRuntime().gc();
+        Runtime.getRuntime().runFinalization();
+
+        final CountDownLatch fence = new CountDownLatch(1);
+        createFinalizationObserver(fence);
+        try {
+            do {
+                Runtime.getRuntime().gc();
+                Runtime.getRuntime().runFinalization();
+            } while (!fence.await(100, TimeUnit.MILLISECONDS));
+        } catch (InterruptedException ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    // Create the observer in the scope of a method to minimize the chance that
+    // it remains live in a DEX/machine register at the point of the fence guard.
+    // This must be kept to avoid R8 inlining it.
+    @Keep
+    private static void createFinalizationObserver(CountDownLatch fence) {
+        new Object() {
+            @Override
+            protected void finalize() throws Throwable {
+                try {
+                    fence.countDown();
+                } finally {
+                    super.finalize();
+                }
+            }
+        };
+    }
 }
diff --git a/src/com/android/launcher3/testing/TestLogging.java b/src/com/android/launcher3/testing/TestLogging.java
index 60d0e95..459fa07 100644
--- a/src/com/android/launcher3/testing/TestLogging.java
+++ b/src/com/android/launcher3/testing/TestLogging.java
@@ -62,7 +62,14 @@
 
     public static void recordKeyEvent(String sequence, String message, KeyEvent event) {
         if (Utilities.isRunningInTestHarness()) {
-            recordEventSlow(sequence, message + ": " + event, true);
+            // This removes expecting ACTION_DOWN key event in the test. ACTION_UP is
+            // always preceded by ACTION_DOWN.
+            // Sometimes test doesn't receive ACTION_DOWN key event and we will assume that
+            // Launcher relies only on ACTION_UP.
+            // However in the test we will send both ACTION_DOWN and ACTION_UP key events.
+            // But stop reporting to tapl if action is down.
+            boolean reportToTapl = event.getAction() != KeyEvent.ACTION_DOWN;
+            recordEventSlow(sequence, message + ": " + event, reportToTapl);
             registerEventNotFromTest(event);
         }
     }
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index de24be7..2a9ebbd 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -64,7 +64,7 @@
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.uioverrides.ApiWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.views.FloatingIconView;
 import com.android.launcher3.views.Snackbar;
@@ -158,20 +158,27 @@
                             ? R.string.app_pair_needs_unfold
                             : R.string.app_pair_unlaunchable_at_screen_size,
                     Toast.LENGTH_SHORT).show();
+            return;
         } else if (appPairIcon.getInfo().isDisabled()) {
             WorkspaceItemInfo app1 = appPairIcon.getInfo().getFirstApp();
             WorkspaceItemInfo app2 = appPairIcon.getInfo().getSecondApp();
             // Show the user why the app pair is disabled.
-            if (app1.isDisabled() && !handleDisabledItemClicked(app1, launcher)) {
-                // If handleDisabledItemClicked() did not handle the error message, we initiate an
-                // app launch so Framework can tell the user why the app is suspended.
-                onClickAppShortcut(v, app1, launcher);
-            } else if (app2.isDisabled() && !handleDisabledItemClicked(app2, launcher)) {
-                onClickAppShortcut(v, app2, launcher);
+            if (app1.isDisabled() && app2.isDisabled()) {
+                // Both apps are disabled, show "app pair is not available" toast.
+                Toast.makeText(launcher, R.string.app_pair_not_available, Toast.LENGTH_SHORT)
+                        .show();
+                return;
+            } else if ((app1.isDisabled() && handleDisabledItemClicked(app1, launcher))
+                    || (app2.isDisabled() && handleDisabledItemClicked(app2, launcher))) {
+                // Only one is disabled, and handleDisabledItemClicked() will show a toast, so we
+                // are done.
+                return;
             }
-        } else {
-            launcher.launchAppPair(appPairIcon);
         }
+
+        // Either the app pair is not disabled, or it is a disabled state that can be handled by
+        // framework directly (e.g. one app is paused), so go ahead and launch.
+        launcher.launchAppPair(appPairIcon);
     }
 
     /**
@@ -228,7 +235,7 @@
                 }
             }
             // Fallback to using custom market intent.
-            Intent intent = ApiWrapper.getAppMarketActivityIntent(launcher,
+            Intent intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent(
                     packageName, Process.myUserHandle());
             launcher.startActivitySafely(v, intent, item);
         };
@@ -366,12 +373,12 @@
         if (item instanceof ItemInfoWithIcon itemInfoWithIcon) {
             if ((itemInfoWithIcon.runtimeStatusFlags
                     & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
-                intent = ApiWrapper.getAppMarketActivityIntent(launcher,
+                intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent(
                         itemInfoWithIcon.getTargetComponent().getPackageName(),
                         Process.myUserHandle());
-            } else if ((itemInfoWithIcon.runtimeStatusFlags
-                    & ItemInfoWithIcon.FLAG_PRIVATE_SPACE_INSTALL_APP) != 0) {
-                intent = ApiWrapper.getAppMarketActivityIntent(launcher,
+            } else if (itemInfoWithIcon.itemType
+                    == LauncherSettings.Favorites.ITEM_TYPE_PRIVATE_SPACE_INSTALL_APP_BUTTON) {
+                intent = ApiWrapper.INSTANCE.get(launcher).getAppMarketActivityIntent(
                         BuildConfig.APPLICATION_ID,
                         launcher.getAppsView().getPrivateProfileManager().getProfileUser());
                 launcher.getStatsLogManager().logger().log(
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index 116f13a..89057a2 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -39,6 +39,7 @@
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.PrivateSpaceInstallAppButtonInfo;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.views.BubbleTextHolder;
@@ -150,7 +151,10 @@
         if (launcher.getWorkspace().isSwitchingState()) return false;
 
         StatsLogger logger = launcher.getStatsLogManager().logger();
-        if (v.getTag() instanceof ItemInfo) {
+        if (v.getTag() instanceof ItemInfo itemInfo) {
+            if (itemInfo instanceof PrivateSpaceInstallAppButtonInfo) {
+                return false;
+            }
             logger.withItemInfo((ItemInfo) v.getTag());
         }
         logger.log(LAUNCHER_ALLAPPS_ITEM_LONG_PRESSED);
diff --git a/src/com/android/launcher3/util/ActivityTracker.java b/src/com/android/launcher3/util/ActivityTracker.java
index 405d2bb..95a0511 100644
--- a/src/com/android/launcher3/util/ActivityTracker.java
+++ b/src/com/android/launcher3/util/ActivityTracker.java
@@ -18,10 +18,13 @@
 import static com.android.launcher3.testing.shared.TestProtocol.GET_FROM_RECENTS_FAILURE;
 import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
 
+import android.util.Log;
+
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.BaseActivity;
 
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -31,6 +34,8 @@
  */
 public final class ActivityTracker<T extends BaseActivity> {
 
+    private static final String TAG = "ActivityTracker";
+
     private WeakReference<T> mCurrentActivity = new WeakReference<>(null);
     private CopyOnWriteArrayList<SchedulerCallback<T>> mCallbacks = new CopyOnWriteArrayList<>();
 
@@ -57,12 +62,13 @@
      *
      * @param callback The callback to call init() on when the activity is ready.
      */
-    public void registerCallback(SchedulerCallback<T> callback) {
+    public void registerCallback(SchedulerCallback<T> callback, String reasonString) {
+        Log.d(TAG, "Registering callback: " + callback + ", reason=" + reasonString);
         T activity = mCurrentActivity.get();
         mCallbacks.add(callback);
         if (activity != null) {
             if (!callback.init(activity, activity.isStarted())) {
-                unregisterCallback(callback);
+                unregisterCallback(callback, "ActivityTracker.registerCallback: Intent handled");
             }
         }
     }
@@ -70,7 +76,8 @@
     /**
      * Unregisters a registered callback.
      */
-    public void unregisterCallback(SchedulerCallback<T> callback) {
+    public void unregisterCallback(SchedulerCallback<T> callback, String reasonString) {
+        Log.d(TAG, "Unregistering callback: " + callback + ", reason=" + reasonString);
         mCallbacks.remove(callback);
     }
 
@@ -87,16 +94,25 @@
 
     private boolean handleIntent(T activity, boolean alreadyOnHome) {
         boolean handled = false;
+        if (!mCallbacks.isEmpty()) {
+            Log.d(TAG, "handleIntent: mCallbacks=" + mCallbacks);
+        }
         for (SchedulerCallback<T> cb : mCallbacks) {
             if (!cb.init(activity, alreadyOnHome)) {
                 // Callback doesn't want any more updates
-                unregisterCallback(cb);
+                unregisterCallback(cb, "ActivityTracker.handleIntent: Intent handled");
             }
             handled = true;
         }
         return handled;
     }
 
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(prefix + "ActivityTracker:");
+        writer.println(prefix + "\tmCurrentActivity=" + mCurrentActivity.get());
+        writer.println(prefix + "\tmCallbacks=" + mCallbacks);
+    }
+
     public interface SchedulerCallback<T extends BaseActivity> {
 
         /**
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java b/src/com/android/launcher3/util/ApiWrapper.java
similarity index 65%
rename from src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
rename to src/com/android/launcher3/util/ApiWrapper.java
index efde7d8..6429a43 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/ApiWrapper.java
+++ b/src/com/android/launcher3/util/ApiWrapper.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.launcher3.uioverrides;
+package com.android.launcher3.util;
+
+import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
 
 import android.app.ActivityOptions;
 import android.app.Person;
@@ -28,10 +30,12 @@
 import android.os.UserManager;
 import android.util.ArrayMap;
 
-import com.android.launcher3.Utilities;
-import com.android.launcher3.util.UserIconInfo;
+import androidx.annotation.Nullable;
 
-import java.util.ArrayList;
+import com.android.launcher3.BuildConfig;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -39,30 +43,40 @@
 /**
  * A wrapper for the hidden API calls
  */
-public class ApiWrapper {
+public class ApiWrapper implements ResourceBasedOverride, SafeCloseable {
 
-    public static final boolean TASKBAR_DRAWN_IN_PROCESS = false;
+    public static final MainThreadInitializedObject<ApiWrapper> INSTANCE =
+            forOverride(ApiWrapper.class, R.string.api_wrapper_class);
 
-    public static Person[] getPersons(ShortcutInfo si) {
+    protected final Context mContext;
+
+    public ApiWrapper(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Returns the list of persons associated with the provided shortcut info
+     */
+    public Person[] getPersons(ShortcutInfo si) {
         return Utilities.EMPTY_PERSON_ARRAY;
     }
 
-    public static Map<String, LauncherActivityInfo> getActivityOverrides(Context context) {
+    public Map<String, LauncherActivityInfo> getActivityOverrides() {
         return Collections.emptyMap();
     }
 
     /**
      * Creates an ActivityOptions to play fade-out animation on closing targets
      */
-    public static ActivityOptions createFadeOutAnimOptions(Context context) {
-        return ActivityOptions.makeCustomAnimation(context, 0, android.R.anim.fade_out);
+    public ActivityOptions createFadeOutAnimOptions() {
+        return ActivityOptions.makeCustomAnimation(mContext, 0, android.R.anim.fade_out);
     }
 
     /**
      * Returns a map of all users on the device to their corresponding UI properties
      */
-    public static Map<UserHandle, UserIconInfo> queryAllUsers(Context context) {
-        UserManager um = context.getSystemService(UserManager.class);
+    public Map<UserHandle, UserIconInfo> queryAllUsers() {
+        UserManager um = mContext.getSystemService(UserManager.class);
         Map<UserHandle, UserIconInfo> users = new ArrayMap<>();
         List<UserHandle> usersActual = um.getUserProfiles();
         if (usersActual != null) {
@@ -72,7 +86,7 @@
                 // Simple check to check if the provided user is work profile
                 // TODO: Migrate to a better platform API
                 NoopDrawable d = new NoopDrawable();
-                boolean isWork = (d != context.getPackageManager().getUserBadgedIcon(d, user));
+                boolean isWork = (d != mContext.getPackageManager().getUserBadgedIcon(d, user));
                 UserIconInfo info = new UserIconInfo(
                         user,
                         isWork ? UserIconInfo.TYPE_WORK : UserIconInfo.TYPE_MAIN,
@@ -87,16 +101,15 @@
      * Returns the list of the system packages that are installed at user creation.
      * An empty list denotes that all system packages are installed for that user at creation.
      */
-    public static List<String> getPreInstalledSystemPackages(Context context, UserHandle user) {
-        return new ArrayList<>();
+    public List<String> getPreInstalledSystemPackages(UserHandle user) {
+        return Collections.emptyList();
     }
 
     /**
      * Returns an intent which can be used to start the App Market activity (Installer
      * Activity).
      */
-    public static Intent getAppMarketActivityIntent(Context context, String packageName,
-            UserHandle user) {
+    public Intent getAppMarketActivityIntent(String packageName, UserHandle user) {
         return new Intent(Intent.ACTION_VIEW)
                 .setData(new Uri.Builder()
                         .scheme("market")
@@ -104,17 +117,27 @@
                         .appendQueryParameter("id", packageName)
                         .build())
                 .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
-                        .authority(context.getPackageName()).build());
+                        .authority(BuildConfig.APPLICATION_ID).build());
+    }
+
+    /**
+     * Returns an intent which can be used to open Private Space Settings.
+     */
+    @Nullable
+    public Intent getPrivateSpaceSettingsIntent() {
+        return null;
     }
 
     /**
      * Checks if an activity is flagged as non-resizeable.
      */
-    public static boolean isNonResizeableActivity(LauncherActivityInfo lai) {
+    public boolean isNonResizeableActivity(LauncherActivityInfo lai) {
         // Overridden in quickstep
         return false;
     }
 
+    @Override
+    public void close() { }
 
     private static class NoopDrawable extends ColorDrawable {
         @Override
diff --git a/src/com/android/launcher3/util/GridOccupancy.java b/src/com/android/launcher3/util/GridOccupancy.java
index 43e486c..f248e58 100644
--- a/src/com/android/launcher3/util/GridOccupancy.java
+++ b/src/com/android/launcher3/util/GridOccupancy.java
@@ -7,7 +7,7 @@
 /**
  * Utility object to manage the occupancy in a grid.
  */
-public class GridOccupancy extends AbsGridOccupancy {
+public class GridOccupancy {
 
     private final int mCountX;
     private final int mCountY;
@@ -30,7 +30,24 @@
      * @return true if a vacant cell was found
      */
     public boolean findVacantCell(int[] vacantOut, int spanX, int spanY) {
-        return super.findVacantCell(vacantOut, cells, mCountX, mCountY, spanX, spanY);
+        for (int y = 0; (y + spanY) <= mCountY; y++) {
+            for (int x = 0; (x + spanX) <= mCountX; x++) {
+                boolean available = !cells[x][y];
+                out:
+                for (int i = x; i < x + spanX; i++) {
+                    for (int j = y; j < y + spanY; j++) {
+                        available = available && !cells[i][j];
+                        if (!available) break out;
+                    }
+                }
+                if (available) {
+                    vacantOut[0] = x;
+                    vacantOut[1] = y;
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     public void copyTo(GridOccupancy dest) {
diff --git a/src/com/android/launcher3/util/LogConfig.java b/src/com/android/launcher3/util/LogConfig.java
index e5bbcb1..d59c339 100644
--- a/src/com/android/launcher3/util/LogConfig.java
+++ b/src/com/android/launcher3/util/LogConfig.java
@@ -65,4 +65,9 @@
      * When turned on, we enable AGA related session summary logging.
      */
     public static final String AGA_SESSION_SUMMARY_LOG = "AGASessionSummaryLog";
+
+    /**
+     * When turned on, we enable long press nav handle related logging.
+     */
+    public static final String NAV_HANDLE_LONG_PRESS = "NavHandleLongPress";
 }
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.kt b/src/com/android/launcher3/util/OnboardingPrefs.kt
index 4528cba..370b4c8 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.kt
+++ b/src/com/android/launcher3/util/OnboardingPrefs.kt
@@ -75,4 +75,8 @@
 
     @JvmField
     val HOTSEAT_LONGPRESS_TIP_SEEN = backedUpItem("launcher.hotseat_longpress_tip_seen", false)
+
+    @JvmField
+    val TASKBAR_CIRCLE_TO_SEARCH_EDU_SEEN =
+        backedUpItem("launcher.taskbar_circle_to_search_edu_seen", false)
 }
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 851c795..608bed7 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3.util;
 
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
+
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
@@ -47,9 +49,7 @@
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.uioverrides.ApiWrapper;
 
-import java.net.URISyntaxException;
 import java.util.List;
 import java.util.Objects;
 
@@ -108,6 +108,7 @@
     /**
      * Returns whether the target app is archived for a given user
      */
+    @SuppressWarnings("NewApi")
     public boolean isAppArchivedForUser(@NonNull final String packageName,
             @NonNull final UserHandle user) {
         if (!Flags.enableSupportForArchiving()) {
@@ -167,30 +168,12 @@
     }
 
     /**
-     * Creates a new market search intent.
-     */
-    public static Intent getMarketSearchIntent(Context context, String query) {
-        try {
-            Intent intent = Intent.parseUri(context.getString(R.string.market_search_intent), 0);
-            if (!TextUtils.isEmpty(query)) {
-                intent.setData(
-                        intent.getData().buildUpon().appendQueryParameter("q", query).build());
-            }
-            return intent;
-        } catch (URISyntaxException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
      * Starts the details activity for {@code info}
      */
     public void startDetailsActivityForInfo(ItemInfo info, Rect sourceBounds, Bundle opts) {
-        if (info instanceof ItemInfoWithIcon
-                && (((ItemInfoWithIcon) info).runtimeStatusFlags
-                & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
-            ItemInfoWithIcon appInfo = (ItemInfoWithIcon) info;
-            mContext.startActivity(ApiWrapper.getAppMarketActivityIntent(mContext,
+        if (info instanceof ItemInfoWithIcon appInfo
+                && (appInfo.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
+            mContext.startActivity(ApiWrapper.INSTANCE.get(mContext).getAppMarketActivityIntent(
                     appInfo.getTargetComponent().getPackageName(), Process.myUserHandle()));
             return;
         }
diff --git a/src/com/android/launcher3/util/ResourceBasedOverride.java b/src/com/android/launcher3/util/ResourceBasedOverride.java
index e2c4992..36b9cf7 100644
--- a/src/com/android/launcher3/util/ResourceBasedOverride.java
+++ b/src/com/android/launcher3/util/ResourceBasedOverride.java
@@ -34,16 +34,20 @@
         public static <T extends ResourceBasedOverride> T getObject(
                 Class<T> clazz, Context context, int resId) {
             String className = context.getString(resId);
-            if (!TextUtils.isEmpty(className)) {
-                try {
-                    Class<?> cls = Class.forName(className);
-                    return (T) cls.getDeclaredConstructor(Context.class).newInstance(context);
-                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
-                        | ClassCastException | NoSuchMethodException | InvocationTargetException e) {
+            boolean isOverridden = !TextUtils.isEmpty(className);
+
+            // First try to load the class with "Context" param
+            try {
+                Class<?> cls = isOverridden ? Class.forName(className) : clazz;
+                return (T) cls.getDeclaredConstructor(Context.class).newInstance(context);
+            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+                     | ClassCastException | NoSuchMethodException | InvocationTargetException e) {
+                if (isOverridden) {
                     Log.e(TAG, "Bad overriden class", e);
                 }
             }
 
+            // Load the base class with no parameter
             try {
                 return clazz.newInstance();
             } catch (InstantiationException|IllegalAccessException e) {
diff --git a/src/com/android/launcher3/util/ShortcutUtil.java b/src/com/android/launcher3/util/ShortcutUtil.java
index 91cf835..07b7941 100644
--- a/src/com/android/launcher3/util/ShortcutUtil.java
+++ b/src/com/android/launcher3/util/ShortcutUtil.java
@@ -15,9 +15,10 @@
  */
 package com.android.launcher3.util;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
+
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutKey;
@@ -34,7 +35,7 @@
      * Returns true when we should show depp shortcuts in shortcut menu for the item.
      */
     public static boolean supportsDeepShortcuts(ItemInfo info) {
-        return isActive(info) && isApp(info) && !WidgetsModel.GO_DISABLE_WIDGETS;
+        return isActive(info) && isApp(info) && !!WIDGETS_ENABLED;
     }
 
     /**
diff --git a/src/com/android/launcher3/util/VibratorWrapper.java b/src/com/android/launcher3/util/VibratorWrapper.java
index e1695e9..cd60c1d 100644
--- a/src/com/android/launcher3/util/VibratorWrapper.java
+++ b/src/com/android/launcher3/util/VibratorWrapper.java
@@ -19,11 +19,6 @@
 import static android.os.VibrationEffect.createPredefined;
 import static android.provider.Settings.System.HAPTIC_FEEDBACK_ENABLED;
 
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_DELAY;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_END_SCALE_PERCENT;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_ITERATIONS;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_SCALE_EXPONENT;
-import static com.android.launcher3.config.FeatureFlags.LPNH_HAPTIC_HINT_START_SCALE_PERCENT;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
@@ -40,7 +35,6 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
 
 /**
  * Wrapper around {@link Vibrator} to easily perform haptic feedback where necessary.
@@ -71,9 +65,6 @@
     @Nullable
     private final VibrationEffect mBumpEffect;
 
-    @Nullable
-    private final VibrationEffect mSearchEffect;
-
     private long mLastDragTime;
     private final int mThresholdUntilNextDragCallMillis;
 
@@ -133,25 +124,6 @@
             mBumpEffect = null;
             mThresholdUntilNextDragCallMillis = 0;
         }
-
-        if (mVibrator.areAllPrimitivesSupported(
-                VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
-                VibrationEffect.Composition.PRIMITIVE_TICK)) {
-            if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get()) {
-                mSearchEffect = VibrationEffect.startComposition()
-                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f)
-                        .compose();
-            } else {
-                // quiet ramp, short pause, then sharp tick
-                mSearchEffect = VibrationEffect.startComposition()
-                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE, 0.25f)
-                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1f, 50)
-                        .compose();
-            }
-        } else {
-            // fallback for devices without composition support
-            mSearchEffect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK);
-        }
     }
 
     /**
@@ -233,13 +205,6 @@
         }
     }
 
-    /** Indicates that search has been invoked. */
-    public void vibrateForSearch() {
-        if (mSearchEffect != null) {
-            vibrate(mSearchEffect);
-        }
-    }
-
     /** Indicates that Taskbar has been invoked. */
     public void vibrateForTaskbarUnstash() {
         if (Utilities.ATLEAST_S && mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
@@ -251,32 +216,4 @@
             vibrate(primitiveLowTickEffect);
         }
     }
-
-    /** Indicates that search will be invoked if the current gesture is maintained. */
-    public void vibrateForSearchHint() {
-        if (FeatureFlags.ENABLE_SEARCH_HAPTIC_HINT.get() && Utilities.ATLEAST_S
-                && mVibrator.areAllPrimitivesSupported(PRIMITIVE_LOW_TICK)) {
-            float startScale = LPNH_HAPTIC_HINT_START_SCALE_PERCENT.get() / 100f;
-            float endScale = LPNH_HAPTIC_HINT_END_SCALE_PERCENT.get() / 100f;
-            int scaleExponent = LPNH_HAPTIC_HINT_SCALE_EXPONENT.get();
-            int iterations = LPNH_HAPTIC_HINT_ITERATIONS.get();
-            int delayMs = LPNH_HAPTIC_HINT_DELAY.get();
-
-            VibrationEffect.Composition composition = VibrationEffect.startComposition();
-            for (int i = 0; i < iterations; i++) {
-                float t = i / (iterations - 1f);
-                float scale = (float) Math.pow((1 - t) * startScale + t * endScale,
-                        scaleExponent);
-                if (i == 0) {
-                    // Adds a delay before the ramp starts
-                    composition.addPrimitive(PRIMITIVE_LOW_TICK, scale,
-                            delayMs);
-                } else {
-                    composition.addPrimitive(PRIMITIVE_LOW_TICK, scale);
-                }
-            }
-
-            vibrate(composition.compose());
-        }
-    }
 }
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 4a906d3..998191e 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -94,6 +94,13 @@
     }
 
     /**
+     * Returns true if taskbar is drawn in process
+     */
+    public boolean isTaskbarDrawnInProcess() {
+        return mTaskbarDrawnInProcess;
+    }
+
+    /**
      * Returns a map of normalized info of internal displays to estimated window bounds
      * for that display
      */
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index 30e0971..9f6e8f8 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -82,7 +82,6 @@
             };
     protected static final float TRANSLATION_SHIFT_CLOSED = 1f;
     protected static final float TRANSLATION_SHIFT_OPENED = 0f;
-    private static final float VIEW_NO_SCALE = 1f;
     private static final int DEFAULT_DURATION = 300;
 
     protected final T mActivityContext;
@@ -129,9 +128,13 @@
     protected @Nullable OnCloseListener mOnCloseBeginListener;
     protected List<OnCloseListener> mOnCloseListeners = new ArrayList<>();
 
-    protected final AnimatedFloat mSlideInViewScale =
-            new AnimatedFloat(this::onScaleProgressChanged, VIEW_NO_SCALE);
-    protected boolean mIsBackProgressing;
+    /**
+     * How far through a "user initiated dismissal" the UI is. e.g. Predictive back, swipe to home,
+     * 0 is regular state, 1 is fully dismissed.
+     */
+    protected final AnimatedFloat mSwipeToDismissProgress =
+            new AnimatedFloat(this::onUserSwipeToDismissProgressChanged, 0f);
+    protected boolean mIsDismissInProgress;
     private @Nullable Drawable mContentBackground;
     private @Nullable View mContentBackgroundParentView;
 
@@ -285,35 +288,31 @@
     @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     public void onBackProgressed(BackEvent backEvent) {
         final float progress = backEvent.getProgress();
-        float deceleratedProgress =
-                Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
-        mIsBackProgressing = progress > 0f;
-        mSlideInViewScale.updateValue(PREDICTIVE_BACK_MIN_SCALE
-                + (1 - PREDICTIVE_BACK_MIN_SCALE) * (1 - deceleratedProgress));
+        float deceleratedProgress = Interpolators.BACK_GESTURE.getInterpolation(progress);
+        mSwipeToDismissProgress.updateValue(deceleratedProgress);
     }
 
-    protected void onScaleProgressChanged() {
-        float scaleProgress = mSlideInViewScale.value;
-        SCALE_PROPERTY.set(this, scaleProgress);
-        setClipChildren(!mIsBackProgressing);
-        mContent.setClipChildren(!mIsBackProgressing);
+    protected void onUserSwipeToDismissProgressChanged() {
+        float progress = mSwipeToDismissProgress.value;
+        mIsDismissInProgress = progress > 0f;
+
+        float scale = PREDICTIVE_BACK_MIN_SCALE + (1 - PREDICTIVE_BACK_MIN_SCALE) * (1f - progress);
+        SCALE_PROPERTY.set(this, scale);
+        setClipChildren(!mIsDismissInProgress);
+        setClipToPadding(!mIsDismissInProgress);
+        mContent.setClipChildren(!mIsDismissInProgress);
+        mContent.setClipToPadding(!mIsDismissInProgress);
         invalidate();
     }
 
     @Override
-    public void onBackInvoked() {
-        super.onBackInvoked();
-        animateSlideInViewToNoScale();
-    }
-
-    @Override
     public void onBackCancelled() {
         super.onBackCancelled();
-        animateSlideInViewToNoScale();
+        animateSwipeToDismissProgressToStart();
     }
 
-    protected void animateSlideInViewToNoScale() {
-        mSlideInViewScale.animateToValue(1f)
+    protected void animateSwipeToDismissProgressToStart() {
+        mSwipeToDismissProgress.animateToValue(0f)
                 .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS)
                 .start();
     }
@@ -344,15 +343,14 @@
                 mContentBackgroundParentView.getTop() + (int) mContent.getTranslationY(),
                 mContentBackgroundParentView.getRight(),
                 mContentBackgroundParentView.getBottom()
-                        + (mIsBackProgressing ? getBottomOffsetPx() : 0));
+                        + (mIsDismissInProgress ? getBottomOffsetPx() : 0));
         mContentBackground.draw(canvas);
     }
 
     /** Return extra space revealed during predictive back animation. */
     @Px
     protected int getBottomOffsetPx() {
-        final int height = getMeasuredHeight();
-        return (int) ((height / PREDICTIVE_BACK_MIN_SCALE - height) / 2);
+        return (int) (getMeasuredHeight() * (1 - PREDICTIVE_BACK_MIN_SCALE));
     }
 
     /**
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 31f5d65..bf43a22 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -17,12 +17,12 @@
 
 import static android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.LauncherSettings.Animation.DEFAULT_NO_ICON;
 import static com.android.launcher3.Utilities.allowBGLaunch;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_KEYBOARD_CLOSED;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_PENDING_INTENT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
-import static com.android.launcher3.model.WidgetsModel.GO_DISABLE_WIDGETS;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
@@ -389,7 +389,7 @@
         boolean isShortcut = (item instanceof WorkspaceItemInfo)
                 && item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
                 && !((WorkspaceItemInfo) item).isPromise();
-        if (isShortcut && GO_DISABLE_WIDGETS) {
+        if (isShortcut && !WIDGETS_ENABLED) {
             return null;
         }
         ActivityOptionsWrapper options = v != null ? getActivityLaunchOptions(v, item)
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index c60e1a4..cab7982 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.views;
 
+import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.views.FloatingIconView.getLocationBoundsForView;
 import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
 
@@ -159,7 +160,7 @@
         if (mContract == null) {
             return;
         }
-        View icon = mLauncher.getFirstMatchForAppClose(-1,
+        View icon = mLauncher.getFirstMatchForAppClose(NO_MATCHING_ID,
                 mContract.componentName.getPackageName(), mContract.user,
                 false /* supportsAllAppsState */);
 
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 5cdad03..62eed5c 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -17,6 +17,7 @@
 
 import static androidx.core.content.ContextCompat.getColorStateList;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.LauncherState.EDIT_MODE;
 import static com.android.launcher3.config.FeatureFlags.MULTI_SELECT_EDIT_MODE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
@@ -47,7 +48,6 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.logging.StatsLogManager.EventEnum;
-import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.popup.ArrowPopup;
 import com.android.launcher3.shortcuts.DeepShortcutView;
@@ -207,7 +207,7 @@
                 R.drawable.ic_palette,
                 IGNORE,
                 OptionsPopupView::startWallpaperPicker));
-        if (!WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (WIDGETS_ENABLED) {
             options.add(new OptionItem(launcher,
                     R.string.widget_button_text,
                     R.drawable.ic_widget,
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index ca80c51..f6c4984 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -26,6 +26,7 @@
 import android.view.View;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Px;
 import androidx.core.graphics.ColorUtils;
 
 import com.android.launcher3.BaseActivity;
@@ -187,9 +188,19 @@
      * A Utility interface allowing for other surfaces to draw on ScrimView
      */
     public interface ScrimDrawingController {
-        /**
-         * Called inside ScrimView#OnDraw
-         */
-        void drawOnScrimWithScale(Canvas canvas, float scale);
+
+        /** Draw scrim view on canvas with scale. */
+        default void drawOnScrimWithScale(Canvas canvas, float scale) {
+            drawOnScrimWithScaleAndBottomOffset(canvas, scale, 0);
+        }
+
+        /** Draw scrim view on canvas with bottomOffset. */
+        default void drawOnScrimWithBottomOffset(Canvas canvas, @Px int bottomOffsetPx) {
+            drawOnScrimWithScaleAndBottomOffset(canvas, 1f, bottomOffsetPx);
+        }
+
+        /** Draw scrim view on canvas with scale and bottomOffset. */
+        void drawOnScrimWithScaleAndBottomOffset(
+                Canvas canvas, float scale, @Px int bottomOffsetPx);
     }
 }
diff --git a/src/com/android/launcher3/views/WidgetsEduView.java b/src/com/android/launcher3/views/WidgetsEduView.java
index 40c6115..53fbd8f 100644
--- a/src/com/android/launcher3/views/WidgetsEduView.java
+++ b/src/com/android/launcher3/views/WidgetsEduView.java
@@ -59,6 +59,7 @@
         mContent = findViewById(R.id.edu_view);
         findViewById(R.id.edu_close_button)
                 .setOnClickListener(v -> close(/* animate= */ true));
+        setContentBackgroundWithParent(mContent.getBackground(), mContent);
     }
 
     @Override
@@ -68,6 +69,12 @@
                 mContent.getPaddingTop(), mContent.getPaddingEnd(), insets.bottom);
     }
 
+    @Override
+    protected void onUserSwipeToDismissProgressChanged() {
+        super.onUserSwipeToDismissProgressChanged();
+        setTranslationY(getMeasuredHeight() * (mSwipeToDismissProgress.value / 2));
+    }
+
     private void show() {
         attachToContainer();
         animateOpen();
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 54ce973..c17ae09 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -18,7 +18,9 @@
 import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
 import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
+import static com.android.launcher3.Flags.enableWidgetTapToAdd;
 import static com.android.launcher3.LauncherPrefs.WIDGETS_EDUCATION_TIP_SEEN;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_ADD_BUTTON_TAP;
 
 import android.content.Context;
 import android.graphics.Canvas;
@@ -31,6 +33,7 @@
 import android.view.WindowInsets;
 import android.view.animation.Interpolator;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.Px;
 import androidx.core.view.ViewCompat;
@@ -41,6 +44,7 @@
 import com.android.launcher3.Insettable;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.PendingAddItemInfo;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.popup.PopupDataProvider;
@@ -52,6 +56,8 @@
 import com.android.launcher3.views.AbstractSlideInView;
 import com.android.launcher3.views.ArrowTipView;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 /**
  * Base class for various widgets popup
  */
@@ -73,6 +79,8 @@
 
     private boolean mDisableNavBarScrim = false;
 
+    @Nullable private WidgetCell mWidgetCellWithAddButton = null;
+
     public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         mContentHorizontalMargin = getWidgetListHorizontalMargin();
@@ -123,13 +131,62 @@
 
     @Override
     public final void onClick(View v) {
-        if (v instanceof WidgetCell) {
-            mActivityContext.getItemOnClickListener().onClick(v);
-        } else if (v.getParent() instanceof WidgetCell wc) {
+        WidgetCell wc;
+        if (v instanceof WidgetCell view) {
+            wc = view;
+        }  else if (v.getParent() instanceof WidgetCell parent) {
+            wc = parent;
+        } else {
+            return;
+        }
+
+        if (enableWidgetTapToAdd()) {
+            if (mWidgetCellWithAddButton != null) {
+                // If there is a add button currently showing, hide it.
+                mWidgetCellWithAddButton.hideAddButton(/* animate= */ true);
+            }
+
+            if (mWidgetCellWithAddButton != wc) {
+                // If click is on a cell not showing an add button, show it now.
+                final PendingAddItemInfo info = (PendingAddItemInfo) wc.getTag();
+                if (mActivityContext instanceof Launcher) {
+                    wc.showAddButton((view) -> addWidget(info));
+                } else {
+                    wc.showAddButton((view) -> mActivityContext.getItemOnClickListener()
+                            .onClick(wc));
+                }
+            }
+
+            mWidgetCellWithAddButton = mWidgetCellWithAddButton != wc ? wc : null;
+        } else {
             mActivityContext.getItemOnClickListener().onClick(wc);
         }
     }
 
+    /**
+     * Click handler for tap to add button.
+     */
+    private void addWidget(@NonNull PendingAddItemInfo info) {
+        // Using a boolean flag here to make sure the callback is only run once. This should never
+        // happen because we close the sheet and it will be reconstructed the next time it is
+        // needed.
+        final AtomicBoolean hasRun = new AtomicBoolean(false);
+        addOnCloseListener(() -> {
+            if (!hasRun.get()) {
+                Launcher.getLauncher(mActivityContext).getAccessibilityDelegate().addToWorkspace(
+                        info, /*accessibility=*/ false,
+                        /*finishCallback=*/ (success) -> {
+                            mActivityContext.getStatsLogManager()
+                                    .logger()
+                                    .withItemInfo(info)
+                                    .log(LAUNCHER_WIDGET_ADD_BUTTON_TAP);
+                        });
+                hasRun.set(true);
+            }
+        });
+        handleClose(true);
+    }
+
     @Override
     public boolean onLongClick(View v) {
         TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "Widgets.onLongClick");
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index 2259e3c..c3e9ad6 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -92,6 +92,8 @@
 
     private boolean mTrackingWidgetUpdate = false;
 
+    private int mFocusRectOutsets = 0;
+
     public LauncherAppWidgetHostView(Context context) {
         super(context);
         mActivityContext = ActivityContext.lookupContext(context);
@@ -100,6 +102,8 @@
         setBackgroundResource(R.drawable.widget_internal_focus_bg);
         if (Flags.enableFocusOutline()) {
             setDefaultFocusHighlightEnabled(false);
+            mFocusRectOutsets = context.getResources().getDimensionPixelSize(
+                    R.dimen.focus_rect_widget_outsets);
         }
 
         if (Themes.getAttrBoolean(context, R.attr.isWorkspaceDarkText)) {
@@ -269,6 +273,13 @@
     }
 
     @Override
+    public void getFocusedRect(Rect r) {
+        super.getFocusedRect(r);
+        // Outset to a larger rect for drawing a padding between focus outline and widget
+        r.inset(mFocusRectOutsets, mFocusRectOutsets);
+    }
+
+    @Override
     public void onTouchComplete() {
         if (!mLongPressHelper.hasPerformedLongPress()) {
             // If a long press has been performed, we don't want to clear the record of that since
diff --git a/src/com/android/launcher3/widget/LauncherWidgetHolder.java b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
index 2fcf8c5..a5e22c5 100644
--- a/src/com/android/launcher3/widget/LauncherWidgetHolder.java
+++ b/src/com/android/launcher3/widget/LauncherWidgetHolder.java
@@ -17,6 +17,7 @@
 
 import static android.app.Activity.RESULT_CANCELED;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
 import static com.android.launcher3.Flags.enableWorkspaceInflation;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.fromProviderInfo;
@@ -40,7 +41,6 @@
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
@@ -100,7 +100,7 @@
      * Starts listening to the widget updates from the server side
      */
     public void startListening() {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return;
         }
 
@@ -177,7 +177,7 @@
      * @return The allocated app widget id if allocation is successful, returns -1 otherwise
      */
     public int allocateAppWidgetId() {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return AppWidgetManager.INVALID_APPWIDGET_ID;
         }
 
@@ -210,7 +210,7 @@
      */
     public void startConfigActivity(@NonNull BaseDraggingActivity activity, int widgetId,
             int requestCode) {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             sendActionCancelled(activity, requestCode);
             return;
         }
@@ -261,7 +261,7 @@
      */
     public void startBindFlow(@NonNull BaseActivity activity,
             int appWidgetId, @NonNull AppWidgetProviderInfo info, int requestCode) {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             sendActionCancelled(activity, requestCode);
             return;
         }
@@ -279,7 +279,7 @@
      * Stop the host from listening to the widget updates
      */
     public void stopListening() {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return;
         }
         mWidgetHost.stopListening();
@@ -349,7 +349,13 @@
     @NonNull
     public final AppWidgetHostView attachViewToHostAndGetAttachedView(
             @NonNull LauncherAppWidgetHostView view) {
-        if (mViews.get(view.getAppWidgetId()) != view) {
+
+        // Binder can also inflate placeholder widgets in case of backup-restore. Skip
+        // attaching such widgets
+        boolean isRealWidget = ((view instanceof PendingAppWidgetHostView pw)
+                ? pw.isDeferredWidget() : true)
+                && view.getAppWidgetInfo() != null;
+        if (isRealWidget && mViews.get(view.getAppWidgetId()) != view) {
             view = recycleExistingView(view);
             mViews.put(view.getAppWidgetId(), view);
         }
diff --git a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
index 86400ba..9c9b80d 100644
--- a/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/PendingAppWidgetHostView.java
@@ -29,9 +29,11 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -76,6 +78,10 @@
 
     private final Rect mRect = new Rect();
 
+    private final Matrix mMatrix = new Matrix();
+    private final RectF mPreviewBitmapRect = new RectF();
+    private final RectF mCanvasRect = new RectF();
+
     private final LauncherWidgetHolder mWidgetHolder;
     private final LauncherAppWidgetProviderInfo mAppwidget;
     private final LauncherAppWidgetInfo mInfo;
@@ -103,9 +109,14 @@
 
     public PendingAppWidgetHostView(Context context, LauncherWidgetHolder widgetHolder,
             LauncherAppWidgetInfo info, @Nullable LauncherAppWidgetProviderInfo appWidget) {
-        this(context, widgetHolder, info, appWidget,
-                context.getResources().getText(R.string.gadget_complete_setup_text));
+        this(context, widgetHolder, info, appWidget, null);
+    }
 
+    public PendingAppWidgetHostView(Context context, LauncherWidgetHolder widgetHolder,
+            LauncherAppWidgetInfo info, @Nullable LauncherAppWidgetProviderInfo appWidget,
+            @Nullable Bitmap previewBitmap) {
+        this(context, widgetHolder, info, appWidget,
+                context.getResources().getText(R.string.gadget_complete_setup_text), previewBitmap);
         super.updateAppWidget(null);
         setOnClickListener(mActivityContext.getItemOnClickListener());
 
@@ -123,7 +134,7 @@
             Context context, LauncherWidgetHolder widgetHolder,
             int appWidgetId, @NonNull LauncherAppWidgetProviderInfo appWidget) {
         this(context, widgetHolder, new LauncherAppWidgetInfo(appWidgetId, appWidget.provider),
-                appWidget, appWidget.label);
+                appWidget, appWidget.label, null);
         getBackground().mutate().setAlpha(DEFERRED_ALPHA);
 
         mCenterDrawable = new ColorDrawable(Color.TRANSPARENT);
@@ -132,8 +143,12 @@
         mIsDeferredWidget = true;
     }
 
-    /** Set {@link Bitmap} of widget preview. */
-    public void setPreviewBitmap(@Nullable Bitmap previewBitmap) {
+    /**
+     * Set {@link Bitmap} of widget preview and update background drawable. When showing preview
+     * bitmap, we shouldn't draw background.
+     */
+    public void setPreviewBitmapAndUpdateBackground(@Nullable Bitmap previewBitmap) {
+        setBackgroundResource(previewBitmap != null ? 0 : R.drawable.pending_widget_bg);
         if (this.mPreviewBitmap == previewBitmap) {
             return;
         }
@@ -143,7 +158,8 @@
 
     private PendingAppWidgetHostView(Context context,
             LauncherWidgetHolder widgetHolder, LauncherAppWidgetInfo info,
-            LauncherAppWidgetProviderInfo appwidget, CharSequence label) {
+            LauncherAppWidgetProviderInfo appwidget, CharSequence label,
+            @Nullable Bitmap previewBitmap) {
         super(new ContextThemeWrapper(context, R.style.WidgetContainerTheme));
         mWidgetHolder = widgetHolder;
         mAppwidget = appwidget;
@@ -161,7 +177,7 @@
         mPreviewPaint = new Paint(ANTI_ALIAS_FLAG | DITHER_FLAG | FILTER_BITMAP_FLAG);
 
         setWillNotDraw(false);
-        setBackgroundResource(R.drawable.pending_widget_bg);
+        setPreviewBitmapAndUpdateBackground(previewBitmap);
     }
 
     @Override
@@ -440,7 +456,11 @@
     protected void onDraw(Canvas canvas) {
         if (mPreviewBitmap != null
                 && (mInfo.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0) {
-            canvas.drawBitmap(mPreviewBitmap, 0, 0, mPreviewPaint);
+            mPreviewBitmapRect.set(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
+            mCanvasRect.set(0, 0, getWidth(), getHeight());
+
+            mMatrix.setRectToRect(mPreviewBitmapRect, mCanvasRect, Matrix.ScaleToFit.CENTER);
+            canvas.drawBitmap(mPreviewBitmap, mMatrix, mPreviewPaint);
             return;
         }
         if (mCenterDrawable == null) {
@@ -463,7 +483,6 @@
             mSetupTextLayout.draw(canvas);
             canvas.restore();
         }
-
     }
 
     /**
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index f2f83c8..ab007fb 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -18,6 +18,7 @@
 
 import static android.appwidget.AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN;
 
+import static com.android.launcher3.Flags.enableWidgetTapToAdd;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY;
 import static com.android.launcher3.widget.LauncherAppWidgetProviderInfo.fromProviderInfo;
 import static com.android.launcher3.widget.util.WidgetSizes.getWidgetItemSizePx;
@@ -25,7 +26,6 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
-import android.os.Process;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -36,8 +36,8 @@
 import android.view.ViewGroup;
 import android.view.ViewPropertyAnimator;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.Button;
 import android.widget.FrameLayout;
-import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.RemoteViews;
 import android.widget.TextView;
@@ -57,6 +57,8 @@
 import com.android.launcher3.model.data.PackageItemInfo;
 import com.android.launcher3.util.CancellableTask;
 import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize;
+import com.android.launcher3.widget.util.WidgetSizes;
 
 import java.util.function.Consumer;
 
@@ -75,18 +77,20 @@
     private static final boolean DEBUG = false;
 
     private static final int FADE_IN_DURATION_MS = 90;
+    private static final int ADD_BUTTON_FADE_DURATION_MS = 300;
 
     /**
      * The requested scale of the preview container. It can be lower than this as well.
      */
     private float mPreviewContainerScale = 1f;
-
+    private Size mPreviewContainerSize = new Size(0, 0);
     private FrameLayout mWidgetImageContainer;
     private WidgetImageView mWidgetImage;
-    private ImageView mWidgetBadge;
     private TextView mWidgetName;
     private TextView mWidgetDims;
     private TextView mWidgetDescription;
+    private Button mWidgetAddButton;
+    private LinearLayout mWidgetTextContainer;
 
     private WidgetItem mItem;
     private Size mWidgetSize;
@@ -135,10 +139,14 @@
 
         mWidgetImageContainer = findViewById(R.id.widget_preview_container);
         mWidgetImage = findViewById(R.id.widget_preview);
-        mWidgetBadge = findViewById(R.id.widget_badge);
         mWidgetName = findViewById(R.id.widget_name);
         mWidgetDims = findViewById(R.id.widget_dims);
         mWidgetDescription = findViewById(R.id.widget_description);
+        mWidgetTextContainer = findViewById(R.id.widget_text_container);
+        mWidgetAddButton = findViewById(R.id.widget_add_button);
+        if (enableWidgetTapToAdd()) {
+            mWidgetAddButton.setVisibility(INVISIBLE);
+        }
     }
 
     public void setRemoteViewsPreview(RemoteViews view) {
@@ -170,12 +178,16 @@
         mWidgetImage.animate().cancel();
         mWidgetImage.setDrawable(null);
         mWidgetImage.setVisibility(View.VISIBLE);
-        mWidgetBadge.setImageDrawable(null);
-        mWidgetBadge.setVisibility(View.GONE);
         mWidgetName.setText(null);
         mWidgetDims.setText(null);
         mWidgetDescription.setText(null);
         mWidgetDescription.setVisibility(GONE);
+        showDescription(true);
+        showDimensions(true);
+
+        if (enableWidgetTapToAdd()) {
+            hideAddButton(/* animate= */ false);
+        }
 
         if (mActiveRequest != null) {
             mActiveRequest.cancel();
@@ -186,6 +198,7 @@
             mWidgetImageContainer.removeView(mAppWidgetHostViewPreview);
         }
         mAppWidgetHostViewPreview = null;
+        mPreviewContainerSize = new Size(0, 0);
         mAppWidgetHostViewScale = 1f;
         mPreviewContainerScale = 1f;
         mItem = null;
@@ -201,38 +214,25 @@
      * Applies the item to this view
      */
     public void applyFromCellItem(WidgetItem item) {
-        applyFromCellItem(item, 1f);
-    }
-
-    /**
-     * Applies the item to this view
-     */
-    public void applyFromCellItem(WidgetItem item, float previewScale) {
-        applyFromCellItem(item, previewScale, this::applyPreview, null);
+        applyFromCellItem(item, this::applyPreview, /*cachedPreview=*/null);
     }
 
     /**
      * Applies the item to this view
      * @param item item to apply
-     * @param previewScale factor to scale the preview
      * @param callback callback when preview is loaded in case the preview is being loaded or cached
      * @param cachedPreview previously cached preview bitmap is present
      */
-    public void applyFromCellItem(WidgetItem item, float previewScale,
-            @NonNull Consumer<Bitmap> callback, @Nullable Bitmap cachedPreview) {
-        mPreviewContainerScale = previewScale;
-
+    public void applyFromCellItem(WidgetItem item, @NonNull Consumer<Bitmap> callback,
+            @Nullable Bitmap cachedPreview) {
         Context context = getContext();
         mItem = item;
         mWidgetSize = getWidgetItemSizePx(getContext(), mActivity.getDeviceProfile(), mItem);
+        initPreviewContainerSizeAndScale();
 
         mWidgetName.setText(mItem.label);
-        mWidgetName.setContentDescription(
-                context.getString(R.string.widget_preview_context_description, mItem.label));
         mWidgetDims.setText(context.getString(R.string.widget_dims_format,
                 mItem.spanX, mItem.spanY));
-        mWidgetDims.setContentDescription(context.getString(
-                R.string.widget_accessible_dims_format, mItem.spanX, mItem.spanY));
         if (!TextUtils.isEmpty(mItem.description)) {
             mWidgetDescription.setText(mItem.description);
             mWidgetDescription.setVisibility(VISIBLE);
@@ -240,6 +240,14 @@
             mWidgetDescription.setVisibility(GONE);
         }
 
+        // Setting the content description on the WidgetCell itself ensures that it remains
+        // screen reader focusable when the add button is showing and the text is hidden.
+        setContentDescription(createContentDescription(context));
+        if (mWidgetAddButton != null) {
+            mWidgetAddButton.setContentDescription(context.getString(
+                    R.string.widget_add_button_content_description, mItem.label));
+        }
+
         if (item.activityInfo != null) {
             setTag(new PendingAddShortcutInfo(item.activityInfo));
         } else {
@@ -278,6 +286,27 @@
         }
     }
 
+    private void initPreviewContainerSizeAndScale() {
+        WidgetPreviewContainerSize previewSize = WidgetPreviewContainerSize.Companion.forItem(mItem,
+                mActivity.getDeviceProfile());
+        mPreviewContainerSize = WidgetSizes.getWidgetSizePx(mActivity.getDeviceProfile(),
+                previewSize.spanX, previewSize.spanY);
+
+        float scaleX = (float) mPreviewContainerSize.getWidth() / mWidgetSize.getWidth();
+        float scaleY = (float) mPreviewContainerSize.getHeight() / mWidgetSize.getHeight();
+        mPreviewContainerScale = Math.min(scaleX, scaleY);
+    }
+
+    private String createContentDescription(Context context) {
+        String contentDescription =
+                context.getString(R.string.widget_preview_name_and_dims_content_description,
+                        mItem.label, mItem.spanX, mItem.spanY);
+        if (!TextUtils.isEmpty(mItem.description)) {
+            contentDescription += " " + mItem.description;
+        }
+        return contentDescription;
+    }
+
     private void setAppWidgetHostViewPreview(
             NavigableAppWidgetHostView appWidgetHostViewPreview,
             LauncherAppWidgetProviderInfo providerInfo,
@@ -362,17 +391,6 @@
         }
     }
 
-    /** Used to show the badge when the widget is in the recommended section
-     */
-    public void showBadge() {
-        if (Process.myUserHandle().equals(mItem.user)) {
-            mWidgetBadge.setVisibility(View.GONE);
-        } else {
-            mWidgetBadge.setVisibility(View.VISIBLE);
-            mWidgetBadge.setImageResource(R.drawable.ic_work_app_badge);
-        }
-    }
-
     /**
      * Shows or hides the long description displayed below each widget.
      *
@@ -384,6 +402,16 @@
     }
 
     /**
+     * Shows or hides the dimensions displayed below each widget.
+     *
+     * @param show a flag that shows the dimensions of the widget if {@code true}, hides it if
+     *             {@code false}.
+     */
+    public void showDimensions(boolean show) {
+        mWidgetDims.setVisibility(show ? VISIBLE : GONE);
+    }
+
+    /**
      * Set whether the app icon, for the app that provides the widget, should be shown next to the
      * title text of the widget.
      *
@@ -448,17 +476,22 @@
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         ViewGroup.LayoutParams containerLp = mWidgetImageContainer.getLayoutParams();
-
-        mAppWidgetHostViewScale = mPreviewContainerScale;
         int maxWidth = MeasureSpec.getSize(widthMeasureSpec);
-        containerLp.width = Math.round(mWidgetSize.getWidth() * mAppWidgetHostViewScale);
+
+        // mPreviewContainerScale ensures the needed scaling with respect to original widget size.
+        mAppWidgetHostViewScale = mPreviewContainerScale;
+        containerLp.width = mPreviewContainerSize.getWidth();
+        containerLp.height = mPreviewContainerSize.getHeight();
+
+        // If we don't have enough available width, scale the preview container to fit.
         if (containerLp.width > maxWidth) {
             containerLp.width = maxWidth;
-            mAppWidgetHostViewScale = (float) containerLp.width / mWidgetSize.getWidth();
+            mAppWidgetHostViewScale = (float) containerLp.width / mPreviewContainerSize.getWidth();
+            containerLp.height = Math.round(
+                    mPreviewContainerSize.getHeight() * mAppWidgetHostViewScale);
         }
-        containerLp.height = Math.round(mWidgetSize.getHeight() * mAppWidgetHostViewScale);
-        // No need to call mWidgetImageContainer.setLayoutParams as we are in measure pass
 
+        // No need to call mWidgetImageContainer.setLayoutParams as we are in measure pass
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
 
@@ -495,4 +528,55 @@
             mIconLoadRequest = null;
         }
     }
+
+    /**
+     * Show tap to add button.
+     * @param callback Callback to be set on the button.
+     */
+    public void showAddButton(View.OnClickListener callback) {
+        mWidgetAddButton.setAlpha(0F);
+        mWidgetAddButton.setVisibility(VISIBLE);
+        mWidgetAddButton.setOnClickListener(callback);
+        mWidgetAddButton.animate().cancel();
+        mWidgetAddButton.animate()
+                .alpha(1F)
+                .setDuration(ADD_BUTTON_FADE_DURATION_MS);
+
+        mWidgetTextContainer.animate().cancel();
+        mWidgetTextContainer.animate()
+                .alpha(0F)
+                .setDuration(ADD_BUTTON_FADE_DURATION_MS)
+                .withEndAction(() -> {
+                    mWidgetTextContainer.setVisibility(INVISIBLE);
+                });
+    }
+
+    /**
+     * Hide tap to add button.
+     */
+    public void hideAddButton(boolean animate) {
+        mWidgetAddButton.setOnClickListener(null);
+        mWidgetAddButton.animate().cancel();
+        mWidgetTextContainer.animate().cancel();
+
+        if (!animate) {
+            mWidgetAddButton.setVisibility(INVISIBLE);
+            mWidgetTextContainer.setVisibility(VISIBLE);
+            mWidgetTextContainer.setAlpha(1F);
+            return;
+        }
+
+        mWidgetAddButton.animate()
+                .alpha(0F)
+                .setDuration(ADD_BUTTON_FADE_DURATION_MS)
+                .withEndAction(() -> {
+                    mWidgetAddButton.setVisibility(INVISIBLE);
+                });
+
+        mWidgetTextContainer.setAlpha(0F);
+        mWidgetTextContainer.setVisibility(VISIBLE);
+        mWidgetTextContainer.animate()
+                .alpha(1F)
+                .setDuration(ADD_BUTTON_FADE_DURATION_MS);
+    }
 }
diff --git a/src/com/android/launcher3/widget/WidgetImageView.java b/src/com/android/launcher3/widget/WidgetImageView.java
index 11f4485..f332054 100644
--- a/src/com/android/launcher3/widget/WidgetImageView.java
+++ b/src/com/android/launcher3/widget/WidgetImageView.java
@@ -24,8 +24,6 @@
 import android.util.AttributeSet;
 import android.view.View;
 
-import com.android.launcher3.R;
-
 /**
  * View that draws a bitmap horizontally centered. If the image width is greater than the view
  * width, the image is scaled down appropriately.
@@ -33,8 +31,6 @@
 public class WidgetImageView extends View {
 
     private final RectF mDstRectF = new RectF();
-    private final int mBadgeMargin;
-
     private Drawable mDrawable;
 
     public WidgetImageView(Context context) {
@@ -47,9 +43,6 @@
 
     public WidgetImageView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-
-        mBadgeMargin = context.getResources()
-                .getDimensionPixelSize(R.dimen.profile_badge_margin);
     }
 
     /** Set the drawable to use for this view. */
@@ -82,15 +75,27 @@
     private void updateDstRectF() {
         float myWidth = getWidth();
         float myHeight = getHeight();
-        float bitmapWidth = mDrawable.getIntrinsicWidth();
+        final float bitmapWidth = mDrawable.getIntrinsicWidth();
+        final float bitmapHeight = mDrawable.getIntrinsicHeight();
+        final float bitmapAspectRatio = bitmapWidth / bitmapHeight;
+        final float containerAspectRatio = myWidth / myHeight;
 
-        final float scale = bitmapWidth > myWidth ? myWidth / bitmapWidth : 1;
-        float scaledWidth = bitmapWidth * scale;
-        float scaledHeight = mDrawable.getIntrinsicHeight() * scale;
+        // Scale by width if image has larger aspect ratio than the container else by height; and
+        // avoid cropping the previews
+        final float scale = bitmapAspectRatio > containerAspectRatio ? myWidth / bitmapWidth
+                : myHeight / bitmapHeight;
 
-        mDstRectF.left = (myWidth - scaledWidth) / 2;
-        mDstRectF.right = (myWidth + scaledWidth) / 2;
+        final float scaledWidth = bitmapWidth * scale;
+        final float scaledHeight = bitmapHeight * scale;
 
+        // Avoid cropping by checking bounds after scaling.
+        if (scaledWidth > myWidth) {
+            mDstRectF.left = 0;
+            mDstRectF.right = scaledWidth;
+        } else {
+            mDstRectF.left = (myWidth - scaledWidth) / 2;
+            mDstRectF.right = (myWidth + scaledWidth) / 2;
+        }
         if (scaledHeight > myHeight) {
             mDstRectF.top = 0;
             mDstRectF.bottom = scaledHeight;
diff --git a/src/com/android/launcher3/widget/WidgetInflater.kt b/src/com/android/launcher3/widget/WidgetInflater.kt
index dd50b71..271c9c2 100644
--- a/src/com/android/launcher3/widget/WidgetInflater.kt
+++ b/src/com/android/launcher3/widget/WidgetInflater.kt
@@ -17,11 +17,11 @@
 package com.android.launcher3.widget
 
 import android.content.Context
+import com.android.launcher3.BuildConfig
 import com.android.launcher3.Launcher
 import com.android.launcher3.LauncherAppState
 import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError
 import com.android.launcher3.logging.FileLog
-import com.android.launcher3.model.WidgetsModel
 import com.android.launcher3.model.data.LauncherAppWidgetInfo
 import com.android.launcher3.qsb.QsbContainerView
 
@@ -55,7 +55,7 @@
             // The widget id is not valid. Try to find the widget based on the provider info.
             appWidgetInfo = widgetHelper.findProvider(item.providerName, item.user)
             if (appWidgetInfo == null) {
-                if (WidgetsModel.GO_DISABLE_WIDGETS) {
+                if (!BuildConfig.WIDGETS_ENABLED) {
                     removalReason = "widgets are disabled on go device."
                     logReason = RestoreError.WIDGETS_DISABLED
                 } else {
diff --git a/src/com/android/launcher3/widget/WidgetManagerHelper.java b/src/com/android/launcher3/widget/WidgetManagerHelper.java
index 52767a4..d293d15 100644
--- a/src/com/android/launcher3/widget/WidgetManagerHelper.java
+++ b/src/com/android/launcher3/widget/WidgetManagerHelper.java
@@ -16,6 +16,8 @@
 
 package com.android.launcher3.widget;
 
+import static com.android.launcher3.BuildConfig.WIDGETS_ENABLED;
+
 import android.annotation.TargetApi;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -30,7 +32,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.RequiresApi;
 
-import com.android.launcher3.model.WidgetsModel;
+import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.util.PackageUserKey;
@@ -46,6 +48,7 @@
  */
 public class WidgetManagerHelper {
 
+    private static final String TAG = "WidgetManagerHelper";
     //TODO: replace this with OPTION_APPWIDGET_RESTORE_COMPLETED b/63667276
     public static final String WIDGET_OPTION_RESTORE_COMPLETED = "appWidgetRestoreCompleted";
 
@@ -60,6 +63,7 @@
     /**
      * @see AppWidgetManager#getAppWidgetInfo(int)
      */
+    @Nullable
     public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(
             int appWidgetId, ComponentName componentName) {
 
@@ -69,7 +73,14 @@
         }
 
         AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
-        return info == null ? null : LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
+        if (info == null) {
+            FileLog.w(TAG,
+                    "getLauncherAppWidgetInfo: AppWidgetManager returned null AppWidgetInfo for"
+                            + " appWidgetId=" + appWidgetId
+                            + ", componentName=" + componentName);
+            return null;
+        }
+        return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
     }
 
     /**
@@ -77,7 +88,7 @@
      */
     @TargetApi(Build.VERSION_CODES.O)
     public List<AppWidgetProviderInfo> getAllProviders(@Nullable PackageUserKey packageUser) {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return Collections.emptyList();
         }
 
@@ -102,7 +113,7 @@
      */
     public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info,
             Bundle options) {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return false;
         }
         if (appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
@@ -113,7 +124,7 @@
     }
 
     public LauncherAppWidgetProviderInfo findProvider(ComponentName provider, UserHandle user) {
-        if (WidgetsModel.GO_DISABLE_WIDGETS) {
+        if (!WIDGETS_ENABLED) {
             return null;
         }
         for (AppWidgetProviderInfo info :
@@ -129,17 +140,16 @@
      * Returns if a AppWidgetProvider has marked a widget restored
      */
     public boolean isAppWidgetRestored(int appWidgetId) {
-        return !WidgetsModel.GO_DISABLE_WIDGETS && mAppWidgetManager.getAppWidgetOptions(
-                appWidgetId).getBoolean(WIDGET_OPTION_RESTORE_COMPLETED);
+        return WIDGETS_ENABLED && mAppWidgetManager.getAppWidgetOptions(appWidgetId)
+                .getBoolean(WIDGET_OPTION_RESTORE_COMPLETED);
     }
 
 
     /**
      * Load RemoteViews preview for this provider if available.
      *
-     * @param info The provider info for the widget you want to preview.
+     * @param info           The provider info for the widget you want to preview.
      * @param widgetCategory The widget category for which you want to display previews.
-     *
      * @return Returns the widget preview that matches selected category, if available.
      */
     @Nullable
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index ceb0072..f1b80e4 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher3.widget;
 
-import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_BOTTOM_WIDGETS_TRAY;
 
 import android.content.Context;
@@ -119,6 +118,9 @@
         mContent = findViewById(R.id.widgets_bottom_sheet);
         setContentBackgroundWithParent(
                 getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet), mContent);
+        View scrollView = findViewById(R.id.widgets_table_scroll_view);
+        scrollView.setOutlineProvider(mViewOutlineProvider);
+        scrollView.setClipToOutline(true);
     }
 
     @Override
@@ -188,13 +190,7 @@
                 mWidgetCellHorizontalPadding)
                 .forEach(row -> {
                     TableRow tableRow = new TableRow(getContext());
-                    if (enableCategorizedWidgetSuggestions()) {
-                        // Vertically center align items, so that even if they don't fill bounds,
-                        // they can look organized when placed together in a row.
-                        tableRow.setGravity(Gravity.CENTER_VERTICAL);
-                    } else {
-                        tableRow.setGravity(Gravity.TOP);
-                    }
+                    tableRow.setGravity(Gravity.TOP);
                     row.forEach(widgetItem -> {
                         WidgetCell widget = addItemCell(tableRow);
                         widget.applyFromCellItem(widgetItem);
@@ -284,6 +280,6 @@
     @Override
     public void addHintCloseAnim(
             float distanceToMove, Interpolator interpolator, PendingAnimation target) {
-        target.setInt(this, PADDING_BOTTOM, (int) (distanceToMove + mInsets.bottom), interpolator);
+        target.addAnimatedFloat(mSwipeToDismissProgress, 0f, 1f, interpolator);
     }
 }
diff --git a/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java b/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java
index 68f18ae..0d775c3 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListHeaderEntry.java
@@ -36,41 +36,49 @@
             (context, entry) -> entry.mWidgets.stream()
                     .map(item -> item.label).sorted().collect(Collectors.joining(", "));
 
-    private static final BiFunction<Context, WidgetsListHeaderEntry, String> SUBTITLE_DEFAULT =
-            (context, entry) -> {
-                List<WidgetItem> items = entry.mWidgets;
-                int wc = (int) items.stream().filter(item -> item.widgetInfo != null).count();
-                int sc = Math.max(0, items.size() - wc);
+    @Nullable
+    private static String buildWidgetsCountString(Context context, int wc, int sc) {
+        Resources resources = context.getResources();
+        if (wc == 0 && sc == 0) {
+            return null;
+        }
 
-                Resources resources = context.getResources();
-                if (wc == 0 && sc == 0) {
-                    return null;
-                }
-
-                String subtitle;
-                if (wc > 0 && sc > 0) {
-                    String widgetsCount = PluralMessageFormat.getIcuPluralString(context,
-                            R.string.widgets_count, wc);
-                    String shortcutsCount = PluralMessageFormat.getIcuPluralString(context,
-                            R.string.shortcuts_count, sc);
-                    subtitle = resources.getString(R.string.widgets_and_shortcuts_count,
-                            widgetsCount, shortcutsCount);
-                } else if (wc > 0) {
-                    subtitle = PluralMessageFormat.getIcuPluralString(context,
-                            R.string.widgets_count, wc);
-                } else {
-                    subtitle = PluralMessageFormat.getIcuPluralString(context,
-                            R.string.shortcuts_count, sc);
-                }
-                return subtitle;
-            };
+        String subtitle;
+        if (wc > 0 && sc > 0) {
+            String widgetsCount = PluralMessageFormat.getIcuPluralString(context,
+                    R.string.widgets_count, wc);
+            String shortcutsCount = PluralMessageFormat.getIcuPluralString(context,
+                    R.string.shortcuts_count, sc);
+            subtitle = resources.getString(R.string.widgets_and_shortcuts_count,
+                    widgetsCount, shortcutsCount);
+        } else if (wc > 0) {
+            subtitle = PluralMessageFormat.getIcuPluralString(context,
+                    R.string.widgets_count, wc);
+        } else {
+            subtitle = PluralMessageFormat.getIcuPluralString(context,
+                    R.string.shortcuts_count, sc);
+        }
+        return subtitle;
+    }
 
     private final boolean mIsWidgetListShown;
+    /** Selected widgets displayed */
+    private final int mVisibleWidgetsCount;
     private final boolean mIsSearchEntry;
 
     private WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName,
+            List<WidgetItem> items, int visibleWidgetsCount,
+            boolean isSearchEntry, boolean isWidgetListShown) {
+        super(pkgItem, titleSectionName, items);
+        mVisibleWidgetsCount = visibleWidgetsCount;
+        mIsSearchEntry = isSearchEntry;
+        mIsWidgetListShown = isWidgetListShown;
+    }
+
+    private WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName,
             List<WidgetItem> items, boolean isSearchEntry, boolean isWidgetListShown) {
         super(pkgItem, titleSectionName, items);
+        mVisibleWidgetsCount = (int) items.stream().filter(w -> w.widgetInfo != null).count();
         mIsSearchEntry = isSearchEntry;
         mIsWidgetListShown = isWidgetListShown;
     }
@@ -91,8 +99,13 @@
 
     @Nullable
     public String getSubtitle(Context context) {
-        return mIsSearchEntry
-                ? SUBTITLE_SEARCH.apply(context, this) : SUBTITLE_DEFAULT.apply(context, this);
+        if (mIsSearchEntry) {
+            return SUBTITLE_SEARCH.apply(context, this);
+        } else {
+            int shortcutsCount = Math.max(0,
+                    (int) mWidgets.stream().filter(WidgetItem::isShortcut).count());
+            return buildWidgetsCountString(context, mVisibleWidgetsCount, shortcutsCount);
+        }
     }
 
     @Override
@@ -102,6 +115,7 @@
         return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem)
                 && mTitleSectionName.equals(otherEntry.mTitleSectionName)
                 && mIsWidgetListShown == otherEntry.mIsWidgetListShown
+                && mVisibleWidgetsCount == otherEntry.mVisibleWidgetsCount
                 && mIsSearchEntry == otherEntry.mIsSearchEntry;
     }
 
@@ -112,6 +126,7 @@
                 mPkgItem,
                 mTitleSectionName,
                 mWidgets,
+                mVisibleWidgetsCount,
                 mIsSearchEntry,
                 /* isWidgetListShown= */ true);
     }
@@ -122,7 +137,28 @@
                 pkgItem,
                 titleSectionName,
                 items,
-                /* forSearch */ false,
+                /* isSearchEntry= */ false,
+                /* isWidgetListShown= */ false);
+    }
+
+    /**
+     * Creates a widget list holder for an header ("app" / "suggestions") which has widgets or/and
+     * shortcuts.
+     *
+     * @param pkgItem             package item info for the header section
+     * @param titleSectionName    title string for the header
+     * @param items               all items for the given header
+     * @param visibleWidgetsCount widgets count when only selected widgets are shown due to
+     *                            limited space.
+     */
+    public static WidgetsListHeaderEntry create(PackageItemInfo pkgItem, String titleSectionName,
+            List<WidgetItem> items, int visibleWidgetsCount) {
+        return new WidgetsListHeaderEntry(
+                pkgItem,
+                titleSectionName,
+                items,
+                visibleWidgetsCount,
+                /* isSearchEntry= */ false,
                 /* isWidgetListShown= */ false);
     }
 
@@ -132,7 +168,7 @@
                 pkgItem,
                 titleSectionName,
                 items,
-                /* forSearch */ true,
+                /* isSearchEntry */ true,
                 /* isWidgetListShown= */ false);
     }
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
index 801b1f6..c3906a6 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProvider.java
@@ -18,13 +18,13 @@
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.util.Log;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.R;
 import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.Preconditions;
 import com.android.launcher3.util.ResourceBasedOverride;
 
@@ -54,6 +54,7 @@
      * to display the recommendation grouped by categories.
      */
     @WorkerThread
+    @Nullable
     public WidgetRecommendationCategory getWidgetRecommendationCategory(Context context,
             WidgetItem item) {
         // This is a default implementation that uses application category to derive the category to
@@ -61,17 +62,16 @@
         // via the overridden WidgetRecommendationCategoryProvider resource.
 
         Preconditions.assertWorkerThread();
-        PackageManager pm = context.getPackageManager();
+        PackageManagerHelper pmHelper = new PackageManagerHelper(context);
         if (item.widgetInfo != null && item.widgetInfo.getComponent() != null) {
             String widgetComponentName = item.widgetInfo.getComponent().getClassName();
-            try {
-                int predictionCategory = pm.getApplicationInfo(
-                        item.widgetInfo.getComponent().getPackageName(), 0 /* flags */).category;
+            ApplicationInfo applicationInfo = pmHelper.getApplicationInfo(
+                    item.widgetInfo.getComponent().getPackageName(), item.widgetInfo.getUser(),
+                    0 /* flags */);
+            if (applicationInfo != null) {
+                int predictionCategory = applicationInfo.category;
                 return getCategoryFromApplicationCategory(context, predictionCategory,
                         widgetComponentName);
-            } catch (PackageManager.NameNotFoundException e) {
-                Log.e(TAG, "Failed to retrieve application category when determining the "
-                        + "widget category for " + widgetComponentName, e);
             }
         }
         return null;
@@ -112,17 +112,22 @@
                     R.string.news_widget_recommendation_category_label, /*order=*/1);
         }
 
-        if (applicationCategory == ApplicationInfo.CATEGORY_SOCIAL
-                || applicationCategory == ApplicationInfo.CATEGORY_AUDIO
+        if (applicationCategory == ApplicationInfo.CATEGORY_SOCIAL) {
+            return new WidgetRecommendationCategory(
+                    R.string.social_widget_recommendation_category_label,
+                    /*order=*/5);
+        }
+
+        if (applicationCategory == ApplicationInfo.CATEGORY_AUDIO
                 || applicationCategory == ApplicationInfo.CATEGORY_VIDEO
                 || applicationCategory == ApplicationInfo.CATEGORY_IMAGE) {
             return new WidgetRecommendationCategory(
-                    R.string.social_and_entertainment_widget_recommendation_category_label,
-                    /*order=*/4);
+                    R.string.entertainment_widget_recommendation_category_label,
+                    /*order=*/6);
         }
 
         return new WidgetRecommendationCategory(
-                R.string.others_widget_recommendation_category_label, /*order=*/5);
+                R.string.others_widget_recommendation_category_label, /*order=*/4);
     }
 
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
index 426a3ae..4f73e66 100644
--- a/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
+++ b/src/com/android/launcher3/widget/picker/WidgetRecommendationsView.java
@@ -18,7 +18,9 @@
 
 import static com.android.launcher3.widget.util.WidgetsTableUtils.groupWidgetItemsUsingRowPxWithoutReordering;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.os.Bundle;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -31,13 +33,19 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.PagedView;
 import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.pageindicators.PageIndicatorDots;
 
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
 
 /**
  * A {@link PagedView} that displays widget recommendations in categories with dots as paged
@@ -45,15 +53,20 @@
  */
 public final class WidgetRecommendationsView extends PagedView<PageIndicatorDots> {
     private @Px float mAvailableHeight = Float.MAX_VALUE;
-
+    private static final String INITIALLY_DISPLAYED_WIDGETS_STATE_KEY =
+            "widgetRecommendationsView:mDisplayedWidgets";
     private static final int MAX_CATEGORIES = 3;
     private TextView mRecommendationPageTitle;
     private final List<String> mCategoryTitles = new ArrayList<>();
 
+    /** Callbacks to run when page changes */
+    private final List<Consumer<Integer>> mPageSwitchListeners = new ArrayList<>();
+
     @Nullable
     private OnLongClickListener mWidgetCellOnLongClickListener;
     @Nullable
     private OnClickListener mWidgetCellOnClickListener;
+    private Set<ComponentName> mDisplayedWidgets = Collections.emptySet();
 
     public WidgetRecommendationsView(Context context) {
         this(context, /* attrs= */ null);
@@ -73,6 +86,38 @@
         mRecommendationPageTitle = parent.findViewById(R.id.recommendations_page_title);
     }
 
+    /**
+     * Saves the necessary state in the provided bundle. To be called in case of orientation /
+     * other config changes.
+     */
+    public void saveState(Bundle bundle) {
+        // Save the widgets that were displayed, so that, on rotation / fold / unfold, we can
+        // maintain the "initial" set of widgets that user first saw (if they fit).
+        bundle.putParcelableArrayList(INITIALLY_DISPLAYED_WIDGETS_STATE_KEY,
+                new ArrayList<>(mDisplayedWidgets));
+    }
+
+    /**
+     * Restores the state that was saved by the saveState method during orientation / other config
+     * changes.
+     */
+    public void restoreState(Bundle bundle) {
+        ArrayList<ComponentName> componentList;
+        if (Utilities.ATLEAST_T) {
+            componentList = bundle.getParcelableArrayList(
+                    INITIALLY_DISPLAYED_WIDGETS_STATE_KEY, ComponentName.class);
+        } else {
+            componentList = bundle.getParcelableArrayList(
+                    INITIALLY_DISPLAYED_WIDGETS_STATE_KEY);
+        }
+
+        // Restore the "initial" set of widgets that were displayed, so that, on rotation / fold /
+        // unfold, we can maintain the set of widgets that user first saw (if they fit).
+        if (componentList != null) {
+            mDisplayedWidgets = new HashSet<>(componentList);
+        }
+    }
+
     /** Sets a {@link android.view.View.OnLongClickListener} for all widget cells in this table. */
     public void setWidgetCellLongClickListener(OnLongClickListener onLongClickListener) {
         mWidgetCellOnLongClickListener = onLongClickListener;
@@ -84,6 +129,13 @@
     }
 
     /**
+     * Add a callback to run when the current displayed page changes.
+     */
+    public void addPageSwitchListener(Consumer<Integer> pageChangeListener) {
+        mPageSwitchListeners.add(pageChangeListener);
+    }
+
+    /**
      * Displays all the provided recommendations in a single table if they fit.
      *
      * @param recommendedWidgets list of widgets to be displayed in recommendation section.
@@ -93,18 +145,27 @@
      * @param availableWidth     width in px that the recommendations should display in
      * @param cellPadding        padding in px that should be applied to each widget in the
      *                           recommendations
-     * @return {@code false} if no recommendations could fit in the available space.
+     * @return number of recommendations that could fit in the available space.
      */
-    public boolean setRecommendations(
+    public int setRecommendations(
             List<WidgetItem> recommendedWidgets, DeviceProfile deviceProfile,
             final @Px float availableHeight, final @Px int availableWidth,
             final @Px int cellPadding) {
         this.mAvailableHeight = availableHeight;
-        removeAllViews();
+        clear();
 
-        maybeDisplayInTable(recommendedWidgets, deviceProfile, availableWidth, cellPadding);
-        updateTitleAndIndicator();
-        return getChildCount() > 0;
+        Set<ComponentName> displayedWidgets = maybeDisplayInTable(recommendedWidgets,
+                deviceProfile,
+                availableWidth, cellPadding);
+
+        if (mDisplayedWidgets.isEmpty()) {
+            // Save the widgets shown for the first time user opened the picker; so that, they can
+            // be maintained across orientation changes.
+            mDisplayedWidgets = displayedWidgets;
+        }
+
+        updateTitleAndIndicator(/* requestedPage= */ 0);
+        return displayedWidgets.size();
     }
 
     /**
@@ -118,29 +179,36 @@
      * @param availableWidth  width in px that the recommendations should display in
      * @param cellPadding     padding in px that should be applied to each widget in the
      *                        recommendations
-     * @return {@code false} if no recommendations could fit in the available space.
+     * @param requestedPage   page number to display initially.
+     * @return number of recommendations that could fit in the available space.
      */
-    public boolean setRecommendations(
+    public int setRecommendations(
             Map<WidgetRecommendationCategory, List<WidgetItem>> recommendations,
-            DeviceProfile deviceProfile,
-            final @Px float availableHeight, final @Px int availableWidth,
-            final @Px int cellPadding) {
+            DeviceProfile deviceProfile, final @Px float availableHeight,
+            final @Px int availableWidth, final @Px int cellPadding, final int requestedPage) {
         this.mAvailableHeight = availableHeight;
         Context context = getContext();
-        mPageIndicator.setPauseScroll(true, deviceProfile.isTwoPanels);
-        removeAllViews();
+        // For purpose of recommendations section, we don't want paging dots to be halved in two
+        // pane display, so, we always provide isTwoPanels = "false".
+        mPageIndicator.setPauseScroll(/*pause=*/true, /*isTwoPanels=*/ false);
+        clear();
 
         int displayedCategories = 0;
+        Set<ComponentName> allDisplayedWidgets = new HashSet<>();
 
         // Render top MAX_CATEGORIES in separate tables. Each table becomes a page.
         for (Map.Entry<WidgetRecommendationCategory, List<WidgetItem>> entry :
                 new TreeMap<>(recommendations).entrySet()) {
             // If none of the recommendations for the category could fit in the mAvailableHeight, we
             // don't want to add that category; and we look for the next one.
-            if (maybeDisplayInTable(entry.getValue(), deviceProfile, availableWidth, cellPadding)) {
+            Set<ComponentName> displayedWidgetsForCategory = maybeDisplayInTable(entry.getValue(),
+                    deviceProfile,
+                    availableWidth, cellPadding);
+            if (!displayedWidgetsForCategory.isEmpty()) {
                 mCategoryTitles.add(
                         context.getResources().getString(entry.getKey().categoryTitleRes));
                 displayedCategories++;
+                allDisplayedWidgets.addAll(displayedWidgetsForCategory);
             }
 
             if (displayedCategories == MAX_CATEGORIES) {
@@ -148,21 +216,39 @@
             }
         }
 
-        updateTitleAndIndicator();
-        mPageIndicator.setPauseScroll(false, deviceProfile.isTwoPanels);
-        return getChildCount() > 0;
+        if (mDisplayedWidgets.isEmpty()) {
+            // Save the widgets shown for the first time user opened the picker; so that, they can
+            // be maintained across orientation changes.
+            mDisplayedWidgets = allDisplayedWidgets;
+        }
+
+        updateTitleAndIndicator(requestedPage);
+        // For purpose of recommendations section, we don't want paging dots to be halved in two
+        // pane display, so, we always provide isTwoPanels = "false".
+        mPageIndicator.setPauseScroll(/*pause=*/false, /*isTwoPanels=*/false);
+        return allDisplayedWidgets.size();
+    }
+
+    private void clear() {
+        mCategoryTitles.clear();
+        removeAllViews();
+        setCurrentPage(0);
+        mPageIndicator.setActiveMarker(0);
     }
 
     /** Displays the page title and paging indicator if there are multiple pages. */
-    private void updateTitleAndIndicator() {
+    private void updateTitleAndIndicator(int requestedPage) {
         boolean showPaginatedView = getPageCount() > 1;
         int titleAndIndicatorVisibility = showPaginatedView ? View.VISIBLE : View.GONE;
         mRecommendationPageTitle.setVisibility(titleAndIndicatorVisibility);
         mPageIndicator.setVisibility(titleAndIndicatorVisibility);
         if (showPaginatedView) {
-            mPageIndicator.setActiveMarker(0);
-            setCurrentPage(0);
-            mRecommendationPageTitle.setText(mCategoryTitles.get(0));
+            if (requestedPage <= 0 || requestedPage >= getPageCount()) {
+                requestedPage = 0;
+            }
+            setCurrentPage(requestedPage);
+            mPageIndicator.setActiveMarker(requestedPage);
+            mRecommendationPageTitle.setText(mCategoryTitles.get(requestedPage));
         }
     }
 
@@ -170,9 +256,10 @@
     protected void notifyPageSwitchListener(int prevPage) {
         if (getPageCount() > 1) {
             // Since the title is outside the paging scroll, we update the title on page switch.
-            mRecommendationPageTitle.setText(mCategoryTitles.get(getNextPage()));
+            int nextPage = getNextPage();
+            mRecommendationPageTitle.setText(mCategoryTitles.get(nextPage));
+            mPageSwitchListeners.forEach(listener -> listener.accept(nextPage));
             super.notifyPageSwitchListener(prevPage);
-            requestLayout();
         }
     }
 
@@ -199,21 +286,8 @@
             for (int i = 0; i < getChildCount(); i++) {
                 View child = getChildAt(i);
                 measureChild(child, widthMeasureSpec, heightMeasureSpec);
-                if (mAvailableHeight == Float.MAX_VALUE) {
-                    // When we are not limited by height, use currentPage's height. This is the case
-                    // when the paged layout is placed in a scrollable container. We cannot use
-                    // height
-                    // of tallest child in such case, as it will display a scrollbar even for
-                    // smaller
-                    // pages that don't have more content.
-                    if (i == mCurrentPage) {
-                        int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
-                        desiredHeight = Math.max(parentHeight, child.getMeasuredHeight());
-                    }
-                } else {
-                    // Use height of tallest child when we are limited to a certain height.
-                    desiredHeight = Math.max(desiredHeight, child.getMeasuredHeight());
-                }
+                // Use height of tallest child as we have limited height.
+                desiredHeight = Math.max(desiredHeight, child.getMeasuredHeight());
             }
 
             int finalHeight = resolveSizeAndState(desiredHeight, heightMeasureSpec, 0);
@@ -224,18 +298,25 @@
     }
 
     /**
-     * Groups the provided recommendations into rows and displays them in a table if at least one
-     * fits.
-     * <p>Returns false if none of the recommendations could fit.</p>
+     * Groups the provided recommendations into rows and displays ones that fit in a table.
+     * <p>Returns the set of widgets that could fit.</p>
      */
-    private boolean maybeDisplayInTable(List<WidgetItem> recommendedWidgets,
+    private Set<ComponentName> maybeDisplayInTable(List<WidgetItem> recommendedWidgets,
             DeviceProfile deviceProfile,
             final @Px int availableWidth, final @Px int cellPadding) {
+        List<WidgetItem> filteredRecommendedWidgets = recommendedWidgets;
+        // Show only those widgets that were displayed when user first opened the picker.
+        if (!mDisplayedWidgets.isEmpty()) {
+            filteredRecommendedWidgets = recommendedWidgets.stream().filter(
+                    w -> mDisplayedWidgets.contains(w.componentName)).toList();
+        }
         Context context = getContext();
         LayoutInflater inflater = LayoutInflater.from(context);
 
+        // Since we are limited by space, we don't sort recommendations - to show most relevant
+        // (if possible).
         List<ArrayList<WidgetItem>> rows = groupWidgetItemsUsingRowPxWithoutReordering(
-                recommendedWidgets,
+                filteredRecommendedWidgets,
                 context,
                 deviceProfile,
                 availableWidth,
@@ -249,13 +330,17 @@
         recommendationsTable.setWidgetCellOnClickListener(mWidgetCellOnClickListener);
         recommendationsTable.setWidgetCellLongClickListener(mWidgetCellOnLongClickListener);
 
-        boolean displayedAtLeastOne = recommendationsTable.setRecommendedWidgets(rows,
+        List<ArrayList<WidgetItem>> displayedItems = recommendationsTable.setRecommendedWidgets(
+                rows,
                 deviceProfile, mAvailableHeight);
-        if (displayedAtLeastOne) {
+
+        if (!displayedItems.isEmpty()) {
             addView(recommendationsTable);
         }
 
-        return displayedAtLeastOne;
+        return displayedItems.stream().flatMap(
+                        items -> items.stream().map(w -> w.componentName))
+                .collect(Collectors.toSet());
     }
 
     /** Returns location of a widget cell for displaying the "touch and hold" education tip. */
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index f5742af..c3067a5 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -15,11 +15,8 @@
  */
 package com.android.launcher3.widget.picker;
 
-import static android.view.View.MeasureSpec.makeMeasureSpec;
-
 import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
 import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.LauncherPrefs.WIDGETS_EDUCATION_DIALOG_SEEN;
 import static com.android.launcher3.allapps.ActivityAllAppsContainerView.AdapterHolder.SEARCH;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGETSTRAY_SEARCHED;
@@ -29,7 +26,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
-import android.os.Build;
+import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.Process;
 import android.os.UserHandle;
@@ -48,12 +45,9 @@
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.TextView;
-import android.window.BackEvent;
 
-import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.Px;
-import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
 import androidx.recyclerview.widget.DefaultItemAnimator;
 import androidx.recyclerview.widget.RecyclerView;
@@ -67,6 +61,7 @@
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.model.UserManagerState;
+import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.views.ArrowTipView;
 import com.android.launcher3.views.RecyclerViewFastScroller;
@@ -81,7 +76,9 @@
 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Predicate;
 import java.util.stream.IntStream;
 
@@ -98,8 +95,11 @@
 
     // The widget recommendation table can easily take over the entire screen on devices with small
     // resolution or landscape on phone. This ratio defines the max percentage of content area that
-    // the table can display.
-    private static final float RECOMMENDATION_TABLE_HEIGHT_RATIO = 0.75f;
+    // the table can display with respect to bottom sheet's height.
+    private static final float RECOMMENDATION_TABLE_HEIGHT_RATIO = 0.45f;
+    private static final String RECOMMENDATIONS_SAVED_STATE_KEY =
+            "widgetsFullSheet:mRecommendationsCurrentPage";
+    private static final String SUPER_SAVED_STATE_KEY = "widgetsFullSheet:superHierarchyState";
     private final UserCache mUserCache;
     private final UserManagerState mUserManagerState = new UserManagerState();
     private final UserHandle mCurrentUser = Process.myUserHandle();
@@ -107,9 +107,15 @@
             entry -> mCurrentUser.equals(entry.mPkgItem.user);
     private final Predicate<WidgetsListBaseEntry> mWorkWidgetsFilter;
     protected final boolean mHasWorkProfile;
-    protected boolean mHasRecommendedWidgets;
+    // Number of recommendations displayed
+    protected int mRecommendedWidgetsCount;
+    private List<WidgetItem> mRecommendedWidgets = new ArrayList<>();
+    private Map<WidgetRecommendationCategory, List<WidgetItem>> mRecommendedWidgetsMap =
+            new HashMap<>();
+    protected int mRecommendationsCurrentPage = 0;
     protected final SparseArray<AdapterHolder> mAdapters = new SparseArray();
-    @Nullable private ArrowTipView mLatestEducationalTip;
+    @Nullable
+    private ArrowTipView mLatestEducationalTip;
     private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
             new OnLayoutChangeListener() {
                 @Override
@@ -155,14 +161,19 @@
                 }
             };
 
-    @Px private final int mTabsHeight;
+    @Px
+    private final int mTabsHeight;
 
-    @Nullable private WidgetsRecyclerView mCurrentWidgetsRecyclerView;
-    @Nullable private WidgetsRecyclerView mCurrentTouchEventRecyclerView;
-    @Nullable PersonalWorkPagedView mViewPager;
+    @Nullable
+    private WidgetsRecyclerView mCurrentWidgetsRecyclerView;
+    @Nullable
+    private WidgetsRecyclerView mCurrentTouchEventRecyclerView;
+    @Nullable
+    PersonalWorkPagedView mViewPager;
     private boolean mIsInSearchMode;
     private boolean mIsNoWidgetsViewNeeded;
-    @Px protected int mMaxSpanPerRow;
+    @Px
+    protected int mMaxSpanPerRow;
     protected DeviceProfile mDeviceProfile;
 
     protected TextView mNoWidgetsView;
@@ -226,13 +237,16 @@
                 R.id.widget_recommendations_container);
         mWidgetRecommendationsView = mSearchScrollView.findViewById(
                 R.id.widget_recommendations_view);
+        // To save the currently displayed page, so that, it can be requested when rebinding
+        // recommendations with different size constraints.
+        mWidgetRecommendationsView.addPageSwitchListener(
+                newPage -> mRecommendationsCurrentPage = newPage);
         mWidgetRecommendationsView.initParentViews(mWidgetRecommendationsContainer);
         mWidgetRecommendationsView.setWidgetCellLongClickListener(this);
         mWidgetRecommendationsView.setWidgetCellOnClickListener(this);
 
         mHeaderTitle = mSearchScrollView.findViewById(R.id.title);
 
-        onRecommendedWidgetsBound();
         onWidgetsBound();
         setUpEducationViewsIfNeeded();
     }
@@ -291,13 +305,6 @@
         attachScrollbarToRecyclerView(currentRecyclerView);
     }
 
-    @Override
-    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
-    public void onBackProgressed(@NonNull BackEvent backEvent) {
-        super.onBackProgressed(backEvent);
-        mFastScroller.setVisibility(backEvent.getProgress() > 0 ? View.INVISIBLE : View.VISIBLE);
-    }
-
     private void attachScrollbarToRecyclerView(WidgetsRecyclerView recyclerView) {
         recyclerView.bindFastScrollbar(mFastScroller);
         if (mCurrentWidgetsRecyclerView != recyclerView) {
@@ -360,7 +367,6 @@
         super.onAttachedToWindow();
         LauncherAppState.getInstance(mActivityContext).getModel()
                 .refreshAndBindWidgetsAndShortcuts(null);
-        onRecommendedWidgetsBound();
     }
 
     @Override
@@ -541,6 +547,14 @@
     public void exitSearchMode() {
         if (!mIsInSearchMode) return;
         onSearchResults(new ArrayList<>());
+        WidgetsRecyclerView searchRecyclerView = mAdapters.get(
+                AdapterHolder.SEARCH).mWidgetsRecyclerView;
+        // Remove all views when exiting the search mode; this prevents animating from stale results
+        // to new ones the next time we enter search mode. By the time recycler view is hidden,
+        // layout may not have happened to clear up existing results. So, instead of waiting for it
+        // to happen, we clear the views here.
+        searchRecyclerView.swapAdapter(
+                searchRecyclerView.getAdapter(), /*removeAndRecycleExistingViews=*/ true);
         setViewVisibilityBasedOnSearch(/*isInSearchMode=*/ false);
         if (mHasWorkProfile) {
             mViewPager.snapToPage(AdapterHolder.PRIMARY);
@@ -588,44 +602,46 @@
         }
 
         if (enableCategorizedWidgetSuggestions()) {
-            mHasRecommendedWidgets = mWidgetRecommendationsView.setRecommendations(
-                    mActivityContext.getPopupDataProvider().getCategorizedRecommendedWidgets(),
+            // We avoid applying new recommendations when some are already displayed.
+            if (mRecommendedWidgetsMap.isEmpty()) {
+                mRecommendedWidgetsMap =
+                        mActivityContext.getPopupDataProvider().getCategorizedRecommendedWidgets();
+            }
+            mRecommendedWidgetsCount = mWidgetRecommendationsView.setRecommendations(
+                    mRecommendedWidgetsMap,
                     mDeviceProfile,
                     /* availableHeight= */ getMaxAvailableHeightForRecommendations(),
                     /* availableWidth= */ mMaxSpanPerRow,
-                    /* cellPadding= */ mWidgetCellHorizontalPadding
+                    /* cellPadding= */ mWidgetCellHorizontalPadding,
+                    /* requestedPage= */ mRecommendationsCurrentPage
             );
         } else {
-            mHasRecommendedWidgets = mWidgetRecommendationsView.setRecommendations(
-                    mActivityContext.getPopupDataProvider().getRecommendedWidgets(),
+            if (mRecommendedWidgets.isEmpty()) {
+                mRecommendedWidgets =
+                        mActivityContext.getPopupDataProvider().getRecommendedWidgets();
+            }
+            mRecommendedWidgetsCount = mWidgetRecommendationsView.setRecommendations(
+                    mRecommendedWidgets,
                     mDeviceProfile,
                     /* availableHeight= */ getMaxAvailableHeightForRecommendations(),
                     /* availableWidth= */ mMaxSpanPerRow,
                     /* cellPadding= */ mWidgetCellHorizontalPadding
             );
         }
-        mWidgetRecommendationsContainer.setVisibility(mHasRecommendedWidgets ? VISIBLE : GONE);
+        mWidgetRecommendationsContainer.setVisibility(
+                mRecommendedWidgetsCount > 0 ? VISIBLE : GONE);
     }
 
     @Px
-    private float getMaxAvailableHeightForRecommendations() {
-        float noWidgetsViewHeight = 0;
-        if (mIsNoWidgetsViewNeeded) {
-            // Make sure recommended section leaves enough space for noWidgetsView.
-            Rect noWidgetsViewTextBounds = new Rect();
-            mNoWidgetsView.getPaint()
-                    .getTextBounds(mNoWidgetsView.getText().toString(), /* start= */ 0,
-                            mNoWidgetsView.getText().length(), noWidgetsViewTextBounds);
-            noWidgetsViewHeight = noWidgetsViewTextBounds.height();
+    protected float getMaxAvailableHeightForRecommendations() {
+        // There isn't enough space to show recommendations in landscape orientation on phones with
+        // a full sheet design. Tablets use a two pane picker.
+        if (mDeviceProfile.isLandscape) {
+            return 0f;
         }
-        if (!isTwoPane()) {
-            doMeasure(
-                    makeMeasureSpec(mActivityContext.getDeviceProfile().availableWidthPx,
-                            MeasureSpec.EXACTLY),
-                    makeMeasureSpec(mActivityContext.getDeviceProfile().availableHeightPx,
-                            MeasureSpec.EXACTLY));
-        }
-        return getMaxTableHeight(noWidgetsViewHeight);
+
+        return (mDeviceProfile.heightPx - mDeviceProfile.bottomSheetTopPadding)
+                * RECOMMENDATION_TABLE_HEIGHT_RATIO;
     }
 
     /** b/209579563: "Widgets" header should be focused first. */
@@ -634,14 +650,6 @@
         return mHeaderTitle;
     }
 
-    @Px
-    protected float getMaxTableHeight(@Px float noWidgetsViewHeight) {
-        return (mContent.getMeasuredHeight()
-                - mTabsHeight - getHeaderViewHeight()
-                - noWidgetsViewHeight)
-                * RECOMMENDATION_TABLE_HEIGHT_RATIO;
-    }
-
     private void open(boolean animate) {
         if (animate) {
             if (getPopupContainer().getInsets().bottom > 0) {
@@ -710,6 +718,29 @@
         return sheet;
     }
 
+    @Override
+    public void saveHierarchyState(SparseArray<Parcelable> sparseArray) {
+        Bundle bundle = new Bundle();
+        // With widget picker open, when we open shade to switch theme, Launcher re-creates the
+        // picker and calls save/restore hierarchy state. We save the state of recommendations
+        // across those updates.
+        bundle.putInt(RECOMMENDATIONS_SAVED_STATE_KEY, mRecommendationsCurrentPage);
+        mWidgetRecommendationsView.saveState(bundle);
+        SparseArray<Parcelable> superState = new SparseArray<>();
+        super.saveHierarchyState(superState);
+        bundle.putSparseParcelableArray(SUPER_SAVED_STATE_KEY, superState);
+        sparseArray.put(0, bundle);
+    }
+
+    @Override
+    public void restoreHierarchyState(SparseArray<Parcelable> sparseArray) {
+        Bundle state = (Bundle) sparseArray.get(0);
+        mRecommendationsCurrentPage = state.getInt(
+                RECOMMENDATIONS_SAVED_STATE_KEY, /*defaultValue=*/0);
+        mWidgetRecommendationsView.restoreState(state);
+        super.restoreHierarchyState(state.getSparseParcelableArray(SUPER_SAVED_STATE_KEY));
+    }
+
     private static int getWidgetSheetId(BaseActivity activity) {
         boolean isTwoPane = (activity.getDeviceProfile().isTablet
                 // Enables two pane picker for tablets in all orientations when the
@@ -776,8 +807,7 @@
     @Override
     public void addHintCloseAnim(
             float distanceToMove, Interpolator interpolator, PendingAnimation target) {
-        target.setFloat(getRecyclerView(), VIEW_TRANSLATE_Y, -distanceToMove, interpolator);
-        target.setViewAlpha(getRecyclerView(), 0.5f, interpolator);
+        target.addAnimatedFloat(mSwipeToDismissProgress, 0f, 1f, interpolator);
     }
 
     @Override
@@ -797,8 +827,8 @@
     }
 
     /** private the height, in pixel, + the vertical margins of a given view. */
-    private static int measureHeightWithVerticalMargins(View view) {
-        if (view.getVisibility() != VISIBLE) {
+    protected static int measureHeightWithVerticalMargins(View view) {
+        if (view == null || view.getVisibility() != VISIBLE) {
             return 0;
         }
         MarginLayoutParams marginLayoutParams = (MarginLayoutParams) view.getLayoutParams();
@@ -833,6 +863,7 @@
             saveHierarchyState(widgetsState);
             handleClose(false);
             WidgetsFullSheet sheet = show(BaseActivity.fromContext(getContext()), false);
+            sheet.restoreRecommendations(mRecommendedWidgets, mRecommendedWidgetsMap);
             sheet.restoreHierarchyState(widgetsState);
             sheet.restorePreviousAdapterHolderType(getCurrentAdapterHolderType());
         } else if (!isTwoPane()) {
@@ -843,6 +874,12 @@
         mDeviceProfile = dp;
     }
 
+    private void restoreRecommendations(List<WidgetItem> recommendedWidgets,
+            Map<WidgetRecommendationCategory, List<WidgetItem>> recommendedWidgetsMap) {
+        mRecommendedWidgets = recommendedWidgets;
+        mRecommendedWidgetsMap = recommendedWidgetsMap;
+    }
+
     /**
      * Indicates if layout should be re-created on device profile change - so that a different
      * layout can be displayed.
@@ -866,7 +903,7 @@
     public void onBackInvoked() {
         if (mIsInSearchMode) {
             mSearchBar.reset();
-            animateSlideInViewToNoScale();
+            animateSwipeToDismissProgressToStart();
         } else {
             super.onBackInvoked();
         }
@@ -881,7 +918,8 @@
         }
     }
 
-    @Nullable private View getViewToShowEducationTip() {
+    @Nullable
+    private View getViewToShowEducationTip() {
         if (mWidgetRecommendationsContainer.getVisibility() == VISIBLE) {
             return mWidgetRecommendationsView.getViewForEducationTip();
         }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
index ef3ccf0..a7f7785 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
@@ -15,8 +15,6 @@
  */
 package com.android.launcher3.widget.picker;
 
-import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
-
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.util.Log;
@@ -121,7 +119,7 @@
                 widget.setVisibility(View.VISIBLE);
 
                 // When preview loads, notify adapter to rebind the item and possibly animate
-                widget.applyFromCellItem(widgetItem, 1f,
+                widget.applyFromCellItem(widgetItem,
                         bitmap -> holder.onPreviewLoaded(Pair.create(widgetItem, bitmap)),
                         holder.previewCache.get(widgetItem));
                 widget.requestLayout();
@@ -150,13 +148,7 @@
                 tableRow = (TableRow) table.getChildAt(i);
             } else {
                 tableRow = new TableRow(table.getContext());
-                if (enableCategorizedWidgetSuggestions()) {
-                    // Vertically center align items, so that even if they don't fill bounds, they
-                    // can look organized when placed together in a row.
-                    tableRow.setGravity(Gravity.CENTER_VERTICAL);
-                } else {
-                    tableRow.setGravity(Gravity.TOP);
-                }
+                tableRow.setGravity(Gravity.TOP);
                 table.addView(tableRow);
             }
             if (tableRow.getChildCount() > widgetItems.size()) {
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index 12564f4..a565780 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -17,11 +17,13 @@
 
 import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
+import static com.android.launcher3.widget.util.WidgetSizes.getWidgetSizePx;
+import static com.android.launcher3.widget.util.WidgetsTableUtils.WIDGETS_TABLE_ROW_SIZE_COMPARATOR;
+
+import static java.lang.Math.max;
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Size;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -30,26 +32,23 @@
 import android.widget.TableRow;
 
 import androidx.annotation.Nullable;
+import androidx.annotation.Px;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.model.WidgetItem;
 import com.android.launcher3.widget.WidgetCell;
-import com.android.launcher3.widget.util.WidgetSizes;
+import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize;
 
 import java.util.ArrayList;
 import java.util.List;
 
 /** A {@link TableLayout} for showing recommended widgets. */
 public final class WidgetsRecommendationTableLayout extends TableLayout {
-    private static final String TAG = "WidgetsRecommendationTableLayout";
-    private static final float DOWN_SCALE_RATIO = 0.9f;
-    private static final float MAX_DOWN_SCALE_RATIO = 0.5f;
     private final float mWidgetsRecommendationTableVerticalPadding;
     private final float mWidgetCellVerticalPadding;
     private final float mWidgetCellTextViewsHeight;
 
-    private float mRecommendationTableMaxHeight = Float.MAX_VALUE;
     @Nullable private OnLongClickListener mWidgetCellOnLongClickListener;
     @Nullable private OnClickListener mWidgetCellOnClickListener;
 
@@ -82,47 +81,38 @@
      * desired {@code recommendationTableMaxHeight}.
      *
      * <p>If the content can't fit {@code recommendationTableMaxHeight}, this view will remove a
-     * last row from the {@code recommendedWidgets} until it fits or only one row left. If the only
-     * row still doesn't fit, we scale down the preview image.
+     * last row from the {@code recommendedWidgets} until it fits or only one row left.
      *
-     * <p>Returns {@code false} if none of the widgets could fit</p>
+     * <p>Returns the list of widgets that could fit</p>
      */
-    public boolean setRecommendedWidgets(List<ArrayList<WidgetItem>> recommendedWidgets,
-            DeviceProfile deviceProfile,
-            float recommendationTableMaxHeight) {
-        mRecommendationTableMaxHeight = recommendationTableMaxHeight;
-        RecommendationTableData data = fitRecommendedWidgetsToTableSpace(/* previewScale= */ 1f,
-                deviceProfile,
-                recommendedWidgets);
-        bindData(data);
-        return !data.mRecommendationTable.isEmpty();
+    public List<ArrayList<WidgetItem>> setRecommendedWidgets(
+            List<ArrayList<WidgetItem>> recommendedWidgets,
+            DeviceProfile deviceProfile, float recommendationTableMaxHeight) {
+        List<ArrayList<WidgetItem>> rows = selectRowsThatFitInAvailableHeight(recommendedWidgets,
+                recommendationTableMaxHeight, deviceProfile);
+        bindData(rows);
+        return rows;
     }
 
-    private void bindData(RecommendationTableData data) {
-        if (data.mRecommendationTable.isEmpty()) {
+    private void bindData(List<ArrayList<WidgetItem>> recommendationTable) {
+        if (recommendationTable.isEmpty()) {
             setVisibility(GONE);
             return;
         }
 
         removeAllViews();
 
-        for (int i = 0; i < data.mRecommendationTable.size(); i++) {
-            List<WidgetItem> widgetItems = data.mRecommendationTable.get(i);
+        for (int i = 0; i < recommendationTable.size(); i++) {
+            List<WidgetItem> widgetItems = recommendationTable.get(i);
             TableRow tableRow = new TableRow(getContext());
-            if (enableCategorizedWidgetSuggestions()) {
-                // Vertically center align items, so that even if they don't fill bounds, they can
-                // look organized when placed together in a row.
-                tableRow.setGravity(Gravity.CENTER_VERTICAL);
-            } else {
-                tableRow.setGravity(Gravity.TOP);
-            }
+            tableRow.setGravity(Gravity.TOP);
             for (WidgetItem widgetItem : widgetItems) {
                 WidgetCell widgetCell = addItemCell(tableRow);
-                widgetCell.applyFromCellItem(widgetItem, data.mPreviewScale);
+                widgetCell.applyFromCellItem(widgetItem);
                 widgetCell.showAppIconInWidgetTitle(true);
-                widgetCell.showBadge();
                 if (enableCategorizedWidgetSuggestions()) {
                     widgetCell.showDescription(false);
+                    widgetCell.showDimensions(false);
                 }
             }
             addView(tableRow);
@@ -144,58 +134,32 @@
         return widget;
     }
 
-    private RecommendationTableData fitRecommendedWidgetsToTableSpace(
-            float previewScale,
-            DeviceProfile deviceProfile,
-            List<ArrayList<WidgetItem>> recommendedWidgetsInTable) {
-        if (previewScale < MAX_DOWN_SCALE_RATIO) {
-            Log.w(TAG, "Hide recommended widgets. Can't down scale previews to " + previewScale);
-            return new RecommendationTableData(List.of(), previewScale);
-        }
+    private List<ArrayList<WidgetItem>> selectRowsThatFitInAvailableHeight(
+            List<ArrayList<WidgetItem>> recommendedWidgets, @Px float recommendationTableMaxHeight,
+            DeviceProfile deviceProfile) {
+        List<ArrayList<WidgetItem>> filteredRows = new ArrayList<>();
         // A naive estimation of the widgets recommendation table height without inflation.
         float totalHeight = mWidgetsRecommendationTableVerticalPadding;
-        for (int i = 0; i < recommendedWidgetsInTable.size(); i++) {
-            List<WidgetItem> widgetItems = recommendedWidgetsInTable.get(i);
+
+        for (int i = 0; i < recommendedWidgets.size(); i++) {
+            List<WidgetItem> widgetItems = recommendedWidgets.get(i);
             float rowHeight = 0;
             for (int j = 0; j < widgetItems.size(); j++) {
                 WidgetItem widgetItem = widgetItems.get(j);
-                Size widgetSize = WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile,
-                        widgetItem);
-                float previewHeight = widgetSize.getHeight() * previewScale;
-                rowHeight = Math.max(rowHeight,
-                        previewHeight + mWidgetCellTextViewsHeight + mWidgetCellVerticalPadding);
+                WidgetPreviewContainerSize previewContainerSize =
+                        WidgetPreviewContainerSize.Companion.forItem(widgetItem, deviceProfile);
+                float widgetItemHeight = getWidgetSizePx(deviceProfile, previewContainerSize.spanX,
+                        previewContainerSize.spanY).getHeight();
+                rowHeight = max(rowHeight,
+                        widgetItemHeight + mWidgetCellTextViewsHeight + mWidgetCellVerticalPadding);
             }
-            totalHeight += rowHeight;
+            if (totalHeight + rowHeight <= recommendationTableMaxHeight) {
+                totalHeight += rowHeight;
+                filteredRows.add(new ArrayList<>(widgetItems));
+            }
         }
 
-        if (totalHeight < mRecommendationTableMaxHeight) {
-            return new RecommendationTableData(recommendedWidgetsInTable, previewScale);
-        }
-
-        if (recommendedWidgetsInTable.size() > 1) {
-            // We don't want to scale down widgets preview unless we really need to. Reduce the
-            // num of row by 1 to see if it fits.
-            return fitRecommendedWidgetsToTableSpace(
-                    previewScale,
-                    deviceProfile,
-                    recommendedWidgetsInTable.subList(/* fromIndex= */0,
-                            /* toIndex= */recommendedWidgetsInTable.size() - 1));
-        }
-
-        float nextPreviewScale = previewScale * DOWN_SCALE_RATIO;
-        return fitRecommendedWidgetsToTableSpace(nextPreviewScale, deviceProfile,
-                recommendedWidgetsInTable);
-    }
-
-    /** Data class for the widgets recommendation table and widgets preview scaling. */
-    private class RecommendationTableData {
-        private final List<ArrayList<WidgetItem>> mRecommendationTable;
-        private final float mPreviewScale;
-
-        RecommendationTableData(List<ArrayList<WidgetItem>> recommendationTable,
-                float previewScale) {
-            mRecommendationTable = recommendationTable;
-            mPreviewScale = previewScale;
-        }
+        // Perform re-ordering once we have filtered out recommendations that fit.
+        return filteredRows.stream().sorted(WIDGETS_TABLE_ROW_SIZE_COMPARATOR).toList();
     }
 }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
index 165b2fe..14985bf 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsTwoPaneSheet.java
@@ -17,6 +17,10 @@
 
 import static com.android.launcher3.Flags.enableCategorizedWidgetSuggestions;
 import static com.android.launcher3.Flags.enableUnfoldedTwoPanePicker;
+import static com.android.launcher3.UtilitiesKt.CLIP_CHILDREN_FALSE_MODIFIER;
+import static com.android.launcher3.UtilitiesKt.CLIP_TO_PADDING_FALSE_MODIFIER;
+import static com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree;
+import static com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree;
 
 import android.content.Context;
 import android.graphics.Outline;
@@ -27,6 +31,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewOutlineProvider;
+import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
@@ -57,13 +62,19 @@
     private static final int MAXIMUM_WIDTH_LEFT_PANE_FOLDABLE_DP = 395;
     private static final String SUGGESTIONS_PACKAGE_NAME = "widgets_list_suggestions_entry";
 
+    // This ratio defines the max percentage of content area that the recommendations can display
+    // with respect to the bottom sheet's height.
+    private static final float RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE = 0.75f;
     private FrameLayout mSuggestedWidgetsContainer;
     private WidgetsListHeader mSuggestedWidgetsHeader;
     private PackageUserKey mSuggestedWidgetsPackageUserKey;
+    private View mPrimaryWidgetListView;
     private LinearLayout mRightPane;
 
     private ScrollView mRightPaneScrollView;
     private WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder;
+
+    private boolean mOldIsSwipeToDismissInProgress;
     private int mActivePage = -1;
     private PackageUserKey mSelectedHeader;
 
@@ -118,14 +129,23 @@
         mWidgetRecommendationsView.initParentViews(mWidgetRecommendationsContainer);
         mWidgetRecommendationsView.setWidgetCellLongClickListener(this);
         mWidgetRecommendationsView.setWidgetCellOnClickListener(this);
+        // To save the currently displayed page, so that, it can be requested when rebinding
+        // recommendations with different size constraints.
+        mWidgetRecommendationsView.addPageSwitchListener(
+                newPage -> mRecommendationsCurrentPage = newPage);
 
         mHeaderTitle = mContent.findViewById(R.id.title);
         mRightPane = mContent.findViewById(R.id.right_pane);
         mRightPane.setOutlineProvider(mViewOutlineProviderRightPane);
         mRightPaneScrollView = mContent.findViewById(R.id.right_pane_scroll_view);
         mRightPaneScrollView.setOverScrollMode(View.OVER_SCROLL_NEVER);
+        mRightPaneScrollView.setOutlineProvider(mViewOutlineProvider);
+        mRightPaneScrollView.setClipToOutline(true);
 
-        onRecommendedWidgetsBound();
+        mPrimaryWidgetListView = findViewById(R.id.primary_widgets_list_view);
+        mPrimaryWidgetListView.setOutlineProvider(mViewOutlineProvider);
+        mPrimaryWidgetListView.setClipToOutline(true);
+
         onWidgetsBound();
         setUpEducationViewsIfNeeded();
 
@@ -134,6 +154,27 @@
     }
 
     @Override
+    protected void onUserSwipeToDismissProgressChanged() {
+        super.onUserSwipeToDismissProgressChanged();
+        boolean isSwipeToDismissInProgress = mSwipeToDismissProgress.value > 0;
+        if (isSwipeToDismissInProgress == mOldIsSwipeToDismissInProgress) {
+            return;
+        }
+        mOldIsSwipeToDismissInProgress = isSwipeToDismissInProgress;
+        if (isSwipeToDismissInProgress) {
+            modifyAttributesOnViewTree(mPrimaryWidgetListView, (ViewParent) mContent,
+                    CLIP_CHILDREN_FALSE_MODIFIER);
+            modifyAttributesOnViewTree(mRightPaneScrollView,  (ViewParent) mContent,
+                    CLIP_CHILDREN_FALSE_MODIFIER, CLIP_TO_PADDING_FALSE_MODIFIER);
+        } else {
+            restoreAttributesOnViewTree(mPrimaryWidgetListView, mContent,
+                    CLIP_CHILDREN_FALSE_MODIFIER);
+            restoreAttributesOnViewTree(mRightPaneScrollView, mContent,
+                    CLIP_CHILDREN_FALSE_MODIFIER, CLIP_TO_PADDING_FALSE_MODIFIER);
+        }
+    }
+
+    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
         if (changed && mDeviceProfile.isTwoPanels && enableUnfoldedTwoPanePicker()) {
@@ -167,7 +208,7 @@
     @Override
     public void onWidgetsBound() {
         super.onWidgetsBound();
-        if (!mHasRecommendedWidgets && mSelectedHeader == null) {
+        if (mRecommendedWidgetsCount == 0 && mSelectedHeader == null) {
             mAdapters.get(mActivePage).mWidgetsListAdapter.selectFirstHeaderEntry();
             mAdapters.get(mActivePage).mWidgetsRecyclerView.scrollToTop();
         }
@@ -177,7 +218,7 @@
     public void onRecommendedWidgetsBound() {
         super.onRecommendedWidgetsBound();
 
-        if (mSuggestedWidgetsContainer == null && mHasRecommendedWidgets) {
+        if (mSuggestedWidgetsContainer == null && mRecommendedWidgetsCount > 0) {
             setupSuggestedWidgets(LayoutInflater.from(getContext()));
             mSuggestedWidgetsHeader.callOnClick();
         }
@@ -207,10 +248,13 @@
         String suggestionsRightPaneTitle = getContext().getString(
                 R.string.widget_picker_right_pane_accessibility_title, suggestionsHeaderTitle);
         packageItemInfo.title = suggestionsHeaderTitle;
+        // Suggestions may update at run time. The widgets count on suggestions doesn't add any
+        // value, so, we don't show the count.
         WidgetsListHeaderEntry widgetsListHeaderEntry = WidgetsListHeaderEntry.create(
                         packageItemInfo,
-                        suggestionsHeaderTitle,
-                        mActivityContext.getPopupDataProvider().getRecommendedWidgets())
+                        /*titleSectionName=*/ suggestionsHeaderTitle,
+                        /*items=*/ mActivityContext.getPopupDataProvider().getRecommendedWidgets(),
+                        /*visibleWidgetsCount=*/ 0)
                 .withWidgetListShown();
 
         mSuggestedWidgetsHeader.applyFromItemInfoWithIcon(widgetsListHeaderEntry);
@@ -232,8 +276,15 @@
 
     @Override
     @Px
-    protected float getMaxTableHeight(@Px float noWidgetsViewHeight) {
-        return Float.MAX_VALUE;
+    protected float getMaxAvailableHeightForRecommendations() {
+        if (mRecommendedWidgetsCount > 0) {
+            // If widgets were already selected for display, we show them all on orientation change
+            // in a two pane picker
+            return Float.MAX_VALUE;
+        }
+
+        return (mDeviceProfile.heightPx - mDeviceProfile.bottomSheetTopPadding)
+                * RECOMMENDATION_SECTION_HEIGHT_RATIO_TWO_PANE;
     }
 
     @Override
diff --git a/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSize.kt b/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSize.kt
new file mode 100644
index 0000000..a0414ba
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSize.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.picker.util
+
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.model.WidgetItem
+import kotlin.math.abs
+
+/** Size of a preview container in terms of the grid spans. */
+data class WidgetPreviewContainerSize(@JvmField val spanX: Int, @JvmField val spanY: Int) {
+    companion object {
+        /**
+         * Returns the size of the preview container in which the given widget's preview should be
+         * displayed (by scaling it if necessary).
+         */
+        fun forItem(item: WidgetItem, dp: DeviceProfile): WidgetPreviewContainerSize {
+            val sizes =
+                if (dp.isTablet && !dp.isTwoPanels) {
+                    TABLET_WIDGET_PREVIEW_SIZES
+                } else {
+                    HANDHELD_WIDGET_PREVIEW_SIZES
+                }
+
+            for ((index, containerSize) in sizes.withIndex()) {
+                if (containerSize.spanX == item.spanX && containerSize.spanY == item.spanY) {
+                    return containerSize // Exact match!
+                }
+                if (containerSize.spanX <= item.spanX && containerSize.spanY <= item.spanY) {
+                    return findClosestFittingContainer(
+                        containerSizes = sizes.toList(),
+                        startIndex = index,
+                        item = item
+                    )
+                }
+            }
+            // Use largest container if no match found
+            return sizes.elementAt(0)
+        }
+
+        private fun findClosestFittingContainer(
+            containerSizes: List<WidgetPreviewContainerSize>,
+            startIndex: Int,
+            item: WidgetItem
+        ): WidgetPreviewContainerSize {
+            // Checks if it's a smaller container, but close enough to keep the down-scale minimal.
+            fun hasAcceptableSize(currentIndex: Int): Boolean {
+                val container = containerSizes[currentIndex]
+                val isSmallerThanItem =
+                    container.spanX <= item.spanX && container.spanY <= item.spanY
+                val isCloseToItemSize =
+                    (item.spanY - container.spanY <= 1) && (item.spanX - container.spanX <= 1)
+
+                return isSmallerThanItem && isCloseToItemSize
+            }
+
+            var currentIndex = startIndex
+            var match = containerSizes[currentIndex]
+            val itemCellSizeRatio = item.spanX.toFloat() / item.spanY
+            var lastCellSizeRatioDiff = Float.MAX_VALUE
+
+            // Look for a smaller container (up to an acceptable extent) with closest cell size
+            // ratio.
+            while (currentIndex <= containerSizes.lastIndex && hasAcceptableSize(currentIndex)) {
+                val current = containerSizes[currentIndex]
+                val currentCellSizeRatio = current.spanX.toFloat() / current.spanY
+                val currentCellSizeRatioDiff = abs(itemCellSizeRatio - currentCellSizeRatio)
+
+                if (currentCellSizeRatioDiff < lastCellSizeRatioDiff) {
+                    lastCellSizeRatioDiff = currentCellSizeRatioDiff
+                    match = containerSizes[currentIndex]
+                }
+                currentIndex++
+            }
+            return match
+        }
+    }
+}
diff --git a/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizes.kt b/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizes.kt
new file mode 100644
index 0000000..a016676
--- /dev/null
+++ b/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizes.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.picker.util
+
+/**
+ * An ordered list of recommended sizes for the preview containers in handheld devices.
+ *
+ * Size of the preview container in which a widget's preview can be displayed.
+ */
+val HANDHELD_WIDGET_PREVIEW_SIZES: List<WidgetPreviewContainerSize> =
+    listOf(
+        WidgetPreviewContainerSize(spanX = 4, spanY = 3),
+        WidgetPreviewContainerSize(spanX = 4, spanY = 2),
+        WidgetPreviewContainerSize(spanX = 2, spanY = 3),
+        WidgetPreviewContainerSize(spanX = 2, spanY = 2),
+        WidgetPreviewContainerSize(spanX = 4, spanY = 1),
+        WidgetPreviewContainerSize(spanX = 2, spanY = 1),
+        WidgetPreviewContainerSize(spanX = 1, spanY = 1),
+    )
+
+/**
+ * An ordered list of recommended sizes for the preview containers in tablet devices (with larger
+ * grids).
+ *
+ * Size of the preview container in which a widget's preview can be displayed (by scaling the
+ * preview if necessary).
+ */
+val TABLET_WIDGET_PREVIEW_SIZES: List<WidgetPreviewContainerSize> =
+    listOf(
+        WidgetPreviewContainerSize(spanX = 3, spanY = 4),
+        WidgetPreviewContainerSize(spanX = 3, spanY = 3),
+        WidgetPreviewContainerSize(spanX = 3, spanY = 2),
+        WidgetPreviewContainerSize(spanX = 2, spanY = 3),
+        WidgetPreviewContainerSize(spanX = 2, spanY = 2),
+        WidgetPreviewContainerSize(spanX = 3, spanY = 1),
+        WidgetPreviewContainerSize(spanX = 2, spanY = 1),
+        WidgetPreviewContainerSize(spanX = 1, spanY = 1),
+    )
diff --git a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
index 74d3062..5e0e203 100644
--- a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
+++ b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
@@ -16,11 +16,13 @@
 package com.android.launcher3.widget.util;
 
 import android.content.Context;
+import android.util.Size;
 
 import androidx.annotation.Px;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.model.WidgetItem;
+import com.android.launcher3.widget.picker.util.WidgetPreviewContainerSize;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -33,8 +35,8 @@
     /**
      * Groups widgets in the following order:
      * 1. Widgets always go before shortcuts.
-     * 2. Widgets with smaller horizontal spans will be shown first.
-     * 3. If widgets have the same horizontal spans, then widgets with a smaller vertical spans will
+     * 2. Widgets with smaller vertical spans will be shown first.
+     * 3. If widgets have the same vertical spans, then widgets with a smaller horizontal spans will
      *    go first.
      * 4. If both widgets have the same horizontal and vertical spans, they will use the same order
      *    from the given {@code widgetItems}.
@@ -43,14 +45,29 @@
         if (item.widgetInfo != null && otherItem.widgetInfo == null) return -1;
 
         if (item.widgetInfo == null && otherItem.widgetInfo != null) return 1;
-        if (item.spanX == otherItem.spanX) {
-            if (item.spanY == otherItem.spanY) return 0;
-            return item.spanY > otherItem.spanY ? 1 : -1;
+        if (item.spanY == otherItem.spanY) {
+            if (item.spanX == otherItem.spanX) return 0;
+            return item.spanX > otherItem.spanX ? 1 : -1;
         }
-        return item.spanX > otherItem.spanX ? 1 : -1;
+        return item.spanY > otherItem.spanY ? 1 : -1;
     };
 
     /**
+     * Comparator that enables displaying rows in increasing order of their size (totalW * H);
+     * except for shortcuts which always show at the bottom.
+     */
+    public static final Comparator<ArrayList<WidgetItem>> WIDGETS_TABLE_ROW_SIZE_COMPARATOR =
+            Comparator.comparingInt(row -> {
+                if (row.stream().anyMatch(WidgetItem::isShortcut)) {
+                    return Integer.MAX_VALUE;
+                } else {
+                    int rowWidth = row.stream().mapToInt(w -> w.spanX).sum();
+                    int rowHeight = row.get(0).spanY;
+                    return (rowWidth * rowHeight);
+                }
+            });
+
+    /**
      * Groups {@code widgetItems} items into a 2D array which matches their appearance in a UI
      * table. This takes liberty to rearrange widgets to make the table visually appealing.
      */
@@ -59,72 +76,70 @@
             final @Px int rowPx, final @Px int cellPadding) {
         List<WidgetItem> sortedWidgetItems = widgetItems.stream().sorted(WIDGET_SHORTCUT_COMPARATOR)
                 .collect(Collectors.toList());
-        return groupWidgetItemsUsingRowPxWithoutReordering(sortedWidgetItems, context, dp, rowPx,
+        List<ArrayList<WidgetItem>> rows = groupWidgetItemsUsingRowPxWithoutReordering(
+                sortedWidgetItems, context, dp, rowPx,
                 cellPadding);
+        return rows.stream().sorted(WIDGETS_TABLE_ROW_SIZE_COMPARATOR).toList();
     }
 
     /**
      * Groups {@code widgetItems} into a 2D array which matches their appearance in a UI table while
      * maintaining their order. This function is a variant of
-     * {@code groupWidgetItemsIntoTableWithoutReordering} in that this uses widget pixels for
-     * calculation.
+     * {@code groupWidgetItemsIntoTableWithoutReordering} in that this uses widget container's
+     * pixels for calculation.
      *
      * <p>Grouping:
      * 1. Widgets and shortcuts never group together in the same row.
-     * 2. The ordered widgets are grouped together in the same row until their individual occupying
-     *    pixels exceed the total allowed pixels for the cell.
+     * 2. Widgets are grouped together only if they have same preview container size.
+     * 3. Widgets are grouped together in the same row until the total of individual container sizes
+     *    exceed the total allowed pixels for the row.
      * 3. The ordered shortcuts are grouped together in the same row until their individual
      *    occupying pixels exceed the total allowed pixels for the cell.
      * 4. If there is only one widget in a row, its width may exceed the {@code rowPx}.
      *
-     * <p>Let's say the {@code rowPx} is set to 600 and we have 5 widgets. Widgets can be grouped
-     * in the same row if each of their individual occupying pixels does not exceed
-     * {@code rowPx} / 5 - 2 * {@code cellPadding}.
-     * Example 1: Row 1: 200x200, 200x300, 100x100. Average horizontal pixels is 200 and no widgets
-     * exceed that width. This is okay.
-     * Example 2: Row 1: 200x200, 400x300, 100x100. Average horizontal pixels is 200 and one widget
-     * exceed that width. This is not allowed.
-     * Example 3: Row 1: 700x400. This is okay because this is the only item in the row.
+     * <p>See WidgetTableUtilsTest
      */
     public static List<ArrayList<WidgetItem>> groupWidgetItemsUsingRowPxWithoutReordering(
             List<WidgetItem> widgetItems, Context context, final DeviceProfile dp,
             final @Px int rowPx, final @Px int cellPadding) {
-
         List<ArrayList<WidgetItem>> widgetItemsTable = new ArrayList<>();
         ArrayList<WidgetItem> widgetItemsAtRow = null;
+        // A row displays only items of same container size.
+        WidgetPreviewContainerSize containerSizeForRow = null;
+        @Px int currentRowWidth = 0;
+
         for (WidgetItem widgetItem : widgetItems) {
             if (widgetItemsAtRow == null) {
                 widgetItemsAtRow = new ArrayList<>();
                 widgetItemsTable.add(widgetItemsAtRow);
             }
             int numOfWidgetItems = widgetItemsAtRow.size();
-            @Px int individualSpan = (rowPx / (numOfWidgetItems + 1)) - (2 * cellPadding);
+
+            WidgetPreviewContainerSize containerSize =
+                    WidgetPreviewContainerSize.Companion.forItem(widgetItem, dp);
+            Size containerSizePx = WidgetSizes.getWidgetSizePx(dp, containerSize.spanX,
+                    containerSize.spanY);
+            @Px int containerWidth = containerSizePx.getWidth() + (2 * cellPadding);
+
             if (numOfWidgetItems == 0) {
                 widgetItemsAtRow.add(widgetItem);
-            } else if (
-                    // Since the size of the widget cell is determined by dividing the maximum span
-                    // pixels evenly, making sure that each widget would have enough span pixels to
-                    // show their contents.
-                    widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))
-                    && widgetItemsAtRow.stream().allMatch(
-                            item -> WidgetSizes.getWidgetItemSizePx(context, dp, item)
-                                    .getWidth() <= individualSpan)
-                    && WidgetSizes.getWidgetItemSizePx(context, dp, widgetItem)
-                            .getWidth() <= individualSpan) {
+                containerSizeForRow = containerSize;
+                currentRowWidth = containerWidth;
+            } else if ((currentRowWidth + containerWidth) <= rowPx
+                    && widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))
+                    && containerSize.equals(containerSizeForRow)) {
                 // Group items in the same row if
                 // 1. they are with the same type, i.e. a row can only have widgets or shortcuts but
                 //    never a mix of both.
-                // 2. Each widget will have horizontal cell span pixels that is at least as large as
-                //    it is required to fit in the horizontal content, unless the widget horizontal
-                //    span pixels is larger than the maximum allowed.
-                //    If an item has horizontal span pixels larger than the maximum allowed pixels
-                //    per row, we just place it in its own row regardless of the horizontal span
-                //    limit.
+                // 2. Each widget in the given row has same preview container size.
                 widgetItemsAtRow.add(widgetItem);
+                currentRowWidth += containerWidth;
             } else {
                 widgetItemsAtRow = new ArrayList<>();
                 widgetItemsTable.add(widgetItemsAtRow);
                 widgetItemsAtRow.add(widgetItem);
+                containerSizeForRow = containerSize;
+                currentRowWidth = containerWidth;
             }
         }
         return widgetItemsTable;
diff --git a/src/com/android/quickstep/views/RecentsViewContainer.java b/src/com/android/quickstep/views/RecentsViewContainer.java
new file mode 100644
index 0000000..0c3f4f1
--- /dev/null
+++ b/src/com/android/quickstep/views/RecentsViewContainer.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.views;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.LocusId;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.util.SystemUiController;
+import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.ScrimView;
+
+/**
+ * Interface to be implemented by the parent view of RecentsView
+ */
+public interface RecentsViewContainer extends ActivityContext {
+
+    /**
+     * Returns an instance of an implementation of RecentsViewContainer
+     * @param context will find instance of recentsViewContainer from given context.
+     */
+    static <T extends RecentsViewContainer> T containerFromContext(Context context) {
+        if (context instanceof RecentsViewContainer) {
+            return (T) context;
+        } else if (context instanceof ContextWrapper) {
+            return containerFromContext(((ContextWrapper) context).getBaseContext());
+        } else {
+            throw new IllegalArgumentException("Cannot find RecentsViewContainer in parent tree");
+        }
+    }
+
+    /**
+     * Returns {@link SystemUiController} to manage various window flags to control system UI.
+     */
+    SystemUiController getSystemUiController();
+
+    /**
+     * Returns {@link ScrimView}
+     */
+    ScrimView getScrimView();
+
+    /**
+     * Returns the Overview Panel as a View
+     */
+    <T extends View> T getOverviewPanel();
+
+    /**
+     * Returns the RootView
+     */
+    View getRootView();
+
+    /**
+     * Dispatches a generic motion event to the view hierarchy.
+     * Returns the current RecentsViewContainer as context
+     */
+    default Context asContext() {
+        return (Context) this;
+    }
+
+    /**
+     * @see Window.Callback#dispatchGenericMotionEvent(MotionEvent)
+     */
+    boolean dispatchGenericMotionEvent(MotionEvent ev);
+
+    /**
+     * @see Window.Callback#dispatchKeyEvent(KeyEvent)
+     */
+    boolean dispatchKeyEvent(KeyEvent ev);
+
+    /**
+     * Returns overview actions view as a view
+     */
+    View getActionsView();
+
+    /**
+     * @see BaseActivity#addForceInvisibleFlag(int)
+     * @param flag {@link BaseActivity.InvisibilityFlags}
+     */
+    void addForceInvisibleFlag(@BaseActivity.InvisibilityFlags int flag);
+
+    /**
+     * @see BaseActivity#clearForceInvisibleFlag(int)
+     * @param flag {@link BaseActivity.InvisibilityFlags}
+     */
+    void clearForceInvisibleFlag(@BaseActivity.InvisibilityFlags int flag);
+
+    /**
+     * @see android.app.Activity#setLocusContext(LocusId, Bundle)
+     * @param id {@link LocusId}
+     * @param bundle {@link Bundle}
+     */
+    void setLocusContext(LocusId id, Bundle bundle);
+
+    /**
+     * @see BaseActivity#isStarted()
+     * @return boolean
+     */
+    boolean isStarted();
+
+    /**
+     * @see BaseActivity#addEventCallback(int, Runnable)
+     * @param event {@link BaseActivity.ActivityEvent}
+     * @param callback runnable to be executed upon event
+     */
+    void addEventCallback(@BaseActivity.ActivityEvent int event, Runnable callback);
+
+    /**
+     * @see BaseActivity#removeEventCallback(int, Runnable)
+     * @param event {@link BaseActivity.ActivityEvent}
+     * @param callback runnable to be executed upon event
+     */
+    void removeEventCallback(@BaseActivity.ActivityEvent int event, Runnable callback);
+
+    /**
+     * @see com.android.quickstep.util.TISBindHelper#runOnBindToTouchInteractionService(Runnable)
+     * @param r runnable to be executed upon event
+     */
+    void runOnBindToTouchInteractionService(Runnable r);
+
+    /**
+     * @see Activity#getWindow()
+     * @return Window
+     */
+    Window getWindow();
+
+    /**
+     * @see
+     * BaseActivity#addMultiWindowModeChangedListener(BaseActivity.MultiWindowModeChangedListener)
+     * @param listener {@link BaseActivity.MultiWindowModeChangedListener}
+     */
+    void addMultiWindowModeChangedListener(
+            BaseActivity.MultiWindowModeChangedListener listener);
+
+    /**
+     * @see
+     * BaseActivity#removeMultiWindowModeChangedListener(
+     * BaseActivity.MultiWindowModeChangedListener)
+     * @param listener {@link BaseActivity.MultiWindowModeChangedListener}
+     */
+    void removeMultiWindowModeChangedListener(
+            BaseActivity.MultiWindowModeChangedListener listener);
+
+    /**
+     * Begins transition from overview back to homescreen
+     */
+    void returnToHomescreen();
+}
diff --git a/src_build_config/com/android/launcher3/BuildConfig.java b/src_build_config/com/android/launcher3/BuildConfig.java
index 3841969..6d4f56d 100644
--- a/src_build_config/com/android/launcher3/BuildConfig.java
+++ b/src_build_config/com/android/launcher3/BuildConfig.java
@@ -35,4 +35,9 @@
      * Flag to control various developer centric features
      */
     public static final boolean IS_DEBUG_DEVICE = false;
+
+    // Flag to control widgets support in Launcher
+    public static final boolean WIDGETS_ENABLED = true;
+    // Flag to control notification dots support in Launcher
+    public static final boolean NOTIFICATION_DOTS_ENABLED = true;
 }
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/PredictedAppIconInflater.java b/src_no_quickstep/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
similarity index 100%
rename from src_ui_overrides/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
rename to src_no_quickstep/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java b/src_no_quickstep/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java
similarity index 100%
rename from src_ui_overrides/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java
rename to src_no_quickstep/com/android/launcher3/uioverrides/flags/DeveloperOptionsUI.java
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/src_no_quickstep/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
similarity index 100%
rename from src_ui_overrides/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
rename to src_no_quickstep/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_no_quickstep/com/android/launcher3/uioverrides/states/AllAppsState.java
similarity index 100%
rename from src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
rename to src_no_quickstep/com/android/launcher3/uioverrides/states/AllAppsState.java
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_no_quickstep/com/android/launcher3/uioverrides/states/OverviewState.java
similarity index 100%
rename from src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
rename to src_no_quickstep/com/android/launcher3/uioverrides/states/OverviewState.java
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/LauncherBinder.java b/src_shortcuts_overrides/com/android/launcher3/model/LauncherBinder.java
deleted file mode 100644
index 7e73ab5..0000000
--- a/src_shortcuts_overrides/com/android/launcher3/model/LauncherBinder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2017 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 static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.model.BgDataModel.Callbacks;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.widget.model.WidgetsListBaseEntry;
-
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
- */
-public class LauncherBinder extends BaseLauncherBinder {
-
-    public LauncherBinder(LauncherAppState app, BgDataModel dataModel,
-            AllAppsList allAppsList, Callbacks[] callbacks) {
-        super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
-    }
-
-    @Override
-    public void bindDeepShortcuts() {
-        final HashMap<ComponentKey, Integer> shortcutMapCopy;
-        synchronized (mBgDataModel) {
-            shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
-        }
-        executeCallbacksTask(c -> c.bindDeepShortcutMap(shortcutMapCopy), mUiExecutor);
-    }
-
-    @Override
-    public void bindWidgets() {
-        final List<WidgetsListBaseEntry> widgets =
-                mBgDataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());
-        executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor);
-    }
-
-    @Override
-    public void bindSmartspaceWidget() {
-        executeCallbacksTask(c -> c.bindSmartspaceWidget(), mUiExecutor);
-    }
-}
diff --git a/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java b/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java
deleted file mode 100644
index 968b281..0000000
--- a/src_shortcuts_overrides/com/android/launcher3/util/AbsGridOccupancy.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.util;
-
-/**
- * Defines method to find the next vacant cell on a grid.
- * This uses the default top-down, left-right approach and can be over-written through
- * code swaps in different launchers.
- */
-public abstract class AbsGridOccupancy {
-    /**
-     * Find the first vacant cell, if there is one.
-     *
-     * @param vacantOut Holds the x and y coordinate of the vacant cell
-     * @param spanX Horizontal cell span.
-     * @param spanY Vertical cell span.
-     *
-     * @return true if a vacant cell was found
-     */
-    protected boolean findVacantCell(int[] vacantOut, boolean[][] cells, int countX, int countY,
-            int spanX, int spanY) {
-        for (int y = 0; (y + spanY) <= countY; y++) {
-            for (int x = 0; (x + spanX) <= countX; x++) {
-                boolean available = !cells[x][y];
-                out:
-                for (int i = x; i < x + spanX; i++) {
-                    for (int j = y; j < y + spanY; j++) {
-                        available = available && !cells[i][j];
-                        if (!available) break out;
-                    }
-                }
-                if (available) {
-                    vacantOut[0] = x;
-                    vacantOut[1] = y;
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-}
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
deleted file mode 100644
index b193d37..0000000
--- a/src_ui_overrides/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.uioverrides.flags;
-
-import static com.android.launcher3.config.FeatureFlags.FlagState.ENABLED;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.ConstantItem;
-import com.android.launcher3.config.FeatureFlags.BooleanFlag;
-import com.android.launcher3.config.FeatureFlags.FlagState;
-import com.android.launcher3.config.FeatureFlags.IntFlag;
-
-import java.io.PrintWriter;
-
-/**
- * Helper class to create various flags for launcher build. The base implementation does
- * not provide any flagging system, and simply replies with the default value.
- */
-public class FlagsFactory {
-
-    /**
-     * Creates a new debug flag
-     */
-    public static BooleanFlag getDebugFlag(
-            int bugId, String key, FlagState flagState, String description) {
-        return new BooleanFlag(flagState == ENABLED);
-    }
-
-    /**
-     * Creates a new debug flag
-     */
-    public static BooleanFlag getReleaseFlag(
-            int bugId, String key, FlagState flagState, String description) {
-        return new BooleanFlag(flagState == ENABLED);
-    }
-
-    /**
-     * Creates a new integer flag. Integer flags are always release flags
-     */
-    public static IntFlag getIntFlag(
-            int bugId, String key, int defaultValueInCode, String description) {
-        return new IntFlag(defaultValueInCode);
-    }
-
-    /**
-     * Creates a new debug integer flag and it is saved in LauncherPrefs.
-     */
-    public static IntFlag getIntFlag(
-            int bugId, String key, int defaultValueInCode, String description,
-            @Nullable ConstantItem<Integer> launcherPrefFlag) {
-        return new IntFlag(defaultValueInCode);
-    }
-
-    /**
-     * Dumps the current flags state to the print writer
-     */
-    public static void dump(PrintWriter pw) { }
-}
diff --git a/tests/Android.bp b/tests/Android.bp
index e9111ea..3822ff8 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -23,37 +23,20 @@
     srcs: [
         "src/**/*.java",
         "src/**/*.kt",
-        "multivalentTests/src/**/*.java",
-        "multivalentTests/src/**/*.kt",
+        ":launcher3-robo-src",
     ],
     exclude_srcs: [
         ":launcher-non-quickstep-tests-src",
     ],
 }
 
-// Source code used for screenshot tests
 filegroup {
-    name: "launcher-image-tests-helpers",
+    name: "launcher3-robo-src",
+    // multivalentTests directory is a shared folder for not only robolectric converted test
+    // classes but also shared helper classes.
     srcs: [
-        "src/com/android/launcher3/celllayout/board/*.java",
-        "src/com/android/launcher3/celllayout/board/*.kt",
-        "src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java",
-        "src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
-        "src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
-        "src/com/android/launcher3/ui/TestViewHelpers.java",
-        "multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java",
-        "src/com/android/launcher3/util/ModelTestExtensions.kt",
-        "src/com/android/launcher3/util/TestConstants.java",
-        "multivalentTests/src/com/android/launcher3/util/TestUtil.java",
-        "src/com/android/launcher3/util/Wait.java",
-        "multivalentTests/src/com/android/launcher3/util/WidgetUtils.java",
-        "src/com/android/launcher3/util/rule/*.java",
-        "src/com/android/launcher3/util/rule/*.kt",
-        "multivalentTests/src/com/android/launcher3/util/rule/*.java",
-        "multivalentTests/src/com/android/launcher3/util/rule/*.kt",
-        "src/com/android/launcher3/util/viewcapture_analysis/*.java",
-        "src/com/android/launcher3/testcomponent/*.java",
-        "src/com/android/launcher3/testcomponent/*.kt",
+        "multivalentTests/src/**/*.java",
+        "multivalentTests/src/**/*.kt",
     ],
 }
 
@@ -70,35 +53,15 @@
 filegroup {
     name: "launcher-oop-tests-src",
     srcs: [
+        ":launcher-testing-helpers",
         "src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java",
         "src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java",
         "src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java",
         "src/com/android/launcher3/dragging/TaplDragTest.java",
         "src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java",
-        "src/com/android/launcher3/ui/AbstractLauncherUiTest.java",
-        "src/com/android/launcher3/ui/PortraitLandscapeRunner.java",
         "src/com/android/launcher3/ui/TaplTestsLauncher3Test.java",
         "src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java",
         "src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java",
-        "multivalentTests/src/com/android/launcher3/util/LauncherLayoutBuilder.java",
-        "src/com/android/launcher3/util/TestConstants.java",
-        "multivalentTests/src/com/android/launcher3/util/TestUtil.java",
-        "src/com/android/launcher3/util/Wait.java",
-        "multivalentTests/src/com/android/launcher3/util/WidgetUtils.java",
-        "src/com/android/launcher3/util/rule/FailureWatcher.java",
-        "src/com/android/launcher3/util/rule/ViewCaptureRule.kt",
-        "src/com/android/launcher3/util/rule/SamplerRule.java",
-        "src/com/android/launcher3/util/rule/ScreenRecordRule.java",
-        "src/com/android/launcher3/util/rule/ShellCommandRule.java",
-        "src/com/android/launcher3/util/rule/TestIsolationRule.java",
-        "multivalentTests/src/com/android/launcher3/util/rule/TestStabilityRule.java",
-        "src/com/android/launcher3/util/viewcapture_analysis/*.java",
-        "src/com/android/launcher3/testcomponent/BaseTestingActivity.java",
-        "src/com/android/launcher3/testcomponent/OtherBaseTestingActivity.java",
-        "src/com/android/launcher3/testcomponent/CustomShortcutConfigActivity.java",
-        "src/com/android/launcher3/testcomponent/TestCommandReceiver.java",
-        "src/com/android/launcher3/testcomponent/TestLauncherActivity.java",
-        "src/com/android/launcher3/testcomponent/ImeTestActivity.java",
     ],
 }
 
@@ -123,6 +86,7 @@
         "mockito-target-extended-minus-junit4",
         "launcher_log_protos_lite",
         "truth",
+        "kotlinx_coroutines_test",
         "platform-test-rules",
         "testables",
         "com_android_launcher3_flags_lib",
@@ -177,7 +141,7 @@
     name: "launcher-testing-shared",
     srcs: [
         "multivalentTests/shared/com/android/launcher3/testing/shared/**/*.java",
-        "multivalentTests/shared/com/android/launcher3/testing/shared/**/*.kt"
+        "multivalentTests/shared/com/android/launcher3/testing/shared/**/*.kt",
     ],
     resource_dirs: [],
     manifest: "multivalentTests/shared/AndroidManifest.xml",
@@ -205,28 +169,11 @@
     ],
 }
 
-android_library {
-    name: "Launcher3Lib",
-    srcs: [
-        ":launcher-src",
-        ":launcher-src_shortcuts_overrides",
-        ":launcher-src_ui_overrides",
-    ],
-    static_libs: [
-        "Launcher3CommonDepsLib",
-    ],
-    // TODO(b/319712088): re-enable use_resource_processor
-    use_resource_processor: false,
-}
-
 android_robolectric_test {
     enabled: true,
     name: "Launcher3RoboTests",
-    // multivalentTests directory is a shared folder for not only robolectric converted test
-    // classes but also shared helper classes.
     srcs: [
-        "multivalentTests/src/com/android/launcher3/util/*.java",
-        "multivalentTests/src/com/android/launcher3/util/*.kt",
+        ":launcher3-robo-src",
 
         // Test util classes
         ":launcher-testing-helpers",
@@ -246,7 +193,10 @@
         "androidx.test.uiautomator_uiautomator",
         "androidx.core_core-animation-testing",
         "androidx.test.ext.junit",
-        "inline-mockito-robolectric-prebuilt",
+        "androidx.test.rules",
+        "uiautomator-helpers",
+        "mockito-robolectric-prebuilt",
+        "mockito-kotlin2",
         "platform-parametric-runner-lib",
         "testables",
         "Launcher3TestResources",
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index 7cb7964..27dd2a9 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -388,6 +388,15 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity-alias>
+        <activity android:name="com.android.launcher3.testcomponent.ExcludeFromRecentsTestActivity"
+            android:label="ExcludeFromRecentsTestActivity"
+            android:exported="true"
+            android:excludeFromRecents="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
 
         <!-- [b/197780098] Disable eager initialization of Jetpack libraries. -->
         <provider
diff --git a/tests/Launcher3Tests.xml b/tests/Launcher3Tests.xml
index bcbe343..29c34be 100644
--- a/tests/Launcher3Tests.xml
+++ b/tests/Launcher3Tests.xml
@@ -13,14 +13,27 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<!-- This test config file is auto-generated. -->
+
 <configuration description="Runs Launcher3 tests.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-instrumentation" />
 
+    <option name="max-tmp-logcat-file" value="104857600" /> <!-- 100 * 1024 * 1024 -->
+
+    <logger class="com.android.tradefed.log.FileLogger">
+        <option name="max-log-size" value="20" />
+    </logger>
+
+    <!-- Disables the "Ramdump uploader to betterbug" -->
+    <option name="post-boot-command" value="am broadcast --async --user 0 -a com.google.gservices.intent.action.GSERVICES_OVERRIDE -e betterbug_enable_ramdump_uploader false" />
+
     <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
         <option name="set-test-harness" value="true" />
-        <option name="run-command" value="am force-stop com.android.launcher3" />
+
+        <option name="run-command" value="svc nfc disable" />
+        <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+        <option name="run-command" value="svc bluetooth disable" />
+
         <option name="run-command" value="pm uninstall com.google.android.apps.nexuslauncher" />
         <option name="run-command" value="pm uninstall com.google.android.apps.nexuslauncher.out_of_proc_tests" />
         <option name="run-command" value="pm uninstall com.google.android.apps.nexuslauncher.tests" />
@@ -30,6 +43,9 @@
         <option name="run-command" value="settings delete secure assistant" />
         <option name="run-command" value="settings put global airplane_mode_on 1" />
         <option name="run-command" value="am broadcast -a android.intent.action.AIRPLANE_MODE" />
+
+        <option name="run-command" value="settings put system pointer_location 1" />
+        <option name="run-command" value="settings put system show_touches 1" />
     </target_preparer>
 
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/assets/databases/BackupAndRestore/launcher.db b/tests/assets/databases/BackupAndRestore/launcher.db
new file mode 100644
index 0000000..126d166
--- /dev/null
+++ b/tests/assets/databases/BackupAndRestore/launcher.db
Binary files differ
diff --git a/tests/assets/databases/BackupAndRestore/launcher_3_by_3.db b/tests/assets/databases/BackupAndRestore/launcher_3_by_3.db
new file mode 100644
index 0000000..6d8cd73
--- /dev/null
+++ b/tests/assets/databases/BackupAndRestore/launcher_3_by_3.db
Binary files differ
diff --git a/tests/assets/databases/BackupAndRestore/launcher_4_by_4.db b/tests/assets/databases/BackupAndRestore/launcher_4_by_4.db
new file mode 100644
index 0000000..00061dd
--- /dev/null
+++ b/tests/assets/databases/BackupAndRestore/launcher_4_by_4.db
Binary files differ
diff --git a/tests/assets/databases/BackupAndRestore/launcher_4_by_5.db b/tests/assets/databases/BackupAndRestore/launcher_4_by_5.db
new file mode 100644
index 0000000..e2e65aa
--- /dev/null
+++ b/tests/assets/databases/BackupAndRestore/launcher_4_by_5.db
Binary files differ
diff --git a/tests/assets/databases/GridMigrationTest/flagged_result5x5to5x8.db b/tests/assets/databases/GridMigrationTest/flagged_result5x5to5x8.db
new file mode 100644
index 0000000..8bea3ce
--- /dev/null
+++ b/tests/assets/databases/GridMigrationTest/flagged_result5x5to5x8.db
Binary files differ
diff --git a/tests/assets/databases/GridMigrationTest/result5x5to3x3.db b/tests/assets/databases/GridMigrationTest/result5x5to3x3.db
new file mode 100644
index 0000000..686056d
--- /dev/null
+++ b/tests/assets/databases/GridMigrationTest/result5x5to3x3.db
Binary files differ
diff --git a/tests/assets/databases/GridMigrationTest/result5x5to4x7.db b/tests/assets/databases/GridMigrationTest/result5x5to4x7.db
new file mode 100644
index 0000000..cd105c5
--- /dev/null
+++ b/tests/assets/databases/GridMigrationTest/result5x5to4x7.db
Binary files differ
diff --git a/tests/assets/databases/GridMigrationTest/result5x5to5x8.db b/tests/assets/databases/GridMigrationTest/result5x5to5x8.db
new file mode 100644
index 0000000..4b46969
--- /dev/null
+++ b/tests/assets/databases/GridMigrationTest/result5x5to5x8.db
Binary files differ
diff --git a/tests/assets/databases/GridMigrationTest/test_launcher.db b/tests/assets/databases/GridMigrationTest/test_launcher.db
new file mode 100644
index 0000000..c680e95
--- /dev/null
+++ b/tests/assets/databases/GridMigrationTest/test_launcher.db
Binary files differ
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
index af8f67f..197e687 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 42.0px (16.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1927.0px (734.0952dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
-	getWorkspaceSpringLoadScale(): 0.7781155px (0.29642496dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+	getWorkspaceSpringLoadScale(): 0.7666667px (0.2920635dp)
 	getCellLayoutHeight(): 1974.0px (752.0dp)
 	getCellLayoutWidth(): 1080.0px (411.42856dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
index 5b83dd7..4a9e2e6 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phonePortrait3Button.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 42.0px (16.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1906.0px (726.0952dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
-	getWorkspaceSpringLoadScale(): 0.77572966px (0.29551607dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
+	getWorkspaceSpringLoadScale(): 0.76666665px (0.29206347dp)
 	getCellLayoutHeight(): 1953.0px (744.0dp)
 	getCellLayoutWidth(): 1080.0px (411.42856dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
index 03a0048..9e89a16 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 16.0px (6.095238dp)
 	getCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)
 	getCellLayoutSpringLoadShrunkBottom(): 961.0px (366.09525dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.8059385px (0.30702418dp)
 	getCellLayoutHeight(): 943.0px (359.2381dp)
 	getCellLayoutWidth(): 2073.0px (789.7143dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
index 84258b3..ce168b4 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/phoneVerticalBar3Button.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 16.0px (6.095238dp)
 	getCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1017.0px (387.42856dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.8111332px (0.3090031dp)
 	getCellLayoutHeight(): 1006.0px (383.2381dp)
 	getCellLayoutWidth(): 1947.0px (741.7143dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
index 87a9700..7926033 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 64.0px (32.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 96.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)
 	getCellLayoutHeight(): 1252.0px (626.0dp)
 	getCellLayoutWidth(): 2198.0px (1099.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
index 169256d..eb20578 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletLandscape3Button.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 64.0px (32.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 96.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)
 	getCellLayoutHeight(): 1252.0px (626.0dp)
 	getCellLayoutWidth(): 2198.0px (1099.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
index 59da1be..dba0ec4 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 96.0px (48.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)
 	getCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 96.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)
 	getCellLayoutHeight(): 1856.0px (928.0dp)
 	getCellLayoutWidth(): 1528.0px (764.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
index ad1f095..495afb2 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/tabletPortrait3Button.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 96.0px (48.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)
 	getCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 96.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)
 	getCellLayoutHeight(): 1856.0px (928.0dp)
 	getCellLayoutWidth(): 1528.0px (764.0dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
index 61d5ee6..e7dd3e0 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 42.0px (16.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
 	getCellLayoutHeight(): 1370.0px (521.9048dp)
 	getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
index ac73e2f..fcbd427 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelLandscape3Button.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 42.0px (16.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)
 	getCellLayoutHeight(): 1370.0px (521.9048dp)
 	getCellLayoutWidth(): 1083.0px (412.57144dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
index 3169f41..319247c 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 84.0px (32.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
 	getCellLayoutHeight(): 1721.0px (655.619dp)
 	getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
index 9d3d7bc..50c1d4b 100644
--- a/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
+++ b/tests/assets/dumpTests/DeviceProfileDumpTest/twoPanelPortrait3Button.txt
@@ -123,7 +123,7 @@
 	dropTargetBarBottomMarginPx: 84.0px (32.0dp)
 	getCellLayoutSpringLoadShrunkTop(): 364.0px (138.66667dp)
 	getCellLayoutSpringLoadShrunkBottom(): 1773.0px (675.4286dp)
-	workspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)
+	workspaceSpringLoadedMinNextPageVisiblePx: 126.0px (48.0dp)
 	getWorkspaceSpringLoadScale(): 0.81871px (0.31188953dp)
 	getCellLayoutHeight(): 1721.0px (655.619dp)
 	getCellLayoutWidth(): 899.0px (342.4762dp)
diff --git a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index 7d195fd..fea0330 100644
--- a/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/multivalentTests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -120,6 +120,8 @@
     public static final String REQUEST_CLEAR_DATA = "clear-data";
     public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names";
     public static final String REQUEST_IS_TABLET = "is-tablet";
+    public static final String REQUEST_IS_PREDICTIVE_BACK_SWIPE_ENABLED =
+            "is-predictive-back-swipe-enabled";
     public static final String REQUEST_ENABLE_TASKBAR_NAVBAR_UNIFICATION =
             "enable-taskbar-navbar-unification";
     public static final String REQUEST_NUM_ALL_APPS_COLUMNS = "num-all-apps-columns";
@@ -176,6 +178,9 @@
     public static final String SUCCESSFUL_GESTURE_MISMATCH_EVENTS = "b/324940434";
     public static final String TEST_DRAG_APP_ICON_TO_MULTIPLE_WORKSPACES_FAILURE = "b/326908466";
     public static final String TEST_TAPL_OVERVIEW_ACTIONS_MENU_FAILURE = "b/326073471";
+    public static final String WIDGET_CONFIG_NULL_EXTRA_INTENT = "b/324419890";
+    public static final String ACTIVITY_NOT_RESUMED_AFTER_BACK = "b/322823209";
+    public static final String UPDATE_OVERVIEW_TARGETS_RUNNING_LATE = "b/321775748";
 
     public static final String REQUEST_EMULATE_DISPLAY = "emulate-display";
     public static final String REQUEST_STOP_EMULATE_DISPLAY = "stop-emulate-display";
diff --git a/tests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt b/tests/multivalentTests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/AppWidgetsRestoredReceiverTest.kt
diff --git a/tests/src/com/android/launcher3/celllayout/CellPosMapperTest.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/CellPosMapperTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/CellPosMapperTest.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/CellPosMapperTest.java
diff --git a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
similarity index 89%
rename from tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
index 6d8f5f0..0c3081f 100644
--- a/tests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/FavoriteItemsTransaction.java
@@ -15,8 +15,6 @@
  */
 package com.android.launcher3.celllayout;
 
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
 import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -24,8 +22,6 @@
 
 import android.content.Context;
 
-import androidx.test.uiautomator.UiDevice;
-
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherSettings;
@@ -33,7 +29,6 @@
 import com.android.launcher3.model.data.CollectionInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
-import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.util.ContentWriter;
 import com.android.launcher3.util.ModelTestExtensions;
 
@@ -105,15 +100,4 @@
         runOnExecutorSync(MAIN_EXECUTOR, model::forceReload);
         ModelTestExtensions.INSTANCE.loadModelSync(model);
     }
-
-    /**
-     * Commits the transaction and waits for home load
-     */
-    public void commitAndLoadHome(LauncherInstrumentation inst) {
-        commit();
-
-        // Launch the home activity
-        UiDevice.getInstance(getInstrumentation()).pressHome();
-        inst.waitForLauncherInitialized();
-    }
 }
diff --git a/tests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java
similarity index 96%
rename from tests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java
index 62f2259..e5ad888 100644
--- a/tests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellLayoutBoard.java
@@ -199,6 +199,19 @@
         return 'z';
     }
 
+    /**
+     * Check if the given area is empty.
+     */
+    public boolean isEmpty(int x, int y, int spanX, int spanY) {
+        for (int xi = x; xi < x + spanX; xi++) {
+            for (int yi = y; yi < y + spanY; yi++) {
+                if (mWidget[xi][yi] == CellType.IGNORE) continue;
+                if (mWidget[xi][yi] != CellType.EMPTY) return false;
+            }
+        }
+        return true;
+    }
+
     public void addWidget(int x, int y, int spanX, int spanY, char type) {
         Rect rect = new Rect(x, y + spanY - 1, x + spanX - 1, y);
         removeOverlappingItems(rect);
diff --git a/tests/src/com/android/launcher3/celllayout/board/CellType.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellType.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/board/CellType.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/CellType.java
diff --git a/tests/src/com/android/launcher3/celllayout/board/FolderPoint.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/FolderPoint.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/board/FolderPoint.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/FolderPoint.java
diff --git a/tests/src/com/android/launcher3/celllayout/board/IconPoint.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IconPoint.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/board/IconPoint.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/IconPoint.java
diff --git a/tests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/IdenticalBoardComparator.kt
diff --git a/tests/src/com/android/launcher3/celllayout/board/PermutedBoardComparator.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/PermutedBoardComparator.kt
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/board/PermutedBoardComparator.kt
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/PermutedBoardComparator.kt
diff --git a/tests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java
similarity index 94%
rename from tests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java
index 06a7db2..8a427dd 100644
--- a/tests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java
+++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.java
@@ -22,7 +22,6 @@
 import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
 
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Process;
@@ -32,11 +31,6 @@
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.celllayout.FavoriteItemsTransaction;
-import com.android.launcher3.celllayout.board.CellLayoutBoard;
-import com.android.launcher3.celllayout.board.CellType;
-import com.android.launcher3.celllayout.board.FolderPoint;
-import com.android.launcher3.celllayout.board.IconPoint;
-import com.android.launcher3.celllayout.board.WidgetRect;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.ItemInfo;
@@ -56,12 +50,10 @@
     private UserHandle mMyUser;
 
     private Context mContext;
-    private ContentResolver mResolver;
 
     public TestWorkspaceBuilder(Context context) {
         mMyUser = Process.myUserHandle();
         mContext = context;
-        mResolver = mContext.getContentResolver();
     }
 
     /**
diff --git a/tests/src/com/android/launcher3/celllayout/board/WidgetRect.java b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/WidgetRect.java
similarity index 100%
rename from tests/src/com/android/launcher3/celllayout/board/WidgetRect.java
rename to tests/multivalentTests/src/com/android/launcher3/celllayout/board/WidgetRect.java
diff --git a/tests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java b/tests/multivalentTests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
rename to tests/multivalentTests/src/com/android/launcher3/icons/FastBitmapDrawableTest.java
diff --git a/tests/src/com/android/launcher3/logging/FileLogTest.java b/tests/multivalentTests/src/com/android/launcher3/logging/FileLogTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/logging/FileLogTest.java
rename to tests/multivalentTests/src/com/android/launcher3/logging/FileLogTest.java
diff --git a/tests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt b/tests/multivalentTests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/logging/StartupLatencyLoggerTest.kt
diff --git a/tests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt b/tests/multivalentTests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/model/data/ItemInfoWithIconTest.kt
diff --git a/tests/src/com/android/launcher3/popup/PopupPopulatorTest.java b/tests/multivalentTests/src/com/android/launcher3/popup/PopupPopulatorTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/popup/PopupPopulatorTest.java
rename to tests/multivalentTests/src/com/android/launcher3/popup/PopupPopulatorTest.java
diff --git a/tests/src/com/android/launcher3/testcomponent/AppWidgetDynamicColors.java b/tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetDynamicColors.java
similarity index 100%
rename from tests/src/com/android/launcher3/testcomponent/AppWidgetDynamicColors.java
rename to tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetDynamicColors.java
diff --git a/tests/src/com/android/launcher3/testcomponent/AppWidgetHidden.java b/tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetHidden.java
similarity index 100%
rename from tests/src/com/android/launcher3/testcomponent/AppWidgetHidden.java
rename to tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetHidden.java
diff --git a/tests/src/com/android/launcher3/testcomponent/AppWidgetNoConfig.java b/tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetNoConfig.java
similarity index 100%
rename from tests/src/com/android/launcher3/testcomponent/AppWidgetNoConfig.java
rename to tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetNoConfig.java
diff --git a/tests/src/com/android/launcher3/testcomponent/AppWidgetWithConfig.java b/tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetWithConfig.java
similarity index 100%
rename from tests/src/com/android/launcher3/testcomponent/AppWidgetWithConfig.java
rename to tests/multivalentTests/src/com/android/launcher3/testcomponent/AppWidgetWithConfig.java
diff --git a/tests/src/com/android/launcher3/ui/TestViewHelpers.java b/tests/multivalentTests/src/com/android/launcher3/ui/TestViewHelpers.java
similarity index 100%
rename from tests/src/com/android/launcher3/ui/TestViewHelpers.java
rename to tests/multivalentTests/src/com/android/launcher3/ui/TestViewHelpers.java
diff --git a/tests/src/com/android/launcher3/util/ModelTestExtensions.kt b/tests/multivalentTests/src/com/android/launcher3/util/ModelTestExtensions.kt
similarity index 100%
rename from tests/src/com/android/launcher3/util/ModelTestExtensions.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/ModelTestExtensions.kt
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java b/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java
index 95444ba..3646f0c 100644
--- a/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/multivalentTests/src/com/android/launcher3/util/TestUtil.java
@@ -46,12 +46,8 @@
 
 import androidx.test.uiautomator.UiDevice;
 
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.config.FeatureFlags.BooleanFlag;
-import com.android.launcher3.config.FeatureFlags.IntFlag;
 import com.android.launcher3.tapl.LauncherInstrumentation;
 import com.android.launcher3.tapl.Workspace;
-import com.android.launcher3.util.rule.TestStabilityRule;
 
 import org.junit.Assert;
 
@@ -66,8 +62,6 @@
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
-import java.util.function.Predicate;
-import java.util.function.ToIntFunction;
 
 public class TestUtil {
     private static final String TAG = "TestUtil";
@@ -138,49 +132,12 @@
      */
     public static Point[] getCornersAndCenterPositions(LauncherInstrumentation launcher) {
         final Point dimensions = launcher.getWorkspace().getIconGridDimensions();
-        if (TestStabilityRule.isPresubmit()) {
-            // Return only center in presubmit to fit under the presubmit SLO.
-            return new Point[]{
-                    new Point(dimensions.x / 2, dimensions.y / 2)
-            };
-        } else {
-            return new Point[]{
-                    new Point(0, 1),
-                    new Point(0, dimensions.y - 2),
-                    new Point(dimensions.x - 1, 1),
-                    new Point(dimensions.x - 1, dimensions.y - 2),
-                    new Point(dimensions.x / 2, dimensions.y / 2)
-            };
-        }
-    }
-
-    /**
-     * Utility class to override a boolean flag during test. Note that the returned SafeCloseable
-     * must be closed to restore the original state
-     */
-    public static SafeCloseable overrideFlag(BooleanFlag flag, boolean value) {
-        Predicate<BooleanFlag> originalProxy = FeatureFlags.sBooleanReader;
-        Predicate<BooleanFlag> testProxy = f -> f == flag ? value : originalProxy.test(f);
-        FeatureFlags.sBooleanReader = testProxy;
-        return () -> {
-            if (FeatureFlags.sBooleanReader == testProxy) {
-                FeatureFlags.sBooleanReader = originalProxy;
-            }
-        };
-    }
-
-    /**
-     * Utility class to override a int flag during test. Note that the returned SafeCloseable
-     * must be closed to restore the original state
-     */
-    public static SafeCloseable overrideFlag(IntFlag flag, int value) {
-        ToIntFunction<IntFlag> originalProxy = FeatureFlags.sIntReader;
-        ToIntFunction<IntFlag> testProxy = f -> f == flag ? value : originalProxy.applyAsInt(f);
-        FeatureFlags.sIntReader = testProxy;
-        return () -> {
-            if (FeatureFlags.sIntReader == testProxy) {
-                FeatureFlags.sIntReader = originalProxy;
-            }
+        return new Point[]{
+                new Point(0, 1),
+                new Point(0, dimensions.y - 2),
+                new Point(dimensions.x - 1, 1),
+                new Point(dimensions.x - 1, dimensions.y - 2),
+                new Point(dimensions.x / 2, dimensions.y / 2)
         };
     }
 
diff --git a/tests/multivalentTests/src/com/android/launcher3/util/rule/BackAndRestoreRule.kt b/tests/multivalentTests/src/com/android/launcher3/util/rule/BackAndRestoreRule.kt
new file mode 100644
index 0000000..da96939
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/util/rule/BackAndRestoreRule.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util.rule
+
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherPrefs
+import java.io.File
+import java.nio.file.Paths
+import kotlin.io.path.pathString
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * Removes all launcher's DBs from the device and copies the dbs in
+ * assets/databases/BackupAndRestore to the device. It also set's the needed LauncherPrefs variables
+ * needed to kickstart a backup and restore.
+ */
+class BackAndRestoreRule : TestRule {
+
+    private val phoneContext = getInstrumentation().targetContext
+
+    private fun dbBackUp() = File(phoneContext.dataDir.path, "/databasesBackUp")
+
+    private fun dbDirectory() = File(phoneContext.dataDir.path, "/databases")
+
+    private fun isWorkspaceDatabase(rawFileName: String): Boolean {
+        val fileName = Paths.get(rawFileName).fileName.pathString
+        return fileName.startsWith("launcher") && fileName.endsWith(".db")
+    }
+
+    fun getDatabaseFiles() = dbDirectory().listFiles().filter { isWorkspaceDatabase(it.name) }
+
+    /**
+     * Setting RESTORE_DEVICE would trigger a restore next time the Launcher starts, and we remove
+     * the widgets and apps ids to prevent issues when loading the database.
+     */
+    private fun setRestoreConstants() {
+        LauncherPrefs.get(phoneContext)
+            .put(LauncherPrefs.RESTORE_DEVICE.to(InvariantDeviceProfile.TYPE_MULTI_DISPLAY))
+        LauncherPrefs.get(phoneContext)
+            .remove(LauncherPrefs.OLD_APP_WIDGET_IDS, LauncherPrefs.APP_WIDGET_IDS)
+    }
+
+    private fun uploadDatabase(dbName: String) {
+        val file = File(File(getInstrumentation().targetContext.dataDir, "/databases"), dbName)
+        file.writeBytes(
+            getInstrumentation()
+                .context
+                .assets
+                .open("databases/BackupAndRestore/$dbName")
+                .readBytes()
+        )
+        file.setWritable(true, false)
+    }
+
+    private fun uploadDbs() {
+        uploadDatabase("launcher.db")
+        uploadDatabase("launcher_4_by_4.db")
+        uploadDatabase("launcher_4_by_5.db")
+        uploadDatabase("launcher_3_by_3.db")
+    }
+
+    private fun savePreviousState() {
+        dbBackUp().deleteRecursively()
+        if (!dbDirectory().renameTo(dbBackUp())) {
+            throw Exception("Unable to move databases to backup directory")
+        }
+        dbDirectory().mkdir()
+        if (!dbDirectory().exists()) {
+            throw Exception("Databases directory doesn't exists")
+        }
+    }
+
+    private fun restorePreviousState() {
+        dbDirectory().deleteRecursively()
+        if (!dbBackUp().renameTo(dbDirectory())) {
+            throw Exception("Unable to restore backup directory to databases directory")
+        }
+        dbBackUp().delete()
+    }
+
+    fun before() {
+        savePreviousState()
+        setRestoreConstants()
+        uploadDbs()
+    }
+
+    fun after() {
+        restorePreviousState()
+    }
+
+    override fun apply(base: Statement?, description: Description?): Statement =
+        object : Statement() {
+            override fun evaluate() {
+                before()
+                try {
+                    base?.evaluate()
+                } finally {
+                    after()
+                }
+            }
+        }
+}
diff --git a/tests/src/com/android/launcher3/util/window/WindowManagerProxyTest.kt b/tests/multivalentTests/src/com/android/launcher3/util/window/WindowManagerProxyTest.kt
similarity index 100%
rename from tests/src/com/android/launcher3/util/window/WindowManagerProxyTest.kt
rename to tests/multivalentTests/src/com/android/launcher3/util/window/WindowManagerProxyTest.kt
diff --git a/tests/multivalentTests/src/com/android/launcher3/widget/picker/OWNERS b/tests/multivalentTests/src/com/android/launcher3/widget/picker/OWNERS
new file mode 100644
index 0000000..775b0c7
--- /dev/null
+++ b/tests/multivalentTests/src/com/android/launcher3/widget/picker/OWNERS
@@ -0,0 +1,18 @@
+set noparent
+
+# Bug component: 1481801
+# People who can approve changes for submission
+#
+
+# Widget Picker OWNERS
+zakcohen@google.com
+shamalip@google.com
+wvk@google.com
+
+# For Tests
+vadimt@google.com
+
+# Launcher OWNERS
+captaincole@google.com
+sunnygoyal@google.com
+
diff --git a/tests/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarControllerTest.java b/tests/multivalentTests/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarControllerTest.java
similarity index 100%
rename from tests/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarControllerTest.java
rename to tests/multivalentTests/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarControllerTest.java
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index ffcf83f..577334b 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -38,17 +38,18 @@
 import com.android.launcher3.util.window.CachedDisplayInfo
 import com.android.launcher3.util.window.WindowManagerProxy
 import com.google.common.truth.Truth
-import org.junit.Rule
-import org.mockito.kotlin.any
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.spy
-import org.mockito.kotlin.whenever
 import java.io.BufferedReader
 import java.io.File
 import java.io.PrintWriter
 import java.io.StringWriter
 import kotlin.math.max
 import kotlin.math.min
+import org.junit.Rule
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
 
 /**
  * This is an abstract class for DeviceProfile tests that create an InvariantDeviceProfile based on
@@ -286,6 +287,9 @@
             .thenReturn(
                 if (isGestureMode) NavigationMode.NO_BUTTON else NavigationMode.THREE_BUTTONS
             )
+        doReturn(WindowManagerProxy.INSTANCE[runningContext].isTaskbarDrawnInProcess)
+            .whenever(windowManagerProxy)
+            .isTaskbarDrawnInProcess()
 
         val density = densityDpi / DisplayMetrics.DENSITY_DEFAULT.toFloat()
         val config =
diff --git a/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt b/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
new file mode 100644
index 0000000..7ff544d
--- /dev/null
+++ b/tests/src/com/android/launcher3/AbstractFloatingViewHelperTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import android.view.View
+import com.android.launcher3.dragndrop.DragLayer
+import com.android.launcher3.views.ActivityContext
+import org.junit.Before
+import org.junit.Test
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.verifyZeroInteractions
+import org.mockito.kotlin.whenever
+
+/** Test for AbstractFloatingViewHelper */
+class AbstractFloatingViewHelperTest {
+    private val activityContext: ActivityContext = mock()
+    private val dragLayer: DragLayer = mock()
+    private val view: View = mock()
+    private val folderView: AbstractFloatingView = mock()
+    private val taskMenuView: AbstractFloatingView = mock()
+    private val abstractFloatingViewHelper = AbstractFloatingViewHelper()
+
+    @Before
+    fun setup() {
+        whenever(activityContext.dragLayer).thenReturn(dragLayer)
+        whenever(dragLayer.childCount).thenReturn(3)
+        whenever(dragLayer.getChildAt(0)).thenReturn(view)
+        whenever(dragLayer.getChildAt(1)).thenReturn(folderView)
+        whenever(dragLayer.getChildAt(2)).thenReturn(taskMenuView)
+        whenever(folderView.isOfType(any())).thenAnswer {
+            (it.getArgument<Int>(0) and AbstractFloatingView.TYPE_FOLDER) != 0
+        }
+        whenever(taskMenuView.isOfType(any())).thenAnswer {
+            (it.getArgument<Int>(0) and AbstractFloatingView.TYPE_TASK_MENU) != 0
+        }
+    }
+
+    @Test
+    fun closeOpenViews_all() {
+        abstractFloatingViewHelper.closeOpenViews(
+            activityContext,
+            true,
+            AbstractFloatingView.TYPE_ALL
+        )
+
+        verifyZeroInteractions(view)
+        verify(folderView).close(true)
+        verify(taskMenuView).close(true)
+    }
+
+    @Test
+    fun closeOpenViews_taskMenu() {
+        abstractFloatingViewHelper.closeOpenViews(
+            activityContext,
+            true,
+            AbstractFloatingView.TYPE_TASK_MENU
+        )
+
+        verifyZeroInteractions(view)
+        verify(folderView, never()).close(any())
+        verify(taskMenuView).close(true)
+    }
+
+    @Test
+    fun closeOpenViews_other() {
+        abstractFloatingViewHelper.closeOpenViews(
+            activityContext,
+            true,
+            AbstractFloatingView.TYPE_PIN_IME_POPUP
+        )
+
+        verifyZeroInteractions(view)
+        verify(folderView, never()).close(any())
+        verify(taskMenuView, never()).close(any())
+    }
+
+    @Test
+    fun closeOpenViews_both_animationOff() {
+        abstractFloatingViewHelper.closeOpenViews(
+            activityContext,
+            false,
+            AbstractFloatingView.TYPE_FOLDER or AbstractFloatingView.TYPE_TASK_MENU
+        )
+
+        verifyZeroInteractions(view)
+        verify(folderView).close(false)
+        verify(taskMenuView).close(false)
+    }
+}
diff --git a/tests/src/com/android/launcher3/LauncherIntentTest.java b/tests/src/com/android/launcher3/LauncherIntentTest.java
new file mode 100644
index 0000000..aeeb42a
--- /dev/null
+++ b/tests/src/com/android/launcher3/LauncherIntentTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.platform.test.annotations.LargeTest;
+import android.view.KeyEvent;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.allapps.ActivityAllAppsContainerView;
+import com.android.launcher3.allapps.SearchRecyclerView;
+import com.android.launcher3.ui.AbstractLauncherUiTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class LauncherIntentTest extends AbstractLauncherUiTest<Launcher> {
+
+    public final Intent allAppsIntent = new Intent(Intent.ACTION_ALL_APPS);
+
+    @Test
+    public void testAllAppsIntent() {
+        // Try executing ALL_APPS intent
+        executeOnLauncher(launcher -> launcher.onNewIntent(allAppsIntent));
+        // A-Z view with Main adapter should be loaded
+        assertOnMainAdapterAToZView();
+
+
+        // Try Moving to search view now
+        moveToSearchView();
+        // Try executing ALL_APPS intent
+        executeOnLauncher(launcher -> launcher.onNewIntent(allAppsIntent));
+        // A-Z view with Main adapter should be loaded
+        assertOnMainAdapterAToZView();
+    }
+
+    // Highlights the search bar, then fills text to display the SearchView.
+    private void moveToSearchView() {
+        // All Apps view should be loaded
+        assertTrue("Launcher internal state is not All Apps",
+                isInState(() -> LauncherState.ALL_APPS));
+        executeOnLauncher(launcher -> launcher.getAppsView().getSearchView().requestFocus());
+        // Search view should be in focus
+        waitForLauncherCondition("Search view is not in focus.",
+                launcher -> launcher.getAppsView().getSearchView().hasFocus());
+        mLauncher.pressAndHoldKeyCode(KeyEvent.KEYCODE_C, 0);
+        // Upon key press, search recycler view should be loaded
+        waitForLauncherCondition("Search view not active.",
+                launcher -> launcher.getAppsView().getActiveRecyclerView()
+                        instanceof SearchRecyclerView);
+        mLauncher.unpressKeyCode(KeyEvent.KEYCODE_C, 0);
+    }
+
+    // Checks if main adapter view is selected, search bar is out of focus and scroller is at start.
+    private void assertOnMainAdapterAToZView() {
+        // All Apps State should be loaded
+        assertTrue("Launcher internal state is not All Apps",
+                isInState(() -> LauncherState.ALL_APPS));
+
+        // A-Z recycler view should be active.
+        waitForLauncherCondition("A-Z view not active.",
+                launcher -> !(launcher.getAppsView().getActiveRecyclerView()
+                        instanceof SearchRecyclerView));
+        // Personal Adapter should be selected.
+        waitForLauncherCondition("Not on Main Adapter View",
+                launcher -> launcher.getAppsView().getCurrentPage()
+                        == ActivityAllAppsContainerView.AdapterHolder.MAIN);
+        // Search view should not be in focus
+        waitForLauncherCondition("Search view has focus.",
+                launcher -> !launcher.getAppsView().getSearchView().hasFocus());
+        // Scroller should be at top
+        executeOnLauncher(launcher -> assertEquals(
+                "All Apps started in already scrolled state", 0,
+                getAllAppsScroll(launcher)));
+    }
+}
diff --git a/tests/src/com/android/launcher3/UtilitiesKtTest.kt b/tests/src/com/android/launcher3/UtilitiesKtTest.kt
new file mode 100644
index 0000000..dd83871
--- /dev/null
+++ b/tests/src/com/android/launcher3/UtilitiesKtTest.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.UtilitiesKt.CLIP_CHILDREN_FALSE_MODIFIER
+import com.android.launcher3.UtilitiesKt.CLIP_TO_PADDING_FALSE_MODIFIER
+import com.android.launcher3.UtilitiesKt.modifyAttributesOnViewTree
+import com.android.launcher3.UtilitiesKt.restoreAttributesOnViewTree
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.views.WidgetsEduView
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class UtilitiesKtTest {
+
+    val context: Context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+
+    private lateinit var rootView: WidgetsEduView
+    private lateinit var midView: ViewGroup
+    private lateinit var childView: View
+    @Before
+    fun setup() {
+        rootView =
+            LayoutInflater.from(context).inflate(R.layout.widgets_edu, null) as WidgetsEduView
+        midView = rootView.requireViewById(R.id.edu_view)
+        childView = rootView.requireViewById(R.id.edu_header)
+    }
+
+    @Test
+    fun set_clipChildren_false() {
+        assertThat(rootView.clipChildren).isTrue()
+        assertThat(midView.clipChildren).isTrue()
+
+        modifyAttributesOnViewTree(childView, rootView, CLIP_CHILDREN_FALSE_MODIFIER)
+
+        assertThat(rootView.clipChildren).isFalse()
+        assertThat(midView.clipChildren).isFalse()
+    }
+
+    @Test
+    fun restore_clipChildren_true() {
+        assertThat(rootView.clipChildren).isTrue()
+        assertThat(midView.clipChildren).isTrue()
+        modifyAttributesOnViewTree(childView, rootView, CLIP_CHILDREN_FALSE_MODIFIER)
+        assertThat(rootView.clipChildren).isFalse()
+        assertThat(midView.clipChildren).isFalse()
+
+        restoreAttributesOnViewTree(childView, rootView, CLIP_CHILDREN_FALSE_MODIFIER)
+
+        assertThat(rootView.clipChildren).isTrue()
+        assertThat(midView.clipChildren).isTrue()
+    }
+
+    @Test
+    fun restore_clipChildren_skipRestoreMidView() {
+        assertThat(rootView.clipChildren).isTrue()
+        assertThat(midView.clipChildren).isTrue()
+        rootView.clipChildren = false
+        modifyAttributesOnViewTree(childView, rootView, CLIP_CHILDREN_FALSE_MODIFIER)
+        assertThat(rootView.clipChildren).isFalse()
+        assertThat(midView.clipChildren).isFalse()
+
+        restoreAttributesOnViewTree(childView, rootView, CLIP_CHILDREN_FALSE_MODIFIER)
+
+        assertThat(rootView.clipChildren).isFalse()
+        assertThat(midView.clipChildren).isTrue()
+    }
+
+    @Test
+    fun set_clipToPadding_false() {
+        assertThat(rootView.clipToPadding).isTrue()
+        assertThat(midView.clipToPadding).isTrue()
+
+        modifyAttributesOnViewTree(childView, rootView, CLIP_TO_PADDING_FALSE_MODIFIER)
+
+        assertThat(rootView.clipToPadding).isFalse()
+        assertThat(midView.clipToPadding).isFalse()
+    }
+
+    @Test
+    fun restore_clipToPadding_true() {
+        assertThat(rootView.clipToPadding).isTrue()
+        assertThat(midView.clipToPadding).isTrue()
+        modifyAttributesOnViewTree(childView, rootView, CLIP_TO_PADDING_FALSE_MODIFIER)
+        assertThat(rootView.clipToPadding).isFalse()
+        assertThat(midView.clipToPadding).isFalse()
+
+        restoreAttributesOnViewTree(childView, rootView, CLIP_TO_PADDING_FALSE_MODIFIER)
+
+        assertThat(rootView.clipToPadding).isTrue()
+        assertThat(midView.clipToPadding).isTrue()
+    }
+}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
index 0907f8f..2dcbda4 100644
--- a/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
+++ b/tests/src/com/android/launcher3/allapps/PrivateProfileManagerTest.java
@@ -26,7 +26,6 @@
 import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
@@ -39,6 +38,7 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -48,6 +48,7 @@
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.util.ActivityContextWrapper;
+import com.android.launcher3.util.ApiWrapper;
 import com.android.launcher3.util.UserIconInfo;
 import com.android.launcher3.util.rule.TestStabilityRule;
 
@@ -79,7 +80,7 @@
 
     private PrivateProfileManager mPrivateProfileManager;
     @Mock
-    private ActivityAllAppsContainerView mActivityAllAppsContainerView;
+    private ActivityAllAppsContainerView mAllApps;
     @Mock
     private StatsLogManager mStatsLogManager;
     @Mock
@@ -89,13 +90,15 @@
     @Mock
     private Context mContext;
     @Mock
-    private AllAppsStore mAllAppsStore;
+    private AllAppsStore<?> mAllAppsStore;
     @Mock
     private PackageManager mPackageManager;
     @Mock
     private LauncherApps mLauncherApps;
-
-    private boolean mRunnableCalled = false;
+    @Mock
+    private AllAppsRecyclerView mAllAppsRecyclerView;
+    @Mock
+    private Resources mResources;
 
     @Before
     public void setUp() {
@@ -104,8 +107,11 @@
                 .thenReturn(Arrays.asList(MAIN_HANDLE, PRIVATE_HANDLE));
         when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO);
         when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO);
-        when(mActivityAllAppsContainerView.getContext()).thenReturn(mContext);
-        when(mActivityAllAppsContainerView.getAppsStore()).thenReturn(mAllAppsStore);
+        when(mAllApps.getContext()).thenReturn(mContext);
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getApplicationContext()).thenReturn(getApplicationContext());
+        when(mAllApps.getAppsStore()).thenReturn(mAllAppsStore);
+        when(mAllApps.getActiveRecyclerView()).thenReturn(mAllAppsRecyclerView);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.resolveActivity(any(), any())).thenReturn(new ResolveInfo());
         when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps);
@@ -116,7 +122,7 @@
                 .thenReturn("com.android.launcher3.tests.privateProfileManager");
         when(mLauncherApps.getPreInstalledSystemPackages(any())).thenReturn(new ArrayList<>());
         mPrivateProfileManager = new PrivateProfileManager(mUserManager,
-                mActivityAllAppsContainerView, mStatsLogManager, mUserCache);
+                mAllApps, mStatsLogManager, mUserCache);
     }
 
     @Test
@@ -133,7 +139,7 @@
     public void unlockPrivateProfile_requestsQuietModeAsFalse() throws Exception {
         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED)).thenReturn(true);
 
-        mPrivateProfileManager.unlockPrivateProfile(() -> {});
+        mPrivateProfileManager.unlockPrivateProfile();
 
         awaitTasksCompleted();
         Mockito.verify(mUserManager).requestQuietModeEnabled(false, PRIVATE_HANDLE);
@@ -143,6 +149,7 @@
     public void quietModeFlagPresent_privateSpaceIsResetToDisabled() {
         PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
         doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
+        doNothing().when(privateProfileManager).executeLock();
         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
                 .thenReturn(false, true);
 
@@ -159,41 +166,54 @@
 
     @Test
     @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/320703862
-    public void transitioningToUnlocked_resetCallsPendingRunnable() throws Exception {
+    public void transitioningToUnlocked_resetCallsPostUnlock() throws Exception {
         PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
         doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
         when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
                 .thenReturn(false);
+        doNothing().when(privateProfileManager).expandPrivateSpace();
         when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
-        mRunnableCalled = false;
 
-        privateProfileManager.unlockPrivateProfile(this::testRunnable);
+        privateProfileManager.unlockPrivateProfile();
         privateProfileManager.reset();
 
         awaitTasksCompleted();
-        Mockito.verify(privateProfileManager).applyUnlockRunnable();
-        assertTrue("Unlock Runnable not Invoked", mRunnableCalled);
+        Mockito.verify(privateProfileManager).postUnlock();
     }
 
     @Test
-    public void openPrivateSpaceSettings_triggersSecurityAndPrivacyIntent() {
-        Intent expectedIntent = PrivateProfileManager.PRIVATE_SPACE_INTENT;
+    @TestStabilityRule.Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT)
+    public void transitioningToLocked_resetCallsExecuteLock() throws Exception {
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        doNothing().when(privateProfileManager).resetPrivateSpaceDecorator(anyInt());
+        doNothing().when(privateProfileManager).executeLock();
+        when(mAllAppsStore.hasModelFlag(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED))
+                .thenReturn(true);
+        doNothing().when(privateProfileManager).expandPrivateSpace();
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
+
+        privateProfileManager.lockPrivateProfile();
+        privateProfileManager.reset();
+
+        awaitTasksCompleted();
+        Mockito.verify(privateProfileManager).executeLock();
+    }
+
+    @Test
+    public void openPrivateSpaceSettings_triggersCorrectIntent() {
+        Intent expectedIntent = ApiWrapper.INSTANCE.get(mContext).getPrivateSpaceSettingsIntent();
         ArgumentCaptor<Intent> acIntent = ArgumentCaptor.forClass(Intent.class);
         mPrivateProfileManager.setPrivateSpaceSettingsAvailable(true);
 
         mPrivateProfileManager.openPrivateSpaceSettings();
 
         Mockito.verify(mContext).startActivity(acIntent.capture());
-        Intent actualIntent = acIntent.getValue();
-        assertEquals("Intent Action is different", expectedIntent.getAction(),
-                actualIntent.getAction());
+        assertEquals("Intent Action is different",
+                expectedIntent == null ? null : expectedIntent.toUri(0),
+                acIntent.getValue() == null ? null : acIntent.getValue().toUri(0));
     }
 
     private static void awaitTasksCompleted() throws Exception {
         UI_HELPER_EXECUTOR.submit(() -> null).get();
     }
-
-    private void testRunnable() {
-        mRunnableCalled = true;
-    }
 }
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
deleted file mode 100644
index 490cb47..0000000
--- a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewControllerTest.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.allapps;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-
-import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
-import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED;
-import static com.android.launcher3.allapps.UserProfileManager.STATE_TRANSITION;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageButton;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-import android.widget.TextView;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.launcher3.R;
-import com.android.launcher3.util.ActivityContextWrapper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class PrivateSpaceHeaderViewControllerTest {
-
-    private static final int CONTAINER_HEADER_ELEMENT_COUNT = 1;
-    private static final int LOCK_UNLOCK_BUTTON_COUNT = 1;
-    private static final int PS_SETTINGS_BUTTON_COUNT_VISIBLE = 1;
-    private static final int PS_SETTINGS_BUTTON_COUNT_INVISIBLE = 0;
-    private static final int PS_TRANSITION_IMAGE_COUNT = 1;
-
-    private Context mContext;
-    private PrivateSpaceHeaderViewController mPsHeaderViewController;
-    private RelativeLayout mPsHeaderLayout;
-    @Mock
-    private PrivateProfileManager mPrivateProfileManager;
-    @Mock
-    private ActivityAllAppsContainerView mAllApps;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = new ActivityContextWrapper(getApplicationContext());
-        mPsHeaderViewController = new PrivateSpaceHeaderViewController(mAllApps,
-                mPrivateProfileManager);
-        mPsHeaderLayout = (RelativeLayout) LayoutInflater.from(mContext).inflate(
-                R.layout.private_space_header, null);
-    }
-
-    @Test
-    public void privateProfileDisabled_psHeaderContainsLockedView() throws Exception {
-        Bitmap unlockButton = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
-        when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
-
-        mPsHeaderViewController.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
-        awaitTasksCompleted();
-
-        int totalContainerHeaderView = 0;
-        int totalLockUnlockButtonView = 0;
-        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
-            View view = mPsHeaderLayout.getChildAt(i);
-            if (view.getId() == R.id.ps_container_header) {
-                totalContainerHeaderView += 1;
-                assertEquals(View.VISIBLE, view.getVisibility());
-            } else if (view.getId() == R.id.settingsAndLockGroup) {
-                ImageView lockIcon = view.findViewById(R.id.lock_icon);
-                assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(unlockButton));
-                assertEquals(View.VISIBLE, lockIcon.getVisibility());
-
-                // Verify textView shouldn't be showing when disabled.
-                TextView lockText = view.findViewById(R.id.lock_text);
-                assertEquals(View.GONE, lockText.getVisibility());
-                totalLockUnlockButtonView += 1;
-            } else {
-                assertEquals(View.GONE, view.getVisibility());
-            }
-        }
-        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
-        assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
-    }
-
-    @Test
-    public void privateProfileEnabled_psHeaderContainsUnlockedView() throws Exception {
-        Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
-        Bitmap settingsImage = getBitmap(mContext.getDrawable(R.drawable.ic_ps_settings));
-        when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
-        when(mPrivateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(true);
-
-        mPsHeaderViewController.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
-        awaitTasksCompleted();
-
-        int totalContainerHeaderView = 0;
-        int totalLockUnlockButtonView = 0;
-        int totalSettingsImageView = 0;
-        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
-            View view = mPsHeaderLayout.getChildAt(i);
-            if (view.getId() == R.id.ps_container_header) {
-                totalContainerHeaderView += 1;
-                assertEquals(View.VISIBLE, view.getVisibility());
-            } else if (view.getId() == R.id.settingsAndLockGroup) {
-                // Look for settings button.
-                ImageButton settingsButton = view.findViewById(R.id.ps_settings_button);
-                assertEquals(View.VISIBLE, settingsButton.getVisibility());
-                totalSettingsImageView += 1;
-                assertTrue(getBitmap(settingsButton.getDrawable()).sameAs(settingsImage));
-
-                // Look for lock_icon and lock_text.
-                ImageView lockIcon = view.findViewById(R.id.lock_icon);
-                assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage));
-                assertEquals(View.VISIBLE, lockIcon.getVisibility());
-                TextView lockText = view.findViewById(R.id.lock_text);
-                assertEquals(View.VISIBLE, lockText.getVisibility());
-                totalLockUnlockButtonView += 1;
-            } else {
-                assertEquals(View.GONE, view.getVisibility());
-            }
-        }
-        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
-        assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
-        assertEquals(PS_SETTINGS_BUTTON_COUNT_VISIBLE, totalSettingsImageView);
-    }
-
-    @Test
-    public void privateProfileEnabledAndNoSettingsIntent_psHeaderContainsUnlockedView()
-            throws Exception {
-        Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
-        when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
-        when(mPrivateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(false);
-
-        mPsHeaderViewController.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
-        awaitTasksCompleted();
-
-        int totalContainerHeaderView = 0;
-        int totalLockUnlockButtonView = 0;
-        int totalSettingsImageView = 0;
-        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
-            View view = mPsHeaderLayout.getChildAt(i);
-            if (view.getId() == R.id.ps_container_header) {
-                totalContainerHeaderView += 1;
-                assertEquals(View.VISIBLE, view.getVisibility());
-            } else if (view.getId() == R.id.settingsAndLockGroup) {
-                // Ensure there is no settings button.
-                ImageButton settingsImage = view.findViewById(R.id.ps_settings_button);
-                assertEquals(View.GONE, settingsImage.getVisibility());
-
-                // Check lock icon and lock text is there.
-                ImageView lockIcon = view.findViewById(R.id.lock_icon);
-                assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage));
-                assertEquals(View.VISIBLE, lockIcon.getVisibility());
-                TextView lockText = view.findViewById(R.id.lock_text);
-                assertEquals(View.VISIBLE, lockText.getVisibility());
-                totalLockUnlockButtonView += 1;
-            } else {
-                assertEquals(View.GONE, view.getVisibility());
-            }
-        }
-        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
-        assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
-        assertEquals(PS_SETTINGS_BUTTON_COUNT_INVISIBLE, totalSettingsImageView);
-    }
-
-    @Test
-    public void privateProfileTransitioning_psHeaderContainsTransitionView() throws Exception {
-        Bitmap transitionImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_transition_image));
-        when(mPrivateProfileManager.getCurrentState()).thenReturn(STATE_TRANSITION);
-
-        mPsHeaderViewController.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
-        awaitTasksCompleted();
-
-        int totalContainerHeaderView = 0;
-        int totalLockUnlockButtonView = 0;
-        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
-            View view = mPsHeaderLayout.getChildAt(i);
-            if (view.getId() == R.id.ps_container_header) {
-                totalContainerHeaderView += 1;
-                assertEquals(View.VISIBLE, view.getVisibility());
-            } else if (view.getId() == R.id.ps_transition_image
-                    && view instanceof ImageView imageView) {
-                totalLockUnlockButtonView += 1;
-                assertEquals(View.VISIBLE, view.getVisibility());
-                assertTrue(getBitmap(imageView.getDrawable()).sameAs(transitionImage));
-            } else if (view.getId() == R.id.settingsAndLockGroup) {
-                LinearLayout lockUnlockButton = view.findViewById(R.id.ps_lock_unlock_button);
-                assertEquals(View.GONE, lockUnlockButton.getVisibility());
-            } else {
-                assertEquals(View.GONE, view.getVisibility());
-            }
-        }
-        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
-        assertEquals(PS_TRANSITION_IMAGE_COUNT, totalLockUnlockButtonView);
-    }
-
-    private Bitmap getBitmap(Drawable drawable) {
-        Bitmap result;
-        if (drawable instanceof BitmapDrawable) {
-            result = ((BitmapDrawable) drawable).getBitmap();
-        } else {
-            int width = drawable.getIntrinsicWidth();
-            int height = drawable.getIntrinsicHeight();
-            // Some drawables have no intrinsic width - e.g. solid colours.
-            if (width <= 0) {
-                width = 1;
-            }
-            if (height <= 0) {
-                height = 1;
-            }
-
-            result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(result);
-            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
-            drawable.draw(canvas);
-        }
-        return result;
-    }
-
-    private static void awaitTasksCompleted() throws Exception {
-        UI_HELPER_EXECUTOR.submit(() -> null).get();
-    }
-}
diff --git a/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
new file mode 100644
index 0000000..351b921
--- /dev/null
+++ b/tests/src/com/android/launcher3/allapps/PrivateSpaceHeaderViewTest.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.allapps;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;
+import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
+import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED;
+import static com.android.launcher3.allapps.UserProfileManager.STATE_TRANSITION;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.AdditionalAnswers.answer;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Process;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.launcher3.R;
+import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.pm.UserCache;
+import com.android.launcher3.util.ActivityContextWrapper;
+import com.android.launcher3.util.UserIconInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PrivateSpaceHeaderViewTest {
+
+    private static final UserHandle MAIN_HANDLE = Process.myUserHandle();
+    private static final UserHandle PRIVATE_HANDLE = new UserHandle(11);
+    private static final UserIconInfo MAIN_ICON_INFO =
+            new UserIconInfo(MAIN_HANDLE, UserIconInfo.TYPE_MAIN);
+    private static final UserIconInfo PRIVATE_ICON_INFO =
+            new UserIconInfo(PRIVATE_HANDLE, UserIconInfo.TYPE_PRIVATE);
+    private static final String CAMERA_PACKAGE_NAME = "com.android.launcher3.tests.camera";
+    private static final int CONTAINER_HEADER_ELEMENT_COUNT = 1;
+    private static final int LOCK_UNLOCK_BUTTON_COUNT = 1;
+    private static final int PS_SETTINGS_BUTTON_COUNT_VISIBLE = 1;
+    private static final int PS_SETTINGS_BUTTON_COUNT_INVISIBLE = 0;
+    private static final int PS_TRANSITION_IMAGE_COUNT = 1;
+    private static final int NUM_APP_COLS = 4;
+    private static final int NUM_PRIVATE_SPACE_APPS = 50;
+    private static final int ALL_APPS_HEIGHT = 10;
+    private static final int ALL_APPS_CELL_HEIGHT = 1;
+    private static final int PS_HEADER_HEIGHT = 1;
+    private static final int BIGGER_PS_HEADER_HEIGHT = 2;
+    private static final int SCROLL_NO_WHERE = -1;
+    private static final float HEADER_PROTECTION_HEIGHT = 1F;
+
+    private Context mContext;
+    private RelativeLayout mPsHeaderLayout;
+    private AlphabeticalAppsList<?> mAlphabeticalAppsList;
+    private PrivateProfileManager mPrivateProfileManager;
+    @Mock
+    private ActivityAllAppsContainerView mAllApps;
+    @Mock
+    private AllAppsStore<?> mAllAppsStore;
+    @Mock
+    private UserCache mUserCache;
+    @Mock
+    private UserManager mUserManager;
+    @Mock
+    private StatsLogManager mStatsLogManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = new ActivityContextWrapper(getApplicationContext());
+        when(mAllApps.getContext()).thenReturn(mContext);
+        when(mUserCache.getUserInfo(PRIVATE_HANDLE)).thenReturn(PRIVATE_ICON_INFO);
+        when(mUserCache.getUserProfiles())
+                .thenReturn(Arrays.asList(MAIN_HANDLE, PRIVATE_HANDLE));
+        when(mUserCache.getUserInfo(Process.myUserHandle())).thenReturn(MAIN_ICON_INFO);
+        mPrivateProfileManager = new PrivateProfileManager(mUserManager,
+                mAllApps, mStatsLogManager, mUserCache);
+        mPsHeaderLayout = (RelativeLayout) LayoutInflater.from(mContext).inflate(
+                R.layout.private_space_header, null);
+    }
+
+    @Test
+    public void privateProfileDisabled_psHeaderContainsLockedView() throws Exception {
+        Bitmap unlockButton = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_DISABLED);
+        privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+        awaitTasksCompleted();
+
+        int totalContainerHeaderView = 0;
+        int totalLockUnlockButtonView = 0;
+        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
+            View view = mPsHeaderLayout.getChildAt(i);
+            if (view.getId() == R.id.ps_container_header) {
+                totalContainerHeaderView += 1;
+                assertEquals(View.VISIBLE, view.getVisibility());
+            } else if (view.getId() == R.id.settingsAndLockGroup) {
+                ImageView lockIcon = view.findViewById(R.id.lock_icon);
+                assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(unlockButton));
+                assertEquals(View.VISIBLE, lockIcon.getVisibility());
+
+                // Verify textView shouldn't be showing when disabled.
+                TextView lockText = view.findViewById(R.id.lock_text);
+                assertEquals(View.GONE, lockText.getVisibility());
+                totalLockUnlockButtonView += 1;
+            } else {
+                assertEquals(View.GONE, view.getVisibility());
+            }
+        }
+
+        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
+        assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
+    }
+
+    @Test
+    public void privateProfileEnabled_psHeaderContainsUnlockedView() throws Exception {
+        Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
+        Bitmap settingsImage = getBitmap(mContext.getDrawable(R.drawable.ic_ps_settings));
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
+        when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(true);
+        privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+        awaitTasksCompleted();
+
+        int totalContainerHeaderView = 0;
+        int totalLockUnlockButtonView = 0;
+        int totalSettingsImageView = 0;
+        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
+            View view = mPsHeaderLayout.getChildAt(i);
+            if (view.getId() == R.id.ps_container_header) {
+                totalContainerHeaderView += 1;
+                assertEquals(View.VISIBLE, view.getVisibility());
+            } else if (view.getId() == R.id.settingsAndLockGroup) {
+                // Look for settings button.
+                ImageButton settingsButton = view.findViewById(R.id.ps_settings_button);
+                assertEquals(View.VISIBLE, settingsButton.getVisibility());
+                totalSettingsImageView += 1;
+                assertTrue(getBitmap(settingsButton.getDrawable()).sameAs(settingsImage));
+
+                // Look for lock_icon and lock_text.
+                ImageView lockIcon = view.findViewById(R.id.lock_icon);
+                assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage));
+                assertEquals(View.VISIBLE, lockIcon.getVisibility());
+                TextView lockText = view.findViewById(R.id.lock_text);
+                assertEquals(View.VISIBLE, lockText.getVisibility());
+                totalLockUnlockButtonView += 1;
+            } else {
+                assertEquals(View.GONE, view.getVisibility());
+            }
+        }
+
+        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
+        assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
+        assertEquals(PS_SETTINGS_BUTTON_COUNT_VISIBLE, totalSettingsImageView);
+    }
+
+    @Test
+    public void privateProfileEnabledAndNoSettingsIntent_psHeaderContainsUnlockedView()
+            throws Exception {
+        Bitmap lockImage = getBitmap(mContext.getDrawable(R.drawable.ic_lock));
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
+        when(privateProfileManager.isPrivateSpaceSettingsAvailable()).thenReturn(false);
+        privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+        awaitTasksCompleted();
+
+        int totalContainerHeaderView = 0;
+        int totalLockUnlockButtonView = 0;
+        int totalSettingsImageView = 0;
+        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
+            View view = mPsHeaderLayout.getChildAt(i);
+            if (view.getId() == R.id.ps_container_header) {
+                totalContainerHeaderView += 1;
+                assertEquals(View.VISIBLE, view.getVisibility());
+            } else if (view.getId() == R.id.settingsAndLockGroup) {
+                // Ensure there is no settings button.
+                ImageButton settingsImage = view.findViewById(R.id.ps_settings_button);
+                assertEquals(View.GONE, settingsImage.getVisibility());
+
+                // Check lock icon and lock text is there.
+                ImageView lockIcon = view.findViewById(R.id.lock_icon);
+                assertTrue(getBitmap(lockIcon.getDrawable()).sameAs(lockImage));
+                assertEquals(View.VISIBLE, lockIcon.getVisibility());
+                TextView lockText = view.findViewById(R.id.lock_text);
+                assertEquals(View.VISIBLE, lockText.getVisibility());
+                totalLockUnlockButtonView += 1;
+            } else {
+                assertEquals(View.GONE, view.getVisibility());
+            }
+        }
+
+        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
+        assertEquals(LOCK_UNLOCK_BUTTON_COUNT, totalLockUnlockButtonView);
+        assertEquals(PS_SETTINGS_BUTTON_COUNT_INVISIBLE, totalSettingsImageView);
+    }
+
+    @Test
+    public void privateProfileTransitioning_psHeaderContainsTransitionView() throws Exception {
+        Bitmap transitionImage = getBitmap(mContext.getDrawable(R.drawable.bg_ps_transition_image));
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_TRANSITION);
+        privateProfileManager.addPrivateSpaceHeaderViewElements(mPsHeaderLayout);
+        awaitTasksCompleted();
+
+        int totalContainerHeaderView = 0;
+        int totalLockUnlockButtonView = 0;
+        for (int i = 0; i < mPsHeaderLayout.getChildCount(); i++) {
+            View view = mPsHeaderLayout.getChildAt(i);
+            if (view.getId() == R.id.ps_container_header) {
+                totalContainerHeaderView += 1;
+                assertEquals(View.VISIBLE, view.getVisibility());
+            } else if (view.getId() == R.id.ps_transition_image
+                    && view instanceof ImageView imageView) {
+                totalLockUnlockButtonView += 1;
+                assertEquals(View.VISIBLE, view.getVisibility());
+                assertTrue(getBitmap(imageView.getDrawable()).sameAs(transitionImage));
+            } else if (view.getId() == R.id.settingsAndLockGroup) {
+                LinearLayout lockUnlockButton = view.findViewById(R.id.ps_lock_unlock_button);
+                assertEquals(View.GONE, lockUnlockButton.getVisibility());
+            } else {
+                assertEquals(View.GONE, view.getVisibility());
+            }
+        }
+
+        assertEquals(CONTAINER_HEADER_ELEMENT_COUNT, totalContainerHeaderView);
+        assertEquals(PS_TRANSITION_IMAGE_COUNT, totalLockUnlockButtonView);
+    }
+
+    @Test
+    public void scrollForViewToBeVisibleInContainer_withHeader() {
+        when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
+        when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
+                .thenReturn(iteminfo -> iteminfo.componentName == null
+                        || !iteminfo.componentName.getPackageName()
+                        .equals(CAMERA_PACKAGE_NAME));
+        doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
+        doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
+                .addPrivateSpaceHeader(any());
+        doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
+        doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
+        when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
+        when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
+        mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
+                null, privateProfileManager);
+        mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
+        mAlphabeticalAppsList.updateItemFilter(info -> info != null
+                && info.user.equals(MAIN_HANDLE));
+
+        int rows = (int) (ALL_APPS_HEIGHT - PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT);
+        int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1;
+
+        // The number of adapterItems should be the private space apps + one main app + header.
+        assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1,
+                mAlphabeticalAppsList.getAdapterItems().size());
+        assertEquals(position,
+                privateProfileManager.scrollForHeaderToBeVisibleInContainer(
+                        new AllAppsRecyclerView(mContext),
+                        mAlphabeticalAppsList.getAdapterItems(),
+                        PS_HEADER_HEIGHT,
+                        ALL_APPS_CELL_HEIGHT));
+    }
+
+    @Test
+    public void scrollForViewToBeVisibleInContainer_withHeaderAndLessAppRowSpace() {
+        when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
+        when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
+                .thenReturn(iteminfo -> iteminfo.componentName == null
+                        || !iteminfo.componentName.getPackageName()
+                        .equals(CAMERA_PACKAGE_NAME));
+        doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
+        doAnswer(answer(this::addPrivateSpaceHeader)).when(privateProfileManager)
+                .addPrivateSpaceHeader(any());
+        doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
+        doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
+        when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
+        when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
+        mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
+                null, privateProfileManager);
+        mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
+        mAlphabeticalAppsList.updateItemFilter(info -> info != null
+                && info.user.equals(MAIN_HANDLE));
+
+        int rows = (int) (ALL_APPS_HEIGHT - BIGGER_PS_HEADER_HEIGHT - HEADER_PROTECTION_HEIGHT);
+        int position = rows * NUM_APP_COLS - (NUM_APP_COLS-1) + 1;
+
+        // The number of adapterItems should be the private space apps + one main app + header.
+        assertEquals(NUM_PRIVATE_SPACE_APPS + 1 + 1,
+                mAlphabeticalAppsList.getAdapterItems().size());
+        assertEquals(position,
+                privateProfileManager.scrollForHeaderToBeVisibleInContainer(
+                        new AllAppsRecyclerView(mContext),
+                        mAlphabeticalAppsList.getAdapterItems(),
+                        BIGGER_PS_HEADER_HEIGHT,
+                        ALL_APPS_CELL_HEIGHT));
+    }
+
+    @Test
+    public void scrollForViewToBeVisibleInContainer_withNoHeader() {
+        when(mAllAppsStore.getApps()).thenReturn(createAppInfoList());
+        PrivateProfileManager privateProfileManager = spy(mPrivateProfileManager);
+        when(privateProfileManager.getCurrentState()).thenReturn(STATE_ENABLED);
+        when(privateProfileManager.splitIntoUserInstalledAndSystemApps())
+                .thenReturn(iteminfo -> iteminfo.componentName == null
+                        || !iteminfo.componentName.getPackageName()
+                        .equals(CAMERA_PACKAGE_NAME));
+        doReturn(0).when(privateProfileManager).addPrivateSpaceHeader(any());
+        doNothing().when(privateProfileManager).addPrivateSpaceInstallAppButton(any());
+        doReturn(0).when(privateProfileManager).addSystemAppsDivider(any());
+        when(mAllApps.getHeight()).thenReturn(ALL_APPS_HEIGHT);
+        when(mAllApps.getHeaderProtectionHeight()).thenReturn(HEADER_PROTECTION_HEIGHT);
+        mAlphabeticalAppsList = new AlphabeticalAppsList<>(mContext, mAllAppsStore,
+                null, privateProfileManager);
+        mAlphabeticalAppsList.setNumAppsPerRowAllApps(NUM_APP_COLS);
+        mAlphabeticalAppsList.updateItemFilter(info -> info != null
+                && info.user.equals(MAIN_HANDLE));
+
+        // The number of adapterItems should be the private space apps + one main app.
+        assertEquals(NUM_PRIVATE_SPACE_APPS + 1,
+                mAlphabeticalAppsList.getAdapterItems().size());
+        assertEquals(SCROLL_NO_WHERE, privateProfileManager.scrollForHeaderToBeVisibleInContainer(
+                new AllAppsRecyclerView(mContext),
+                mAlphabeticalAppsList.getAdapterItems(),
+                BIGGER_PS_HEADER_HEIGHT,
+                ALL_APPS_CELL_HEIGHT));
+    }
+
+    private Bitmap getBitmap(Drawable drawable) {
+        Bitmap result;
+        if (drawable instanceof BitmapDrawable) {
+            result = ((BitmapDrawable) drawable).getBitmap();
+        } else {
+            int width = drawable.getIntrinsicWidth();
+            int height = drawable.getIntrinsicHeight();
+            // Some drawables have no intrinsic width - e.g. solid colours.
+            if (width <= 0) {
+                width = 1;
+            }
+            if (height <= 0) {
+                height = 1;
+            }
+
+            result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+            Canvas canvas = new Canvas(result);
+            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
+            drawable.draw(canvas);
+        }
+        return result;
+    }
+
+    private static void awaitTasksCompleted() throws Exception {
+        UI_HELPER_EXECUTOR.submit(() -> null).get();
+    }
+
+    private int addPrivateSpaceHeader(List<BaseAllAppsAdapter.AdapterItem> adapterItemList) {
+        BaseAllAppsAdapter.AdapterItem privateSpaceHeader =
+                new BaseAllAppsAdapter.AdapterItem(VIEW_TYPE_PRIVATE_SPACE_HEADER);
+        adapterItemList.add(privateSpaceHeader);
+        return adapterItemList.size();
+    }
+
+    private AppInfo[] createAppInfoList() {
+        List<AppInfo> appInfos = new ArrayList<>();
+        ComponentName gmailComponentName = new ComponentName(mContext,
+                "com.android.launcher3.tests.Activity" + "Gmail");
+        AppInfo gmailAppInfo = new
+                AppInfo(gmailComponentName, "Gmail", MAIN_HANDLE, new Intent());
+        appInfos.add(gmailAppInfo);
+        ComponentName privateCameraComponentName = new ComponentName(
+                CAMERA_PACKAGE_NAME, "CameraActivity");
+        for (int i = 0; i < NUM_PRIVATE_SPACE_APPS; i++) {
+            AppInfo privateCameraAppInfo = new AppInfo(privateCameraComponentName,
+                    "Private Camera " + i, PRIVATE_HANDLE, new Intent());
+            appInfos.add(privateCameraAppInfo);
+        }
+        return appInfos.toArray(AppInfo[]::new);
+    }
+}
diff --git a/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java b/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java
index 10e9f8a..0b233e5 100644
--- a/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplAllAppsIconsWorkingTest.java
@@ -18,6 +18,7 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.tapl.AppIcon;
 import com.android.launcher3.tapl.HomeAllApps;
@@ -30,7 +31,7 @@
  * The test runs in Out of process (Oop) and in process.
  * Makes sure the basic behaviors of Icons on AllApps are working.
  */
-public class TaplAllAppsIconsWorkingTest extends AbstractLauncherUiTest {
+public class TaplAllAppsIconsWorkingTest extends AbstractLauncherUiTest<Launcher> {
 
     /**
      * Makes sure we can launch an icon from All apps
diff --git a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
index 0360470..20684eb 100644
--- a/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplKeyboardFocusTest.java
@@ -26,6 +26,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -37,7 +38,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class TaplKeyboardFocusTest extends AbstractLauncherUiTest {
+public class TaplKeyboardFocusTest extends AbstractLauncherUiTest<Launcher> {
 
     @Test
     public void testAllAppsFocusApp() {
diff --git a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
index 4d73f7a..f3f6fa5 100644
--- a/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
+++ b/tests/src/com/android/launcher3/allapps/TaplOpenCloseAllAppsTest.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeFalse;
 import static org.junit.Assume.assumeTrue;
 
 import android.content.Intent;
@@ -29,7 +28,7 @@
 import androidx.test.filters.FlakyTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import com.android.launcher3.Flags;
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.tapl.AllApps;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -42,7 +41,7 @@
  * Test that we can open and close the all apps in multiple situations.
  * The test runs in Out of process (Oop) and in process.
  */
-public class TaplOpenCloseAllAppsTest extends AbstractLauncherUiTest {
+public class TaplOpenCloseAllAppsTest extends AbstractLauncherUiTest<Launcher> {
 
     public static final String READ_DEVICE_CONFIG_PERMISSION =
             "android.permission.READ_DEVICE_CONFIG";
@@ -199,7 +198,6 @@
     public void testPressBackFromAllAppsToHome() {
         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
                 READ_DEVICE_CONFIG_PERMISSION);
-        assumeFalse(Flags.enablePredictiveBackGesture());
         mLauncher
                 .getWorkspace()
                 .switchToAllApps()
diff --git a/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java b/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java
index c69d1b9..55d3252 100644
--- a/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java
+++ b/tests/src/com/android/launcher3/appiconmenu/TaplAppIconMenuTest.java
@@ -38,7 +38,7 @@
  * Tests the AppIconMenu (the menu that appears when you long press an app icon) and also make sure
  * we can launch a shortcut from it.
  */
-public class TaplAppIconMenuTest extends AbstractLauncherUiTest {
+public class TaplAppIconMenuTest extends AbstractLauncherUiTest<Launcher> {
 
     private boolean isOptionsPopupVisible(Launcher launcher) {
         final ArrowPopup<?> popup = launcher.getOptionsPopup();
diff --git a/tests/src/com/android/launcher3/backuprestore/BackupAndRestoreDBSelectionTest.kt b/tests/src/com/android/launcher3/backuprestore/BackupAndRestoreDBSelectionTest.kt
new file mode 100644
index 0000000..479b201
--- /dev/null
+++ b/tests/src/com/android/launcher3/backuprestore/BackupAndRestoreDBSelectionTest.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.backuprestore
+
+import android.platform.test.flag.junit.SetFlagsRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
+import com.android.launcher3.Flags
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.model.ModelDbController
+import com.android.launcher3.util.Executors.MODEL_EXECUTOR
+import com.android.launcher3.util.TestUtil
+import com.android.launcher3.util.rule.BackAndRestoreRule
+import com.android.launcher3.util.rule.setFlags
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Makes sure to test {@code RestoreDbTask#removeOldDBs}, we need to remove all the dbs that are not
+ * the last one used when we restore the device.
+ */
+@RunWith(AndroidJUnit4::class)
+@MediumTest
+class BackupAndRestoreDBSelectionTest {
+
+    @JvmField @Rule var backAndRestoreRule = BackAndRestoreRule()
+
+    @JvmField
+    @Rule
+    val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT)
+
+    @Before
+    fun setUp() {
+        setFlagsRule.setFlags(true, Flags.FLAG_ENABLE_NARROW_GRID_RESTORE)
+    }
+
+    @Test
+    fun oldDatabasesNotPresentAfterRestore() {
+        val dbController = ModelDbController(getInstrumentation().targetContext)
+        dbController.tryMigrateDB(null)
+        TestUtil.runOnExecutorSync(MODEL_EXECUTOR) {
+            assert(backAndRestoreRule.getDatabaseFiles().size == 1) {
+                "There should only be one database after restoring, the last one used. Actual databases ${backAndRestoreRule.getDatabaseFiles()}"
+            }
+            assert(
+                !LauncherPrefs.get(getInstrumentation().targetContext)
+                    .has(LauncherPrefs.RESTORE_DEVICE)
+            ) {
+                "RESTORE_DEVICE shouldn't be present after a backup and restore."
+            }
+        }
+    }
+}
diff --git a/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java b/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java
index aca9765..389d027 100644
--- a/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java
+++ b/tests/src/com/android/launcher3/celllayout/TaplReorderWidgetsTest.java
@@ -30,6 +30,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.MultipageCellLayout;
 import com.android.launcher3.celllayout.board.CellLayoutBoard;
@@ -39,6 +40,7 @@
 import com.android.launcher3.tapl.WidgetResizeFrame;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.util.ModelTestExtensions;
+import com.android.launcher3.util.rule.ScreenRecordRule;
 import com.android.launcher3.util.rule.ShellCommandRule;
 
 import org.junit.After;
@@ -58,7 +60,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class TaplReorderWidgetsTest extends AbstractLauncherUiTest {
+public class TaplReorderWidgetsTest extends AbstractLauncherUiTest<Launcher> {
 
     @Rule
     public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@@ -236,6 +238,7 @@
     }
 
     @Test
+    @ScreenRecordRule.ScreenRecord // b/330019521
     public void simpleReorder() throws Exception {
         runTestCaseMap(getTestMap("ReorderWidgets/simple_reorder_case"),
                 "push_reorder_case");
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt b/tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
index c5dbce4..ff46987 100644
--- a/tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
+++ b/tests/src/com/android/launcher3/celllayout/testgenerator/RandomBoardGenerator.kt
@@ -21,6 +21,13 @@
 
 /** Generates a random CellLayoutBoard. */
 open class RandomBoardGenerator(generator: Random) : DeterministicRandomGenerator(generator) {
+
+    companion object {
+        // This is the max number of widgets because we encode the widgets as letters A-Z and we
+        // already have some of those letter used by other things so 22 is a safe number
+        val MAX_NUMBER_OF_WIDGETS = 22
+    }
+
     /**
      * @param remainingEmptySpaces the maximum number of spaces we will fill with icons and widgets
      *   meaning that if the number is 100 we will try to fill the board with at most 100 spaces
@@ -33,9 +40,9 @@
     }
 
     protected fun fillBoard(
-            board: CellLayoutBoard,
-            area: Rect,
-            remainingEmptySpacesArg: Int
+        board: CellLayoutBoard,
+        area: Rect,
+        remainingEmptySpacesArg: Int
     ): CellLayoutBoard {
         var remainingEmptySpaces = remainingEmptySpacesArg
         if (area.height() * area.width() <= 0) return board
@@ -45,11 +52,18 @@
         val y = area.top + getRandom(0, area.height() - height)
         if (remainingEmptySpaces > 0) {
             remainingEmptySpaces -= width * height
-        } else if (board.widgets.size <= 22 && width * height > 1) {
+        }
+
+        if (board.widgets.size <= MAX_NUMBER_OF_WIDGETS && width * height > 1) {
             board.addWidget(x, y, width, height)
         } else {
             board.addIcon(x, y)
         }
+
+        if (remainingEmptySpaces < 0) {
+            // optimization, no need to keep going
+            return board
+        }
         fillBoard(board, Rect(area.left, area.top, area.right, y), remainingEmptySpaces)
         fillBoard(board, Rect(area.left, y, x, area.bottom), remainingEmptySpaces)
         fillBoard(board, Rect(x, y + height, area.right, area.bottom), remainingEmptySpaces)
diff --git a/tests/src/com/android/launcher3/celllayout/testgenerator/ValidGridMigrationTestCaseGenerator.kt b/tests/src/com/android/launcher3/celllayout/testgenerator/ValidGridMigrationTestCaseGenerator.kt
new file mode 100644
index 0000000..a006fd7
--- /dev/null
+++ b/tests/src/com/android/launcher3/celllayout/testgenerator/ValidGridMigrationTestCaseGenerator.kt
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.celllayout.testgenerator
+
+import android.graphics.Point
+import com.android.launcher3.LauncherSettings
+import com.android.launcher3.celllayout.board.CellLayoutBoard
+import com.android.launcher3.model.data.LauncherAppWidgetInfo
+import com.android.launcher3.model.gridmigration.WorkspaceItem
+import java.util.Random
+import java.util.concurrent.atomic.AtomicInteger
+
+/**
+ * Generate a list of WorkspaceItem's for the given test case.
+ *
+ * @param repeatAfter a number after which we would repeat the same number of icons and widgets to
+ *   account for cases where the user have the same item multiple times.
+ */
+fun generateItemsForTest(
+    boards: List<CellLayoutBoard>,
+    repeatAfterRange: Point
+): List<WorkspaceItem> {
+    val id = AtomicInteger(0)
+    val widgetId = AtomicInteger(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - 1)
+    // Repeat the same appWidgetProvider and intent to have repeating widgets and icons and test
+    // that case too
+    val getIntent = { i: Int -> "Intent ${(i + repeatAfterRange.x) % repeatAfterRange.y}" }
+    val getProvider = { i: Int ->
+        "com.test/test.Provider${(i + repeatAfterRange.x) % repeatAfterRange.y }"
+    }
+    val hotseatEntries =
+        (0 until boards[0].width).map {
+            WorkspaceItem(
+                x = it,
+                y = 0,
+                spanX = 1,
+                spanY = 1,
+                id = id.getAndAdd(1),
+                screenId = it,
+                title = "Hotseat ${id.get()}",
+                appWidgetId = -1,
+                appWidgetProvider = "Hotseat icons don't have a provider",
+                intent = getIntent(id.get()),
+                type = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION,
+                container = LauncherSettings.Favorites.CONTAINER_HOTSEAT
+            )
+        }
+    var widgetEntries =
+        boards
+            .flatMapIndexed { i, board -> board.widgets.map { Pair(i, it) } }
+            .map {
+                WorkspaceItem(
+                    x = it.second.cellX,
+                    y = it.second.cellY,
+                    spanX = it.second.spanX,
+                    spanY = it.second.spanY,
+                    id = id.getAndAdd(1),
+                    screenId = it.first,
+                    title = "Title Widget ${id.get()}",
+                    appWidgetId = widgetId.getAndAdd(-1),
+                    appWidgetProvider = getProvider(id.get()),
+                    intent = "Widgets don't have intent",
+                    type = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET,
+                    container = LauncherSettings.Favorites.CONTAINER_DESKTOP
+                )
+            }
+    widgetEntries = widgetEntries.filter { it.appWidgetProvider.contains("Provider4") }
+    val iconEntries =
+        boards
+            .flatMapIndexed { i, board -> board.icons.map { Pair(i, it) } }
+            .map {
+                WorkspaceItem(
+                    x = it.second.coord.x,
+                    y = it.second.coord.y,
+                    spanX = 1,
+                    spanY = 1,
+                    id = id.getAndAdd(1),
+                    screenId = it.first,
+                    title = "Title Icon ${id.get()}",
+                    appWidgetId = -1,
+                    appWidgetProvider = "Icons don't have providers",
+                    intent = getIntent(id.get()),
+                    type = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION,
+                    container = LauncherSettings.Favorites.CONTAINER_DESKTOP
+                )
+            }
+    return widgetEntries + hotseatEntries + iconEntries
+}
+
+data class GridMigrationUnitTestCase(
+    val boards: List<CellLayoutBoard>,
+    val destBoards: List<CellLayoutBoard>,
+    val srcSize: Point,
+    val targetSize: Point,
+    val seed: Long
+)
+
+class ValidGridMigrationTestCaseGenerator(private val generator: Random) :
+    DeterministicRandomGenerator(generator) {
+
+    companion object {
+        const val MAX_BOARD_SIZE = 12
+        const val MAX_BOARD_COUNT = 10
+        const val SEED = 10342
+    }
+
+    private fun generateBoards(
+        boardGenerator: RandomBoardGenerator,
+        width: Int,
+        height: Int,
+        boardCount: Int
+    ): List<CellLayoutBoard> {
+        val boards = mutableListOf<CellLayoutBoard>()
+        for (i in 0 until boardCount) {
+            boards.add(
+                boardGenerator.generateBoard(
+                    width,
+                    height,
+                    boardGenerator.getRandom(0, width * height)
+                )
+            )
+        }
+        return boards
+    }
+
+    fun generateTestCase(isDestEmpty: Boolean): GridMigrationUnitTestCase {
+        val seed = generator.nextLong()
+        val randomBoardGenerator = RandomBoardGenerator(Random(seed))
+        val width = randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE)
+        val height = randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE)
+        val targetSize =
+            Point(
+                randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE),
+                randomBoardGenerator.getRandom(3, MAX_BOARD_SIZE)
+            )
+        val destBoards =
+            if (isDestEmpty) {
+                listOf()
+            } else {
+                generateBoards(
+                    boardGenerator = randomBoardGenerator,
+                    width = targetSize.x,
+                    height = targetSize.y,
+                    boardCount = randomBoardGenerator.getRandom(3, MAX_BOARD_COUNT)
+                )
+            }
+        return GridMigrationUnitTestCase(
+            boards =
+                generateBoards(
+                    boardGenerator = randomBoardGenerator,
+                    width = width,
+                    height = height,
+                    boardCount = randomBoardGenerator.getRandom(3, MAX_BOARD_COUNT)
+                ),
+            destBoards = destBoards,
+            srcSize = Point(width, height),
+            targetSize = targetSize,
+            seed = seed
+        )
+    }
+}
diff --git a/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java b/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java
index 7ed0fa5..1500538 100644
--- a/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java
+++ b/tests/src/com/android/launcher3/compat/TaplPromiseIconUiTest.java
@@ -52,7 +52,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplPromiseIconUiTest extends AbstractLauncherUiTest {
+public class TaplPromiseIconUiTest extends AbstractLauncherUiTest<Launcher> {
 
     @Rule
     public final CheckFlagsRule mCheckFlagsRule =
diff --git a/tests/src/com/android/launcher3/dragging/TaplDragTest.java b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
index bf1ba39..d64d096 100644
--- a/tests/src/com/android/launcher3/dragging/TaplDragTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplDragTest.java
@@ -33,6 +33,7 @@
 import android.platform.test.annotations.PlatinumTest;
 import android.util.Log;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.tapl.Folder;
 import com.android.launcher3.tapl.FolderIcon;
 import com.android.launcher3.tapl.HomeAllApps;
@@ -57,7 +58,7 @@
  *    * Can drag an icon from AllApps into the workspace
  *    * Can drag an icon on the Workspace to other positions of the Workspace.
  */
-public class TaplDragTest extends AbstractLauncherUiTest {
+public class TaplDragTest extends AbstractLauncherUiTest<Launcher> {
 
     /**
      * Adds two icons to the Workspace and combines them into a folder, then makes sure the icons
diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
index e21309f..df71ec0 100644
--- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
+++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java
@@ -17,7 +17,6 @@
 
 import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING;
 import static com.android.launcher3.testing.shared.TestProtocol.UIOBJECT_STALE_ELEMENT;
-import static com.android.launcher3.ui.AbstractLauncherUiTest.initialize;
 import static com.android.launcher3.util.TestConstants.AppNames.DUMMY_APP_NAME;
 import static com.android.launcher3.util.TestConstants.AppNames.GMAIL_APP_NAME;
 import static com.android.launcher3.util.TestConstants.AppNames.MAPS_APP_NAME;
@@ -32,6 +31,7 @@
 import android.platform.test.annotations.PlatinumTest;
 import android.util.Log;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.tapl.HomeAppIcon;
 import com.android.launcher3.tapl.Workspace;
@@ -51,7 +51,7 @@
  * Test runs in Out of process (Oop) and In process (Ipc)
  * Test the behaviour of uninstalling and removing apps both from AllApps, Workspace and Hotseat.
  */
-public class TaplUninstallRemoveTest extends AbstractLauncherUiTest {
+public class TaplUninstallRemoveTest extends AbstractLauncherUiTest<Launcher> {
 
     /**
      * Deletes app both built-in and user-installed from the Workspace and makes sure it's no longer
diff --git a/tests/src/com/android/launcher3/model/GridMigrationTest.kt b/tests/src/com/android/launcher3/model/GridMigrationTest.kt
new file mode 100644
index 0000000..15222a4
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/GridMigrationTest.kt
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model
+
+import android.platform.test.flag.junit.SetFlagsRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.Flags
+import com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE
+import com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME
+import com.android.launcher3.celllayout.board.CellLayoutBoard
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.util.rule.TestToPhoneFileCopier
+import com.android.launcher3.util.rule.setFlags
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private val phoneContext = InstrumentationRegistry.getInstrumentation().targetContext
+
+data class EntryData(val x: Int, val y: Int, val spanX: Int, val spanY: Int, val rank: Int)
+
+/**
+ * Holds the data needed to run a test in GridMigrationTest, usually we would have a src
+ * GridMigrationData and a dst GridMigrationData meaning the data after a migration has occurred.
+ * This class holds a gridState, which is the size of the grid like 5x5 (among other things). a
+ * dbHelper which contains the readable database and writable database used to migrate the
+ * databases.
+ *
+ * You can also get all the entries defined in the dbHelper database.
+ */
+class GridMigrationData(dbFileName: String?, val gridState: DeviceGridState) {
+
+    val dbHelper: DatabaseHelper =
+        DatabaseHelper(
+            phoneContext,
+            dbFileName,
+            { UserCache.INSTANCE.get(phoneContext).getSerialNumberForUser(it) },
+            {}
+        )
+
+    fun readEntries(): List<GridSizeMigrationUtil.DbEntry> =
+        GridSizeMigrationUtil.readAllEntries(dbHelper.readableDatabase, TABLE_NAME, phoneContext)
+}
+
+/**
+ * Test the migration of a database from one size to another. It reads a database from the test
+ * assets, uploads it into the phone and migrates the database to a database in memory which is
+ * later compared against a database in the test assets to make sure they are identical.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class GridMigrationTest {
+    private val DB_FILE = "test_launcher.db"
+
+    @JvmField
+    @Rule
+    val setFlagsRule = SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT)
+
+    // Copying the src db for all tests.
+    @JvmField
+    @Rule
+    val fileCopier =
+        TestToPhoneFileCopier(
+            src = "databases/GridMigrationTest/$DB_FILE",
+            dest = "databases/$DB_FILE",
+            removeOnFinish = true
+        )
+
+    @Before
+    fun setup() {
+        setFlagsRule.setFlags(false, Flags.FLAG_ENABLE_GRID_MIGRATION_FIX)
+    }
+
+    private fun migrate(src: GridMigrationData, dst: GridMigrationData) {
+        GridSizeMigrationUtil.migrateGridIfNeeded(
+            phoneContext,
+            src.gridState,
+            dst.gridState,
+            dst.dbHelper,
+            src.dbHelper.readableDatabase
+        )
+    }
+
+    /**
+     * Makes sure that none of the items overlaps on the result, i.e. no widget or icons share the
+     * same space in the db.
+     */
+    private fun validateDb(data: GridMigrationData) {
+        // The array size is just a big enough number to fit all the number of workspaces
+        val boards = Array(100) { CellLayoutBoard(data.gridState.columns, data.gridState.rows) }
+        data.readEntries().forEach {
+            val cellLayoutBoard = boards[it.screenId]
+            assert(cellLayoutBoard.isEmpty(it.cellX, it.cellY, it.spanX, it.spanY)) {
+                "Db has overlapping items"
+            }
+            cellLayoutBoard.addWidget(it.cellX, it.cellY, it.spanX, it.spanY)
+        }
+    }
+
+    private fun compare(dst: GridMigrationData, target: GridMigrationData) {
+        val sort = compareBy<GridSizeMigrationUtil.DbEntry>({ it.cellX }, { it.cellY })
+        val mapF = { it: GridSizeMigrationUtil.DbEntry ->
+            EntryData(it.cellX, it.cellY, it.spanX, it.spanY, it.rank)
+        }
+        val entriesDst = dst.readEntries().sortedWith(sort).map(mapF)
+        val entriesTarget = target.readEntries().sortedWith(sort).map(mapF)
+
+        assert(entriesDst == entriesTarget) {
+            "The elements on the dst database is not the same as in the target"
+        }
+    }
+
+    /**
+     * Migrate src into dst and compare to target. This method validates 3 things:
+     * 1. dst has the same number of items as src after the migration, meaning, none of the items
+     *    were removed during the migration.
+     * 2. dst is valid, meaning that none of the items overlap with each other.
+     * 3. dst is equal to target to ensure we don't unintentionally change the migration logic.
+     */
+    private fun runTest(src: GridMigrationData, dst: GridMigrationData, target: GridMigrationData) {
+        migrate(src, dst)
+        assert(src.readEntries().size == dst.readEntries().size) {
+            "Source db and destination db do not contain the same number of elements"
+        }
+        validateDb(dst)
+        compare(dst, target)
+    }
+
+    @JvmField
+    @Rule
+    val result5x5to3x3 =
+        TestToPhoneFileCopier(
+            src = "databases/GridMigrationTest/result5x5to3x3.db",
+            dest = "databases/result5x5to3x3.db",
+            removeOnFinish = true
+        )
+
+    @Test
+    fun `5x5 to 3x3`() =
+        runTest(
+            src = GridMigrationData(DB_FILE, DeviceGridState(5, 5, 5, TYPE_PHONE, DB_FILE)),
+            dst =
+                GridMigrationData(
+                    null, // in memory db, to download a new db change null for the filename of the
+                    // db name to store it. Do not use existing names.
+                    DeviceGridState(3, 3, 3, TYPE_PHONE, "")
+                ),
+            target =
+                GridMigrationData("result5x5to3x3.db", DeviceGridState(3, 3, 3, TYPE_PHONE, ""))
+        )
+
+    @JvmField
+    @Rule
+    val result5x5to4x7 =
+        TestToPhoneFileCopier(
+            src = "databases/GridMigrationTest/result5x5to4x7.db",
+            dest = "databases/result5x5to4x7.db",
+            removeOnFinish = true
+        )
+
+    @Test
+    fun `5x5 to 4x7`() =
+        runTest(
+            src = GridMigrationData(DB_FILE, DeviceGridState(5, 5, 5, TYPE_PHONE, DB_FILE)),
+            dst =
+                GridMigrationData(
+                    null, // in memory db, to download a new db change null for the filename of the
+                    // db name to store it. Do not use existing names.
+                    DeviceGridState(4, 7, 4, TYPE_PHONE, "")
+                ),
+            target =
+                GridMigrationData("result5x5to4x7.db", DeviceGridState(4, 7, 4, TYPE_PHONE, ""))
+        )
+
+    @JvmField
+    @Rule
+    val result5x5to5x8 =
+        TestToPhoneFileCopier(
+            src = "databases/GridMigrationTest/result5x5to5x8.db",
+            dest = "databases/result5x5to5x8.db",
+            removeOnFinish = true
+        )
+
+    @Test
+    fun `5x5 to 5x8`() =
+        runTest(
+            src = GridMigrationData(DB_FILE, DeviceGridState(5, 5, 5, TYPE_PHONE, DB_FILE)),
+            dst =
+                GridMigrationData(
+                    null, // in memory db, to download a new db change null for the filename of the
+                    // db name to store it. Do not use existing names.
+                    DeviceGridState(5, 8, 5, TYPE_PHONE, "")
+                ),
+            target =
+                GridMigrationData("result5x5to5x8.db", DeviceGridState(5, 8, 5, TYPE_PHONE, ""))
+        )
+
+    @JvmField
+    @Rule
+    val flaggedResult5x5to5x8 =
+        TestToPhoneFileCopier(
+            src = "databases/GridMigrationTest/flagged_result5x5to5x8.db",
+            dest = "databases/flagged_result5x5to5x8.db",
+            removeOnFinish = true
+        )
+
+    @Test
+    fun `flagged 5x5 to 5x8`() {
+        setFlagsRule.setFlags(true, Flags.FLAG_ENABLE_GRID_MIGRATION_FIX)
+        runTest(
+            src = GridMigrationData(DB_FILE, DeviceGridState(5, 5, 5, TYPE_PHONE, DB_FILE)),
+            dst =
+                GridMigrationData(
+                    null, // in memory db, to download a new db change null for the filename of the
+                    // db name to store it. Do not use existing names.
+                    DeviceGridState(5, 8, 5, TYPE_PHONE, "")
+                ),
+            target =
+                GridMigrationData(
+                    "flagged_result5x5to5x8.db",
+                    DeviceGridState(5, 8, 5, TYPE_PHONE, "")
+                )
+        )
+    }
+}
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 04735f2..761f06d 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -28,7 +28,6 @@
 import com.android.launcher3.LauncherPrefs
 import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
 import com.android.launcher3.LauncherSettings.Favorites.*
-import com.android.launcher3.config.FeatureFlags
 import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
 import com.android.launcher3.pm.UserCache
 import com.android.launcher3.provider.LauncherDbUtils
@@ -98,10 +97,7 @@
         modelHelper.destroy()
     }
 
-    /**
-     * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
-     * needed anymore
-     */
+    /** Old migration logic, should be modified once is not needed anymore */
     @Test
     @Throws(Exception::class)
     fun testMigration() {
@@ -208,10 +204,7 @@
         assertThat(locMap[testPackage9]).isEqualTo(Point(0, 2))
     }
 
-    /**
-     * Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
-     * needed anymore
-     */
+    /** Old migration logic, should be modified once is not needed anymore */
     @Test
     @Throws(Exception::class)
     fun testMigrationBackAndForth() {
@@ -606,68 +599,6 @@
     }
 
     /**
-     * Migrating from a smaller grid to a large one should keep the pages if the column difference
-     * is less than 2
-     */
-    @Test
-    @Throws(Exception::class)
-    fun migrateFromSmallerGridSmallDifference() {
-        enableNewMigrationLogic("4,4")
-
-        // Setup src grid
-        addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage1, 5, TMP_TABLE)
-        addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage2, 6, TMP_TABLE)
-        addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 1, testPackage3, 7, TMP_TABLE)
-        addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 2, testPackage4, 8, TMP_TABLE)
-        addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 3, 3, testPackage5, 9, TMP_TABLE)
-
-        idp.numDatabaseHotseatIcons = 4
-        idp.numColumns = 6
-        idp.numRows = 5
-
-        val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
-        val destReader = DbReader(db, TABLE_NAME, context, validPackages)
-        GridSizeMigrationUtil.migrate(
-            dbHelper,
-            srcReader,
-            destReader,
-            idp.numDatabaseHotseatIcons,
-            Point(idp.numColumns, idp.numRows),
-            DeviceGridState(context),
-            DeviceGridState(idp)
-        )
-
-        // Get workspace items
-        val c =
-            db.query(
-                TABLE_NAME,
-                arrayOf(INTENT, SCREEN),
-                "container=$CONTAINER_DESKTOP",
-                null,
-                null,
-                null,
-                null
-            )
-                ?: throw IllegalStateException()
-        val intentIndex = c.getColumnIndex(INTENT)
-        val screenIndex = c.getColumnIndex(SCREEN)
-
-        // Get in which screen the icon is
-        val locMap = HashMap<String?, Int>()
-        while (c.moveToNext()) {
-            locMap[Intent.parseUri(c.getString(intentIndex), 0).getPackage()] =
-                c.getInt(screenIndex)
-        }
-        c.close()
-        assertThat(locMap.size).isEqualTo(5)
-        assertThat(locMap[testPackage1]).isEqualTo(0)
-        assertThat(locMap[testPackage2]).isEqualTo(0)
-        assertThat(locMap[testPackage3]).isEqualTo(1)
-        assertThat(locMap[testPackage4]).isEqualTo(1)
-        assertThat(locMap[testPackage5]).isEqualTo(2)
-    }
-
-    /**
      * Migrating from a smaller grid to a large one should reflow the pages if the column difference
      * is more than 2
      */
diff --git a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
index 3d10a85..5731e2a 100644
--- a/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/LoaderTaskTest.kt
@@ -46,7 +46,7 @@
     @Mock private lateinit var app: LauncherAppState
     @Mock private lateinit var bgAllAppsList: AllAppsList
     @Mock private lateinit var modelDelegate: ModelDelegate
-    @Mock private lateinit var launcherBinder: LauncherBinder
+    @Mock private lateinit var launcherBinder: BaseLauncherBinder
     @Mock private lateinit var launcherModel: LauncherModel
     @Mock private lateinit var transaction: LoaderTransaction
     @Mock private lateinit var iconCache: IconCache
diff --git a/tests/src/com/android/launcher3/model/gridmigration/GridMigrationUtils.kt b/tests/src/com/android/launcher3/model/gridmigration/GridMigrationUtils.kt
new file mode 100644
index 0000000..cc8e61d
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/gridmigration/GridMigrationUtils.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model.gridmigration
+
+import android.content.ContentValues
+import android.database.sqlite.SQLiteDatabase
+import android.graphics.Point
+import com.android.launcher3.LauncherSettings.Favorites
+import com.android.launcher3.celllayout.board.CellLayoutBoard
+
+class MockSet(override val size: Int) : Set<String> {
+    override fun contains(element: String): Boolean = true
+    override fun containsAll(elements: Collection<String>): Boolean = true
+    override fun isEmpty(): Boolean = false
+    override fun iterator(): Iterator<String> = listOf<String>().iterator()
+}
+
+fun itemListToBoard(itemsArg: List<WorkspaceItem>, boardSize: Point): List<CellLayoutBoard> {
+    val items = itemsArg.filter { it.container != Favorites.CONTAINER_HOTSEAT }
+    val boardList =
+        List(items.maxOf { it.screenId + 1 }) { CellLayoutBoard(boardSize.x, boardSize.y) }
+    items.forEach {
+        when (it.type) {
+            Favorites.ITEM_TYPE_FOLDER,
+            Favorites.ITEM_TYPE_APP_PAIR -> throw Exception("Not implemented")
+            Favorites.ITEM_TYPE_APPWIDGET ->
+                boardList[it.screenId].addWidget(it.x, it.y, it.spanX, it.spanY)
+            Favorites.ITEM_TYPE_APPLICATION -> boardList[it.screenId].addIcon(it.x, it.y)
+        }
+    }
+    return boardList
+}
+
+fun insertIntoDb(tableName: String, entry: WorkspaceItem, db: SQLiteDatabase) {
+    val values = ContentValues()
+    values.put(Favorites.SCREEN, entry.screenId)
+    values.put(Favorites.CELLX, entry.x)
+    values.put(Favorites.CELLY, entry.y)
+    values.put(Favorites.SPANX, entry.spanX)
+    values.put(Favorites.SPANY, entry.spanY)
+    values.put(Favorites.TITLE, entry.title)
+    values.put(Favorites.INTENT, entry.intent)
+    values.put(Favorites.APPWIDGET_PROVIDER, entry.appWidgetProvider)
+    values.put(Favorites.APPWIDGET_ID, entry.appWidgetId)
+    values.put(Favorites.CONTAINER, entry.container)
+    values.put(Favorites.ITEM_TYPE, entry.type)
+    values.put(Favorites._ID, entry.id)
+    db.insert(tableName, null, values)
+}
+
+fun readDb(tableName: String, db: SQLiteDatabase): List<WorkspaceItem> {
+    val result = mutableListOf<WorkspaceItem>()
+    val cursor = db.query(tableName, null, null, null, null, null, null)
+    val indexCellX: Int = cursor.getColumnIndexOrThrow(Favorites.CELLX)
+    val indexCellY: Int = cursor.getColumnIndexOrThrow(Favorites.CELLY)
+    val indexSpanX: Int = cursor.getColumnIndexOrThrow(Favorites.SPANX)
+    val indexSpanY: Int = cursor.getColumnIndexOrThrow(Favorites.SPANY)
+    val indexId: Int = cursor.getColumnIndexOrThrow(Favorites._ID)
+    val indexScreen: Int = cursor.getColumnIndexOrThrow(Favorites.SCREEN)
+    val indexTitle: Int = cursor.getColumnIndexOrThrow(Favorites.TITLE)
+    val indexAppWidgetId: Int = cursor.getColumnIndexOrThrow(Favorites.APPWIDGET_ID)
+    val indexWidgetProvider: Int = cursor.getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER)
+    val indexIntent: Int = cursor.getColumnIndexOrThrow(Favorites.INTENT)
+    val indexItemType: Int = cursor.getColumnIndexOrThrow(Favorites.ITEM_TYPE)
+    val container: Int = cursor.getColumnIndexOrThrow(Favorites.CONTAINER)
+    while (cursor.moveToNext()) {
+        result.add(
+            WorkspaceItem(
+                x = cursor.getInt(indexCellX),
+                y = cursor.getInt(indexCellY),
+                spanX = cursor.getInt(indexSpanX),
+                spanY = cursor.getInt(indexSpanY),
+                id = cursor.getInt(indexId),
+                screenId = cursor.getInt(indexScreen),
+                title = cursor.getString(indexTitle),
+                appWidgetId = cursor.getInt(indexAppWidgetId),
+                appWidgetProvider = cursor.getString(indexWidgetProvider),
+                intent = cursor.getString(indexIntent),
+                type = cursor.getInt(indexItemType),
+                container = cursor.getInt(container)
+            )
+        )
+    }
+    return result
+}
+
+data class WorkspaceItem(
+    val x: Int,
+    val y: Int,
+    val spanX: Int,
+    val spanY: Int,
+    val id: Int,
+    val screenId: Int,
+    val title: String,
+    val appWidgetId: Int,
+    val appWidgetProvider: String,
+    val intent: String,
+    val type: Int,
+    val container: Int,
+)
diff --git a/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt b/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
new file mode 100644
index 0000000..58b915f
--- /dev/null
+++ b/tests/src/com/android/launcher3/model/gridmigration/ValidGridMigrationUnitTest.kt
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.model.gridmigration
+
+import android.content.Context
+import android.database.sqlite.SQLiteDatabase
+import android.graphics.Point
+import android.os.Process
+import android.util.Log
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherSettings.Favorites
+import com.android.launcher3.celllayout.testgenerator.ValidGridMigrationTestCaseGenerator
+import com.android.launcher3.celllayout.testgenerator.generateItemsForTest
+import com.android.launcher3.model.DatabaseHelper
+import com.android.launcher3.model.DeviceGridState
+import com.android.launcher3.model.GridSizeMigrationUtil
+import com.android.launcher3.pm.UserCache
+import com.android.launcher3.provider.LauncherDbUtils
+import com.android.launcher3.util.rule.TestStabilityRule
+import com.android.launcher3.util.rule.TestStabilityRule.Stability
+import java.util.Random
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private data class Grid(val tableName: String, val size: Point, val items: List<WorkspaceItem>) {
+    fun toGridState(): DeviceGridState =
+        DeviceGridState(size.x, size.y, size.x, InvariantDeviceProfile.TYPE_PHONE, tableName)
+}
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ValidGridMigrationUnitTest {
+
+    companion object {
+        const val SEED = 1044542
+        val REPEAT_AFTER = Point(0, 10)
+        val REPEAT_AFTER_DST = Point(6, 15)
+        const val TAG = "ValidGridMigrationUnitTest"
+        const val SMALL_TEST_SIZE = 60
+        const val LARGE_TEST_SIZE = 1000
+    }
+
+    private lateinit var context: Context
+
+    @Before
+    fun setUp() {
+        context = InstrumentationRegistry.getInstrumentation().targetContext
+    }
+
+    private fun validate(srcGrid: Grid, dstGrid: Grid, resultItems: List<WorkspaceItem>) {
+        // This returns a map with the number of repeated elements
+        // ex { calculatorIcon : 6, weatherWidget : 2 }
+        val itemsToMap = { it: List<WorkspaceItem> ->
+            it.filter { it.container != Favorites.CONTAINER_HOTSEAT }
+                .groupingBy {
+                    when (it.type) {
+                        Favorites.ITEM_TYPE_FOLDER,
+                        Favorites.ITEM_TYPE_APP_PAIR -> throw Exception("Not implemented")
+                        Favorites.ITEM_TYPE_APPWIDGET -> it.appWidgetProvider
+                        Favorites.ITEM_TYPE_APPLICATION -> it.intent
+                        else -> it.title
+                    }
+                }
+                .eachCount()
+        }
+        resultItems.forEach {
+            assert((it.x in 0..dstGrid.size.x) && (it.y in 0..dstGrid.size.y)) {
+                "Item outside of the board size. Size = ${dstGrid.size} Item = $it"
+            }
+            assert(
+                (it.x + it.spanX in 0..dstGrid.size.x) && (it.y + it.spanY in 0..dstGrid.size.y)
+            ) {
+                "Item doesn't fit in the grid. Size = ${dstGrid.size} Item = $it"
+            }
+        }
+
+        val srcCountMap = itemsToMap(srcGrid.items)
+        val resultCountMap = itemsToMap(resultItems)
+        val diff = resultCountMap - srcCountMap
+
+        diff.forEach { (k, count) ->
+            assert(count >= 0) { "Source item $k not present on the result" }
+        }
+    }
+
+    private fun addItemsToDb(db: SQLiteDatabase, grid: Grid) {
+        LauncherDbUtils.SQLiteTransaction(db).use { transaction ->
+            grid.items.forEach { insertIntoDb(grid.tableName, it, transaction.db) }
+            transaction.commit()
+        }
+    }
+
+    private fun migrate(
+        srcGrid: Grid,
+        dstGrid: Grid,
+    ): List<WorkspaceItem> {
+        val userSerial = UserCache.INSTANCE[context].getSerialNumberForUser(Process.myUserHandle())
+        val dbHelper =
+            DatabaseHelper(
+                context,
+                null,
+                { UserCache.INSTANCE.get(context).getSerialNumberForUser(it) },
+                {}
+            )
+
+        Favorites.addTableToDb(dbHelper.writableDatabase, userSerial, false, srcGrid.tableName)
+
+        addItemsToDb(dbHelper.writableDatabase, srcGrid)
+        addItemsToDb(dbHelper.writableDatabase, dstGrid)
+
+        LauncherDbUtils.SQLiteTransaction(dbHelper.writableDatabase).use {
+            GridSizeMigrationUtil.migrate(
+                dbHelper,
+                GridSizeMigrationUtil.DbReader(it.db, srcGrid.tableName, context, MockSet(1)),
+                GridSizeMigrationUtil.DbReader(it.db, dstGrid.tableName, context, MockSet(1)),
+                dstGrid.size.x,
+                dstGrid.size,
+                srcGrid.toGridState(),
+                dstGrid.toGridState()
+            )
+            it.commit()
+        }
+        return readDb(dstGrid.tableName, dbHelper.readableDatabase)
+    }
+
+    @Test
+    fun runTestCase() {
+        val caseGenerator = ValidGridMigrationTestCaseGenerator(Random(SEED.toLong()))
+        for (i in 0..SMALL_TEST_SIZE) {
+            val testCase = caseGenerator.generateTestCase(isDestEmpty = true)
+            Log.d(TAG, "Test case = $testCase")
+            val srcGrid =
+                Grid(
+                    tableName = Favorites.TMP_TABLE,
+                    size = testCase.srcSize,
+                    items = generateItemsForTest(testCase.boards, REPEAT_AFTER)
+                )
+            val dstGrid =
+                Grid(tableName = Favorites.TABLE_NAME, size = testCase.targetSize, items = listOf())
+            validate(srcGrid, dstGrid, migrate(srcGrid, dstGrid))
+        }
+    }
+
+    @Test
+    fun mergeBoards() {
+        val caseGenerator = ValidGridMigrationTestCaseGenerator(Random(SEED.toLong()))
+        for (i in 0..SMALL_TEST_SIZE) {
+            val testCase = caseGenerator.generateTestCase(isDestEmpty = false)
+            Log.d(TAG, "Test case = $testCase")
+            val srcGrid =
+                Grid(
+                    tableName = Favorites.TMP_TABLE,
+                    size = testCase.srcSize,
+                    items = generateItemsForTest(testCase.boards, REPEAT_AFTER)
+                )
+            val dstGrid =
+                Grid(
+                    tableName = Favorites.TABLE_NAME,
+                    size = testCase.targetSize,
+                    items = generateItemsForTest(testCase.destBoards, REPEAT_AFTER_DST)
+                )
+            validate(srcGrid, dstGrid, migrate(srcGrid, dstGrid))
+        }
+    }
+
+    // This test takes about 4 minutes, there is no need to run it in presubmit.
+    @Stability(flavors = TestStabilityRule.LOCAL or TestStabilityRule.PLATFORM_POSTSUBMIT)
+    @Test
+    fun runExtensiveTestCases() {
+        val caseGenerator = ValidGridMigrationTestCaseGenerator(Random(SEED.toLong()))
+        for (i in 0..LARGE_TEST_SIZE) {
+            val testCase = caseGenerator.generateTestCase(isDestEmpty = true)
+            Log.d(TAG, "Test case = $testCase")
+            val srcGrid =
+                Grid(
+                    tableName = Favorites.TMP_TABLE,
+                    size = testCase.srcSize,
+                    items = generateItemsForTest(testCase.boards, REPEAT_AFTER)
+                )
+            val dstGrid =
+                Grid(tableName = Favorites.TABLE_NAME, size = testCase.targetSize, items = listOf())
+            validate(srcGrid, dstGrid, migrate(srcGrid, dstGrid))
+        }
+    }
+}
diff --git a/tests/src/com/android/launcher3/secondarydisplay/TaplSecondaryDisplayLauncherTest.java b/tests/src/com/android/launcher3/secondarydisplay/TaplSecondaryDisplayLauncherTest.java
deleted file mode 100644
index d7b9638..0000000
--- a/tests/src/com/android/launcher3/secondarydisplay/TaplSecondaryDisplayLauncherTest.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.secondarydisplay;
-
-import static android.content.Context.MODE_PRIVATE;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.view.MotionEvent.ACTION_DOWN;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Intent;
-import android.graphics.Point;
-import android.os.SystemClock;
-import android.view.MotionEvent;
-import android.widget.TextView;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import com.android.launcher3.tapl.LauncherInstrumentation;
-import com.android.launcher3.ui.AbstractLauncherUiTest;
-
-import org.junit.After;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests for {@link SecondaryDisplayLauncher}.
- * TODO (b/242776943): Remove anti-patterns & migrate prediction row tests to Quickstep directory
- */
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public final class TaplSecondaryDisplayLauncherTest extends AbstractLauncherUiTest {
-    private static final int WAIT_TIME_MS = 5000;
-    private static final int LONG_PRESS_DURATION_MS = 1000;
-    private static final int DRAG_TIME_MS = 160;
-
-    private static final String PINNED_APPS_KEY = "pinned_apps";
-
-    // Variables required to coordinate drag steps.
-    private Point mStartPoint;
-    private Point mEndPoint;
-    private long mDownTime;
-
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        setDragNDropFlag(true);
-    }
-
-    @After
-    public void tearDown() {
-        mTargetContext.getSharedPreferences(PINNED_APPS_KEY, MODE_PRIVATE)
-                .edit().clear().commit();
-    }
-
-    @Test
-    @Ignore
-    public void initializeSecondaryDisplayLauncher_allAppsButtonVisible() {
-        assertThat(findObjectByResourceName("all_apps_button")).isNotNull();
-    }
-
-    @Test
-    @Ignore
-    public void allAppsButtonTap_opensAppDrawer() {
-        openAppDrawer();
-        assertThat(findObjectByResourceName("search_container_all_apps")).isNotNull();
-    }
-
-    @Test
-    @Ignore("Launcher3 without quickstep doesn't have a predictions row.")
-    public void appDrawerOpened_predictionRowAppDividerVisible() {
-        openAppDrawer();
-        assertThat(findObjectByResourceName("apps_divider_view")).isNotNull();
-    }
-
-    @Test
-    @Ignore
-    public void dragNDropDisabled_pinIconAddsToWorkspace() {
-        setDragNDropFlag(false);
-        openAppDrawer();
-        UiObject2 app = findDescendantByResourceName(
-                findObjectByResourceName("apps_list_view"), "icon");
-        app.click(LONG_PRESS_DURATION_MS);
-        UiObject2 popupContainer = findObjectByResourceName("popup_container");
-        assertThat(popupContainer).isNotNull();
-        UiObject2 pinIcon = findDescendantByTextOrDesc(popupContainer, "Add to home screen");
-        assertThat(pinIcon).isNotNull();
-        pinIcon.click();
-        String appName = app.getContentDescription();
-        assertThat(findAppInWorkspace(appName)).isNotNull();
-    }
-
-    @Test
-    @Ignore
-    public void pressBackFromAllApps_popupMenuOpen_returnsToWorkspace() {
-        openAppDrawer();
-        assertThat(findObjectByResourceName("search_container_all_apps")).isNotNull();
-
-        findDescendantByResourceName(findObjectByResourceName("apps_list_view"), "icon")
-                .click(LONG_PRESS_DURATION_MS);
-        assertThat(findObjectByResourceName("popup_container")).isNotNull();
-
-        // First back press should close only popup menu.
-        mDevice.pressBack();
-        assertThat(findObjectByResourceName("search_container_all_apps")).isNotNull();
-        assertThat(findObjectByResourceName("popup_container")).isNull();
-
-        // Second back press should close app drawer.
-        mDevice.pressBack();
-        assertThat(findObjectByResourceName("popup_container")).isNull();
-        assertThat(findObjectByResourceName("search_container_all_apps")).isNull();
-    }
-
-    @Test
-    @Ignore("Launcher3 without quickstep doesn't have a predictions row.")
-    public void dragNDropFromPredictionsRow_pinToGrid() {
-        openAppDrawer();
-        assertThat(findObjectByResourceName("prediction_row")).isNotNull();
-        String appName = startDragFromPredictionRow();
-        moveAppToCenterOfScreen();
-        dropApp();
-
-        // Ensure app was added.
-        assertThat(findAppInWorkspace(appName)).isNotNull();
-    }
-
-    @Test
-    @Ignore
-    public void dragNDropFromAppDrawer_pinToGrid() {
-        openAppDrawer();
-        String draggedAppName = startDragFromAllApps();
-        moveAppToCenterOfScreen();
-        dropApp();
-
-        // Ensure app was added.
-        assertThat(findAppInWorkspace(draggedAppName)).isNotNull();
-    }
-
-    @Test
-    @Ignore
-    public void tapRemoveButton_unpinApp() {
-        openAppDrawer();
-        String draggedAppName = startDragFromAllApps();
-        moveAppToCenterOfScreen();
-        dropApp();
-        removeAppByName(draggedAppName);
-        assertThat(findAppInWorkspace(draggedAppName)).isNull();
-    }
-
-    private void openAppDrawer() {
-        UiObject2 allAppsButton = findObjectByResourceName("all_apps_button");
-        assertThat(allAppsButton).isNotNull();
-        allAppsButton.click();
-    }
-
-    private String startDragFromAllApps() {
-        // Find app from app drawer.
-        UiObject2 allApps = findObjectByResourceName("apps_list_view");
-        assertThat(allApps).isNotNull();
-        UiObject2 icon = findDescendantByResourceName(allApps, "icon");
-        assertThat(icon).isNotNull();
-        String appName = icon.getContentDescription();
-
-        // Start drag action.
-        mDownTime = SystemClock.uptimeMillis();
-        mStartPoint = icon.getVisibleCenter();
-        mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
-        mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
-                LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
-        assertThat(findObjectByResourceName("popup_container")).isNotNull();
-        return appName;
-    }
-
-    private String startDragFromPredictionRow() {
-        // Find app from predictions.
-        UiObject2 predictionRow = findObjectByResourceName("prediction_row");
-        assertThat(predictionRow).isNotNull();
-
-        UiObject2 icon = findDescendantByResourceName(predictionRow, "icon");
-        assertThat(icon).isNotNull();
-
-        String appName = icon.getContentDescription();
-        UiObject2 app = findDescendantByAppName(predictionRow, appName);
-        assertThat(app).isNotNull();
-
-        // Start drag action.
-        mDownTime = SystemClock.uptimeMillis();
-        mStartPoint = icon.getVisibleCenter();
-        mEndPoint = new Point(mStartPoint.x, mStartPoint.y);
-        mLauncher.sendPointer(mDownTime, mDownTime, ACTION_DOWN, mStartPoint,
-                LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
-        assertThat(findObjectByResourceName("popup_container")).isNotNull();
-        return appName;
-    }
-
-    private void moveAppToCenterOfScreen() {
-        mEndPoint.set(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() / 2);
-        mLauncher.movePointer(mDownTime, SystemClock.uptimeMillis(), DRAG_TIME_MS, true,
-                mStartPoint, mEndPoint, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
-    }
-
-    private void dropApp() {
-        mLauncher.sendPointer(mDownTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,
-                mEndPoint, LauncherInstrumentation.GestureScope.DONT_EXPECT_PILFER);
-    }
-
-    private void removeAppByName(String appName) {
-        // Find app within home screen.
-        UiObject2 app = findDescendantByAppName(findObjectByResourceName("workspace_grid"),
-                appName);
-        if (app == null) return;
-
-        // Open app's popup container.
-        app.click(LONG_PRESS_DURATION_MS);
-        UiObject2 popupContainer = findObjectByResourceName("popup_container");
-        assertThat(popupContainer).isNotNull();
-
-        // Grab & click remove button.
-        UiObject2 removeButton = findDescendantByTextOrDesc(popupContainer, "Remove");
-        assertThat(removeButton).isNotNull();
-        removeButton.click();
-    }
-
-    private UiObject2 findAppInWorkspace(String appName) {
-        UiObject2 workspace = findObjectByResourceName("workspace_grid");
-        return findDescendantByAppName(workspace, appName);
-    }
-
-    private UiObject2 findObjectByResourceName(String resourceName) {
-        return mDevice.wait(Until.findObject(By.res(mTargetPackage, resourceName)), WAIT_TIME_MS);
-    }
-
-    private UiObject2 findDescendantByResourceName(UiObject2 outerObject,
-            String resourceName) {
-        assertThat(outerObject).isNotNull();
-        return outerObject.findObject(By.res(mTargetPackage, resourceName));
-    }
-
-    private UiObject2 findDescendantByAppName(UiObject2 outerObject, String appName) {
-        assertThat(outerObject).isNotNull();
-        return outerObject.findObject(By.clazz(TextView.class).text(appName)
-                .pkg(mDevice.getLauncherPackageName()));
-    }
-
-    private UiObject2 findDescendantByTextOrDesc(UiObject2 outerObject, String content) {
-        assertThat(outerObject).isNotNull();
-        UiObject2 innerObject = outerObject.findObject(By.desc(content));
-        if (innerObject == null) innerObject = outerObject.findObject(By.text(content));
-        return innerObject;
-    }
-
-    private void startSecondaryDisplayActivity() {
-        mTargetContext.startActivity((
-                new Intent(mTargetContext, SecondaryDisplayLauncher.class).addFlags(
-                        FLAG_ACTIVITY_NEW_TASK)));
-    }
-
-    private void setDragNDropFlag(Boolean status) {
-        startSecondaryDisplayActivity();
-    }
-}
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index 1f824b8..7109083 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -20,6 +20,7 @@
 import static androidx.test.InstrumentationRegistry.getInstrumentation;
 
 import static com.android.launcher3.testing.shared.TestProtocol.ICON_MISSING;
+import static com.android.launcher3.testing.shared.TestProtocol.WIDGET_CONFIG_NULL_EXTRA_INTENT;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
 import static org.junit.Assert.assertEquals;
@@ -55,6 +56,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.celllayout.FavoriteItemsTransaction;
 import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.tapl.HomeAppIcon;
 import com.android.launcher3.tapl.LauncherInstrumentation;
@@ -64,6 +66,7 @@
 import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.launcher3.util.TestUtil;
 import com.android.launcher3.util.Wait;
+import com.android.launcher3.util.rule.ExtendedLongPressTimeoutRule;
 import com.android.launcher3.util.rule.FailureWatcher;
 import com.android.launcher3.util.rule.SamplerRule;
 import com.android.launcher3.util.rule.ScreenRecordRule;
@@ -92,7 +95,7 @@
 /**
  * Base class for all instrumentation tests providing various utility methods.
  */
-public abstract class AbstractLauncherUiTest {
+public abstract class AbstractLauncherUiTest<LAUNCHER_TYPE extends Launcher> {
 
     public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
     public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 5;
@@ -217,6 +220,9 @@
     @Rule
     public SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
 
+    @Rule
+    public ExtendedLongPressTimeoutRule mLongPressTimeoutRule = new ExtendedLongPressTimeoutRule();
+
     public static void initialize(AbstractLauncherUiTest test) throws Exception {
         test.reinitializeLauncherData();
         test.mDevice.pressHome();
@@ -245,7 +251,7 @@
         final ViewCaptureRule viewCaptureRule = new ViewCaptureRule(
                 Launcher.ACTIVITY_TRACKER::getCreatedActivity);
         final RuleChain inner = RuleChain
-                .outerRule(new PortraitLandscapeRunner(this))
+                .outerRule(new PortraitLandscapeRunner<LAUNCHER_TYPE>(this))
                 .around(new FailureWatcher(mLauncher, viewCaptureRule::getViewCaptureData))
                 // .around(viewCaptureRule) // b/315482167
                 .around(new TestIsolationRule(mLauncher, true));
@@ -420,12 +426,12 @@
         }
     }
 
-    protected <T> T getFromLauncher(Function<Launcher, T> f) {
+    protected <T> T getFromLauncher(Function<LAUNCHER_TYPE, T> f) {
         if (!TestHelpers.isInLauncherProcess()) return null;
         return getOnUiThread(() -> f.apply(Launcher.ACTIVITY_TRACKER.getCreatedActivity()));
     }
 
-    protected void executeOnLauncher(Consumer<Launcher> f) {
+    protected void executeOnLauncher(Consumer<LAUNCHER_TYPE> f) {
         getFromLauncher(launcher -> {
             f.accept(launcher);
             return null;
@@ -435,7 +441,7 @@
     // Execute an action on Launcher, but forgive it when launcher is null.
     // Launcher can be null if teardown is happening after a failed setup step where launcher
     // activity failed to be created.
-    protected void executeOnLauncherInTearDown(Consumer<Launcher> f) {
+    protected void executeOnLauncherInTearDown(Consumer<LAUNCHER_TYPE> f) {
         executeOnLauncher(launcher -> {
             if (launcher != null) f.accept(launcher);
         });
@@ -463,20 +469,20 @@
     // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
     // flakiness.
     protected void waitForLauncherCondition(String
-            message, Function<Launcher, Boolean> condition) {
+            message, Function<LAUNCHER_TYPE, Boolean> condition) {
         waitForLauncherCondition(message, condition, DEFAULT_ACTIVITY_TIMEOUT);
     }
 
     // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
     // flakiness.
-    protected <T> T getOnceNotNull(String message, Function<Launcher, T> f) {
+    protected <O> O getOnceNotNull(String message, Function<LAUNCHER_TYPE, O> f) {
         return getOnceNotNull(message, f, DEFAULT_ACTIVITY_TIMEOUT);
     }
 
     // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
     // flakiness.
     protected void waitForLauncherCondition(
-            String message, Function<Launcher, Boolean> condition, long timeout) {
+            String message, Function<LAUNCHER_TYPE, Boolean> condition, long timeout) {
         verifyKeyguardInvisible();
         if (!TestHelpers.isInLauncherProcess()) return;
         Wait.atMost(message, () -> getFromLauncher(condition), timeout, mLauncher);
@@ -484,7 +490,7 @@
 
     // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide
     // flakiness.
-    protected <T> T getOnceNotNull(String message, Function<Launcher, T> f, long timeout) {
+    protected <T> T getOnceNotNull(String message, Function<LAUNCHER_TYPE, T> f, long timeout) {
         if (!TestHelpers.isInLauncherProcess()) return null;
 
         final Object[] output = new Object[1];
@@ -500,7 +506,7 @@
     // flakiness.
     protected void waitForLauncherCondition(
             String message,
-            Runnable testThreadAction, Function<Launcher, Boolean> condition,
+            Runnable testThreadAction, Function<LAUNCHER_TYPE, Boolean> condition,
             long timeout) {
         if (!TestHelpers.isInLauncherProcess()) return;
         Wait.atMost(message, () -> {
@@ -529,13 +535,23 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
+            Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, intent == null
+                    ? "AbstractLauncherUiTest.onReceive(): inputted intent NULL"
+                    : "AbstractLauncherUiTest.onReceive(): inputted intent NOT NULL");
             mIntent = intent;
             latch.countDown();
+            Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT,
+                    "AbstractLauncherUiTest.onReceive() Countdown Latch started");
         }
 
         public Intent blockingGetIntent() throws InterruptedException {
+            Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT,
+                    "AbstractLauncherUiTest.blockingGetIntent()");
             latch.await(DEFAULT_BROADCAST_TIMEOUT_SECS, TimeUnit.SECONDS);
             mTargetContext.unregisterReceiver(this);
+            Log.d(WIDGET_CONFIG_NULL_EXTRA_INTENT, mIntent == null
+                    ? "AbstractLauncherUiTest.onReceive(): mIntent NULL"
+                    : "AbstractLauncherUiTest.onReceive(): mIntent NOT NULL");
             return mIntent;
         }
 
@@ -578,6 +594,17 @@
                 false /* newTask */);
     }
 
+    /** Starts ExcludeFromRecentsTestActivity, which has excludeFromRecents="true". */
+    public static void startExcludeFromRecentsTestActivity() {
+        final String packageName = getAppPackageName();
+        final Intent intent = getInstrumentation().getContext().getPackageManager()
+                .getLaunchIntentForPackage(packageName);
+        intent.setComponent(new ComponentName(packageName,
+                "com.android.launcher3.testcomponent.ExcludeFromRecentsTestActivity"));
+        startIntent(intent, By.pkg(packageName).text("ExcludeFromRecentsTestActivity"),
+                false /* newTask */);
+    }
+
     private static void startIntent(Intent intent, BySelector selector, boolean newTask) {
         intent.addCategory(Intent.CATEGORY_LAUNCHER);
         if (newTask) {
@@ -621,7 +648,7 @@
                 "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT);
     }
 
-    protected boolean isInLaunchedApp(Launcher launcher) {
+    protected boolean isInLaunchedApp(LAUNCHER_TYPE launcher) {
         return launcher == null || !launcher.hasBeenResumed();
     }
 
@@ -631,11 +658,11 @@
                 launcher -> launcher.getStateManager().getState() == state.get());
     }
 
-    protected int getAllAppsScroll(Launcher launcher) {
+    protected int getAllAppsScroll(LAUNCHER_TYPE launcher) {
         return launcher.getAppsView().getActiveRecyclerView().computeVerticalScrollOffset();
     }
 
-    protected void onLauncherActivityClose(Launcher launcher) {
+    protected void onLauncherActivityClose(LAUNCHER_TYPE launcher) {
     }
 
     protected HomeAppIcon createShortcutInCenterIfNotExist(String name) {
@@ -663,4 +690,12 @@
         }
         return homeAppIcon;
     }
+
+    protected void commitTransactionAndLoadHome(FavoriteItemsTransaction transaction) {
+        transaction.commit();
+
+        // Launch the home activity
+        UiDevice.getInstance(getInstrumentation()).pressHome();
+        mLauncher.waitForLauncherInitialized();
+    }
 }
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index 5ef63da..c4e74f2 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -3,8 +3,9 @@
 import android.util.Log;
 import android.view.Surface;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.tapl.TestHelpers;
-import com.android.launcher3.util.rule.TestStabilityRule;
+import com.android.launcher3.util.rule.FailureWatcher;
 
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
@@ -14,11 +15,12 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
-public class PortraitLandscapeRunner implements TestRule {
+public class PortraitLandscapeRunner<LAUNCHER_TYPE extends Launcher> implements TestRule {
     private static final String TAG = "PortraitLandscapeRunner";
-    private AbstractLauncherUiTest mTest;
+    private AbstractLauncherUiTest<LAUNCHER_TYPE> mTest;
 
     // Annotation for tests that need to be run in portrait and landscape modes.
     @Retention(RetentionPolicy.RUNTIME)
@@ -26,18 +28,14 @@
     public @interface PortraitLandscape {
     }
 
-    public PortraitLandscapeRunner(AbstractLauncherUiTest test) {
+    public PortraitLandscapeRunner(AbstractLauncherUiTest<LAUNCHER_TYPE> test) {
         mTest = test;
     }
 
     @Override
     public Statement apply(Statement base, Description description) {
         if (!TestHelpers.isInLauncherProcess()
-                || description.getAnnotation(PortraitLandscape.class) == null
-                // If running in presubmit, don't run in both orientations.
-                // It's important to keep presubmits fast even if we will occasionally miss
-                // regressions in presubmit.
-                || TestStabilityRule.isPresubmit()) {
+                || description.getAnnotation(PortraitLandscape.class) == null) {
             return base;
         }
 
@@ -45,17 +43,23 @@
             @Override
             public void evaluate() throws Throwable {
                 try {
-                    // we expect to begin unlocked...
-                    AbstractLauncherUiTest.verifyKeyguardInvisible();
+                    try {
+                        // we expect to begin unlocked...
+                        AbstractLauncherUiTest.verifyKeyguardInvisible();
 
-                    mTest.mDevice.pressHome();
-                    mTest.waitForLauncherCondition("Launcher activity wasn't created",
-                            launcher -> launcher != null,
-                            TimeUnit.SECONDS.toMillis(20));
+                        mTest.mDevice.pressHome();
+                        mTest.waitForLauncherCondition("Launcher activity wasn't created",
+                                Objects::nonNull,
+                                TimeUnit.SECONDS.toMillis(20));
 
-                    mTest.executeOnLauncher(launcher ->
-                            launcher.getRotationHelper().forceAllowRotationForTesting(
-                                    true));
+                        mTest.executeOnLauncher(launcher ->
+                                launcher.getRotationHelper().forceAllowRotationForTesting(
+                                        true));
+
+                    } catch (Throwable e) {
+                        FailureWatcher.onError(mTest.mLauncher, description, e);
+                        throw e;
+                    }
 
                     evaluateInPortrait();
                     evaluateInLandscape();
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
index 4eae7e1..342eedf 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3Test.java
@@ -21,13 +21,17 @@
 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;
 import org.junit.runner.RunWith;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplTestsLauncher3Test extends AbstractLauncherUiTest {
+public class TaplTestsLauncher3Test extends AbstractLauncherUiTest<Launcher> {
 
+    @ScreenRecord // b/322823478
     @Test
     public void testDevicePressMenu() throws Exception {
         mDevice.pressMenu();
diff --git a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
index a9947a0..cccda88 100644
--- a/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
+++ b/tests/src/com/android/launcher3/ui/TaplWorkProfileTest.java
@@ -35,6 +35,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.R;
 import com.android.launcher3.allapps.ActivityAllAppsContainerView;
@@ -58,7 +59,7 @@
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplWorkProfileTest extends AbstractLauncherUiTest {
+public class TaplWorkProfileTest extends AbstractLauncherUiTest<Launcher> {
 
     private static final int WORK_PAGE = ActivityAllAppsContainerView.AdapterHolder.WORK;
 
@@ -195,6 +196,7 @@
 
     }
 
+    @ScreenRecord // b/322823478
     @Test
     public void testEdu() {
         assumeTrue(mWorkProfileSetupSuccessful);
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java
index 7aa26a1..e6e02b4 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java
@@ -52,7 +52,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest {
+public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest<Launcher> {
 
     @Rule
     public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@@ -87,7 +87,7 @@
      * @param acceptConfig accept the config activity
      */
     private void runTest(boolean acceptConfig) throws Throwable {
-        new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+        commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
 
         // Drag widget to homescreen
         WidgetConfigStartupMonitor monitor = new WidgetConfigStartupMonitor();
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
index 5ca5ba5..7845dec 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java
@@ -25,6 +25,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.celllayout.FavoriteItemsTransaction;
 import com.android.launcher3.tapl.Widget;
 import com.android.launcher3.tapl.WidgetResizeFrame;
@@ -46,7 +47,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplAddWidgetTest extends AbstractLauncherUiTest {
+public class TaplAddWidgetTest extends AbstractLauncherUiTest<Launcher> {
 
     @Rule
     public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@@ -56,7 +57,7 @@
     @ScreenRecord // b/316910614
     public void testDragIcon() throws Throwable {
         mLauncher.enableDebugTracing(); // b/289161193
-        new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+        commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
 
         waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
 
@@ -92,7 +93,7 @@
         // TODO(b/322820039): Enable test for tablets - the picker UI has changed and test needs to
         //  be updated to look for appropriate UI elements.
         Assume.assumeFalse(mLauncher.isTablet());
-        new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+        commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
 
         mLauncher.getWorkspace().openAllWidgets()
                 .getWidget("com.android.launcher3.testcomponent.CustomShortcutConfigActivity")
@@ -104,11 +105,12 @@
     /**
      * Test dragging a widget to the workspace and resize it.
      */
+    @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/316910614
     @PlatinumTest(focusArea = "launcher")
     @Test
     @ScreenRecord // b/316910614
     public void testResizeWidget() throws Throwable {
-        new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+        commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
 
         waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
 
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java
index 6aa746d..28d1faa 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java
@@ -43,6 +43,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.LargeTest;
 
+import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherSettings;
@@ -76,7 +77,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplBindWidgetTest extends AbstractLauncherUiTest {
+public class TaplBindWidgetTest extends AbstractLauncherUiTest<Launcher> {
 
     @Rule
     public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@@ -251,22 +252,20 @@
     private void addPendingItemToScreen(LauncherAppWidgetInfo item, int restoreStatus) {
         item.restoreStatus = restoreStatus;
         item.screenId = FIRST_SCREEN_ID;
-        new FavoriteItemsTransaction(mTargetContext)
-                .addItem(() -> item)
-                .commitAndLoadHome(mLauncher);
+        commitTransactionAndLoadHome(
+                new FavoriteItemsTransaction(mTargetContext).addItem(() -> item));
     }
 
     private LauncherAppWidgetProviderInfo addWidgetToScreen(boolean hasConfigureScreen,
             boolean bindWidget, Consumer<LauncherAppWidgetInfo> itemOverride) {
         LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(hasConfigureScreen);
-        new FavoriteItemsTransaction(mTargetContext)
+        commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext)
                 .addItem(() -> {
                     LauncherAppWidgetInfo item = createWidgetInfo(info, mTargetContext, bindWidget);
                     item.screenId = FIRST_SCREEN_ID;
                     itemOverride.accept(item);
                     return item;
-                })
-                .commitAndLoadHome(mLauncher);
+                }));
         return info;
     }
 
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java
index 7dba728..74047f0 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java
@@ -59,7 +59,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplRequestPinItemTest extends AbstractLauncherUiTest {
+public class TaplRequestPinItemTest extends AbstractLauncherUiTest<Launcher> {
 
     @Rule
     public ShellCommandRule mGrantWidgetRule = ShellCommandRule.grantWidgetBind();
@@ -128,7 +128,7 @@
 
     private void runTest(String activityMethod, boolean isWidget, ItemOperator itemMatcher,
             Intent... commandIntents) throws Throwable {
-        new FavoriteItemsTransaction(mTargetContext).commitAndLoadHome(mLauncher);
+        commitTransactionAndLoadHome(new FavoriteItemsTransaction(mTargetContext));
 
         // Open Pin item activity
         BlockingBroadcastReceiver openMonitor = new BlockingBroadcastReceiver(
diff --git a/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java b/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java
index 1cd8c88..79724e1 100644
--- a/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/TaplWidgetPickerTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.ui.widget;
 
+import static com.android.launcher3.util.rule.ShellCommandRule.createEnableInputTransportPublisherRule;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
@@ -30,7 +32,9 @@
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
 import com.android.launcher3.widget.picker.WidgetsRecyclerView;
 
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 
 /**
@@ -39,7 +43,10 @@
  */
 @MediumTest
 @RunWith(AndroidJUnit4.class)
-public class TaplWidgetPickerTest extends AbstractLauncherUiTest {
+public class TaplWidgetPickerTest extends AbstractLauncherUiTest<Launcher> {
+    // b/325377690 : To get the log printed where DOWN key event is getting lost from TAPL.
+    @Rule public final TestRule mEnableInputTransportPublisherRule =
+            createEnableInputTransportPublisherRule();
 
     private WidgetsRecyclerView getWidgetsView(Launcher launcher) {
         return WidgetsFullSheet.getWidgetsView(launcher);
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java
index c60ee8c..d653317 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplThemeIconsTest.java
@@ -31,6 +31,7 @@
 import androidx.test.filters.LargeTest;
 
 import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.Launcher;
 import com.android.launcher3.icons.ThemedIconDrawable;
 import com.android.launcher3.tapl.HomeAllApps;
 import com.android.launcher3.tapl.HomeAppIcon;
@@ -49,7 +50,7 @@
  * Note running these tests will clear the workspace on the device.
  */
 @LargeTest
-public class TaplThemeIconsTest extends AbstractLauncherUiTest {
+public class TaplThemeIconsTest extends AbstractLauncherUiTest<Launcher> {
 
     private static final String APP_NAME = "IconThemedActivity";
     private static final String SHORTCUT_NAME = "Shortcut 1";
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
index 43fc8ff..2ce8eef 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplTwoPanelWorkspaceTest.java
@@ -37,6 +37,7 @@
 import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.util.LauncherLayoutBuilder;
 import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule;
 
 import org.junit.After;
 import org.junit.Before;
@@ -54,7 +55,7 @@
  */
 @LargeTest
 @RunWith(AndroidJUnit4.class)
-public class TaplTwoPanelWorkspaceTest extends AbstractLauncherUiTest {
+public class TaplTwoPanelWorkspaceTest extends AbstractLauncherUiTest<Launcher> {
 
     private AutoCloseable mLauncherLayout;
 
@@ -240,6 +241,7 @@
         });
     }
 
+    @ScreenRecordRule.ScreenRecord // b/329935119
     @Test
     @PortraitLandscape
     public void testEmptyPageDoesNotGetRemovedIfPagePairIsNotEmpty() {
diff --git a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java
index 4edeb42..9afde0d 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TaplWorkspaceTest.java
@@ -37,7 +37,7 @@
 /**
  * Test the basic interactions of the Workspace, adding pages, moving the pages and removing pages.
  */
-public class TaplWorkspaceTest extends AbstractLauncherUiTest {
+public class TaplWorkspaceTest extends AbstractLauncherUiTest<Launcher> {
 
     private AutoCloseable mLauncherLayout;
 
diff --git a/tests/src/com/android/launcher3/util/rule/ExtendedLongPressTimeoutRule.java b/tests/src/com/android/launcher3/util/rule/ExtendedLongPressTimeoutRule.java
new file mode 100644
index 0000000..702988c
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/rule/ExtendedLongPressTimeoutRule.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util.rule;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.ViewConfiguration;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+public class ExtendedLongPressTimeoutRule implements TestRule {
+
+    private static final String TAG = "ExtendedLongPressTimeoutRule";
+
+    private static final float LONG_PRESS_TIMEOUT_MULTIPLIER = 10f;
+
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                ContentResolver contentResolver = InstrumentationRegistry.getInstrumentation()
+                        .getContext()
+                        .getContentResolver();
+                int prevLongPressTimeout = Settings.Secure.getInt(
+                        contentResolver,
+                        Settings.Secure.LONG_PRESS_TIMEOUT,
+                        ViewConfiguration.getLongPressTimeout());
+                int newLongPressTimeout =
+                        (int) (prevLongPressTimeout * LONG_PRESS_TIMEOUT_MULTIPLIER);
+
+                try {
+                    Log.d(TAG, "In try-block: Setting long press timeout from "
+                            + prevLongPressTimeout + "ms to " + newLongPressTimeout + "ms");
+                    Settings.Secure.putInt(
+                            contentResolver,
+                            Settings.Secure.LONG_PRESS_TIMEOUT,
+                            (int) (prevLongPressTimeout * LONG_PRESS_TIMEOUT_MULTIPLIER));
+
+                    base.evaluate();
+                } catch (Exception e) {
+                    Log.e(TAG, "Error", e);
+                    throw e;
+                } finally {
+                    Log.d(TAG, "In finally-block: resetting long press timeout to "
+                            + prevLongPressTimeout + "ms");
+                    Settings.Secure.putInt(
+                            contentResolver,
+                            Settings.Secure.LONG_PRESS_TIMEOUT,
+                            prevLongPressTimeout);
+                }
+            }
+        };
+    }
+}
diff --git a/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java b/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java
index 08953fc..977995e 100644
--- a/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java
+++ b/tests/src/com/android/launcher3/util/rule/ShellCommandRule.java
@@ -21,6 +21,7 @@
 
 import android.content.ComponentName;
 import android.content.pm.ActivityInfo;
+import android.text.TextUtils;
 
 import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
@@ -40,6 +41,9 @@
  */
 public class ShellCommandRule implements TestRule {
 
+    private static final String SETPROP_PREFIX = "setprop";
+    private static final String GETPROP_PREFIX = "getprop";
+    private static final String UNKNOWN = "UNKNOWN";
     private final String mCmd;
     private final String mRevertCommand;
     private final boolean mCheckSuccess;
@@ -62,6 +66,19 @@
         return new Statement() {
             @Override
             public void evaluate() throws Throwable {
+                String revertSetPropCmd = null;
+                if (mCmd.startsWith(SETPROP_PREFIX) && mRevertCommand == null) {
+                    // setprop command always follows format : setprop <TAG> <value>
+                    // We are stripping out only the TAG here
+                    String tag = mCmd.split("\\s")[1];
+                    String getpropCmd = GETPROP_PREFIX + " " + tag;
+                    String initialValue = UiDevice.getInstance(
+                            getInstrumentation()).executeShellCommand(getpropCmd);
+                    if (TextUtils.isEmpty(initialValue.trim())) {
+                        initialValue = UNKNOWN;
+                    }
+                    revertSetPropCmd = SETPROP_PREFIX + " " + tag + " " + initialValue;
+                }
                 final String result =
                         UiDevice.getInstance(getInstrumentation()).executeShellCommand(mCmd);
                 if (mCheckSuccess) {
@@ -73,13 +90,15 @@
                 try {
                     base.evaluate();
                 } finally {
-                    if (mRevertCommand != null) {
+                    if (mRevertCommand != null || revertSetPropCmd != null) {
+                        String revertCmd =
+                                mRevertCommand != null ? mRevertCommand : revertSetPropCmd;
                         final String revertResult = UiDevice.getInstance(
                                 getInstrumentation()).executeShellCommand(
-                                mRevertCommand);
+                                revertCmd);
                         if (mCheckSuccess) {
                             Assert.assertTrue(
-                                    "Failed command: " + mRevertCommand
+                                    "Failed command: " + revertCmd
                                             + ", result: " + revertResult,
                                     "Success".equals(result.replaceAll("\\s", "")));
                         }
@@ -122,4 +141,14 @@
         return new ShellCommandRule("settings put global heads_up_notifications_enabled 0",
                 "settings put global heads_up_notifications_enabled 1");
     }
+
+    /**
+     * Enables "InputTransportPublisher" debug flag. This prints the key input events dispatched by
+     * the system server.
+     * adb shell setprop log.tag.InputTransportPublisher DEBUG
+     * See {@link com.android.cts.input.DebugInputRule} for more details.
+     */
+    public static ShellCommandRule createEnableInputTransportPublisherRule() {
+        return new ShellCommandRule("setprop log.tag.InputTransportPublisher DEBUG", null);
+    }
 }
diff --git a/tests/src/com/android/launcher3/util/rule/TestToPhoneFileCopier.kt b/tests/src/com/android/launcher3/util/rule/TestToPhoneFileCopier.kt
new file mode 100644
index 0000000..d3516d1
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/rule/TestToPhoneFileCopier.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.util.rule
+
+import androidx.test.platform.app.InstrumentationRegistry
+import java.io.File
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/** Copy a file from the tests assets folder to the phone. */
+class TestToPhoneFileCopier(
+    val src: String,
+    dest: String,
+    private val removeOnFinish: Boolean = false
+) : TestRule {
+
+    private val dstFile =
+        File(InstrumentationRegistry.getInstrumentation().targetContext.dataDir, dest)
+
+    fun getDst() = dstFile.absolutePath
+
+    fun before() =
+        dstFile.writeBytes(
+            InstrumentationRegistry.getInstrumentation().context.assets.open(src).readBytes()
+        )
+
+    fun after() {
+        if (removeOnFinish) {
+            dstFile.delete()
+        }
+    }
+
+    override fun apply(base: Statement, description: Description): Statement =
+        object : Statement() {
+            override fun evaluate() {
+                before()
+                try {
+                    base.evaluate()
+                } finally {
+                    after()
+                }
+            }
+        }
+}
diff --git a/tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt b/tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
index 11855e6..460058b 100644
--- a/tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
+++ b/tests/src/com/android/launcher3/widget/GeneratedPreviewTest.kt
@@ -12,6 +12,7 @@
 import android.platform.test.annotations.RequiresFlagsEnabled
 import android.platform.test.flag.junit.CheckFlagsRule
 import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.view.ContextThemeWrapper
 import android.view.LayoutInflater
 import android.widget.RemoteViews
 import androidx.test.core.app.ApplicationProvider.getApplicationContext
@@ -53,7 +54,14 @@
         context = getApplicationContext()
         generatedPreview = RemoteViews(context.packageName, generatedPreviewLayout)
         widgetCell =
-            LayoutInflater.from(ActivityContextWrapper(context))
+            LayoutInflater.from(
+                    ActivityContextWrapper(
+                        ContextThemeWrapper(
+                            context,
+                            com.android.launcher3.R.style.WidgetContainerTheme
+                        )
+                    )
+                )
                 .inflate(com.android.launcher3.R.layout.widget_cell, null) as WidgetCell
         appWidgetProviderInfo =
             AppWidgetProviderInfo()
@@ -111,6 +119,18 @@
     }
 
     @Test
+    @RequiresFlagsEnabled(FLAG_ENABLE_GENERATED_PREVIEWS)
+    fun widgetItem_hasGeneratedPreview_nullPreview() {
+        appWidgetProviderInfo.generatedPreviewCategories =
+            WIDGET_CATEGORY_HOME_SCREEN or WIDGET_CATEGORY_KEYGUARD
+        createWidgetItem()
+        assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_HOME_SCREEN)).isTrue()
+        // loadGeneratedPreview returns null for KEYGUARD, so this should still be false.
+        assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_KEYGUARD)).isFalse()
+        assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_SEARCHBOX)).isFalse()
+    }
+
+    @Test
     @RequiresFlagsDisabled(FLAG_ENABLE_GENERATED_PREVIEWS)
     fun widgetItem_hasGeneratedPreview_flagDisabled() {
         assertThat(widgetItem.hasGeneratedPreview(WIDGET_CATEGORY_HOME_SCREEN)).isFalse()
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt b/tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
new file mode 100644
index 0000000..6e751e0
--- /dev/null
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetImageViewTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.picker
+
+import android.content.Context
+import android.graphics.Rect
+import android.graphics.drawable.Drawable
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.MediumTest
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.widget.WidgetImageView
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.spy
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.whenever
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class WidgetImageViewTest {
+    private lateinit var context: Context
+    private lateinit var widgetImageView: WidgetImageView
+
+    @Mock private lateinit var testDrawable: Drawable
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        widgetImageView = spy(WidgetImageView(context))
+    }
+
+    @Test
+    fun getBitmapBounds_aspectRatioLargerThanView_scaledByWidth() {
+        // view - 100 x 100
+        whenever(widgetImageView.width).thenReturn(100)
+        whenever(widgetImageView.height).thenReturn(100)
+        // bitmap - 200 x 100
+        whenever(testDrawable.intrinsicWidth).thenReturn(200)
+        whenever(testDrawable.intrinsicHeight).thenReturn(100)
+
+        widgetImageView.drawable = testDrawable
+        val bitmapBounds = widgetImageView.bitmapBounds
+
+        // new scaled width of bitmap is = 100, and height is scaled to 1/2 = 50
+        assertThat(bitmapBounds).isEqualTo(Rect(0, 25, 100, 75))
+    }
+
+    @Test
+    fun getBitmapBounds_aspectRatioSmallerThanView_scaledByHeight() {
+        // view - 100 x 100
+        whenever(widgetImageView.width).thenReturn(100)
+        whenever(widgetImageView.height).thenReturn(100)
+        // bitmap - 100 x 200
+        whenever(testDrawable.intrinsicWidth).thenReturn(100)
+        whenever(testDrawable.intrinsicHeight).thenReturn(200)
+        widgetImageView.drawable = testDrawable
+
+        val bitmapBounds = widgetImageView.bitmapBounds
+
+        // new scaled height of bitmap is = 100, and width is scaled to 1/2 = 50
+        assertThat(bitmapBounds).isEqualTo(Rect(25, 0, 75, 100))
+    }
+
+    @Test
+    fun getBitmapBounds_noScale_returnsOriginalDrawableBounds() {
+        // view - 200 x 100
+        whenever(widgetImageView.width).thenReturn(200)
+        whenever(widgetImageView.height).thenReturn(100)
+        // bitmap - 200 x 100
+        whenever(testDrawable.intrinsicWidth).thenReturn(200)
+        whenever(testDrawable.intrinsicHeight).thenReturn(100)
+
+        widgetImageView.drawable = testDrawable
+        val bitmapBounds = widgetImageView.bitmapBounds
+
+        // no scaling
+        assertThat(bitmapBounds).isEqualTo(Rect(0, 0, 200, 100))
+    }
+}
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
index c807771..60a4cd3 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetRecommendationCategoryProviderTest.java
@@ -23,6 +23,7 @@
 import static android.content.pm.ApplicationInfo.CATEGORY_SOCIAL;
 import static android.content.pm.ApplicationInfo.CATEGORY_UNDEFINED;
 import static android.content.pm.ApplicationInfo.CATEGORY_VIDEO;
+import static android.content.pm.ApplicationInfo.FLAG_INSTALLED;
 
 import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -30,8 +31,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.when;
 
@@ -41,7 +41,7 @@
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
+import android.content.pm.LauncherApps;
 import android.os.Process;
 
 import androidx.test.core.content.pm.ApplicationInfoBuilder;
@@ -70,10 +70,25 @@
 public class WidgetRecommendationCategoryProviderTest {
     private static final String TEST_PACKAGE = "com.foo.test";
     private static final String TEST_APP_NAME = "foo";
-    public static final WidgetRecommendationCategory SOCIAL_AND_ENTERTAINMENT_CATEGORY =
+    private static final WidgetRecommendationCategory PRODUCTIVITY =
             new WidgetRecommendationCategory(
-                    R.string.social_and_entertainment_widget_recommendation_category_label,
-                    /*order=*/4);
+                    R.string.productivity_widget_recommendation_category_label,
+                    /*order=*/0);
+    private static final WidgetRecommendationCategory NEWS =
+            new WidgetRecommendationCategory(
+                    R.string.news_widget_recommendation_category_label, /*order=*/1);
+    private static final WidgetRecommendationCategory SUGGESTED_FOR_YOU =
+            new WidgetRecommendationCategory(
+                    R.string.others_widget_recommendation_category_label, /*order=*/4);
+    private static final WidgetRecommendationCategory SOCIAL =
+            new WidgetRecommendationCategory(
+                    R.string.social_widget_recommendation_category_label,
+                    /*order=*/5);
+    private static final WidgetRecommendationCategory ENTERTAINMENT =
+            new WidgetRecommendationCategory(
+                    R.string.entertainment_widget_recommendation_category_label,
+                    /*order=*/6);
+
     private final ApplicationInfo mTestAppInfo = ApplicationInfoBuilder.newBuilder().setPackageName(
             TEST_PACKAGE).setName(TEST_APP_NAME).build();
     private Context mContext;
@@ -82,7 +97,7 @@
 
     private WidgetItem mTestWidgetItem;
     @Mock
-    private PackageManager mPackageManager;
+    private LauncherApps mLauncherApps;
     private InvariantDeviceProfile mTestProfile;
 
     @Before
@@ -90,10 +105,12 @@
         MockitoAnnotations.initMocks(this);
         mContext = new ContextWrapper(getInstrumentation().getTargetContext()) {
             @Override
-            public PackageManager getPackageManager() {
-                return mPackageManager;
+            public Object getSystemService(String name) {
+                return LAUNCHER_APPS_SERVICE.equals(name) ? mLauncherApps : super.getSystemService(
+                        name);
             }
         };
+        mTestAppInfo.flags = FLAG_INSTALLED;
         mTestProfile = new InvariantDeviceProfile();
         mTestProfile.numRows = 5;
         mTestProfile.numColumns = 5;
@@ -103,25 +120,22 @@
     @Test
     public void getWidgetRecommendationCategory_returnsMappedCategory() throws Exception {
         ImmutableMap<Integer, WidgetRecommendationCategory> testCategories = ImmutableMap.of(
-                CATEGORY_PRODUCTIVITY, new WidgetRecommendationCategory(
-                        R.string.productivity_widget_recommendation_category_label,
-                        /*order=*/
-                        0),
-                CATEGORY_NEWS, new WidgetRecommendationCategory(
-                        R.string.news_widget_recommendation_category_label, /*order=*/1),
-                CATEGORY_SOCIAL, SOCIAL_AND_ENTERTAINMENT_CATEGORY,
-                CATEGORY_AUDIO, SOCIAL_AND_ENTERTAINMENT_CATEGORY,
-                CATEGORY_IMAGE, SOCIAL_AND_ENTERTAINMENT_CATEGORY,
-                CATEGORY_VIDEO, SOCIAL_AND_ENTERTAINMENT_CATEGORY,
-                CATEGORY_UNDEFINED, new WidgetRecommendationCategory(
-                        R.string.others_widget_recommendation_category_label, /*order=*/5));
+                CATEGORY_PRODUCTIVITY, PRODUCTIVITY,
+                CATEGORY_NEWS, NEWS,
+                CATEGORY_SOCIAL, SOCIAL,
+                CATEGORY_AUDIO, ENTERTAINMENT,
+                CATEGORY_IMAGE, ENTERTAINMENT,
+                CATEGORY_VIDEO, ENTERTAINMENT,
+                CATEGORY_UNDEFINED, SUGGESTED_FOR_YOU);
 
         for (Map.Entry<Integer, WidgetRecommendationCategory> testCategory :
                 testCategories.entrySet()) {
 
             mTestAppInfo.category = testCategory.getKey();
-            when(mPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
-                    mTestAppInfo);
+            when(mLauncherApps.getApplicationInfo(/*packageName=*/ eq(TEST_PACKAGE),
+                    /*flags=*/ eq(0),
+                    /*user=*/ eq(Process.myUserHandle())))
+                    .thenReturn(mTestAppInfo);
 
             WidgetRecommendationCategory category = Executors.MODEL_EXECUTOR.submit(() ->
                     new WidgetRecommendationCategoryProvider().getWidgetRecommendationCategory(
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 0286279..85fb380 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -29,6 +29,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.UserHandle;
+import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -96,7 +97,8 @@
 
         mViewHolderBinder = new WidgetsListTableViewHolderBinder(
                 mContext,
-                LayoutInflater.from(mContext),
+                LayoutInflater.from(new ContextThemeWrapper(mContext,
+                        com.android.launcher3.R.style.WidgetContainerTheme)),
                 mOnIconClickListener,
                 mOnLongClickListener);
     }
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt b/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
new file mode 100644
index 0000000..040fbf5
--- /dev/null
+++ b/tests/src/com/android/launcher3/widget/picker/util/WidgetPreviewContainerSizesTest.kt
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.picker.util
+
+import android.content.ComponentName
+import android.content.Context
+import android.graphics.Point
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.InvariantDeviceProfile
+import com.android.launcher3.LauncherAppState
+import com.android.launcher3.icons.IconCache
+import com.android.launcher3.model.WidgetItem
+import com.android.launcher3.util.ActivityContextWrapper
+import com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class WidgetPreviewContainerSizesTest {
+    private lateinit var context: Context
+    private lateinit var deviceProfile: DeviceProfile
+    private lateinit var testInvariantProfile: InvariantDeviceProfile
+
+    @Mock private lateinit var iconCache: IconCache
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        context = ActivityContextWrapper(ApplicationProvider.getApplicationContext())
+        testInvariantProfile = LauncherAppState.getIDP(context)
+        deviceProfile = testInvariantProfile.getDeviceProfile(context).copy(context)
+    }
+
+    @Test
+    fun widgetPreviewContainerSize_forItem_returnsCorrectContainerSize() {
+        val testSizes = getTestSizes(deviceProfile)
+        val expectedPreviewContainers = testSizes.values.toList()
+
+        for ((index, widgetSize) in testSizes.keys.withIndex()) {
+            val widgetItem = createWidgetItem(widgetSize, context, testInvariantProfile, iconCache)
+
+            assertWithMessage("size for $widgetSize should be: ${expectedPreviewContainers[index]}")
+                .that(WidgetPreviewContainerSize.forItem(widgetItem, deviceProfile))
+                .isEqualTo(expectedPreviewContainers[index])
+        }
+    }
+
+    companion object {
+        private const val TEST_PACKAGE = "com.google.test"
+
+        private val HANDHELD_TEST_SIZES: Map<Point, WidgetPreviewContainerSize> =
+            mapOf(
+                // 1x1
+                Point(1, 1) to WidgetPreviewContainerSize(1, 1),
+                // 2x1
+                Point(2, 1) to WidgetPreviewContainerSize(2, 1),
+                Point(3, 1) to WidgetPreviewContainerSize(2, 1),
+                // 4x1
+                Point(4, 1) to WidgetPreviewContainerSize(4, 1),
+                // 2x2
+                Point(2, 2) to WidgetPreviewContainerSize(2, 2),
+                Point(3, 3) to WidgetPreviewContainerSize(2, 2),
+                Point(3, 2) to WidgetPreviewContainerSize(2, 2),
+                // 2x3
+                Point(2, 3) to WidgetPreviewContainerSize(2, 3),
+                Point(3, 4) to WidgetPreviewContainerSize(2, 3),
+                Point(3, 5) to WidgetPreviewContainerSize(2, 3),
+                // 4x2
+                Point(4, 2) to WidgetPreviewContainerSize(4, 2),
+                // 4x3
+                Point(4, 3) to WidgetPreviewContainerSize(4, 3),
+                Point(4, 4) to WidgetPreviewContainerSize(4, 3),
+            )
+
+        private val TABLET_TEST_SIZES: Map<Point, WidgetPreviewContainerSize> =
+            mapOf(
+                // 1x1
+                Point(1, 1) to WidgetPreviewContainerSize(1, 1),
+                // 2x1
+                Point(2, 1) to WidgetPreviewContainerSize(2, 1),
+                // 3x1
+                Point(3, 1) to WidgetPreviewContainerSize(3, 1),
+                Point(4, 1) to WidgetPreviewContainerSize(3, 1),
+                // 2x2
+                Point(2, 2) to WidgetPreviewContainerSize(2, 2),
+                // 2x3
+                Point(2, 3) to WidgetPreviewContainerSize(2, 3),
+                // 3x2
+                Point(3, 2) to WidgetPreviewContainerSize(3, 2),
+                Point(4, 2) to WidgetPreviewContainerSize(3, 2),
+                Point(5, 2) to WidgetPreviewContainerSize(3, 2),
+                // 3x3
+                Point(3, 3) to WidgetPreviewContainerSize(3, 3),
+                Point(4, 4) to WidgetPreviewContainerSize(3, 3),
+                // 3x4
+                Point(5, 4) to WidgetPreviewContainerSize(3, 4),
+                Point(3, 4) to WidgetPreviewContainerSize(3, 4),
+                Point(5, 5) to WidgetPreviewContainerSize(3, 4),
+                Point(6, 4) to WidgetPreviewContainerSize(3, 4),
+                Point(6, 5) to WidgetPreviewContainerSize(3, 4),
+            )
+
+        private fun getTestSizes(dp: DeviceProfile) =
+            if (dp.isTablet && !dp.isTwoPanels) {
+                TABLET_TEST_SIZES
+            } else {
+                HANDHELD_TEST_SIZES
+            }
+
+        private fun createWidgetItem(
+            widgetSize: Point,
+            context: Context,
+            invariantDeviceProfile: InvariantDeviceProfile,
+            iconCache: IconCache
+        ): WidgetItem {
+            val providerInfo =
+                createAppWidgetProviderInfo(
+                    ComponentName.createRelative(
+                        TEST_PACKAGE,
+                        /*cls=*/ ".WidgetProvider_" + widgetSize.x + "x" + widgetSize.y
+                    )
+                )
+            val widgetInfo =
+                LauncherAppWidgetProviderInfo.fromProviderInfo(context, providerInfo).apply {
+                    spanX = widgetSize.x
+                    spanY = widgetSize.y
+                }
+            return WidgetItem(widgetInfo, invariantDeviceProfile, iconCache, context)
+        }
+    }
+}
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index 2c5a396..b2cb266 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -63,6 +63,7 @@
     private static final String TEST_PACKAGE = "com.google.test";
 
     private static final int SPACE_SIZE = 10;
+    // Note - actual widget size includes SPACE_SIZE (border) + cell padding.
     private static final int CELL_SIZE = 50;
     private static final int NUM_OF_COLS = 5;
     private static final int NUM_OF_ROWS = 5;
@@ -105,7 +106,7 @@
 
 
     @Test
-    public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding0_shouldGroupWidgetsInTable() {
+    public void groupWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding0() {
         List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
                 mWidget2x2);
 
@@ -113,17 +114,20 @@
                 WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
                         mTestDeviceProfile, 220, 0);
 
-        // Row 0: 1x1(50px), 2x2(110px)
-        // Row 1: 2x3(110px), 2x4(110px)
-        // Row 2: 4x4(230px)
-        assertThat(widgetItemInTable).hasSize(3);
-        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
-        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget2x4);
-        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
+        // With reordering, rows displayed in order of increasing size.
+        // Row 0: 1x1(50px)
+        // Row 1: 2x2(in a 2x2 container - 110px)
+        // Row 2: 2x3(in a 2x3 container - 110px), 2x4(in a 2x3 container - 110px)
+        // Row 3: 4x4(in a 3x3 container in tablet - 170px; 4x3 on phone - 230px)
+        assertThat(widgetItemInTable).hasSize(4);
+        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
+        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
+        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x3, mWidget2x4);
+        assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
     }
 
     @Test
-    public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding10_shouldGroupWidgetsInTable() {
+    public void groupWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding10() {
         List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
                 mWidget2x2);
 
@@ -131,9 +135,13 @@
                 WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
                         mTestDeviceProfile, 220, 10);
 
-        // Row 0: 1x1(50px), 2x2(110px)
-        // Row 1: 2x3(110px), 2x4(110px)
-        // Row 2: 4x4(230px)
+        // With reordering, but space taken up by cell padding, so, no grouping (even if 2x2 and 2x3
+        // use same preview container).
+        // Row 0: 1x1(50px)
+        // Row 1: 2x2(in a 2x2 container: 130px)
+        // Row 2: 2x3(in a 2x3 container: 130px)
+        // Row 3: 2x4(in a 2x3 container: 130px)
+        // Row 4: 4x4(in a 3x3 container in tablet - 190px; 4x3 on phone - 250px)
         assertThat(widgetItemInTable).hasSize(5);
         assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
         assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
@@ -143,7 +151,29 @@
     }
 
     @Test
-    public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow350_cellPadding0_shouldGroupWidgetsInTable() {
+    public void groupWithReordering_widgetsOnly_maxSpanPxPerRow260_cellPadding10() {
+        List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
+                mWidget2x2);
+
+        List<ArrayList<WidgetItem>> widgetItemInTable =
+                WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+                        mTestDeviceProfile, 260, 10);
+
+        // With reordering, even with cellPadding, enough space to group 2x3 and 2x4 (which also use
+        // same container)
+        // Row 0: 1x1(50px)
+        // Row 1: 2x2(in a 2x2 container: 130px)
+        // Row 2: 2x3(in a 2x3 container: 130px), 2x4(in a 2x3 container: 130px)
+        // Row 3: 4x4(in a 3x3 container in tablet - 190px; 4x3 on phone - 250px)
+        assertThat(widgetItemInTable).hasSize(4);
+        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
+        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
+        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x3, mWidget2x4);
+        assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
+    }
+
+    @Test
+    public void groupWithReordering_widgetsOnly_maxSpanPxPerRow350_cellPadding0() {
         List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
                 mWidget2x2);
 
@@ -151,17 +181,20 @@
                 WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
                         mTestDeviceProfile, 350, 0);
 
-        // Row 0: 1x1(50px), 2x2(110px), 2x3(110px)
-        // Row 1: 2x4(110px)
-        // Row 2: 4x4(230px)
-        assertThat(widgetItemInTable).hasSize(3);
-        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2, mWidget2x3);
-        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x4);
-        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
+        // With reordering, rows displayed in order of increasing size.
+        // Row 0: 1x1(50px)
+        // Row 1: 2x2(in a 2x2 container: 110px)
+        // Row 2: 2x3(in a 2x3 container: 110px), 2x4(in a 2x3 container: 110px)
+        // Row 3: 4x4(in a 3x3 container in tablet - 170px; 4x3 on phone - 230px)
+        assertThat(widgetItemInTable).hasSize(4);
+        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
+        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
+        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x3, mWidget2x4);
+        assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
     }
 
     @Test
-    public void groupWidgetItemsIntoTableWithReordering_mixItems_maxSpanPxPerRow350_cellPadding0_shouldGroupWidgetsInTable() {
+    public void groupWithReordering_mixItems_maxSpanPxPerRow350_cellPadding0() {
         List<WidgetItem> widgetItems = List.of(mWidget4x4, mShortcut3, mWidget2x3, mShortcut1,
                 mWidget1x1, mShortcut2, mWidget2x4, mWidget2x2);
 
@@ -169,19 +202,22 @@
                 WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
                         mTestDeviceProfile, 350, 0);
 
-        // Row 0: 1x1(50px), 2x2(110px), 2x3(110px)
-        // Row 1: 2x4(110px),
-        // Row 2: 4x4(230px)
-        // Row 3: shortcut3(50px), shortcut1(50px), shortcut2(50px)
-        assertThat(widgetItemInTable).hasSize(4);
-        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2, mWidget2x3);
-        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x4);
-        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
-        assertThat(widgetItemInTable.get(3)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
+        // With reordering - rows displays in order of increasing size:
+        // Row 0: 1x1(50px)
+        // Row 1: 2x2(110px)
+        // Row 2: 2x3 (in a 2x3 container 110px), 2x4 (in a 2x3 container 110px)
+        // Row 3: 4x4 (in a 3x3 container in tablet - 170px; 4x3 on phone - 230px)
+        // Row 4: shortcut3, shortcut1, shortcut2 (shortcuts are always displayed at bottom)
+        assertThat(widgetItemInTable).hasSize(5);
+        assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
+        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
+        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x3, mWidget2x4);
+        assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
+        assertThat(widgetItemInTable.get(4)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
     }
 
     @Test
-    public void groupWidgetItemsIntoTableWithoutReordering_maxSpanPxPerRow220_cellPadding0_shouldMaintainTheOrder() {
+    public void groupWithoutReordering_maxSpanPxPerRow220_cellPadding0() {
         List<WidgetItem> widgetItems =
                 List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4, mWidget2x2);
 
@@ -189,13 +225,19 @@
                 WidgetsTableUtils.groupWidgetItemsUsingRowPxWithoutReordering(widgetItems, mContext,
                         mTestDeviceProfile, 220, 0);
 
-        // Row 0: 4x4(230px)
-        // Row 1: 2x3(110px), 1x1(50px)
-        // Row 2: 2x4(110px), 2x2(110px)
-        assertThat(widgetItemInTable).hasSize(3);
+        // Without reordering, widgets are grouped only if the next one fits and uses same preview
+        // container:
+        // Row 0: 4x4(in a 3x3 container in tablet - 170px; 4x3 on phone - 230px)
+        // Row 1: 2x3(in a 2x3 container - 110px)
+        // Row 2: 1x1(50px)
+        // Row 3: 2x4(in a 2x3 container - 110px)
+        // Row 4: 2x2(in a 2x2 container - 110px)
+        assertThat(widgetItemInTable).hasSize(5);
         assertThat(widgetItemInTable.get(0)).containsExactly(mWidget4x4);
-        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget1x1);
-        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4, mWidget2x2);
+        assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3);
+        assertThat(widgetItemInTable.get(2)).containsExactly(mWidget1x1);
+        assertThat(widgetItemInTable.get(3)).containsExactly(mWidget2x4);
+        assertThat(widgetItemInTable.get(4)).containsExactly(mWidget2x2);
     }
 
     private void initDP() {
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 9591891..245ec09 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -56,9 +56,6 @@
 
     private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background";
     private static final String FAST_SCROLLER_RES_ID = "fast_scroller";
-
-    private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
-            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
     private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
             "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
 
@@ -407,7 +404,6 @@
     /** Presses the esc key to dismiss AllApps. */
     public void dismissByEscKey() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_UP);
             mLauncher.runToState(
                     () -> mLauncher.getDevice().pressKeyCode(KEYCODE_ESCAPE),
@@ -420,6 +416,14 @@
         }
     }
 
+    /** Returns PrivateSpaceContainer if present in view. */
+    @NonNull
+    public PrivateSpaceContainer getPrivateSpaceUnlockedView() {
+        final UiObject2 allAppsContainer = verifyActiveContainer();
+        final UiObject2 appListRecycler = getAppListRecycler(allAppsContainer);
+        return new PrivateSpaceContainer(mLauncher, appListRecycler);
+    }
+
     protected abstract void verifyVisibleContainerOnDismiss();
 
     /**
diff --git a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
index 777e7b3..68829e0 100644
--- a/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
+++ b/tests/tapl/com/android/launcher3/tapl/BaseOverview.java
@@ -45,9 +45,6 @@
  */
 public class BaseOverview extends LauncherInstrumentation.VisibleContainer {
     protected static final String TASK_RES_ID = "task";
-
-    private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
-            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
     private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
             "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
     private static final Pattern EVENT_ENTER_DOWN = Pattern.compile(
@@ -414,7 +411,6 @@
      */
     public Workspace dismissByEscKey() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_UP);
             mLauncher.runToState(
                     () -> mLauncher.getDevice().pressKeyCode(KEYCODE_ESCAPE),
@@ -433,7 +429,6 @@
      */
     public LaunchedAppState launchFocusedTaskByEnterKey(@NonNull String expectedPackageName) {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ENTER_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ENTER_UP);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
 
diff --git a/tests/tapl/com/android/launcher3/tapl/KeyboardQuickSwitch.java b/tests/tapl/com/android/launcher3/tapl/KeyboardQuickSwitch.java
index 5ef82ca..7ff55fe 100644
--- a/tests/tapl/com/android/launcher3/tapl/KeyboardQuickSwitch.java
+++ b/tests/tapl/com/android/launcher3/tapl/KeyboardQuickSwitch.java
@@ -37,15 +37,9 @@
     private static final Pattern EVENT_ALT_TAB_UP = Pattern.compile(
             "KeyboardQuickSwitchView key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_TAB"
                     + ".*?metaState=META_ALT_ON");
-    private static final Pattern EVENT_ALT_SHIFT_TAB_DOWN = Pattern.compile(
-            "KeyboardQuickSwitchView key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_TAB"
-                    + ".*?metaState=META_ALT_ON|META_SHIFT_ON");
     private static final Pattern EVENT_ALT_SHIFT_TAB_UP = Pattern.compile(
             "KeyboardQuickSwitchView key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_TAB"
                     + ".*?metaState=META_ALT_ON|META_SHIFT_ON");
-    private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
-            "KeyboardQuickSwitchView key event: KeyEvent.*?action=ACTION_DOWN"
-                    + ".*?keyCode=KEYCODE_ESCAPE.*?metaState=META_ALT_ON");
     private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
             "KeyboardQuickSwitchView key event: KeyEvent.*?action=ACTION_UP"
                     + ".*?keyCode=KEYCODE_ESCAPE.*?metaState=META_ALT_ON");
@@ -87,8 +81,6 @@
                 "want to move keyboard quick switch focus forward");
              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             mLauncher.waitForLauncherObject(KEYBOARD_QUICK_SWITCH_RES_ID);
-
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_TAB_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_TAB_UP);
             mLauncher.assertTrue("Failed to press alt+tab",
                     mLauncher.getDevice().pressKeyCode(
@@ -122,7 +114,6 @@
              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             mLauncher.waitForLauncherObject(KEYBOARD_QUICK_SWITCH_RES_ID);
 
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_SHIFT_TAB_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_SHIFT_TAB_UP);
             mLauncher.assertTrue("Failed to press alt+shift+tab",
                     mLauncher.getDevice().pressKeyCode(
@@ -150,7 +141,6 @@
              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             mLauncher.waitForLauncherObject(KEYBOARD_QUICK_SWITCH_RES_ID);
 
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_UP);
             mLauncher.assertTrue("Failed to press alt+tab",
                     mLauncher.getDevice().pressKeyCode(
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index b5414b7..3f96999 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -26,11 +26,11 @@
 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_TASKBAR_FROM_NAV_THRESHOLD;
 import static com.android.launcher3.testing.shared.TestProtocol.SUCCESSFUL_GESTURE_MISMATCH_EVENTS;
 import static com.android.launcher3.testing.shared.TestProtocol.TEST_INFO_RESPONSE_FIELD;
-import static com.android.launcher3.testing.shared.TestProtocol.testLogD;
 
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.SystemClock;
+import android.util.Log;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
@@ -141,7 +141,7 @@
 
             return new Taskbar(mLauncher);
         } finally {
-            testLogD(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
+            Log.d(SUCCESSFUL_GESTURE_MISMATCH_EVENTS,
                     "swipeUpToUnstashTaskbar: completed gesture");
             mLauncher.getTestInfo(REQUEST_DISABLE_BLOCK_TIMEOUT);
         }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 70a5336..0a52955 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -24,6 +24,7 @@
 import static android.view.MotionEvent.ACTION_SCROLL;
 import static android.view.MotionEvent.ACTION_UP;
 import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
+import static android.view.Surface.ROTATION_90;
 
 import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
 import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
@@ -114,9 +115,6 @@
 
     static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
     static final Pattern EVENT_START = Pattern.compile("start:");
-
-    private static final Pattern EVENT_KEY_BACK_DOWN =
-            getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK");
     private static final Pattern EVENT_KEY_BACK_UP =
             getKeyEventPattern("ACTION_UP", "KEYCODE_BACK");
     private static final Pattern EVENT_ON_BACK_INVOKED = Pattern.compile("onBackInvoked");
@@ -405,6 +403,11 @@
                 .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
+    private boolean isPredictiveBackSwipeEnabled() {
+        return getTestInfo(TestProtocol.REQUEST_IS_PREDICTIVE_BACK_SWIPE_ENABLED)
+                .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+    }
+
     public boolean isTaskbarNavbarUnificationEnabled() {
         return getTestInfo(TestProtocol.REQUEST_ENABLE_TASKBAR_NAVBAR_UNIFICATION)
                 .getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD);
@@ -472,12 +475,25 @@
         logShellCommand(cmd);
     }
 
+    /**
+     * Retrieves a resource value from context that defines if nav bar can change position or if it
+     * is fixed position regardless of device orientation.
+     */
+    private boolean getNavBarCanMove() {
+        final Context baseContext = mInstrumentation.getTargetContext();
+        try {
+            final Context ctx = getLauncherContext(baseContext);
+            return getNavBarCanMove(ctx);
+        } catch (Exception e) {
+            fail(e.toString());
+        }
+        return false;
+    }
+
     public NavigationModel getNavigationModel() {
         final Context baseContext = mInstrumentation.getTargetContext();
         try {
-            // Workaround, use constructed context because both the instrumentation context and the
-            // app context are not constructed with resources that take overlays into account
-            final Context ctx = baseContext.createPackageContext(getLauncherPackageName(), 0);
+            final Context ctx = getLauncherContext(baseContext);
             for (int i = 0; i < 100; ++i) {
                 final int currentInteractionMode = getCurrentInteractionMode(ctx);
                 final NavigationModel model = getNavigationModel(currentInteractionMode);
@@ -1099,19 +1115,31 @@
     /**
      * Goes to home from immersive fullscreen app by first swiping up to bring navbar, and then
      * performing {@code goHome()} action.
-     * Currently only supports gesture navigation mode.
      *
      * @return the Workspace object.
      */
     public Workspace goHomeFromImmersiveFullscreenApp() {
-        assertTrue("expected gesture navigation mode",
-                getNavigationModel() == NavigationModel.ZERO_BUTTON);
-        final Point displaySize = getRealDisplaySize();
-        linearGesture(
-                displaySize.x / 2, displaySize.y - 1,
-                displaySize.x / 2, 0,
-                ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
-                false, GestureScope.EXPECT_PILFER);
+        final boolean navBarCanMove = getNavBarCanMove();
+        if (getNavigationModel() == NavigationModel.ZERO_BUTTON || !navBarCanMove) {
+            // in gesture nav we can swipe up at the bottom to bring the navbar handle
+            final Point displaySize = getRealDisplaySize();
+            linearGesture(
+                    displaySize.x / 2, displaySize.y - 1,
+                    displaySize.x / 2, 0,
+                    ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
+                    false, GestureScope.EXPECT_PILFER);
+        } else {
+            // in 3 button nav we swipe up on the side edge of the screen to bring the navbar
+            final boolean rotated90degrees = mDevice.getDisplayRotation() == ROTATION_90;
+            final Point displaySize = getRealDisplaySize();
+            final int startX = rotated90degrees ? displaySize.x : 0;
+            final int endX = rotated90degrees ? 0 : displaySize.x;
+            linearGesture(
+                    startX, displaySize.y / 2,
+                    endX, displaySize.y / 2,
+                    ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME,
+                    false, GestureScope.EXPECT_PILFER);
+        }
         return goHome();
     }
 
@@ -1214,11 +1242,9 @@
             waitForNavigationUiObject("back").click();
         }
         if (launcherVisible) {
-            if (InstrumentationRegistry.getTargetContext().getApplicationInfo()
-                    .isOnBackInvokedCallbackEnabled()) {
+            if (isPredictiveBackSwipeEnabled()) {
                 expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ON_BACK_INVOKED);
             } else {
-                expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_KEY_BACK_DOWN);
                 expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_KEY_BACK_UP);
             }
         }
@@ -1919,17 +1945,21 @@
     }
 
     private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
-            float x, float y, int source) {
+            float x, float y, int source, int toolType) {
         return MotionEvent.obtain(downTime, eventTime, action, 1,
-                new MotionEvent.PointerProperties[]{getPointerProperties(0)},
+                new MotionEvent.PointerProperties[]{getPointerProperties(0, toolType)},
                 new MotionEvent.PointerCoords[]{getPointerCoords(x, y)},
                 0, 0, 1.0f, 1.0f, 0, 0, source, 0);
     }
 
     private static MotionEvent.PointerProperties getPointerProperties(int pointerId) {
+        return getPointerProperties(pointerId, Configurator.getInstance().getToolType());
+    }
+
+    private static MotionEvent.PointerProperties getPointerProperties(int pointerId, int toolType) {
         MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
         properties.id = pointerId;
-        properties.toolType = Configurator.getInstance().getToolType();
+        properties.toolType = toolType;
         return properties;
     }
 
@@ -1975,6 +2005,19 @@
 
     public void sendPointer(long downTime, long currentTime, int action, Point point,
             GestureScope gestureScope, int source, boolean isRightClick) {
+        sendPointer(
+                downTime,
+                currentTime,
+                action,
+                point,
+                gestureScope,
+                source,
+                isRightClick,
+                Configurator.getInstance().getToolType());
+    }
+
+    public void sendPointer(long downTime, long currentTime, int action, Point point,
+            GestureScope gestureScope, int source, boolean isRightClick, int toolType) {
         final boolean hasTIS = hasTIS();
         int pointerCount = mPointerCount;
 
@@ -2009,13 +2052,13 @@
                 ? getTrackpadMotionEvent(
                 downTime, currentTime, action, point.x, point.y, pointerCount,
                 mTrackpadGestureType)
-                : getMotionEvent(downTime, currentTime, action, point.x, point.y, source);
+                : getMotionEvent(downTime, currentTime, action, point.x, point.y, source, toolType);
         if (action == MotionEvent.ACTION_BUTTON_PRESS
                 || action == MotionEvent.ACTION_BUTTON_RELEASE) {
             event.setActionButton(MotionEvent.BUTTON_PRIMARY);
         }
         if (isRightClick) {
-            event.setButtonState(event.getButtonState() & MotionEvent.BUTTON_SECONDARY);
+            event.setButtonState(event.getButtonState() | MotionEvent.BUTTON_SECONDARY);
         }
         injectEvent(event);
     }
@@ -2109,20 +2152,31 @@
         return getSystemIntegerRes(context, "config_navBarInteractionMode");
     }
 
+    /**
+     * Retrieve the resource value that defines if nav bar can moved or if it is fixed position.
+     */
+    private static boolean getNavBarCanMove(Context context) {
+        return getSystemBooleanRes(context, "config_navBarCanMove");
+    }
+
     @NonNull
     UiObject2 clickAndGet(
             @NonNull final UiObject2 target, @NonNull String resName, Pattern longClickEvent) {
         final Point targetCenter = target.getVisibleCenter();
         final long downTime = SystemClock.uptimeMillis();
+        // Use stylus secondary button press to prevent using the exteded long press timeout rule
+        // unnecessarily
         sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, targetCenter,
-                GestureScope.DONT_EXPECT_PILFER);
+                GestureScope.DONT_EXPECT_PILFER, InputDevice.SOURCE_TOUCHSCREEN,
+                /* isRightClick= */ true, MotionEvent.TOOL_TYPE_STYLUS);
         try {
             expectEvent(TestProtocol.SEQUENCE_MAIN, longClickEvent);
             final UiObject2 result = waitForLauncherObject(resName);
             return result;
         } finally {
             sendPointer(downTime, SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, targetCenter,
-                    GestureScope.DONT_EXPECT_PILFER);
+                    GestureScope.DONT_EXPECT_PILFER, InputDevice.SOURCE_TOUCHSCREEN,
+                    /* isRightClick= */ true, MotionEvent.TOOL_TYPE_STYLUS);
         }
     }
 
@@ -2145,6 +2199,18 @@
         }
     }
 
+    private static boolean getSystemBooleanRes(Context context, String resName) {
+        Resources res = context.getResources();
+        int resId = res.getIdentifier(resName, "bool", "android");
+
+        if (resId != 0) {
+            return res.getBoolean(resId);
+        } else {
+            Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?");
+            return false;
+        }
+    }
+
     private static int getSystemIntegerRes(Context context, String resName) {
         Resources res = context.getResources();
         int resId = res.getIdentifier(resName, "integer", "android");
@@ -2410,6 +2476,13 @@
         return Math.max(topRadius, bottomRadius) + tmpBuffer;
     }
 
+    private Context getLauncherContext(Context baseContext)
+            throws PackageManager.NameNotFoundException {
+        // Workaround, use constructed context because both the instrumentation context and the
+        // app context are not constructed with resources that take overlays into account
+        return baseContext.createPackageContext(getLauncherPackageName(), 0);
+    }
+
     private static boolean supportsRoundedCornersOnWindows(Resources resources) {
         return ResourceUtils.getBoolByName(
                 "config_supportsRoundedCornersOnWindows", resources, false);
@@ -2452,7 +2525,7 @@
             int bottomBound = Math.min(
                     containerBounds.bottom,
                     getRealDisplaySize().y - systemGestureRegion.bottom);
-            int y = (bottomBound - containerBounds.top) / 2;
+            int y = (bottomBound + containerBounds.top) / 2;
             // Do not tap in the status bar.
             y = Math.max(y, systemGestureRegion.top);
 
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index d7c40a0..486a63b 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -17,6 +17,7 @@
 package com.android.launcher3.tapl;
 
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.UiObject2;
 
 /**
@@ -110,4 +111,12 @@
             }
         }
     }
+
+    /** Asserts that an item matching the given string is present in the overview actions. */
+    public void assertHasAction(String text) {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to check if the action [" + text + "] is present")) {
+            mLauncher.waitForObjectInContainer(mOverviewActions, By.text(text));
+        }
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index afe5722..99da5c3 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -19,10 +19,13 @@
 import static com.android.launcher3.tapl.OverviewTask.OverviewSplitTask.DEFAULT;
 import static com.android.launcher3.tapl.OverviewTask.OverviewSplitTask.SPLIT_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.tapl.OverviewTask.OverviewSplitTask.SPLIT_TOP_OR_LEFT;
+import static com.android.launcher3.testing.shared.TestProtocol.SUCCESSFUL_GESTURE_MISMATCH_EVENTS;
 
 import android.graphics.Rect;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.BySelector;
 import androidx.test.uiautomator.UiObject2;
@@ -219,6 +222,7 @@
                     return new LaunchedAppState(mLauncher);
                 }
             } else {
+                Log.d(SUCCESSFUL_GESTURE_MISMATCH_EVENTS, "TaskView.launchTaskAnimated");
                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, TASK_START_EVENT);
                 return new LaunchedAppState(mLauncher);
             }
@@ -256,6 +260,23 @@
     }
 
     /**
+     * Returns whether the given String is contained in this Task's contentDescription. Also returns
+     * true if both Strings are null.
+     *
+     * TODO(b/326565120): remove Nullable support once the bug causing it to be null is fixed.
+     */
+    public boolean containsContentDescription(@Nullable String expected) {
+        String actual = mTask.getContentDescription();
+        if (actual == null && expected == null) {
+            return true;
+        }
+        if (actual == null || expected == null) {
+            return false;
+        }
+        return actual.contains(expected);
+    }
+
+    /**
      * Enum used to specify  which task is retrieved when it is a split task.
      */
     public enum OverviewSplitTask {
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
new file mode 100644
index 0000000..2c16e01
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceContainer.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * View containing Private Space elements.
+ */
+public class PrivateSpaceContainer {
+    private static final String PS_HEADER_RES_ID = "ps_header_layout";
+    private static final String INSTALL_APP_TITLE = "Install apps";
+    private static final String DIVIDER_RES_ID = "private_space_divider";
+
+    private final LauncherInstrumentation mLauncher;
+    private final UiObject2 mAppListRecycler;
+
+    PrivateSpaceContainer(LauncherInstrumentation launcherInstrumentation,
+            UiObject2 appListRecycler) {
+        mLauncher = launcherInstrumentation;
+        mAppListRecycler = appListRecycler;
+
+        verifyHeaderIsPresent();
+        verifyInstallAppButtonIsPresent();
+        verifyDividerIsPresent();
+    }
+
+    // Assert PS Header is in view.
+    // Assert PS header has the correct elements.
+    private void verifyHeaderIsPresent() {
+        final UiObject2 psHeader = mLauncher.waitForObjectInContainer(mAppListRecycler,
+                PS_HEADER_RES_ID);
+        new PrivateSpaceHeader(mLauncher, psHeader, true);
+    }
+
+
+    // Assert Install App Item is present in view.
+    private void verifyInstallAppButtonIsPresent() {
+        mLauncher.getAllApps().getAppIcon(INSTALL_APP_TITLE);
+    }
+
+    // Assert Sys App Divider is present in view.
+    private void verifyDividerIsPresent() {
+        mLauncher.waitForObjectInContainer(mAppListRecycler, DIVIDER_RES_ID);
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
new file mode 100644
index 0000000..3a7f038
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/PrivateSpaceHeader.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * View containing Private Space Header.
+ */
+public class PrivateSpaceHeader {
+    private static final String PS_HEADER_TEXT_RES_ID = "ps_container_header";
+    private static final String SETTINGS_BUTTON_RES_ID = "ps_settings_button";
+    private static final String UNLOCK_BUTTON_VIEW_RES_ID = "ps_lock_unlock_button";
+    private static final String LOCK_ICON_RES_ID = "lock_icon";
+    private static final String LOCK_TEXT_RES_ID = "lock_text";
+
+    private final UiObject2 mPrivateSpaceHeader;
+    private final boolean mPrivateSpaceEnabled;
+    private final LauncherInstrumentation mLauncher;
+
+    PrivateSpaceHeader(LauncherInstrumentation launcherInstrumentation,
+            UiObject2 privateSpaceHeader, boolean privateSpaceEnabled) {
+        mLauncher = launcherInstrumentation;
+        mPrivateSpaceHeader = privateSpaceHeader;
+        mPrivateSpaceEnabled =  privateSpaceEnabled;
+        verifyPrivateSpaceHeaderState();
+    }
+
+    /** Verify elements in Private Space Header as per state */
+    private void verifyPrivateSpaceHeaderState() {
+        if (mPrivateSpaceEnabled) {
+            verifyUnlockedState();
+        } else {
+            mLauncher.fail("Private Space found in non enabled state");
+        }
+    }
+
+    /** Verify Unlocked State elements in Private Space Header */
+    private void verifyUnlockedState() {
+        UiObject2 headerText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                PS_HEADER_TEXT_RES_ID);
+        mLauncher.assertEquals("PS Header Text is incorrect ",
+                "Private", headerText.getText());
+
+        UiObject2 settingsButton = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                SETTINGS_BUTTON_RES_ID);
+        mLauncher.waitForObjectEnabled(settingsButton, "Private Space Settings Button");
+        mLauncher.assertTrue("PS Settings button is non-clickable", settingsButton.isClickable());
+
+        UiObject2 unLockButtonView = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                UNLOCK_BUTTON_VIEW_RES_ID);
+        mLauncher.waitForObjectEnabled(unLockButtonView, "Private Space Unlock Button");
+        mLauncher.assertTrue("PS Unlock Button is non-clickable", unLockButtonView.isClickable());
+
+        mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                LOCK_ICON_RES_ID);
+
+        UiObject2 lockText = mLauncher.waitForObjectInContainer(mPrivateSpaceHeader,
+                LOCK_TEXT_RES_ID);
+        mLauncher.assertEquals("PS lock text is incorrect", "Lock", lockText.getText());
+
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
index e2bc17b..6d2631f 100644
--- a/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
+++ b/tests/tapl/com/android/launcher3/tapl/SelectModeButtons.java
@@ -33,9 +33,6 @@
 public class SelectModeButtons {
     private final UiObject2 mSelectModeButtons;
     private final LauncherInstrumentation mLauncher;
-
-    private static final Pattern EVENT_ALT_ESC_DOWN = Pattern.compile(
-            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
     private static final Pattern EVENT_ALT_ESC_UP = Pattern.compile(
             "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_ESCAPE.*?metaState=0");
 
@@ -69,7 +66,6 @@
     @NonNull
     public Overview dismissByEscKey() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_ALT_ESC_UP);
             mLauncher.runToState(
                     () -> mLauncher.getDevice().pressKeyCode(KEYCODE_ESCAPE),
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 4e92634..d176136 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -66,10 +66,6 @@
     private static final String DROP_BAR_RES_ID = "drop_target_bar";
     private static final String DELETE_TARGET_TEXT_ID = "delete_target_text";
     private static final String UNINSTALL_TARGET_TEXT_ID = "uninstall_target_text";
-
-    static final Pattern EVENT_CTRL_W_DOWN = Pattern.compile(
-            "Key event: KeyEvent.*?action=ACTION_DOWN.*?keyCode=KEYCODE_W"
-                    + ".*?metaState=META_CTRL_ON");
     static final Pattern EVENT_CTRL_W_UP = Pattern.compile(
             "Key event: KeyEvent.*?action=ACTION_UP.*?keyCode=KEYCODE_W"
                     + ".*?metaState=META_CTRL_ON");
@@ -822,7 +818,6 @@
     public Widgets openAllWidgets() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             verifyActiveContainer();
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_CTRL_W_DOWN);
             mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_CTRL_W_UP);
             mLauncher.getDevice().pressKeyCode(KeyEvent.KEYCODE_W, KeyEvent.META_CTRL_ON);
             try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer("pressed Ctrl+W")) {