[automerger skipped] Merge "Import translations. DO NOT MERGE ANYWHERE" into udc-d1-dev am: 232c0f33ba -s ours

am skip reason: subject contains skip directive

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

Change-Id: I45805c6aef830b6310b8cc295b1b5c542bbb2b0b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index a7edf2a..9b696a2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -172,6 +172,7 @@
     static_libs: [
         "Launcher3ResLib",
         "launcher-testing-shared",
+        "animationlib"
     ],
     sdk_version: "current",
     min_sdk_version: min_launcher3_sdk_version,
diff --git a/quickstep/res/drawable/bg_floating_desktop_select.xml b/quickstep/res/drawable/bg_floating_desktop_select.xml
new file mode 100644
index 0000000..d7df338
--- /dev/null
+++ b/quickstep/res/drawable/bg_floating_desktop_select.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+    Copyright (C) 2023 The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<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/rounded_button_radius" />
+    <solid android:color="?androidprv:attr/materialColorPrimaryContainer" />
+</shape>
\ No newline at end of file
diff --git a/quickstep/res/layout/floating_desktop_app_select.xml b/quickstep/res/layout/floating_desktop_app_select.xml
new file mode 100644
index 0000000..375fc44
--- /dev/null
+++ b/quickstep/res/layout/floating_desktop_app_select.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+     Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<com.android.quickstep.views.DesktopAppSelectView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="@dimen/desktop_mode_floating_app_select_height"
+    android:layout_gravity="top|center_horizontal"
+    android:background="@drawable/bg_floating_desktop_select"
+    android:elevation="@dimen/desktop_mode_floating_app_select_elevation"
+    android:gravity="center_vertical"
+    android:orientation="horizontal">
+
+    <TextView
+        android:id="@+id/desktop_app_select_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_text_margin"
+        android:layout_marginStart="@dimen/desktop_mode_floating_app_select_margin"
+        android:drawablePadding="@dimen/desktop_mode_floating_app_select_text_margin"
+        android:drawableStart="@drawable/ic_desktop"
+        android:drawableTint="?androidprv:attr/materialColorOnPrimaryContainer"
+        android:fontFamily="google-sans-medium"
+        android:gravity="center_vertical"
+        android:text="@string/desktop_select_app_toast"
+        android:textColor="?androidprv:attr/materialColorOnPrimaryContainer"
+        android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
+
+    <Button
+        android:id="@+id/close_button"
+        style="@android:style/Widget.DeviceDefault.Button.Borderless"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/desktop_mode_floating_app_select_margin"
+        android:minWidth="0dp"
+        android:fontFamily="google-sans-medium"
+        android:text="@string/desktop_button_close_app_toast"
+        android:textAllCaps="false"
+        android:textColor="?androidprv:attr/materialColorPrimary"
+        android:textSize="@dimen/desktop_mode_floating_app_select_text_size" />
+
+</com.android.quickstep.views.DesktopAppSelectView>
diff --git a/quickstep/res/values-af/strings.xml b/quickstep/res/values-af/strings.xml
index 2dc0a1e..56104e0 100644
--- a/quickstep/res/values-af/strings.xml
+++ b/quickstep/res/values-af/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Skuif na regs onder"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Wys nog # app.}other{Wys nog # apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Voeg nou app by werkskerm"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselleer"</string>
 </resources>
diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml
index 36a8bda..b86e873 100644
--- a/quickstep/res/values-am/strings.xml
+++ b/quickstep/res/values-am/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ወደ ታች/ቀኝ ይውሰዱ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ተጨማሪ # መተግበሪያ አሳይ።}one{ተጨማሪ # መተግበሪያ አሳይ።}other{ተጨማሪ # መተግበሪያዎች አሳይ።}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> እና <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"መተግበሪያን ወደ ዴስክቶፕ በማከል ላይ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ይቅር"</string>
 </resources>
diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml
index 4e3cd17..872f40b 100644
--- a/quickstep/res/values-ar/strings.xml
+++ b/quickstep/res/values-ar/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"الانتقال إلى يسار الشاشة أو أسفلها"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{إظهار تطبيق واحد آخر}zero{إظهار # تطبيق آخر}two{إظهار تطبيقَين آخرَين}few{إظهار # تطبيقات أخرى}many{إظهار # تطبيقًا آخر}other{إظهار # تطبيق آخر}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"\"<xliff:g id="APP_NAME_1">%1$s</xliff:g>\" و\"<xliff:g id="APP_NAME_2">%2$s</xliff:g>\""</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"إضافة تطبيق إلى سطح المكتب"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"إلغاء"</string>
 </resources>
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index aab660d..020d911 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"তলৰ সোঁফাললৈ নিয়ক"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আৰু # টা এপ্‌ দেখুৱাওক।}one{আৰু # টা এপ্‌ দেখুৱাওক।}other{আৰু # টা এপ্‌ দেখুৱাওক।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> আৰু <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপত এপ্ যোগ দি থকা হৈছে"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল কৰক"</string>
 </resources>
diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml
index d6cf4ac..a44b1c4 100644
--- a/quickstep/res/values-az/strings.xml
+++ b/quickstep/res/values-az/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Aşağı/sağa köçürün"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Daha # tətbiqi göstərin.}other{Daha # tətbiqi göstərin.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> və <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Tətbiqin masaüstünə əlavə edilməsi"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ləğv edin"</string>
 </resources>
diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml
index 9fc7a74..8c05627 100644
--- a/quickstep/res/values-b+sr+Latn/strings.xml
+++ b/quickstep/res/values-b+sr+Latn/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premesti dole desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaje se aplikacija na radnu povrršinu"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
 </resources>
diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml
index 685c921..a967e40 100644
--- a/quickstep/res/values-be/strings.xml
+++ b/quickstep/res/values-be/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перамясціць уніз/управа"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Паказаць ячшэ # праграму.}one{Паказаць ячшэ # праграму.}few{Паказаць ячшэ # праграмы.}many{Паказаць ячшэ # праграм.}other{Паказаць ячшэ # праграмы.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> і <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Дадаванне праграмы на камп\'ютар"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасаваць"</string>
 </resources>
diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml
index ad87573..ecb976d 100644
--- a/quickstep/res/values-bg/strings.xml
+++ b/quickstep/res/values-bg/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Преместване долу/вдясно"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показване на още # приложение.}other{Показване на още # приложения.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Приложението се добавя на настолния компютър"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отказ"</string>
 </resources>
diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml
index 97dbeae..492ba02 100644
--- a/quickstep/res/values-bn/strings.xml
+++ b/quickstep/res/values-bn/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"নিচে/ডানদিকে সরান"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{আরও #টি অ্যাপ দেখুন।}one{আরও #টি অ্যাপ দেখুন।}other{আরও #টি অ্যাপ দেখুন।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ও <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ডেস্কটপে অ্যাপ যোগ করা হচ্ছে"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"বাতিল করুন"</string>
 </resources>
diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml
index fea5b6a..314fd97 100644
--- a/quickstep/res/values-bs/strings.xml
+++ b/quickstep/res/values-bs/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži još # aplikaciju.}one{Prikaži još # aplikaciju.}few{Prikaži još # aplikacije.}other{Prikaži još # aplikacija.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Otkaži"</string>
 </resources>
diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml
index 011b121..85b4f97 100644
--- a/quickstep/res/values-ca/strings.xml
+++ b/quickstep/res/values-ca/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mou a la part inferior o a la dreta"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # aplicació més.}other{Mostra # aplicacions més.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"S\'està afegint l\'aplicació a l\'ordinador"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel·la"</string>
 </resources>
diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml
index 786e162..a6eac94 100644
--- a/quickstep/res/values-cs/strings.xml
+++ b/quickstep/res/values-cs/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Přesunout doprava dolů"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobrazit # další aplikaci.}few{Zobrazit # další aplikace.}many{Zobrazit # další aplikace.}other{Zobrazit # dalších aplikací.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Přidání aplikace na plochu"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušit"</string>
 </resources>
diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml
index bde4fe1..906e0cf 100644
--- a/quickstep/res/values-da/strings.xml
+++ b/quickstep/res/values-da/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flyt til bunden eller højre side"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app mere.}one{Vis # app mere.}other{Vis # apps mere.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Appen føjes til computeren"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuller"</string>
 </resources>
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index a5766f7..bb4dde1 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Nach unten / Nach rechts verschieben"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# weitere App anzeigen.}other{# weitere Apps anzeigen.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> und <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Hinzufügen einer App zum Desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Abbrechen"</string>
 </resources>
diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml
index 03774c2..70cb41e 100644
--- a/quickstep/res/values-el/strings.xml
+++ b/quickstep/res/values-el/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Μετακίνηση κάτω/δεξιά"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Εμφάνιση # ακόμα εφαρμογής.}other{Εμφάνιση # ακόμα εφαρμογών.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> και <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Γίνεται προσθήκη εφαρμογής στον υπολογιστή"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ακύρωση"</string>
 </resources>
diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml
index f5d7e73..b1ad549 100644
--- a/quickstep/res/values-en-rAU/strings.xml
+++ b/quickstep/res/values-en-rAU/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rCA/strings.xml b/quickstep/res/values-en-rCA/strings.xml
index 9adb0f4..9005ca9 100644
--- a/quickstep/res/values-en-rCA/strings.xml
+++ b/quickstep/res/values-en-rCA/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to Desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml
index f5d7e73..b1ad549 100644
--- a/quickstep/res/values-en-rGB/strings.xml
+++ b/quickstep/res/values-en-rGB/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml
index f5d7e73..b1ad549 100644
--- a/quickstep/res/values-en-rIN/strings.xml
+++ b/quickstep/res/values-en-rIN/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Move to bottom/right"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Show # more app.}other{Show # more apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> and <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adding app to desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancel"</string>
 </resources>
diff --git a/quickstep/res/values-en-rXC/strings.xml b/quickstep/res/values-en-rXC/strings.xml
index 853684d..0b4ac4e 100644
--- a/quickstep/res/values-en-rXC/strings.xml
+++ b/quickstep/res/values-en-rXC/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‎Move to bottom/right‎‏‎‎‏‎"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more app.‎‏‎‎‏‎}other{‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎Show # more apps.‎‏‎‎‏‎}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‎‏‏‎<xliff:g id="APP_NAME_1">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="APP_NAME_2">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎Adding app to Desktop‎‏‎‎‏‎"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‎Cancel‎‏‎‎‏‎"</string>
 </resources>
diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml
index e31466a..c37f6c3 100644
--- a/quickstep/res/values-es-rUS/strings.xml
+++ b/quickstep/res/values-es-rUS/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover a la parte inferior o derecha"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # app más.}other{Mostrar # apps más.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Agregando app al escritorio"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 06078e3..9f2f9fd 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover abajo/a la derecha"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación más.}other{Mostrar # aplicaciones más.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> y <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Añadiendo aplicación al ordenador"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 0095d51..0186c16 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Teisalda alla/paremale"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Kuva veel # rakendus.}other{Kuva veel # rakendust.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Rakenduse lisamine arvutisse"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Tühista"</string>
 </resources>
diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml
index fa624e7..97bee38 100644
--- a/quickstep/res/values-eu/strings.xml
+++ b/quickstep/res/values-eu/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Eraman behera, eskuinetara"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Erakutsi beste # aplikazio.}other{Erakutsi beste # aplikazio.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> eta <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aplikazioa mahaigainean gehitzen"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Utzi"</string>
 </resources>
diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml
index e520acd..55d3786 100644
--- a/quickstep/res/values-fa/strings.xml
+++ b/quickstep/res/values-fa/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"انتقال به پایین/ راست"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{نمایش # برنامه دیگر.}one{نمایش # برنامه دیگر.}other{نمایش # برنامه دیگر.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> و <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"درحال افزودن برنامه به رایانه"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"لغو"</string>
 </resources>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index 5c04d68..933996e 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Siirrä alas tai oikealle"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Näytä # muu sovellus.}other{Näytä # muuta sovellusta.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ja <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Sovelluksen lisääminen työpöydälle"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Peru"</string>
 </resources>
diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml
index 56e5047..b8bcffc 100644
--- a/quickstep/res/values-fr-rCA/strings.xml
+++ b/quickstep/res/values-fr-rCA/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer vers le coin inférieur droit de l\'écran"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre application.}one{Afficher # autre application.}other{Afficher # autres applications.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'application au bureau en cours…"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
 </resources>
diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml
index 31068f7..147db17 100644
--- a/quickstep/res/values-fr/strings.xml
+++ b/quickstep/res/values-fr/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Déplacer en bas ou à droite"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afficher # autre appli.}one{Afficher # autre appli.}other{Afficher # autre applis.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> et <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ajout de l\'appli au bureau"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuler"</string>
 </resources>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index ebec206..2fd2784 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover á parte inferior ou á dereita"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar # aplicación máis.}other{Mostrar # aplicacións máis.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Engadindo aplicación ao ordenador"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 2e1c289..2c14282 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"સૌથી નીચે જમણી બાજુએ ખસેડો"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{વધુ # ઍપ બતાવો.}one{વધુ # ઍપ બતાવો.}other{વધુ # ઍપ બતાવો.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> અને <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ડેસ્કટૉપ પર ઍપ ઉમેરી રહ્યાં છીએ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"રદ કરો"</string>
 </resources>
diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml
index 2dc6603..d84b05a 100644
--- a/quickstep/res/values-hi/strings.xml
+++ b/quickstep/res/values-hi/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"नीचे/दाईं तरफ़ ले जाएं"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# और ऐप्लिकेशन दिखाएं.}one{# और ऐप्लिकेशन दिखाएं.}other{# और ऐप्लिकेशन दिखाएं.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> और <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉप पर ऐप्लिकेशन जोड़ा जा रहा है"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करें"</string>
 </resources>
diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml
index 2a18704..753df15 100644
--- a/quickstep/res/values-hr/strings.xml
+++ b/quickstep/res/values-hr/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premjesti dolje/desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Prikaži više aplikacija (još #).}one{Prikaži više aplikacija (još #).}few{Prikaži više aplikacija (još #).}other{Prikaži više aplikacija (još #).}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodavanje aplikacije na radnu površinu"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Odustani"</string>
 </resources>
diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml
index 27f5efa..63e4baf 100644
--- a/quickstep/res/values-hu/strings.xml
+++ b/quickstep/res/values-hu/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mozgatás alulra vagy a jobb oldalra"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# további alkalmazás megjelenítése.}other{# további alkalmazás megjelenítése.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> és <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Alkalmazás hozzáadása az asztalhoz"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Mégse"</string>
 </resources>
diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml
index 80e6750..6f174ff 100644
--- a/quickstep/res/values-hy/strings.xml
+++ b/quickstep/res/values-hy/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Տեղափոխել ներքևի աջ անկյուն"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Ցուցադրել ևս # հավելված։}one{Ցուցադրել ևս # հավելված։}other{Ցուցադրել ևս # հավելված։}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> և <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Հավելվածն ավելացվում է աշխատասեղանին"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Չեղարկել"</string>
 </resources>
diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml
index 0d4e375..5a06763 100644
--- a/quickstep/res/values-in/strings.xml
+++ b/quickstep/res/values-in/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pindahkan ke bawah/kanan"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tampilkan # aplikasi lain.}other{Tampilkan # aplikasi lain.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan aplikasi ke Desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batalkan"</string>
 </resources>
diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml
index 08b5e99..7ec957b 100644
--- a/quickstep/res/values-is/strings.xml
+++ b/quickstep/res/values-is/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Færa neðst/til hægri"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Sýna # forrit í viðbót.}one{Sýna # forrit í viðbót.}other{Sýna # forrit í viðbót.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Forriti bætt við skjáborð"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Hætta við"</string>
 </resources>
diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml
index 6f2f954..8f142ae 100644
--- a/quickstep/res/values-it/strings.xml
+++ b/quickstep/res/values-it/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sposta in basso/a destra"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostra # altra app.}other{Mostra altre # app.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Aggiunta app a desktop in corso…"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annulla"</string>
 </resources>
diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml
index e158869..56a45b5 100644
--- a/quickstep/res/values-iw/strings.xml
+++ b/quickstep/res/values-iw/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"העברה לפינה הימנית/התחתונה"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{הצגת אפליקציה אחת (#) נוספת.}one{הצגת # אפליקציות נוספות.}two{הצגת # אפליקציות נוספות.}other{הצגת # אפליקציות נוספות.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ו-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"האפליקציה מתווספת לשולחן העבודה"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ביטול"</string>
 </resources>
diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml
index d55a2c0..e8f9ffe 100644
--- a/quickstep/res/values-ja/strings.xml
+++ b/quickstep/res/values-ja/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"下 / 右に移動"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{他 # 件のアプリを表示できます。}other{他 # 件のアプリを表示できます。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> と <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"アプリをデスクトップに追加する"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"キャンセル"</string>
 </resources>
diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml
index c1df53c..171ce78 100644
--- a/quickstep/res/values-ka/strings.xml
+++ b/quickstep/res/values-ka/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ქვემოთ/მარჯვნივ გადატანა"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{#-ით მეტი აპის ჩენება}other{#-ით მეტი აპის ჩვენება.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> და <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"მიმდინარეობს აპის დესკტოპზე დამატება"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"გაუქმება"</string>
 </resources>
diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml
index 68141aa..05cfd74 100644
--- a/quickstep/res/values-kk/strings.xml
+++ b/quickstep/res/values-kk/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмен/оңға жылжыту"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Тағы # қолданбаны көрсету.}other{Тағы # қолданбаны көрсету.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> және <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Жұмыс үстеліне қолданба қосу"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Бас тарту"</string>
 </resources>
diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml
index aa20709..1ece40b 100644
--- a/quickstep/res/values-km/strings.xml
+++ b/quickstep/res/values-km/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ផ្លាស់ទីទៅខាងក្រោម/ស្ដាំ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{បង្ហាញកម្មវិធី # ទៀត។}other{បង្ហាញ​កម្មវិធី # ទៀត។}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> និង <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"កំពុងបញ្ចូល​កម្មវិធីទៅកុំព្យូទ័រ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"បោះបង់"</string>
 </resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 9bb18fa..d526f89 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ಕೆಳಗಿನ/ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ಇನ್ನೂ # ಆ್ಯಪ್ ಅನ್ನು ತೋರಿಸಿ.}one{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}other{ಇನ್ನೂ # ಆ್ಯಪ್‌ಗಳನ್ನು ತೋರಿಸಿ.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ಡೆಸ್ಕ್‌ಟಾಪ್‌ಗೆ ಆ್ಯಪ್ ಅನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ರದ್ದುಮಾಡಿ"</string>
 </resources>
diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml
index 4cef3ca..72900f1 100644
--- a/quickstep/res/values-ko/strings.xml
+++ b/quickstep/res/values-ko/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"하단/오른쪽으로 이동"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{앱 #개 더 표시}other{앱 #개 더 표시}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> 및 <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"데스크톱에 앱 추가하기"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"취소"</string>
 </resources>
diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml
index 64a1c90..5f944ec 100644
--- a/quickstep/res/values-ky/strings.xml
+++ b/quickstep/res/values-ky/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Төмөнкү/оң бурчка жылдыруу"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Дагы # колдонмону көрсөтүү.}other{Дагы # колдонмону көрсөтүү.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> жана <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Колдонмону иш тактага кошуу"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Жокко чыгаруу"</string>
 </resources>
diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml
index 72201f2..a9a9202 100644
--- a/quickstep/res/values-lo/strings.xml
+++ b/quickstep/res/values-lo/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ຍ້າຍໄປຂວາ/ລຸ່ມ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ສະແດງອີກ # ແອັບ.}other{ສະແດງອີກ # ແອັບ.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ແລະ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ການເພີ່ມແອັບໄປໃສ່ເດັສທັອບ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ຍົກເລີກ"</string>
 </resources>
diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml
index ba0df27..5417374 100644
--- a/quickstep/res/values-lt/strings.xml
+++ b/quickstep/res/values-lt/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Perkelti žemyn, dešinėn"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rodyti dar # programą.}one{Rodyti dar # programą.}few{Rodyti dar # programas.}many{Rodyti dar # programos.}other{Rodyti dar # programų.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"„<xliff:g id="APP_NAME_1">%1$s</xliff:g>“ ir „<xliff:g id="APP_NAME_2">%2$s</xliff:g>“"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridedama programa prie darbalaukio"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atšaukti"</string>
 </resources>
diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml
index 3992ebd..d193c9d 100644
--- a/quickstep/res/values-lv/strings.xml
+++ b/quickstep/res/values-lv/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pārvietot uz apakšējo/labo stūri"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Rādīt vēl # lietotni}zero{Rādīt vēl # lietotnes}one{Rādīt vēl # lietotni}other{Rādīt vēl # lietotnes}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"“<xliff:g id="APP_NAME_1">%1$s</xliff:g>” un “<xliff:g id="APP_NAME_2">%2$s</xliff:g>”"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Notiek lietotnes pievienošana datoram"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Atcelt"</string>
 </resources>
diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml
index fcbca7e..130c198 100644
--- a/quickstep/res/values-mk/strings.xml
+++ b/quickstep/res/values-mk/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести долу десно"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи уште # апликација.}one{Прикажи уште # апликација.}other{Прикажи уште # апликации.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додавање на апликацијата во „Работна површина“"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
 </resources>
diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml
index 3d87fb6..4182ee3 100644
--- a/quickstep/res/values-ml/strings.xml
+++ b/quickstep/res/values-ml/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"താഴേക്കോ വലത്തേക്കോ നീക്കുക"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ആപ്പ് കൂടി കാണിക്കുക.}other{# ആപ്പുകൾ കൂടി കാണിക്കുക.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ആപ്പ് ഡെസ്ക്ടോപ്പിലേക്ക് ചേർക്കുന്നു"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"റദ്ദാക്കുക"</string>
 </resources>
diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml
index 40d14f4..005dbd9 100644
--- a/quickstep/res/values-mn/strings.xml
+++ b/quickstep/res/values-mn/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Баруун доод хэсэг рүү зөөх"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Өөр # аппыг харуулна уу.}other{Өөр # аппыг харуулна уу.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> болон <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Компьютерт апп нэмж байна"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Цуцлах"</string>
 </resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index c2ddaf5..7413d9f 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"तळाशी/उजवीकडे हलवा"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{आणखी # अ‍ॅप दाखवा.}other{आणखी # अ‍ॅप्स दाखवा.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> आणि <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटॉपवर ॲप जोडत आहे"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द करा"</string>
 </resources>
diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml
index 129462d..cc3c1ce 100644
--- a/quickstep/res/values-ms/strings.xml
+++ b/quickstep/res/values-ms/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Alihkan ke bawah/kanan"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Tunjukkan # lagi apl.}other{Tunjukkan # lagi apl.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dan <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Menambahkan apl pada Desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Batal"</string>
 </resources>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 287e4a0..a8b53f6 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"အောက်ခြေ/ညာဘက်သို့ ရွှေ့ရန်"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{နောက်ထပ်အက်ပ် # ခု ပြပါ။}other{နောက်ထပ်အက်ပ် # ခု ပြပါ။}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> နှင့် <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"‘ဒက်စ်တော့’ တွင် အက်ပ်ကို ထည့်ခြင်း"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"မလုပ်တော့"</string>
 </resources>
diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml
index 064eaf3..1268ffa 100644
--- a/quickstep/res/values-nb/strings.xml
+++ b/quickstep/res/values-nb/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytt til nederst/høyre"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Vis # app til.}other{Vis # apper til.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> og <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Legg til apper på datamaskin"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
 </resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index f4df28b..00c8451 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"फेद/दायाँतिर सार्नुहोस्"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{थप # एप देखाइयोस्।}other{थप # वटा एप देखाइयोस्।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> र <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"डेस्कटपमा एप हालिँदै छ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"रद्द गर्नुहोस्"</string>
 </resources>
diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml
index 140b4ae..1e273c3 100644
--- a/quickstep/res/values-nl/strings.xml
+++ b/quickstep/res/values-nl/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Naar beneden/rechts verplaatsen"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Nog # app tonen.}other{Nog # apps tonen.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> en <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"App toevoegen aan desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Annuleren"</string>
 </resources>
diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml
index 72729bf..a41fbe7 100644
--- a/quickstep/res/values-or/strings.xml
+++ b/quickstep/res/values-or/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ନିମ୍ନ/ଡାହାଣକୁ ମୁଭ କରନ୍ତୁ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{ଅଧିକ #ଟି ଆପ ଦେଖାନ୍ତୁ।}other{ଅଧିକ #ଟି ଆପ୍ସ ଦେଖାନ୍ତୁ।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ଏବଂ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ଡେସ୍କଟପରେ ଆପ ଯୋଗ କରାଯାଉଛି"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ବାତିଲ କରନ୍ତୁ"</string>
 </resources>
diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml
index 3da7e42..ab76838 100644
--- a/quickstep/res/values-pa/strings.xml
+++ b/quickstep/res/values-pa/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ਹੇਠਾਂ/ਸੱਜੇ ਪਾਸੇ ਲੈ ਕੇ ਜਾਓ"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}one{# ਹੋਰ ਐਪ ਦਿਖਾਓ।}other{# ਹੋਰ ਐਪਾਂ ਦਿਖਾਓ।}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ਐਪ ਨੂੰ ਡੈਸਕਟਾਪ \'ਤੇ ਸ਼ਾਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ਰੱਦ ਕਰੋ"</string>
 </resources>
diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml
index 2ee14ff..e0bec9c 100644
--- a/quickstep/res/values-pl/strings.xml
+++ b/quickstep/res/values-pl/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Przesuń w dolny prawy róg"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaż jeszcze # aplikację.}few{Pokaż jeszcze # aplikacje.}many{Pokaż jeszcze # aplikacji.}other{Pokaż jeszcze # aplikacji.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> i <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodaję aplikację do komputera"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anuluj"</string>
 </resources>
diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml
index c5aad16..1b953ca 100644
--- a/quickstep/res/values-pt-rPT/strings.xml
+++ b/quickstep/res/values-pt-rPT/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para a part superior direita"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"A adicionar a app ao computador"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml
index c2b4d92..1e61ad9 100644
--- a/quickstep/res/values-pt/strings.xml
+++ b/quickstep/res/values-pt/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mover para baixo/para a direita"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Mostrar mais # app.}one{Mostrar mais # app.}other{Mostrar mais # apps.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> e <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Adicionando app ao computador"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Cancelar"</string>
 </resources>
diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml
index 8559f61..3562074 100644
--- a/quickstep/res/values-ro/strings.xml
+++ b/quickstep/res/values-ro/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Mută în dreapta jos"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Afișează încă # aplicație}few{Afișează încă # aplicații}other{Afișează încă # de aplicații}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> și <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Se adaugă aplicația pe computer"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulează"</string>
 </resources>
diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml
index 0634d8b..2e92ee2 100644
--- a/quickstep/res/values-ru/strings.xml
+++ b/quickstep/res/values-ru/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Переместить вниз или вправо"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показать ещё # приложение}one{Показать ещё # приложение}few{Показать ещё # приложения}many{Показать ещё # приложений}other{Показать ещё # приложения}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Добавление приложения на компьютер"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Отмена"</string>
 </resources>
diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml
index 376427b..2369e51 100644
--- a/quickstep/res/values-si/strings.xml
+++ b/quickstep/res/values-si/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"පහළ/දකුණ වෙත ගෙන යන්න"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{තවත් # යෙදුමක් පෙන්වන්න.}one{තවත් යෙදුම් #ක් පෙන්වන්න.}other{තවත් යෙදුම් #ක් පෙන්වන්න.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> සහ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ඩෙස්ක්ටොප් වෙත යෙදුම එක් කිරීම"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"අවලංගු කරන්න"</string>
 </resources>
diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml
index b3f1c29..2291b19 100644
--- a/quickstep/res/values-sk/strings.xml
+++ b/quickstep/res/values-sk/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Presunúť dole alebo doprava"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Zobraziť # ďalšiu aplikáciu.}few{Zobraziť # ďalšie aplikácie.}many{Show # more apps.}other{Zobraziť # ďalších aplikácií.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> a <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Pridanie aplikácie na plochu"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Zrušiť"</string>
 </resources>
diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml
index 38792bd..3c4a45f 100644
--- a/quickstep/res/values-sl/strings.xml
+++ b/quickstep/res/values-sl/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Premakni na dno/desno"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Pokaži še # aplikacijo.}one{Pokaži še # aplikacijo.}two{Pokaži še # aplikaciji.}few{Pokaži še # aplikacije.}other{Pokaži še # aplikacij.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> in <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Dodajanje aplikacije na namizje"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Prekliči"</string>
 </resources>
diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml
index ad9f951..1b207a4 100644
--- a/quickstep/res/values-sq/strings.xml
+++ b/quickstep/res/values-sq/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Lëviz në fund/djathtas"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Shfaq # aplikacion tjetër.}other{Shfaq # aplikacione të tjera.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> dhe <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Shtimi i aplikacionit te desktopi"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Anulo"</string>
 </resources>
diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml
index f443a68..d949138 100644
--- a/quickstep/res/values-sr/strings.xml
+++ b/quickstep/res/values-sr/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Премести доле десно"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Прикажи још # апликацију.}one{Прикажи још # апликацију.}few{Прикажи још # апликације.}other{Прикажи још # апликација.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> и <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Додаје се апликација на радну поврршину"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Откажи"</string>
 </resources>
diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml
index 738b362..0ff9288 100644
--- a/quickstep/res/values-sv/strings.xml
+++ b/quickstep/res/values-sv/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Flytta längst ned/till höger"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Visa # app till.}other{Visa # appar till.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> och <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Lägger till appen på skrivbordet"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Avbryt"</string>
 </resources>
diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml
index c5b588d..d895ebf 100644
--- a/quickstep/res/values-sw/strings.xml
+++ b/quickstep/res/values-sw/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sogeza chini/kulia"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Onyesha programu # zaidi.}other{Onyesha programu # zaidi.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> na <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Kuweka programu kwenye Eneo-kazi"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Ghairi"</string>
 </resources>
diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml
index ea39749..cc589d7 100644
--- a/quickstep/res/values-ta/strings.xml
+++ b/quickstep/res/values-ta/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"கீழே/வலதுபுறம் நகர்த்தும்"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{மேலும் # ஆப்ஸைக் காட்டு.}other{மேலும் # ஆப்ஸைக் காட்டு.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ஆப்ஸை டெஸ்க்டாப்பில் சேர்க்கிறது"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ரத்துசெய்"</string>
 </resources>
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index 9cdd2fa..4e80fb8 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"దిగువ/కుడి వైపునకు తరలించండి"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{మరో # యాప్‌ను చూడండి.}other{మరో # యాప్‌లను చూడండి.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>, <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"డెస్క్‌టాప్‌నకు యాప్‌ను జోడిస్తోంది"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"రద్దు చేయండి"</string>
 </resources>
diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml
index fe8e37f..57af112 100644
--- a/quickstep/res/values-th/strings.xml
+++ b/quickstep/res/values-th/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"ย้ายไปที่ด้านล่างหรือด้านขวา"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{แสดงเพิ่มเติมอีก # แอป}other{แสดงเพิ่มเติมอีก # แอป}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> และ <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"การเพิ่มแอปไปยังเดสก์ท็อป"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"ยกเลิก"</string>
 </resources>
diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml
index bf62a38..505427c 100644
--- a/quickstep/res/values-tl/strings.xml
+++ b/quickstep/res/values-tl/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Ilipat sa ibaba/kanan"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Magpakita ng # pang app.}one{Magpakita ng # pang app.}other{Magpakita ng # pang app.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> at <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Idinaragdag ang app sa Desktop"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Kanselahin"</string>
 </resources>
diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml
index 772ad8b..d263601 100644
--- a/quickstep/res/values-tr/strings.xml
+++ b/quickstep/res/values-tr/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Sağ alta taşı"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# uygulama daha göster.}other{# uygulama daha göster}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> ve <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Uygulama Masaüstü\'ne ekleniyor"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"İptal"</string>
 </resources>
diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml
index 0104798..8c325f3 100644
--- a/quickstep/res/values-uk/strings.xml
+++ b/quickstep/res/values-uk/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Перемістити вниз або вправо"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Показати ще # додаток.}one{Показати ще # додаток.}few{Показати ще # додатки.}many{Показати ще # додатків.}other{Показати ще # додатка.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> та <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Встановлення додатка на комп’ютер"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Скасувати"</string>
 </resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index 7e9b34c..e2df2ee 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"نیچے/دائیں طرف منتقل کریں"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{# مزید ایپ دکھائیں۔}other{# مزید ایپس دکھائیں۔}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> اور <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"ڈیسک ٹاپ پر ایپ شامل کرنا"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"منسوخ کریں"</string>
 </resources>
diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml
index 73ad2f3..43a1b86 100644
--- a/quickstep/res/values-uz/strings.xml
+++ b/quickstep/res/values-uz/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Pastga yoki oʻngga oʻtkazish"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Yana # ta ilovani chiqarish}other{Yana # ta ilovani chiqarish}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> va <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Ilova kompyuterga qoʻshilmoqda"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Bekor qilish"</string>
 </resources>
diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml
index 5b7f12e..635a7bc 100644
--- a/quickstep/res/values-vi/strings.xml
+++ b/quickstep/res/values-vi/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Chuyển xuống dưới cùng/sang bên phải"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Hiện thêm # ứng dụng.}other{Hiện thêm # ứng dụng.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g> và <xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Đang thêm ứng dụng vào máy tính"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Huỷ"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index b88899b..05f92aa 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右侧"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{显示另外 # 个应用。}other{显示另外 # 个应用。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"<xliff:g id="APP_NAME_1">%1$s</xliff:g>和<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"将应用添加到桌面"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml
index e6de624..8b4ea35 100644
--- a/quickstep/res/values-zh-rHK/strings.xml
+++ b/quickstep/res/values-zh-rHK/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移至底部/右側"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"正在新增應用程式至桌面"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml
index 2987a87..29b1ac2 100644
--- a/quickstep/res/values-zh-rTW/strings.xml
+++ b/quickstep/res/values-zh-rTW/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"移到底部/右側"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{顯示另外 # 個應用程式。}other{顯示另外 # 個應用程式。}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"「<xliff:g id="APP_NAME_1">%1$s</xliff:g>」和「<xliff:g id="APP_NAME_2">%2$s</xliff:g>」"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"新增應用程式至桌面"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"取消"</string>
 </resources>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index 2d78ebc..7313972 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -122,4 +122,6 @@
     <string name="move_drop_target_bottom_or_right" msgid="5431393418797620162">"Hamba phansi/kwesokudla"</string>
     <string name="quick_switch_overflow" msgid="6935266023013283353">"{count,plural, =1{Bonisa i-app e-# ngaphezulu.}one{Bonisa ama-app angu-# ngaphezulu.}other{Bonisa ama-app angu-# ngaphezulu.}}"</string>
     <string name="quick_switch_split_task" msgid="5598194724255333896">"I-<xliff:g id="APP_NAME_1">%1$s</xliff:g> ne-<xliff:g id="APP_NAME_2">%2$s</xliff:g>"</string>
+    <string name="desktop_select_app_toast" msgid="2306057322833956910">"Yengeza i-app ku-Deskithophu"</string>
+    <string name="desktop_button_close_app_toast" msgid="5283096349579408560">"Khansela"</string>
 </resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index bb4f74d..0926b19 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -269,6 +269,9 @@
     <dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
     <dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
 
+    <!-- Copied from frameworks/base/packages/SystemUI -->
+    <dimen name="navigation_home_handle_width">108dp</dimen>
+
     <!-- Taskbar -->
     <dimen name="taskbar_size">@*android:dimen/taskbar_frame_height</dimen>
     <dimen name="taskbar_ime_size">48dp</dimen>
@@ -383,4 +386,12 @@
     <dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
     <dimen name="keyboard_quick_switch_no_recent_items_icon_size">24dp</dimen>
     <dimen name="keyboard_quick_switch_no_recent_items_icon_margin">8dp</dimen>
+
+    <!-- Desktop mode -->
+    <dimen name="desktop_mode_floating_app_select_height">56dp</dimen>
+    <dimen name="desktop_mode_floating_app_select_elevation">4dp</dimen>
+    <dimen name="desktop_mode_floating_app_select_margin">16dp</dimen>
+    <dimen name="desktop_mode_floating_app_select_text_size">14sp</dimen>
+    <dimen name="desktop_mode_floating_app_select_text_margin">8dp</dimen>
+
 </resources>
diff --git a/quickstep/res/values/override.xml b/quickstep/res/values/override.xml
index 4f472f0..73c4201 100644
--- a/quickstep/res/values/override.xml
+++ b/quickstep/res/values/override.xml
@@ -25,6 +25,8 @@
 
   <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="secondary_display_predictions_class" translatable="false">com.android.launcher3.secondarydisplay.SecondaryDisplayPredictionsImpl</string>
 
 </resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index bd69f9f..1c8c07c 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -294,4 +294,10 @@
 
     <!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
     <string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
+
+    <!-- ******* Desktop ******* -->
+    <!-- Text shown in popup to choose a desktop app. [CHAR LIMIT=60] -->
+    <string name="desktop_select_app_toast">Adding app to Desktop</string>
+    <!-- Text shown on a button that closes the popup for choosing a desktop app. [CHAR_LIMIT=40] -->
+    <string name="desktop_button_close_app_toast">Cancel</string>
 </resources>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 114965f..0592510 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -30,6 +30,12 @@
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
 import static android.window.TransitionFilter.CONTAINER_ORDER_TOP;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_1_5;
+import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE;
+import static com.android.app.animation.Interpolators.DECELERATE_1_5;
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.EXAGGERATED_EASE;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.BaseActivity.INVISIBLE_ALL;
 import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS;
 import static com.android.launcher3.BaseActivity.INVISIBLE_BY_PENDING_FLAGS;
@@ -41,12 +47,6 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.Utilities.mapBoundToRange;
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_BACK_SWIPE_HOME_ANIMATION;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAUNCH;
 import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
@@ -553,7 +553,7 @@
 
                 ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(view, SCALE_PROPERTY, scales)
                         .setDuration(CONTENT_SCALE_DURATION);
-                scaleAnim.setInterpolator(DEACCEL_1_5);
+                scaleAnim.setInterpolator(DECELERATE_1_5);
                 launcherAnimator.play(scaleAnim);
             });
 
@@ -571,7 +571,7 @@
                     ObjectAnimator scrim = ObjectAnimator.ofArgb(scrimView, VIEW_BACKGROUND_COLOR,
                             colors);
                     scrim.setDuration(CONTENT_SCRIM_DURATION);
-                    scrim.setInterpolator(DEACCEL_1_5);
+                    scrim.setInterpolator(DECELERATE_1_5);
 
                     launcherAnimator.play(scrim);
                 }
@@ -1462,11 +1462,11 @@
         float startShadowRadius = areAllTargetsTranslucent(appTargets) ? 0 : mMaxShadowRadius;
         closingAnimator.setDuration(duration);
         closingAnimator.addUpdateListener(new MultiValueUpdateListener() {
-            FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7);
-            FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DEACCEL_1_7);
+            FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DECELERATE_1_7);
+            FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DECELERATE_1_7);
             FloatProp mAlpha = new FloatProp(1f, 0f, 25, 125, LINEAR);
             FloatProp mShadowRadius = new FloatProp(startShadowRadius, 0, 0, duration,
-                    DEACCEL_1_7);
+                    DECELERATE_1_7);
 
             @Override
             public void onUpdate(float percent, boolean initOnly) {
@@ -2032,7 +2032,7 @@
             if (progress >= end) {
                 return 0f;
             }
-            return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
+            return Utilities.mapToRange(progress, start, end, 1, 0, ACCELERATE_1_5);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 80bdb6f..bd47923 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -30,6 +30,7 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.CellLayout;
 import com.android.launcher3.DeviceProfile;
@@ -37,7 +38,6 @@
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.uioverrides.PredictedAppIcon;
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 7c62763..9afcd2a 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3.statehandlers;
 
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index d087d39..b052deb 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -15,14 +15,21 @@
  */
 package com.android.launcher3.statehandlers;
 
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+
 import android.os.SystemProperties;
 import android.util.Log;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.views.DesktopAppSelectView;
+import com.android.wm.shell.desktopmode.IDesktopTaskListener;
 
 /**
  * Controls the visibility of the workspace and the resumed / paused state when desktop mode
@@ -39,11 +46,51 @@
     private boolean mInOverviewState;
     private boolean mGestureInProgress;
 
+    @Nullable
+    private IDesktopTaskListener mDesktopTaskListener;
+    private DesktopAppSelectView mSelectAppToast;
+
     public DesktopVisibilityController(Launcher launcher) {
         mLauncher = launcher;
     }
 
     /**
+     * Register a listener with System UI to receive updates about desktop tasks state
+     */
+    public void registerSystemUiListener() {
+        mDesktopTaskListener = new IDesktopTaskListener.Stub() {
+            @Override
+            public void onVisibilityChanged(int displayId, boolean visible) {
+                // TODO(b/261234402): move visibility from sysui state to listener
+            }
+
+            @Override
+            public void onStashedChanged(int displayId, boolean stashed) {
+                MAIN_EXECUTOR.execute(() -> {
+                    if (displayId == mLauncher.getDisplayId()) {
+                        if (DEBUG) {
+                            Log.d(TAG, "desktop stashed changed value=" + stashed);
+                        }
+                        if (stashed) {
+                            showSelectAppToast();
+                        } else {
+                            hideSelectAppToast();
+                        }
+                    }
+                });
+            }
+        };
+        SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(mDesktopTaskListener);
+    }
+
+    /**
+     * Clear listener from System UI that was set with {@link #registerSystemUiListener()}
+     */
+    public void unregisterSystemUiListener() {
+        SystemUiProxy.INSTANCE.get(mLauncher).setDesktopTaskListener(null);
+    }
+
+    /**
      * Whether desktop mode is supported.
      */
     private boolean isDesktopModeSupported() {
@@ -68,6 +115,7 @@
         if (!isDesktopModeSupported()) {
             return;
         }
+
         if (freeformTasksVisible != mFreeformTasksVisible) {
             mFreeformTasksVisible = freeformTasksVisible;
             if (mFreeformTasksVisible) {
@@ -130,6 +178,15 @@
         }
     }
 
+    /**
+     * Handle launcher moving to home due to home gesture or home button press.
+     */
+    public void onHomeActionTriggered() {
+        if (areFreeformTasksVisible()) {
+            SystemUiProxy.INSTANCE.get(mLauncher).stashDesktopApps(mLauncher.getDisplayId());
+        }
+    }
+
     private void setLauncherViewsVisibility(int visibility) {
         if (DEBUG) {
             Log.d(TAG, "setLauncherViewsVisibility: visibility=" + visibility);
@@ -168,4 +225,28 @@
             activity.setResumed();
         }
     }
+
+    private void showSelectAppToast() {
+        if (mSelectAppToast != null) {
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "show toast to select desktop apps");
+        }
+        Runnable onCloseCallback = () -> {
+            SystemUiProxy.INSTANCE.get(mLauncher).hideStashedDesktopApps(mLauncher.getDisplayId());
+        };
+        mSelectAppToast = DesktopAppSelectView.show(mLauncher, onCloseCallback);
+    }
+
+    private void hideSelectAppToast() {
+        if (mSelectAppToast == null) {
+            return;
+        }
+        if (DEBUG) {
+            Log.d(TAG, "hide toast to select desktop apps");
+        }
+        mSelectAppToast.hide();
+        mSelectAppToast = null;
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
index 7f655cf..ae1c979 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -22,9 +22,13 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.R;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.quickstep.LauncherActivityInterface;
 import com.android.quickstep.RecentsModel;
+import com.android.quickstep.util.DesktopTask;
 import com.android.quickstep.util.GroupTask;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
@@ -102,21 +106,75 @@
         mQuickSwitchViewController = new KeyboardQuickSwitchViewController(
                 mControllers, overlayContext, keyboardQuickSwitchView, mControllerCallbacks);
 
+        DesktopVisibilityController desktopController =
+                LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
+        final boolean onDesktop =
+                DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED
+                        && desktopController != null
+                        && desktopController.areFreeformTasksVisible();
+
         if (mModel.isTaskListValid(mTaskListChangeId)) {
-            mQuickSwitchViewController.openQuickSwitchView(
-                    mTasks, mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex);
+            mQuickSwitchViewController.openQuickSwitchView(mTasks,
+                    mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex, onDesktop);
             return;
         }
+
         mTaskListChangeId = mModel.getTasks((tasks) -> {
-            // Only store MAX_TASK tasks, from most to least recent
-            Collections.reverse(tasks);
-            mTasks = tasks.stream().limit(MAX_TASKS).collect(Collectors.toList());
-            mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
-            mQuickSwitchViewController.openQuickSwitchView(
-                    mTasks, mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex);
+            if (onDesktop) {
+                processLoadedTasksOnDesktop(tasks);
+            } else {
+                processLoadedTasks(tasks);
+            }
+            mQuickSwitchViewController.openQuickSwitchView(mTasks,
+                    mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex, onDesktop);
         });
     }
 
+    private void processLoadedTasks(ArrayList<GroupTask> tasks) {
+        // Only store MAX_TASK tasks, from most to least recent
+        Collections.reverse(tasks);
+
+        // Hide all desktop tasks and show them on the hidden tile
+        int hiddenDesktopTasks = 0;
+        if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+            // TODO(b/280468885): show desktop task as a grouped desktop tile
+            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)
+                .collect(Collectors.toList());
+        mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS) + hiddenDesktopTasks;
+    }
+
+    private void processLoadedTasksOnDesktop(ArrayList<GroupTask> tasks) {
+        // Find the single desktop task that contains a grouping of desktop tasks
+        DesktopTask desktopTask = findDesktopTask(tasks);
+
+        if (desktopTask != null) {
+            mTasks = desktopTask.tasks.stream().map(GroupTask::new).collect(Collectors.toList());
+            // All other tasks, apart from the grouped desktop task, are hidden
+            mNumHiddenTasks = Math.max(0, tasks.size() - 1);
+        } else {
+            // Desktop tasks were visible, but the recents entry is missing. Fall back to empty list
+            mTasks = Collections.emptyList();
+            mNumHiddenTasks = tasks.size();
+        }
+    }
+
+    @Nullable
+    private DesktopTask findDesktopTask(ArrayList<GroupTask> tasks) {
+        return (DesktopTask) tasks.stream()
+                .filter(t -> t instanceof DesktopTask)
+                .findFirst()
+                .orElse(null);
+    }
+
     void closeQuickSwitchView() {
         if (mQuickSwitchViewController == null) {
             return;
@@ -169,7 +227,7 @@
     class ControllerCallbacks {
 
         int getTaskCount() {
-            return mNumHiddenTasks == 0 ? mTasks.size() : MAX_TASKS + 1;
+            return mTasks.size() + (mNumHiddenTasks == 0 ? 0 : 1);
         }
 
         @Nullable
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index 2cdfb18..4e9e301 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -42,10 +42,10 @@
 import androidx.annotation.Nullable;
 import androidx.constraintlayout.widget.ConstraintLayout;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
 import com.android.quickstep.util.GroupTask;
 
 import java.util.HashMap;
@@ -190,8 +190,12 @@
 
         ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(
                 width, mTaskViewHeight);
-        lp.endToEnd = PARENT_ID;
-        lp.startToEnd = previousView.getId();
+        if (previousView == null) {
+            lp.startToStart = PARENT_ID;
+        } else {
+            lp.endToEnd = PARENT_ID;
+            lp.startToEnd = previousView.getId();
+        }
         lp.topToTop = PARENT_ID;
         lp.bottomToBottom = PARENT_ID;
         lp.setMarginEnd(mSpacing);
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
index 3230c66..a293f74 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -27,6 +27,7 @@
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
 import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer;
+import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.GroupTask;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -52,6 +53,8 @@
 
     private int mCurrentFocusIndex = -1;
 
+    private boolean mOnDesktop;
+
     protected KeyboardQuickSwitchViewController(
             @NonNull TaskbarControllers controllers,
             @NonNull TaskbarOverlayContext overlayContext,
@@ -71,10 +74,12 @@
             @NonNull List<GroupTask> tasks,
             int numHiddenTasks,
             boolean updateTasks,
-            int currentFocusIndexOverride) {
+            int currentFocusIndexOverride,
+            boolean onDesktop) {
         TaskbarOverlayDragLayer dragLayer = mOverlayContext.getDragLayer();
         dragLayer.addView(mKeyboardQuickSwitchView);
         dragLayer.runOnClickOnce(v -> closeQuickSwitchView(true));
+        mOnDesktop = onDesktop;
 
         mKeyboardQuickSwitchView.applyLoadPlan(
                 mOverlayContext,
@@ -136,6 +141,10 @@
         GroupTask task = mControllerCallbacks.getTaskAt(index);
         if (task == null) {
             return Math.max(0, index);
+        } else if (mOnDesktop) {
+            UI_HELPER_EXECUTOR.execute(() ->
+                    SystemUiProxy.INSTANCE.get(mKeyboardQuickSwitchView.getContext())
+                            .showDesktopApp(task.task1.key.id));
         } else if (task.task2 == null) {
             UI_HELPER_EXECUTOR.execute(() ->
                     ActivityManagerWrapper.getInstance().startActivityFromRecents(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
index fe365f7..a9a2ccf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarBackgroundRenderer.kt
@@ -22,12 +22,12 @@
 import android.graphics.Paint
 import android.graphics.Path
 import android.graphics.RectF
+import com.android.app.animation.Interpolators
 import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.launcher3.Utilities.mapRange
 import com.android.launcher3.Utilities.mapToRange
-import com.android.launcher3.anim.Interpolators
 import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
 import com.android.launcher3.util.DisplayController
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 040b8f7..64ba5aa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -15,11 +15,11 @@
  */
 package com.android.launcher3.taskbar;
 
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_ALL_APPS;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_ALL_APPS;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -47,6 +47,7 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.internal.logging.InstanceId;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BubbleTextView;
@@ -55,7 +56,6 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragDriver;
 import com.android.launcher3.dragndrop.DragOptions;
@@ -642,7 +642,7 @@
             final FloatProp mScale = new FloatProp(1f, toScale, 0,
                     ANIM_DURATION_RETURN_ICON_TO_TASKBAR, FAST_OUT_SLOW_IN);
             final FloatProp mAlpha = new FloatProp(1f, toAlpha, 0,
-                    ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCEL_2);
+                    ANIM_DURATION_RETURN_ICON_TO_TASKBAR, Interpolators.ACCELERATE_2);
             @Override
             public void onUpdate(float percent, boolean initOnly) {
                 animListener.updateDragShadow(mDx.value, mDy.value, mScale.value, mAlpha.value);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index d6e559a..4f9b1e4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -21,6 +21,7 @@
 import android.os.IBinder
 import android.view.InsetsFrameProvider
 import android.view.InsetsFrameProvider.SOURCE_DISPLAY
+import android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER
 import android.view.InsetsSource.FLAG_SUPPRESS_SCRIM
 import android.view.ViewTreeObserver
 import android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME
@@ -83,11 +84,23 @@
     }
 
     fun onTaskbarWindowHeightOrInsetsChanged() {
+        val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
+        // We only report tappableElement height for unstashed, persistent taskbar,
+        // which is also when we draw the rounded corners above taskbar.
+        val insetsRoundedCornerFlag =
+            if (tappableHeight > 0) {
+                FLAG_INSETS_ROUNDED_CORNER
+            } else {
+                0
+            }
         if (context.isGestureNav) {
             windowLayoutParams.providedInsets =
                 arrayOf(
                     InsetsFrameProvider(insetsOwner, 0, navigationBars())
-                        .setFlags(FLAG_SUPPRESS_SCRIM, FLAG_SUPPRESS_SCRIM),
+                        .setFlags(
+                            FLAG_SUPPRESS_SCRIM or insetsRoundedCornerFlag,
+                            FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER
+                        ),
                     InsetsFrameProvider(insetsOwner, 0, tappableElement()),
                     InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
                     InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
@@ -98,7 +111,11 @@
         } else {
             windowLayoutParams.providedInsets =
                 arrayOf(
-                    InsetsFrameProvider(insetsOwner, 0, navigationBars()),
+                    InsetsFrameProvider(insetsOwner, 0, navigationBars())
+                        .setFlags(
+                            insetsRoundedCornerFlag,
+                            (FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER)
+                        ),
                     InsetsFrameProvider(insetsOwner, 0, tappableElement()),
                     InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures())
                 )
@@ -112,7 +129,6 @@
             windowLayoutParams.height
         )
         val contentHeight = controllers.taskbarStashController.contentHeightToReportToApps
-        val tappableHeight = controllers.taskbarStashController.tappableHeightToReportToApps
         val res = context.resources
         for (provider in windowLayoutParams.providedInsets) {
             if (provider.type == navigationBars() || provider.type == mandatorySystemGestures()) {
@@ -162,10 +178,6 @@
             }
         }
 
-        // We only report tappableElement height for unstashed, persistent taskbar,
-        // which is also when we draw the rounded corners above taskbar.
-        windowLayoutParams.insetsRoundedCornerFrame = tappableHeight > 0
-
         context.notifyUpdateLayoutParams()
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index 610efeb..0f8de34 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -43,12 +43,15 @@
 
 import com.android.launcher3.R;
 import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.statehandlers.DesktopVisibilityController;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
+import com.android.quickstep.LauncherActivityInterface;
 import com.android.quickstep.OverviewCommandHelper;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskUtils;
 import com.android.quickstep.TouchInteractionService;
+import com.android.quickstep.views.DesktopTaskView;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -267,6 +270,15 @@
 
     private void navigateHome() {
         TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY);
+
+        if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+            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 00e14ad..eb4c136 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -18,11 +18,11 @@
 import static android.view.HapticFeedbackConstants.LONG_PRESS;
 import static android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS;
 
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_PINNING;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
index 1cc6672..ec93846 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
@@ -16,9 +16,9 @@
 package com.android.launcher3.taskbar
 
 import android.view.MotionEvent
+import com.android.app.animation.Interpolators.LINEAR
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
-import com.android.launcher3.anim.Interpolators.LINEAR
 import com.android.launcher3.testing.shared.ResourceUtils
 import com.android.launcher3.touch.SingleAxisSwipeDetector
 import com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
index 065d111..2b4e67c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarTranslationController.java
@@ -26,8 +26,8 @@
 import androidx.annotation.Nullable;
 import androidx.dynamicanimation.animation.SpringForce;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.SpringAnimationBuilder;
 import com.android.launcher3.util.DisplayController;
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4abd995..528a328 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -15,6 +15,8 @@
  */
 package com.android.launcher3.taskbar;
 
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -22,8 +24,6 @@
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.anim.AnimatedFloat.VALUE;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
 import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
@@ -45,6 +45,7 @@
 import androidx.core.graphics.ColorUtils;
 import androidx.core.view.OneShotPreDrawListener;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.R;
@@ -53,7 +54,6 @@
 import com.android.launcher3.anim.AlphaUpdateListener;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.RevealOutlineAnimation;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index cfa1027..84cc002 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.taskbar.allapps;
 
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
index 7397159..8a8e21f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBackground.kt
@@ -21,10 +21,10 @@
 import android.graphics.Paint
 import android.graphics.drawable.Drawable
 import android.graphics.drawable.ShapeDrawable
+import com.android.app.animation.Interpolators
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
 import com.android.launcher3.Utilities.mapToRange
-import com.android.launcher3.anim.Interpolators
 import com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound
 import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.wm.shell.common.TriangleShape
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
index 8de0e40..d4e2be9 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayController.java
@@ -23,6 +23,7 @@
 import static com.android.launcher3.LauncherState.ALL_APPS;
 
 import android.annotation.SuppressLint;
+import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.PixelFormat;
 import android.view.Gravity;
@@ -36,7 +37,6 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
 import com.android.launcher3.taskbar.TaskbarControllers;
-import com.android.quickstep.views.DesktopTaskView;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 
@@ -60,15 +60,15 @@
 
     private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
         @Override
-        public void onTaskStackChanged() {
-            mProxyView.close(false);
+        public void onTaskCreated(int taskId, ComponentName componentName) {
+            // Created task will be below existing overlay, so move out of the way.
+            hideWindow();
         }
 
         @Override
         public void onTaskMovedToFront(int taskId) {
-            if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
-                mProxyView.close(false);
-            }
+            // New front task will be below existing overlay, so move out of the way.
+            hideWindow();
         }
     };
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 955440b..8c8e267 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -16,11 +16,11 @@
 
 package com.android.launcher3.uioverrides;
 
+import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index a8b7698..e61599f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.uioverrides;
 
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
 import static com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter;
 
@@ -260,8 +260,8 @@
                 Keyframe.ofFloat(0.82f, finalTrans - getOutlineOffsetY() / 2f), // Overshoot
                 Keyframe.ofFloat(1f, finalTrans) // Ease back into the final position
         };
-        keyframes[1].setInterpolator(ACCEL_DEACCEL);
-        keyframes[2].setInterpolator(ACCEL_DEACCEL);
+        keyframes[1].setInterpolator(ACCELERATE_DECELERATE);
+        keyframes[2].setInterpolator(ACCELERATE_DECELERATE);
 
         mSlotMachineAnim = ObjectAnimator.ofPropertyValuesHolder(this,
                 PropertyValuesHolder.ofKeyframe(SLOT_MACHINE_TRANSLATION_Y, keyframes));
@@ -337,7 +337,6 @@
         if (getTag() instanceof WorkspaceItemInfo) {
             WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
             isBadged = !Process.myUserHandle().equals(info.user)
-                    || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
                     || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
         }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 95c2326..d626608 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -20,19 +20,18 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
 import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
 
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.LauncherSettings.Animation.DEFAULT_NO_ICON;
 import static com.android.launcher3.LauncherSettings.Animation.VIEW_BACKGROUND;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.NO_OFFSET;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
@@ -259,6 +258,9 @@
         mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
         mDepthController = new DepthController(this);
         mDesktopVisibilityController = new DesktopVisibilityController(this);
+        if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
+            mDesktopVisibilityController.registerSystemUiListener();
+        }
         mHotseatPredictionController = new HotseatPredictionController(this);
 
         mEnableWidgetDepth = SystemProperties.getBoolean("ro.launcher.depth.widget", true);
@@ -280,7 +282,6 @@
 
         if (mAllAppsPredictions != null
                 && (info.itemType == ITEM_TYPE_APPLICATION
-                || info.itemType == ITEM_TYPE_SHORTCUT
                 || info.itemType == ITEM_TYPE_DEEP_SHORTCUT)) {
             int count = mAllAppsPredictions.items.size();
             for (int i = 0; i < count; i++) {
@@ -483,6 +484,10 @@
             mLauncherUnfoldAnimationController.onDestroy();
         }
 
+        if (mDesktopVisibilityController != null) {
+            mDesktopVisibilityController.unregisterSystemUiListener();
+        }
+
         super.onDestroy();
         mHotseatPredictionController.destroy();
         mSplitWithKeyboardShortcutController.onDestroy();
@@ -554,8 +559,14 @@
                 list.add(new PortraitStatesTouchController(this));
                 break;
             case THREE_BUTTONS:
+                list.add(new NoButtonQuickSwitchTouchController(this));
+                list.add(new NavBarToHomeTouchController(this));
+                list.add(new NoButtonNavbarToOverviewTouchController(this));
+                list.add(new PortraitStatesTouchController(this));
+                break;
             default:
                 list.add(new PortraitStatesTouchController(this));
+                break;
         }
 
         if (!getDeviceProfile().isMultiWindowMode) {
@@ -1155,7 +1166,6 @@
         }
         switch (info.itemType) {
             case Favorites.ITEM_TYPE_APPLICATION:
-            case Favorites.ITEM_TYPE_SHORTCUT:
             case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
             case Favorites.ITEM_TYPE_APPWIDGET:
                 // Fall through and continue if it's an app, shortcut, or widget
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index f16b43d..23e922c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,10 +15,10 @@
  */
 package com.android.launcher3.uioverrides;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON;
 import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
 import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
index b901a87..a76eb43 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DeveloperOptionsFragment.java
@@ -23,6 +23,7 @@
 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.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
 import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLUGIN_CHANGED;
 import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey;
@@ -59,6 +60,7 @@
 import androidx.preference.PreferenceGroup;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.PreferenceViewHolder;
+import androidx.preference.SeekBarPreference;
 import androidx.preference.SwitchPreference;
 
 import com.android.launcher3.LauncherPrefs;
@@ -106,6 +108,9 @@
         loadPluginPrefs();
         maybeAddSandboxCategory();
         addOnboardingPrefsCatergory();
+        if (FeatureFlags.ENABLE_ALL_APPS_FROM_OVERVIEW.get()) {
+            addAllAppsFromOverviewCatergory();
+        }
 
         if (getActivity() != null) {
             getActivity().setTitle("Developer Options");
@@ -393,6 +398,33 @@
         }
     }
 
+    private void addAllAppsFromOverviewCatergory() {
+        PreferenceCategory category = newCategory("All Apps from Overview Config");
+
+        SeekBarPreference thresholdPref = new SeekBarPreference(getContext());
+        thresholdPref.setTitle("Threshold to open All Apps from Overview");
+        thresholdPref.setSingleLineTitle(false);
+
+        // These values are 100x swipe up shift value (100 = where overview sits).
+        thresholdPref.setMax(500);
+        thresholdPref.setMin(105);
+        thresholdPref.setUpdatesContinuously(true);
+        thresholdPref.setIconSpaceReserved(false);
+        // Don't directly save to shared prefs, use LauncherPrefs instead.
+        thresholdPref.setPersistent(false);
+        thresholdPref.setOnPreferenceChangeListener((preference, newValue) -> {
+            LauncherPrefs.get(getContext()).put(ALL_APPS_OVERVIEW_THRESHOLD, newValue);
+            preference.setSummary(String.valueOf((int) newValue / 100f));
+            return true;
+        });
+        int value = LauncherPrefs.get(getContext()).get(ALL_APPS_OVERVIEW_THRESHOLD);
+        thresholdPref.setValue(value);
+        // For some reason the initial value is not triggering the summary update, so call manually.
+        thresholdPref.getOnPreferenceChangeListener().onPreferenceChange(thresholdPref, value);
+
+        category.addPreference(thresholdPref);
+    }
+
     private String toName(String action) {
         String str = action.replace("com.android.systemui.action.PLUGIN_", "")
                 .replace("com.android.launcher3.action.PLUGIN_", "");
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 2a42175..a4db375 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.uioverrides.states;
 
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
 
 import android.content.Context;
@@ -91,7 +91,7 @@
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
         PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
-        return new PageAlphaProvider(DEACCEL_2) {
+        return new PageAlphaProvider(DECELERATE_2) {
             @Override
             public float getPageAlpha(int pageIndex) {
                 return launcher.getDeviceProfile().isTablet
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index 214679a..3f0b54e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.uioverrides.states;
 
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
 
 import android.content.Context;
@@ -97,7 +97,7 @@
 
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
-        return new PageAlphaProvider(DEACCEL_2) {
+        return new PageAlphaProvider(DECELERATE_2) {
             @Override
             public float getPageAlpha(int pageIndex) {
                 return 0;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index c7cd39c..fc5f567 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -17,6 +17,20 @@
 
 import static android.view.View.VISIBLE;
 
+import static com.android.app.animation.Interpolators.ACCELERATE;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.DECELERATE_3;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.OVERSHOOT_0_75;
+import static com.android.app.animation.Interpolators.OVERSHOOT_1_2;
+import static com.android.app.animation.Interpolators.clampToProgress;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.HINT_STATE;
 import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
@@ -25,20 +39,6 @@
 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.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
@@ -108,8 +108,8 @@
                     fromState == OVERVIEW_SPLIT_SELECT
                             ? clampToProgress(LINEAR, 0.33f, 1)
                             : LINEAR);
-            config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
-            config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
+            config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATE);
+            config.setInterpolator(ANIM_WORKSPACE_FADE, ACCELERATE);
 
             if (DisplayController.getNavigationMode(mActivity).hasGestures
                     && overview.getTaskViewCount() > 0) {
@@ -135,9 +135,9 @@
                 }
                 overview.snapToPage(DEFAULT_PAGE, Math.toIntExact(config.duration));
             } else {
-                config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
-                config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
-                config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
+                config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCELERATE_DECELERATE);
+                config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCELERATE, 0, 0.9f));
+                config.setInterpolator(ANIM_OVERVIEW_FADE, DECELERATE_1_7);
             }
 
             Workspace<?> workspace = mActivity.getWorkspace();
@@ -163,8 +163,8 @@
                 || fromState == HINT_STATE_TWO_BUTTON) && toState == OVERVIEW) {
             if (DisplayController.getNavigationMode(mActivity).hasGestures) {
                 config.setInterpolator(ANIM_WORKSPACE_SCALE,
-                        fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
-                config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
+                        fromState == NORMAL ? ACCELERATE : OVERSHOOT_1_2);
+                config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCELERATE);
 
                 // Scrolling in tasks, so show straight away
                 if (overview.getTaskViewCount() > 0) {
@@ -192,7 +192,7 @@
             config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_2);
             config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_1_2);
         } else if (fromState == HINT_STATE && toState == NORMAL) {
-            config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
+            config.setInterpolator(ANIM_DEPTH, DECELERATE_3);
             if (mHintToNormalDuration == -1) {
                 ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity,
                         mActivity.getWorkspace(),
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 8cbd6e8..be53220 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -15,17 +15,19 @@
  */
 package com.android.launcher3.uioverrides.touchcontrollers;
 
+import static com.android.app.animation.Interpolators.DECELERATE_3;
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_APPS_EDU;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_ALPHA;
 import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PULL_BACK_TRANSLATION;
 import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
 
 import android.animation.ValueAnimator;
@@ -42,6 +44,7 @@
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.TouchController;
 import com.android.quickstep.TaskUtils;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
@@ -54,7 +57,7 @@
 public class NavBarToHomeTouchController implements TouchController,
         SingleAxisSwipeDetector.Listener {
 
-    private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
+    private static final Interpolator PULLBACK_INTERPOLATOR = DECELERATE_3;
     // The min amount of overview scrim we keep during the transition.
     private static final float OVERVIEW_TO_HOME_SCRIM_MULTIPLIER = 0.5f;
 
@@ -95,6 +98,10 @@
     }
 
     private boolean canInterceptTouch(MotionEvent ev) {
+        if (!isTrackpadMotionEvent(ev) && DisplayController.getNavigationMode(mLauncher)
+                == THREE_BUTTONS) {
+            return false;
+        }
         boolean cameFromNavBar = (ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) != 0;
         if (!cameFromNavBar) {
             return false;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index b7bafd8..2f5467e 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -16,15 +16,17 @@
 
 package com.android.launcher3.uioverrides.touchcontrollers;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_BACKGROUND_COLOR;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.HINT_STATE;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
 import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
 import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
 import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
@@ -43,6 +45,7 @@
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.taskbar.LauncherTaskbarUIController;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.util.AnimatorControllerWithResistance;
@@ -89,6 +92,10 @@
 
     @Override
     protected boolean canInterceptTouch(MotionEvent ev) {
+        if (!isTrackpadMotionEvent(ev) && DisplayController.getNavigationMode(mLauncher)
+                == THREE_BUTTONS) {
+            return false;
+        }
         mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
         boolean isOneHandedModeActive = (SystemUiProxy.INSTANCE.get(mLauncher)
                 .getLastSystemUiStateFlags() & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0;
@@ -273,7 +280,7 @@
             mRecentsView.animate()
                     .translationX(0)
                     .translationY(0)
-                    .setInterpolator(ACCEL_DEACCEL)
+                    .setInterpolator(ACCELERATE_DECELERATE)
                     .setDuration(duration)
                     .withEndAction(goToHomeInsteadOfOverview
                             ? null
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 80f5558..d3ef589 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -18,19 +18,20 @@
 import static android.view.MotionEvent.ACTION_DOWN;
 import static android.view.MotionEvent.ACTION_MOVE;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
+import static com.android.app.animation.Interpolators.DECELERATE_3;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS;
 import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
 import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
 import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
@@ -46,6 +47,7 @@
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
 import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
 import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
+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.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
@@ -74,6 +76,7 @@
 import com.android.launcher3.touch.BaseSwipeDetector;
 import com.android.launcher3.touch.BothAxesSwipeDetector;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.TouchController;
 import com.android.launcher3.util.VibratorWrapper;
 import com.android.quickstep.SystemUiProxy;
@@ -93,8 +96,8 @@
         BothAxesSwipeDetector.Listener {
 
     private static final float Y_ANIM_MIN_PROGRESS = 0.25f;
-    private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_3;
-    private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75;
+    private static final Interpolator FADE_OUT_INTERPOLATOR = DECELERATE_3;
+    private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCELERATE_0_75;
     private static final Interpolator SCALE_DOWN_INTERPOLATOR = LINEAR;
     private static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
 
@@ -110,7 +113,6 @@
             newCancelListener(this::clearState);
 
     private boolean mNoIntercept;
-    private Boolean mIsTrackpadFourFingerSwipe;
     private LauncherState mStartState;
 
     private boolean mIsHomeScreenVisible = true;
@@ -136,9 +138,7 @@
 
     @Override
     public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
-        int action = ev.getActionMasked();
-        if (action == ACTION_DOWN) {
-            mIsTrackpadFourFingerSwipe = null;
+        if (ev.getActionMasked() == ACTION_DOWN) {
             mNoIntercept = !canInterceptTouch(ev);
             if (mNoIntercept) {
                 return false;
@@ -147,13 +147,6 @@
             // Only detect horizontal swipe for intercept, then we will allow swipe up as well.
             mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT,
                     false /* ignoreSlopWhenSettling */);
-        } else if (isTrackpadMultiFingerSwipe(ev) && mIsTrackpadFourFingerSwipe == null
-                && action == ACTION_MOVE) {
-            mIsTrackpadFourFingerSwipe = isTrackpadFourFingerSwipe(ev);
-            mNoIntercept = !mIsTrackpadFourFingerSwipe;
-            if (mNoIntercept) {
-                return false;
-            }
         }
 
         if (mNoIntercept) {
@@ -170,6 +163,10 @@
     }
 
     private boolean canInterceptTouch(MotionEvent ev) {
+        if (!isTrackpadMotionEvent(ev) && DisplayController.getNavigationMode(mLauncher)
+                == THREE_BUTTONS) {
+            return false;
+        }
         if (!mLauncher.isInState(LauncherState.NORMAL)) {
             return false;
         }
@@ -184,6 +181,9 @@
             // TODO(b/268075592): add support for quickswitch to/from desktop
             return false;
         }
+        if (isTrackpadMultiFingerSwipe(ev)) {
+            return isTrackpadFourFingerSwipe(ev);
+        }
         return true;
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 8368f9c..bb74a36 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -24,11 +24,11 @@
 
 import android.view.MotionEvent;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.allapps.AllAppsTransitionController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.touch.AbstractStateChangeTouchController;
 import com.android.launcher3.touch.AllAppsSwipeController;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index f941b02..9a35bb2 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -15,12 +15,12 @@
  */
 package com.android.launcher3.uioverrides.touchcontrollers;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
@@ -128,14 +128,14 @@
     }
 
     private void setupInterpolators(StateAnimationConfig stateAnimationConfig) {
-        stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_2);
-        stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_2);
+        stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_FADE, DECELERATE_2);
+        stateAnimationConfig.setInterpolator(ANIM_ALL_APPS_FADE, DECELERATE_2);
         if (DisplayController.getNavigationMode(mLauncher) == NavigationMode.NO_BUTTON) {
             // Overview lives to the left of workspace, so translate down later than over
-            stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL_2);
-            stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCEL_2);
-            stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_SCALE, ACCEL_2);
-            stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCEL_2);
+            stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCELERATE_2);
+            stateAnimationConfig.setInterpolator(ANIM_VERTICAL_PROGRESS, ACCELERATE_2);
+            stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_SCALE, ACCELERATE_2);
+            stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, ACCELERATE_2);
             stateAnimationConfig.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
         } else {
             stateAnimationConfig.setInterpolator(ANIM_WORKSPACE_TRANSLATE, LINEAR);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
index 395833f..26ab3d6 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java
@@ -76,7 +76,7 @@
     private void dispatchTouchEvent(MotionEvent ev) {
         if (mSystemUiProxy.isActive()) {
             mLastAction = ev.getActionMasked();
-            mSystemUiProxy.onStatusBarMotionEvent(ev);
+            mSystemUiProxy.onStatusBarTouchEvent(ev);
         }
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index eddc50c..3d94857 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -27,13 +27,13 @@
 import android.view.View;
 import android.view.animation.Interpolator;
 
+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;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.touch.BaseSwipeDetector;
 import com.android.launcher3.touch.PagedOrientationHandler;
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 3a6566a..2b92188 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -21,12 +21,13 @@
 import static android.view.Surface.ROTATION_90;
 import static android.widget.Toast.LENGTH_SHORT;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.OVERSHOOT_1_2;
 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.LauncherPrefs.ALL_APPS_OVERVIEW_THRESHOLD;
 import static com.android.launcher3.PagedView.INVALID_PAGE;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.IGNORE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_GESTURE;
@@ -94,6 +95,7 @@
 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;
@@ -101,6 +103,7 @@
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.logging.StatsLogManager;
 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.TaskbarUIController;
@@ -163,9 +166,6 @@
 
     private static final ArrayList<String> STATE_NAMES = new ArrayList<>();
 
-    /** Shift distance to transition to All Apps if ENABLE_ALL_APPS_FROM_OVERVIEW. */
-    public static final float ALL_APPS_SHIFT_THRESHOLD = 2f;
-
     protected final BaseActivityInterface<S, T> mActivityInterface;
     protected final InputConsumerProxy mInputConsumerProxy;
     protected final ActivityInitListener mActivityInitListener;
@@ -731,7 +731,8 @@
      * @param moveRunningTask whether to move running task to front when attaching
      */
     private void maybeUpdateRecentsAttachedState(boolean animate, boolean moveRunningTask) {
-        if (!mDeviceState.isFullyGesturalNavMode() || mRecentsView == null) {
+        if ((!mDeviceState.isFullyGesturalNavMode() && !mGestureState.isTrackpadGesture())
+                || mRecentsView == null) {
             return;
         }
         RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null
@@ -872,7 +873,8 @@
     @UiThread
     @Override
     public void onCurrentShiftUpdated() {
-        setIsInAllAppsRegion(mCurrentShift.value >= ALL_APPS_SHIFT_THRESHOLD);
+        float threshold = LauncherPrefs.get(mContext).get(ALL_APPS_OVERVIEW_THRESHOLD) / 100f;
+        setIsInAllAppsRegion(mCurrentShift.value >= threshold);
         updateSysUiFlags(mCurrentShift.value);
         applyScrollAndTransform();
 
@@ -1147,6 +1149,14 @@
                 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 (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+                    // Notify the SysUI to stash desktop apps if they are visible
+                    DesktopVisibilityController desktopVisibilityController =
+                            mActivityInterface.getDesktopVisibilityController();
+                    if (desktopVisibilityController != null) {
+                        desktopVisibilityController.onHomeActionTriggered();
+                    }
+                }
                 break;
             case RECENTS:
                 mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
@@ -1323,11 +1333,11 @@
         Interpolator interpolator;
         S state = mActivityInterface.stateFromGestureEndTarget(endTarget);
         if (state.displayOverviewTasksAsGrid(mDp)) {
-            interpolator = ACCEL_DEACCEL;
+            interpolator = ACCELERATE_DECELERATE;
         } else if (endTarget == RECENTS) {
             interpolator = OVERSHOOT_1_2;
         } else {
-            interpolator = DEACCEL;
+            interpolator = DECELERATE;
         }
 
         if (endTarget.isLauncher) {
@@ -2418,11 +2428,11 @@
 
         if (scrollOffset < mQuickSwitchScaleScrollThreshold) {
             scaleProgress = Utilities.mapToRange(scrollOffset, 0, mQuickSwitchScaleScrollThreshold,
-                    0, maxScaleProgress, ACCEL_DEACCEL);
+                    0, maxScaleProgress, ACCELERATE_DECELERATE);
         } else if (scrollOffset > (maxScrollOffset - mQuickSwitchScaleScrollThreshold)) {
             scaleProgress = Utilities.mapToRange(scrollOffset,
                     (maxScrollOffset - mQuickSwitchScaleScrollThreshold), maxScrollOffset,
-                    maxScaleProgress, 0, ACCEL_DEACCEL);
+                    maxScaleProgress, 0, ACCELERATE_DECELERATE);
         }
 
         return scaleProgress;
@@ -2451,7 +2461,7 @@
         // "Catch up" with the displacement at mTaskbarCatchUpThreshold.
         if (displacement < mTaskbarCatchUpThreshold) {
             return Utilities.mapToRange(displacement, mTaskbarAppWindowThreshold,
-                    mTaskbarCatchUpThreshold, 0, mTaskbarCatchUpThreshold, ACCEL_DEACCEL);
+                    mTaskbarCatchUpThreshold, 0, mTaskbarCatchUpThreshold, ACCELERATE_DECELERATE);
         }
 
         return displacement;
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 60083c6..5a9d80d 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -15,11 +15,11 @@
  */
 package com.android.quickstep;
 
+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.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 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;
@@ -553,7 +553,7 @@
             long animationDuration = animate ? RECENTS_ATTACH_DURATION : 0;
             Animator fadeAnim = mActivity.getStateManager()
                     .createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
-            fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2);
+            fadeAnim.setInterpolator(attached ? INSTANT : ACCELERATE_2);
             fadeAnim.setDuration(animationDuration);
             animatorSet.play(fadeAnim);
 
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index 1913091..ab37493 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -19,13 +19,13 @@
 import static android.content.Intent.EXTRA_COMPONENT_NAME;
 import static android.content.Intent.EXTRA_USER;
 
+import static com.android.app.animation.Interpolators.ACCELERATE;
 import static com.android.launcher3.GestureNavContract.EXTRA_GESTURE_CONTRACT;
 import static com.android.launcher3.GestureNavContract.EXTRA_ICON_POSITION;
 import static com.android.launcher3.GestureNavContract.EXTRA_ICON_SURFACE;
 import static com.android.launcher3.GestureNavContract.EXTRA_ON_FINISH_CALLBACK;
 import static com.android.launcher3.GestureNavContract.EXTRA_REMOTE_CALLBACK;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
 
 import android.animation.ObjectAnimator;
@@ -295,7 +295,7 @@
         @Override
         public AnimatorPlaybackController createActivityAnimationToHome() {
             PendingAnimation pa = new PendingAnimation(mDuration);
-            pa.setFloat(mRecentsAlpha, AnimatedFloat.VALUE, 0, ACCEL);
+            pa.setFloat(mRecentsAlpha, AnimatedFloat.VALUE, 0, ACCELERATE);
             return pa.createPlaybackController();
         }
 
@@ -323,7 +323,7 @@
         @Override
         public void playAtomicAnimation(float velocity) {
             ObjectAnimator alphaAnim = mHomeAlpha.animateToValue(mHomeAlpha.value, 1);
-            alphaAnim.setDuration(mDuration).setInterpolator(ACCEL);
+            alphaAnim.setDuration(mDuration).setInterpolator(ACCELERATE);
             alphaAnim.start();
 
             if (mRunningOverHome) {
diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java
index 9d7ccb4..3d0f6d5 100644
--- a/quickstep/src/com/android/quickstep/GestureState.java
+++ b/quickstep/src/com/android/quickstep/GestureState.java
@@ -150,15 +150,10 @@
 
     public enum TrackpadGestureType {
         NONE,
-        // Assigned before we know whether it's a 3-finger or 4-finger gesture.
-        MULTI_FINGER,
         THREE_FINGER,
         FOUR_FINGER;
 
         public static TrackpadGestureType getTrackpadGestureType(MotionEvent event) {
-            if (!isTrackpadMultiFingerSwipe(event)) {
-                return TrackpadGestureType.NONE;
-            }
             if (isTrackpadThreeFingerSwipe(event)) {
                 return TrackpadGestureType.THREE_FINGER;
             }
@@ -166,7 +161,7 @@
                 return TrackpadGestureType.FOUR_FINGER;
             }
 
-            return TrackpadGestureType.MULTI_FINGER;
+            return TrackpadGestureType.NONE;
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/InputConsumer.java b/quickstep/src/com/android/quickstep/InputConsumer.java
index 6b189cf..2071103 100644
--- a/quickstep/src/com/android/quickstep/InputConsumer.java
+++ b/quickstep/src/com/android/quickstep/InputConsumer.java
@@ -42,6 +42,7 @@
     int TYPE_TASKBAR_STASH = 1 << 12;
     int TYPE_STATUS_BAR = 1 << 13;
     int TYPE_CURSOR_HOVER = 1 << 14;
+    int TYPE_NAV_HANDLE_LONG_PRESS = 1 << 15;
 
     String[] NAMES = new String[] {
            "TYPE_NO_OP",                    // 0
@@ -59,6 +60,7 @@
             "TYPE_TASKBAR_STASH",           // 12
             "TYPE_STATUS_BAR",              // 13
             "TYPE_CURSOR_HOVER",            // 14
+            "TYPE_NAV_HANDLE_LONG_PRESS",   // 15
     };
 
     InputConsumer NO_OP = () -> TYPE_NO_OP;
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 0e0b022..13da40a 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -15,12 +15,12 @@
  */
 package com.android.quickstep;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index fd5c1a7..a9d8afc 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -15,10 +15,10 @@
  */
 package com.android.quickstep;
 
+import static com.android.app.animation.Interpolators.EXAGGERATED_EASE;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.Utilities.mapBoundToRange;
-import static com.android.launcher3.anim.Interpolators.EXAGGERATED_EASE;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
 import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 07db194..a0d49a4 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -37,7 +37,6 @@
 import com.android.launcher3.taskbar.TaskbarUIController;
 import com.android.launcher3.util.RunnableList;
 import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
-import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -186,11 +185,6 @@
                     && dp != null
                     && (dp.isTablet || dp.isTwoPanels);
 
-            if (DesktopTaskView.DESKTOP_MODE_SUPPORTED) {
-                // TODO(b/268075592): add support for quickswitch to/from desktop
-                allowQuickSwitch = false;
-            }
-
             if (cmd.type == TYPE_HIDE) {
                 if (!allowQuickSwitch) {
                     return true;
diff --git a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 4c9cf8b..031d409 100644
--- a/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -80,8 +80,7 @@
             }
 
             case TestProtocol.REQUEST_HAS_TIS: {
-                response.putBoolean(
-                        TestProtocol.REQUEST_HAS_TIS, true);
+                response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, true);
                 return response;
             }
 
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 38ac5bb..34817c0 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -308,7 +308,6 @@
             task.setLastSnapshotData(taskInfo);
             task.positionInParent = taskInfo.positionInParent;
             task.appBounds = taskInfo.configuration.windowConfiguration.getAppBounds();
-            // TODO(b/244348395): tasks should be sorted from oldest to most recently used
             tasks.add(task);
         }
         return new DesktopTask(tasks);
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 253341d..c1b6e53 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -48,6 +48,7 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.InvariantDeviceProfile;
@@ -56,7 +57,6 @@
 import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.model.data.ItemInfo;
@@ -297,7 +297,7 @@
         if (activityClosing) {
             Animator adjacentAnimation = mFallbackRecentsView
                     .createAdjacentPageAnimForTaskLaunch(taskView);
-            adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
+            adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE);
             adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION);
             adjacentAnimation.addListener(resetStateListener());
             target.play(adjacentAnimation);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 64ec1d8..7d2997e 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -17,7 +17,6 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.content.Intent.ACTION_USER_UNLOCKED;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
@@ -52,10 +51,8 @@
 import android.graphics.Region;
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
@@ -68,7 +65,6 @@
 import com.android.launcher3.util.DisplayController.Info;
 import com.android.launcher3.util.NavigationMode;
 import com.android.launcher3.util.SettingsCache;
-import com.android.launcher3.util.SimpleBroadcastReceiver;
 import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
 import com.android.quickstep.util.NavBarPosition;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -116,15 +112,6 @@
     private final boolean mIsOneHandedModeSupported;
     private boolean mPipIsActive;
 
-    private boolean mIsUserUnlocked;
-    private final ArrayList<Runnable> mUserUnlockedActions = new ArrayList<>();
-    private final SimpleBroadcastReceiver mUserUnlockedReceiver = new SimpleBroadcastReceiver(i -> {
-        if (ACTION_USER_UNLOCKED.equals(i.getAction())) {
-            mIsUserUnlocked = true;
-            notifyUserUnlocked();
-        }
-    });
-
     private int mGestureBlockingTaskId = -1;
     private @NonNull Region mExclusionRegion = new Region();
     private SystemGestureExclusionListenerCompat mExclusionListener;
@@ -150,14 +137,6 @@
             runOnDestroy(mRotationTouchHelper::destroy);
         }
 
-        // Register for user unlocked if necessary
-        mIsUserUnlocked = context.getSystemService(UserManager.class)
-                .isUserUnlocked(Process.myUserHandle());
-        if (!mIsUserUnlocked) {
-            mUserUnlockedReceiver.register(mContext, ACTION_USER_UNLOCKED);
-        }
-        runOnDestroy(() -> mUserUnlockedReceiver.unregisterReceiverSafely(mContext));
-
         // Register for exclusion updates
         mExclusionListener = new SystemGestureExclusionListenerCompat(mDisplayId) {
             @Override
@@ -260,7 +239,7 @@
     public void onDisplayInfoChanged(Context context, Info info, int flags) {
         if ((flags & (CHANGE_ROTATION | CHANGE_NAVIGATION_MODE)) != 0) {
             mMode = info.navigationMode;
-            mNavBarPosition = new NavBarPosition(mMode, info);
+            mNavBarPosition = new NavBarPosition(mContext, mMode, info);
 
             if (mMode == NO_BUTTON) {
                 mExclusionListener.register();
@@ -317,39 +296,12 @@
     }
 
     /**
-     * Adds a callback for when a user is unlocked. If the user is already unlocked, this listener
-     * will be called back immediately.
-     */
-    public void runOnUserUnlocked(Runnable action) {
-        if (mIsUserUnlocked) {
-            action.run();
-        } else {
-            mUserUnlockedActions.add(action);
-        }
-    }
-
-    /**
-     * @return whether the user is unlocked.
-     */
-    public boolean isUserUnlocked() {
-        return mIsUserUnlocked;
-    }
-
-    /**
      * @return whether the user has completed setup wizard
      */
     public boolean isUserSetupComplete() {
         return mIsUserSetupComplete;
     }
 
-    private void notifyUserUnlocked() {
-        for (Runnable action : mUserUnlockedActions) {
-            action.run();
-        }
-        mUserUnlockedActions.clear();
-        mUserUnlockedReceiver.unregisterReceiverSafely(mContext);
-    }
-
     /**
      * Sets the task id where gestures should be blocked
      */
@@ -607,7 +559,6 @@
         pw.println("  assistantAvailable=" + mAssistantAvailable);
         pw.println("  assistantDisabled="
                 + QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
-        pw.println("  isUserUnlocked=" + mIsUserUnlocked);
         pw.println("  isOneHandedModeEnabled=" + mIsOneHandedModeEnabled);
         pw.println("  isSwipeToNotificationEnabled=" + mIsSwipeToNotificationEnabled);
         pw.println("  deferredGestureRegion=" + mDeferredGestureRegion.getBounds());
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index 8626c40..2d47097 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -19,6 +19,7 @@
 import static android.view.Surface.ROTATION_0;
 
 import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadScroll;
 import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
 import static com.android.launcher3.util.DisplayController.CHANGE_ALL;
 import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
@@ -232,16 +233,18 @@
     /**
      * @return whether the coordinates of the {@param event} is in the swipe up gesture region.
      */
-    public boolean isInSwipeUpTouchRegion(MotionEvent event, BaseActivityInterface activity) {
-        return isInSwipeUpTouchRegion(event, 0, activity);
+    public boolean isInSwipeUpTouchRegion(MotionEvent event) {
+        return isInSwipeUpTouchRegion(event, 0);
     }
 
     /**
      * @return whether the coordinates of the {@param event} with the given {@param pointerIndex}
      *         is in the swipe up gesture region.
      */
-    public boolean isInSwipeUpTouchRegion(MotionEvent event, int pointerIndex,
-            BaseActivityInterface activity) {
+    public boolean isInSwipeUpTouchRegion(MotionEvent event, int pointerIndex) {
+        if (isTrackpadScroll(event)) {
+            return false;
+        }
         if (isTrackpadMultiFingerSwipe(event)) {
             return true;
         }
diff --git a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
index 25ac47a..e481165 100644
--- a/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
+++ b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
@@ -15,8 +15,8 @@
  */
 package com.android.quickstep;
 
-import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.ACCELERATE_1_5;
+import static com.android.app.animation.Interpolators.LINEAR;
 
 import android.animation.Animator;
 import android.content.Context;
@@ -218,7 +218,7 @@
             if (progress >= end) {
                 return 0f;
             }
-            return Utilities.mapToRange(progress, start, end, 1, 0, ACCEL_1_5);
+            return Utilities.mapToRange(progress, start, end, 1, 0, ACCELERATE_1_5);
         }
     }
 
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index ba80951..d40558c 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -74,6 +74,7 @@
 import com.android.wm.shell.bubbles.IBubbles;
 import com.android.wm.shell.bubbles.IBubblesListener;
 import com.android.wm.shell.desktopmode.IDesktopMode;
+import com.android.wm.shell.desktopmode.IDesktopTaskListener;
 import com.android.wm.shell.draganddrop.IDragAndDrop;
 import com.android.wm.shell.onehanded.IOneHanded;
 import com.android.wm.shell.pip.IPip;
@@ -130,6 +131,7 @@
     private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
     private IRecentTasksListener mRecentTasksListener;
     private IUnfoldTransitionListener mUnfoldAnimationListener;
+    private IDesktopTaskListener mDesktopTaskListener;
     private final LinkedHashMap<RemoteTransition, TransitionFilter> mRemoteTransitions =
             new LinkedHashMap<>();
     private IBinder mOriginalTransactionToken = null;
@@ -243,6 +245,7 @@
         registerRecentTasksListener(mRecentTasksListener);
         setBackToLauncherCallback(mBackToLauncherCallback, mBackToLauncherRunner);
         setUnfoldAnimationListener(mUnfoldAnimationListener);
+        setDesktopTaskListener(mDesktopTaskListener);
     }
 
     /**
@@ -311,13 +314,24 @@
 
     @MainThread
     @Override
-    public void onStatusBarMotionEvent(MotionEvent event) {
+    public void onStatusBarTouchEvent(MotionEvent event) {
         Preconditions.assertUIThread();
         if (mSystemUiProxy != null) {
             try {
-                mSystemUiProxy.onStatusBarMotionEvent(event);
+                mSystemUiProxy.onStatusBarTouchEvent(event);
             } catch (RemoteException e) {
-                Log.w(TAG, "Failed call onStatusBarMotionEvent", e);
+                Log.w(TAG, "Failed call onStatusBarTouchEvent with arg: " + event, e);
+            }
+        }
+    }
+
+    @Override
+    public void onStatusBarTrackpadEvent(MotionEvent event) {
+        if (mSystemUiProxy != null) {
+            try {
+                mSystemUiProxy.onStatusBarTrackpadEvent(event);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call onStatusBarTrackpadEvent with arg: " + event, e);
             }
         }
     }
@@ -1161,6 +1175,41 @@
         }
     }
 
+    /** Call shell to stash desktop apps */
+    public void stashDesktopApps(int displayId) {
+        if (mDesktopMode != null) {
+            try {
+                mDesktopMode.stashDesktopApps(displayId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call stashDesktopApps", e);
+            }
+        }
+    }
+
+    /** Call shell to hide desktop apps that may be stashed */
+    public void hideStashedDesktopApps(int displayId) {
+        if (mDesktopMode != null) {
+            try {
+                mDesktopMode.hideStashedDesktopApps(displayId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call hideStashedDesktopApps", e);
+            }
+        }
+    }
+
+    /**
+     * If task with the given id is on the desktop, bring it to front
+     */
+    public void showDesktopApp(int taskId) {
+        if (mDesktopMode != null) {
+            try {
+                mDesktopMode.showDesktopApp(taskId);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call showDesktopApp", e);
+            }
+        }
+    }
+
     /** Call shell to get number of visible freeform tasks */
     public int getVisibleDesktopTaskCount(int displayId) {
         if (mDesktopMode != null) {
@@ -1173,6 +1222,18 @@
         return 0;
     }
 
+    /** Set a listener on shell to get updates about desktop task state */
+    public void setDesktopTaskListener(@Nullable IDesktopTaskListener listener) {
+        mDesktopTaskListener = listener;
+        if (mDesktopMode != null) {
+            try {
+                mDesktopMode.setTaskListener(listener);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed call setDesktopTaskListener", e);
+            }
+        }
+    }
+
     //
     // Unfold transition
     //
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 499a260..bfe52dd 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -21,6 +21,9 @@
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.TOUCH_RESPONSE;
+import static com.android.app.animation.Interpolators.clampToProgress;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
@@ -35,9 +38,6 @@
 import static com.android.launcher3.QuickstepTransitionManager.SPLIT_DIVIDER_ANIM_DURATION;
 import static com.android.launcher3.QuickstepTransitionManager.SPLIT_LAUNCH_DURATION;
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.quickstep.views.DesktopTaskView.DESKTOP_MODE_SUPPORTED;
 
@@ -61,12 +61,12 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.AnimatorPlaybackController;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.statehandlers.DepthController;
@@ -237,12 +237,12 @@
         for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
             TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
             out.setFloat(tvsLocal.fullScreenProgress,
-                    AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
+                    AnimatedFloat.VALUE, 1, TOUCH_RESPONSE);
             out.setFloat(tvsLocal.recentsViewScale,
                     AnimatedFloat.VALUE, tvsLocal.getFullScreenScale(),
-                    TOUCH_RESPONSE_INTERPOLATOR);
+                    TOUCH_RESPONSE);
             out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0,
-                    TOUCH_RESPONSE_INTERPOLATOR);
+                    TOUCH_RESPONSE);
             out.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationStart(Animator animation) {
@@ -355,9 +355,9 @@
                 float fullScreenScale =
                         topMostSimulators[i].getTaskViewSimulator().getFullScreenScale();
                 out.addFloat(ttv, VIEW_TRANSLATE_Y, translationY,
-                        translationY / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
+                        translationY / fullScreenScale, TOUCH_RESPONSE);
                 out.addFloat(ttv, VIEW_TRANSLATE_X, translationX,
-                         translationX / fullScreenScale, TOUCH_RESPONSE_INTERPOLATOR);
+                         translationX / fullScreenScale, TOUCH_RESPONSE);
             }
 
             Matrix[] k0i = new Matrix[matrixSize];
@@ -405,7 +405,7 @@
 
         if (depthController != null) {
             out.setFloat(depthController.stateDepth, MULTI_PROPERTY_VALUE,
-                    BACKGROUND_APP.getDepth(baseActivity), TOUCH_RESPONSE_INTERPOLATOR);
+                    BACKGROUND_APP.getDepth(baseActivity), TOUCH_RESPONSE);
         }
     }
 
@@ -639,7 +639,7 @@
                 raController.setWillFinishToHome(false);
             }
             launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
-            launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
+            launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE);
             launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
 
             windowAnimEndListener = new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 1fbfbe6..8d05fa9 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -24,6 +24,8 @@
 import static android.view.MotionEvent.ACTION_UP;
 
 import static com.android.launcher3.Launcher.INTENT_ACTION_ALL_APPS_TOGGLE;
+import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
+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.quickstep.GestureState.DEFAULT_STATE;
@@ -98,11 +100,13 @@
 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.LockedUserState;
 import com.android.launcher3.util.OnboardingPrefs;
 import com.android.launcher3.util.TraceHelper;
 import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
 import com.android.quickstep.inputconsumers.AssistantInputConsumer;
 import com.android.quickstep.inputconsumers.DeviceLockedInputConsumer;
+import com.android.quickstep.inputconsumers.NavHandleLongPressInputConsumer;
 import com.android.quickstep.inputconsumers.OneHandedModeInputConsumer;
 import com.android.quickstep.inputconsumers.OtherActivityInputConsumer;
 import com.android.quickstep.inputconsumers.OverviewInputConsumer;
@@ -110,9 +114,9 @@
 import com.android.quickstep.inputconsumers.ProgressDelegateInputConsumer;
 import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
 import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
-import com.android.quickstep.inputconsumers.StatusBarInputConsumer;
 import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
 import com.android.quickstep.inputconsumers.TaskbarUnstashInputConsumer;
+import com.android.quickstep.inputconsumers.TrackpadStatusBarInputConsumer;
 import com.android.quickstep.util.ActiveGestureLog;
 import com.android.quickstep.util.ActiveGestureLog.CompoundString;
 import com.android.quickstep.util.ProtoTracer;
@@ -442,8 +446,8 @@
         BootAwarePreloader.start(this);
 
         // Call runOnUserUnlocked() before any other callbacks to ensure everything is initialized.
-        mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
-        mDeviceState.runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
+        LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
+        LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
         mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
 
         ProtoTracer.INSTANCE.get(this).add(this);
@@ -465,7 +469,7 @@
     private void initInputMonitor(String reason) {
         disposeEventHandlers("Initializing input monitor due to: " + reason);
 
-        if (mDeviceState.isButtonNavMode()) {
+        if (mDeviceState.isButtonNavMode() && !ENABLE_TRACKPAD_GESTURE.get()) {
             return;
         }
 
@@ -513,7 +517,7 @@
     }
 
     private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
-        if (!mDeviceState.isUserUnlocked() || mDeviceState.isButtonNavMode()) {
+        if (!LockedUserState.get(this).isUserUnlocked() || mDeviceState.isButtonNavMode()) {
             // Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
             // mode doesn't have gestures
             return;
@@ -556,7 +560,7 @@
 
     @UiThread
     private void onSystemUiFlagsChanged(int lastSysUIFlags) {
-        if (mDeviceState.isUserUnlocked()) {
+        if (LockedUserState.get(this).isUserUnlocked()) {
             int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
             SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
             mOverviewComponentObserver.onSystemUiStateChanged();
@@ -601,7 +605,7 @@
 
     @UiThread
     private void onAssistantVisibilityChanged() {
-        if (mDeviceState.isUserUnlocked()) {
+        if (LockedUserState.get(this).isUserUnlocked()) {
             mOverviewComponentObserver.getActivityInterface().onAssistantVisibilityChanged(
                     mDeviceState.getAssistantVisibility());
         }
@@ -611,7 +615,7 @@
     public void onDestroy() {
         Log.d(TAG, "Touch service destroyed: user=" + getUserId());
         sIsInitialized = false;
-        if (mDeviceState.isUserUnlocked()) {
+        if (LockedUserState.get(this).isUserUnlocked()) {
             mInputConsumer.unregisterInputConsumer();
             mOverviewComponentObserver.onDestroy();
         }
@@ -645,7 +649,8 @@
         TestLogging.recordMotionEvent(
                 TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
 
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked() || (mDeviceState.isButtonNavMode()
+                && !isTrackpadMotionEvent(event))) {
             return;
         }
 
@@ -661,8 +666,7 @@
             mRotationTouchHelper.setOrientationTransformIfNeeded(event);
 
             if ((!mDeviceState.isOneHandedModeActive()
-                    && mRotationTouchHelper.isInSwipeUpTouchRegion(event,
-                    mOverviewComponentObserver.getActivityInterface()))
+                    && mRotationTouchHelper.isInSwipeUpTouchRegion(event))
                     || isHoverActionWithoutConsumer) {
                 // Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
                 // onConsumerInactive and wipe the previous gesture state
@@ -674,7 +678,8 @@
                 mGestureState = newGestureState;
                 mConsumer = newConsumer(prevGestureState, mGestureState, event);
                 mUncheckedConsumer = mConsumer;
-            } else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()
+            } else if (LockedUserState.get(this).isUserUnlocked()
+                    && (mDeviceState.isFullyGesturalNavMode() || isTrackpadMultiFingerSwipe(event))
                     && mDeviceState.canTriggerAssistantAction(event)) {
                 mGestureState = createGestureState(mGestureState,
                         getTrackpadGestureType(event));
@@ -737,9 +742,6 @@
         if (mGestureState.isTrackpadGesture() && (action == ACTION_POINTER_DOWN
                 || action == ACTION_POINTER_UP)) {
             // Skip ACTION_POINTER_DOWN and ACTION_POINTER_UP events from trackpad.
-            if (action == ACTION_POINTER_DOWN) {
-                mGestureState.setTrackpadGestureType(getTrackpadGestureType(event));
-            }
         } else if (event.isHoverEvent()) {
             mUncheckedConsumer.onHoverEvent(event);
         } else {
@@ -818,7 +820,7 @@
 
         boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
 
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             CompoundString reasonString = newCompoundString("device locked");
             InputConsumer consumer;
             if (canStartSystemGesture) {
@@ -851,11 +853,12 @@
                     .append(", trying to use default input consumer");
             base = getDefaultInputConsumer(reasonString);
         }
-        if (mDeviceState.isGesturalNavMode()) {
+        if (mDeviceState.isGesturalNavMode() || newGestureState.isTrackpadGesture()) {
             handleOrientationSetup(base);
         }
-        if (mDeviceState.isFullyGesturalNavMode()) {
-            String reasonPrefix = "device is in gesture navigation mode";
+        if (mDeviceState.isFullyGesturalNavMode() || newGestureState.isTrackpadGesture()) {
+            String reasonPrefix = "device is in gesture navigation mode or 3-button mode with a"
+                    + "trackpad gesture";
             if (mDeviceState.canTriggerAssistantAction(event)) {
                 reasonString.append(NEWLINE_PREFIX)
                         .append(reasonPrefix)
@@ -880,6 +883,8 @@
                                     + "using TaskbarUnstashInputConsumer");
                     base = new TaskbarUnstashInputConsumer(this, base, mInputMonitorCompat, tac);
                 }
+            } else if (canStartSystemGesture && FeatureFlags.ENABLE_LONG_PRESS_NAV_HANDLE.get()) {
+                base = new NavHandleLongPressInputConsumer(this, base, mInputMonitorCompat);
             }
 
             if (mDeviceState.isBubblesExpanded()) {
@@ -902,8 +907,9 @@
                     && !previousGestureState.isRecentsAnimationRunning()) {
                 reasonString = newCompoundString(reasonPrefix)
                         .append(SUBSTRING_PREFIX)
-                        .append("Trackpad 3-finger gesture, using StatusBarInputConsumer");
-                base = new StatusBarInputConsumer(getBaseContext(), base, mInputMonitorCompat);
+                        .append("Trackpad 3-finger gesture, using TrackpadStatusBarInputConsumer");
+                base = new TrackpadStatusBarInputConsumer(getBaseContext(), base,
+                        mInputMonitorCompat);
             }
 
             if (mDeviceState.isScreenPinningActive()) {
@@ -1066,17 +1072,21 @@
 
     private InputConsumer createDeviceLockedInputConsumer(
             GestureState gestureState, CompoundString reasonString) {
-        if (mDeviceState.isFullyGesturalNavMode() && gestureState.getRunningTask() != null) {
+        if ((mDeviceState.isFullyGesturalNavMode() || gestureState.isTrackpadGesture())
+                && gestureState.getRunningTask() != null) {
             reasonString.append(SUBSTRING_PREFIX)
-                    .append("device is in gesture nav mode and running task != null")
+                    .append("device is in gesture nav mode or 3-button mode with a trackpad gesture"
+                            + "and running task != null")
                     .append(", using DeviceLockedInputConsumer");
             return new DeviceLockedInputConsumer(
                     this, mDeviceState, mTaskAnimationManager, gestureState, mInputMonitorCompat);
         } else {
             return getDefaultInputConsumer(reasonString
                     .append(SUBSTRING_PREFIX)
-                    .append(mDeviceState.isFullyGesturalNavMode()
-                        ? "running task == null" : "device is not in gesture nav mode")
+                    .append((mDeviceState.isFullyGesturalNavMode()
+                                    || gestureState.isTrackpadGesture())
+                            ? "running task == null"
+                            : "device is not in gesture nav mode and it's not a trackpad gesture")
                     .append(", trying to use default input consumer"));
         }
     }
@@ -1169,7 +1179,7 @@
     }
 
     private void preloadOverview(boolean fromInit, boolean forSUWAllSet) {
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             return;
         }
 
@@ -1205,7 +1215,7 @@
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        if (!mDeviceState.isUserUnlocked()) {
+        if (!LockedUserState.get(this).isUserUnlocked()) {
             return;
         }
         final BaseActivityInterface activityInterface =
@@ -1246,7 +1256,7 @@
         } else {
             // Dump everything
             FlagsFactory.dump(pw);
-            if (mDeviceState.isUserUnlocked()) {
+            if (LockedUserState.get(this).isUserUnlocked()) {
                 PluginManagerWrapper.INSTANCE.get(getBaseContext()).dump(pw);
             }
             mDeviceState.dump(pw);
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
index 8a87f63..66f5c00 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
@@ -42,7 +42,7 @@
         mActivity = activity;
         NavigationMode sysUINavigationMode = DisplayController.getNavigationMode(mActivity);
         if (sysUINavigationMode == NavigationMode.NO_BUTTON) {
-            NavBarPosition navBarPosition = new NavBarPosition(sysUINavigationMode,
+            NavBarPosition navBarPosition = new NavBarPosition(mActivity, sysUINavigationMode,
                     DisplayController.INSTANCE.get(mActivity).getInfo());
             mTriggerSwipeUpTracker = new TriggerSwipeUpTouchTracker(mActivity,
                     true /* disableHorizontalSwipe */, navBarPosition,
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 11b1ab8..8a9e04e 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -15,9 +15,9 @@
  */
 package com.android.quickstep.fallback;
 
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
index 6a36d9f..2abc7ba 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
@@ -103,8 +103,7 @@
                 if (mState == STATE_INACTIVE) {
                     int pointerIndex = ev.getActionIndex();
                     if (mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev,
-                            pointerIndex, mGestureState.getActivityInterface())
-                            && mDelegate.allowInterceptByParent()) {
+                            pointerIndex) && mDelegate.allowInterceptByParent()) {
                         setActive(ev);
 
                         mActivePointerId = ev.getPointerId(pointerIndex);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
index 162ace4..a209b3b 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
@@ -42,9 +42,9 @@
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
 import com.android.quickstep.BaseActivityInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.InputConsumer;
@@ -209,7 +209,7 @@
                             SystemUiProxy.INSTANCE.get(mContext).onAssistantProgress(0f);
                         }
                     });
-                    animator.setInterpolator(Interpolators.DEACCEL_2);
+                    animator.setInterpolator(Interpolators.DECELERATE_2);
                     animator.start();
                 }
                 mPassedSlop = false;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index 59a9582..2a35584 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -39,9 +39,9 @@
 import android.view.RemoteAnimationTarget;
 import android.view.VelocityTracker;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.shared.TestProtocol;
 import com.android.launcher3.util.DisplayController;
@@ -153,8 +153,7 @@
                 if (!mThresholdCrossed) {
                     // Cancel interaction in case of multi-touch interaction
                     int ptrIdx = ev.getActionIndex();
-                    if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx,
-                            mGestureState.getActivityInterface())) {
+                    if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx)) {
                         int action = ev.getAction();
                         ev.setAction(ACTION_CANCEL);
                         finishTouchTracking(ev);
@@ -204,7 +203,7 @@
             // Animate back to fullscreen before finishing
             ObjectAnimator animator = mProgress.animateToValue(mProgress.value, 0);
             animator.setDuration(100);
-            animator.setInterpolator(Interpolators.ACCEL);
+            animator.setInterpolator(Interpolators.ACCELERATE);
             animator.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation) {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
new file mode 100644
index 0000000..5c5b9ca
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressHandler.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.quickstep.inputconsumers;
+
+import android.content.Context;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+/**
+ * Class for extending nav handle long press behavior
+ */
+public class NavHandleLongPressHandler implements ResourceBasedOverride {
+
+    /** Creates NavHandleLongPressHandler as specified by overrides */
+    public static NavHandleLongPressHandler newInstance(Context context) {
+        return Overrides.getObject(NavHandleLongPressHandler.class, context,
+                R.string.nav_handle_long_press_handler_class);
+    }
+
+    /**
+     * Called when nav handle is long pressed.
+     *
+     * @return if the long press was consumed, meaning other input consumers should receive a
+     * cancel event
+     */
+    public boolean onLongPress() {
+        return false;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
new file mode 100644
index 0000000..542dea1
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/inputconsumers/NavHandleLongPressInputConsumer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.inputconsumers;
+
+import android.content.Context;
+import android.view.GestureDetector;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.DisplayController;
+import com.android.quickstep.InputConsumer;
+import com.android.systemui.shared.system.InputMonitorCompat;
+
+/**
+ * Listens for a long press
+ */
+public class NavHandleLongPressInputConsumer extends DelegateInputConsumer {
+
+    private final GestureDetector mLongPressDetector;
+    private final NavHandleLongPressHandler mNavHandleLongPressHandler;
+    private final float mNavHandleWidth;
+    private final float mScreenWidth;
+
+    public NavHandleLongPressInputConsumer(Context context, InputConsumer delegate,
+            InputMonitorCompat inputMonitor) {
+        super(delegate, inputMonitor);
+        mNavHandleWidth = context.getResources()
+                .getDimensionPixelSize(R.dimen.navigation_home_handle_width);
+        mScreenWidth = DisplayController.INSTANCE.get(context).getInfo().currentSize.x;
+
+        mNavHandleLongPressHandler = NavHandleLongPressHandler.newInstance(context);
+
+        mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
+            @Override
+            public void onLongPress(MotionEvent motionEvent) {
+                if (isInArea(motionEvent.getRawX())) {
+                    if (mNavHandleLongPressHandler.onLongPress()) {
+                        setActive(motionEvent);
+                    }
+                }
+            }
+        });
+    }
+
+    @Override
+    public int getType() {
+        return TYPE_NAV_HANDLE_LONG_PRESS | mDelegate.getType();
+    }
+
+    @Override
+    public void onMotionEvent(MotionEvent ev) {
+        mLongPressDetector.onTouchEvent(ev);
+        if (mState != STATE_ACTIVE) {
+            mDelegate.onMotionEvent(ev);
+        }
+    }
+
+    protected boolean isInArea(float x) {
+        float areaFromMiddle = mNavHandleWidth / 2.0f;
+        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 f9cd4ee..5b27f9b 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
@@ -248,8 +248,7 @@
                 if (!mPassedPilferInputSlop) {
                     // Cancel interaction in case of multi-touch interaction
                     int ptrIdx = ev.getActionIndex();
-                    if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx,
-                            mActivityInterface)) {
+                    if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx)) {
                         forceCancelGesture(ev);
                     }
                 }
@@ -352,7 +351,8 @@
                         mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
                     }
 
-                    if (mDeviceState.isFullyGesturalNavMode()) {
+                    if (mDeviceState.isFullyGesturalNavMode()
+                            || mGestureState.isTrackpadGesture()) {
                         boolean minSwipeMet = upDist >= Math.max(mMotionPauseMinDisplacement,
                                 mInteractionHandler.getThresholdToAllowMotionPause());
                         mInteractionHandler.setCanSlowSwipeGoHome(minSwipeMet);
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
index ab70272..5202529 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/ProgressDelegateInputConsumer.java
@@ -15,7 +15,7 @@
  */
 package com.android.quickstep.inputconsumers;
 
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.touch.BaseSwipeDetector.calculateDuration;
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_POSITIVE;
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/StatusBarInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
similarity index 91%
rename from quickstep/src/com/android/quickstep/inputconsumers/StatusBarInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
index 898aa86..7ff9982 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/StatusBarInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TrackpadStatusBarInputConsumer.java
@@ -27,15 +27,15 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.systemui.shared.system.InputMonitorCompat;
 
-/** Allows the status bar to be pull down for notification shade */
-public class StatusBarInputConsumer extends DelegateInputConsumer {
+/** Allows the status bar to be pull down for notification shade using the trackpad. */
+public class TrackpadStatusBarInputConsumer extends DelegateInputConsumer {
 
     private final SystemUiProxy mSystemUiProxy;
     private final float mTouchSlop;
     private final PointF mDown = new PointF();
     private boolean mHasPassedTouchSlop;
 
-    public StatusBarInputConsumer(Context context, InputConsumer delegate,
+    public TrackpadStatusBarInputConsumer(Context context, InputConsumer delegate,
             InputMonitorCompat inputMonitor) {
         super(delegate, inputMonitor);
 
@@ -79,7 +79,7 @@
 
     private void dispatchTouchEvent(MotionEvent ev) {
         if (mSystemUiProxy.isActive()) {
-            mSystemUiProxy.onStatusBarMotionEvent(ev);
+            mSystemUiProxy.onStatusBarTrackpadEvent(ev);
         }
     }
 }
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 8274a51..5e1a46e 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -15,10 +15,10 @@
  */
 package com.android.quickstep.interaction;
 
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Utilities.mapBoundToRange;
 import static com.android.launcher3.Utilities.mapRange;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSafely;
 
 import android.animation.Animator;
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index 54c441b..f1091f2 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -23,9 +23,9 @@
 import android.graphics.PointF;
 import android.view.View;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
 import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
 import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
 import com.android.quickstep.util.LottieAnimationColorUtils;
@@ -176,7 +176,7 @@
                 /* upperBound = */ 1f,
                 /* toMin = */ 1f,
                 /* toMax = */ EXITING_APP_MIN_SIZE_PERCENTAGE,
-                Interpolators.DEACCEL);
+                Interpolators.DECELERATE);
 
         // shrink the exiting app as we progress through the back gesture
         mExitingAppView.setPivotX(isLeftGesture ? mScreenWidth : 0);
@@ -190,7 +190,7 @@
                 /* upperBound = */ 1f,
                 /* toMin = */ 0,
                 /* toMax = */ mExitingAppMargin,
-                Interpolators.DEACCEL)
+                Interpolators.DECELERATE)
                 * (isLeftGesture ? -1 : 1));
 
         // round the corners of the exiting app as we progress through the back gesture
diff --git a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
index 8eb4059..a9dcad8 100644
--- a/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
+++ b/quickstep/src/com/android/quickstep/interaction/EdgeBackGesturePanel.java
@@ -40,8 +40,8 @@
 import androidx.dynamicanimation.animation.SpringAnimation;
 import androidx.dynamicanimation.animation.SpringForce;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.testing.shared.ResourceUtils;
 import com.android.launcher3.util.VibratorWrapper;
 
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
index 6cee690..63e41d5 100644
--- a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -65,7 +65,7 @@
         mDisplaySize.set(currentSize.x, currentSize.y);
         mSwipeUpTouchTracker =
                 new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
-                        new NavBarPosition(NavigationMode.NO_BUTTON, displayRotation),
+                        new NavBarPosition(mContext, NavigationMode.NO_BUTTON, displayRotation),
                         null /*onInterceptTouch*/, this);
         mMotionPauseDetector = new MotionPauseDetector(context);
 
diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
index 667fe4d..1c5ad3f 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -15,7 +15,7 @@
  */
 package com.android.quickstep.interaction;
 
-import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.app.animation.Interpolators.ACCELERATE;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
 
 import android.animation.Animator;
@@ -245,7 +245,7 @@
     public void animateTaskViewToOverview(boolean animateDelayedSuccessFeedback) {
         PendingAnimation anim = new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
         anim.setFloat(mTaskViewSwipeUpAnimation
-                .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
+                .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCELERATE);
 
         if (animateDelayedSuccessFeedback) {
             anim.addListener(new AnimatorListenerAdapter() {
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index 0bbf373..0c14819 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -15,7 +15,7 @@
  */
 package com.android.quickstep.interaction;
 
-import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.app.animation.Interpolators.ACCELERATE;
 import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
 import static com.android.quickstep.AbsSwipeUpHandler.MAX_SWIPE_DURATION;
@@ -160,14 +160,14 @@
         PendingAnimation anim = new PendingAnimation(300);
         if (toOverviewFirst) {
             anim.setFloat(mTaskViewSwipeUpAnimation
-                    .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
+                    .getCurrentShift(), AnimatedFloat.VALUE, 1, ACCELERATE);
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
                 public void onAnimationEnd(Animator animation, boolean isReverse) {
                     PendingAnimation fadeAnim =
                             new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
                     fadeAnim.setFloat(mTaskViewSwipeUpAnimation
-                            .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+                            .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCELERATE);
                     if (resetViews) {
                         fadeAnim.addListener(mResetTaskView);
                     }
@@ -202,7 +202,7 @@
             });
         } else {
             anim.setFloat(mTaskViewSwipeUpAnimation
-                    .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
+                    .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCELERATE);
             if (resetViews) {
                 anim.addListener(mResetTaskView);
             }
@@ -228,8 +228,8 @@
         mFakeTaskView.setVisibility(View.VISIBLE);
         PendingAnimation anim = new PendingAnimation(300);
         anim.setFloat(mTaskViewSwipeUpAnimation
-                .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCEL);
-        anim.setViewAlpha(mFakeTaskView, 1, ACCEL);
+                .getCurrentShift(), AnimatedFloat.VALUE, 0, ACCELERATE);
+        anim.setViewAlpha(mFakeTaskView, 1, ACCELERATE);
         anim.addListener(mResetTaskView);
         AnimatorSet animset = anim.buildAnim();
         if (animateTaskbar) {
@@ -249,7 +249,7 @@
                 mTaskViewSwipeUpAnimation.handleSwipeUpToHome(finalVelocity);
         // After home animation finishes, fade out and run onEndRunnable.
         PendingAnimation fadeAnim = new PendingAnimation(300);
-        fadeAnim.setViewAlpha(mFakeIconView, 0, ACCEL);
+        fadeAnim.setViewAlpha(mFakeIconView, 0, ACCELERATE);
         if (onEndRunnable != null) {
             fadeAnim.addListener(AnimatorListeners.forSuccessCallback(onEndRunnable));
         }
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
index a92ab2a..df9830a 100644
--- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -15,9 +15,9 @@
  */
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.quickstep.AbsSwipeUpHandler.ALL_APPS_SHIFT_THRESHOLD;
+import static com.android.app.animation.Interpolators.DECELERATE;
+import static com.android.app.animation.Interpolators.LINEAR;
+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;
 
@@ -34,6 +34,7 @@
 
 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;
@@ -91,7 +92,7 @@
         public final boolean stopScalingAtTop;
     }
 
-    private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL;
+    private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DECELERATE;
     private static final TimeInterpolator RECENTS_TRANSLATE_RESIST_INTERPOLATOR = LINEAR;
 
     private static final Rect TEMP_RECT = new Rect();
@@ -188,7 +189,8 @@
                         recentsOrientedState.getOrientationHandler());
         float dragLengthFactor = (float) dp.heightPx / transitionDragLength;
         // -1s are because 0-1 is reserved for the normal transition.
-        return (ALL_APPS_SHIFT_THRESHOLD - 1) / (dragLengthFactor - 1);
+        float threshold = LauncherPrefs.get(context).get(ALL_APPS_OVERVIEW_THRESHOLD) / 100f;
+        return (threshold - 1) / (dragLengthFactor - 1);
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.java b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
index 011d45c..7563187 100644
--- a/quickstep/src/com/android/quickstep/util/BorderAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
@@ -29,9 +29,9 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Px;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.anim.Interpolators;
 
 /**
  * Utility class for drawing a rounded-rect border around a view.
diff --git a/quickstep/src/com/android/quickstep/util/GroupTask.java b/quickstep/src/com/android/quickstep/util/GroupTask.java
index 2be4f0a..9c49647 100644
--- a/quickstep/src/com/android/quickstep/util/GroupTask.java
+++ b/quickstep/src/com/android/quickstep/util/GroupTask.java
@@ -37,6 +37,10 @@
     @TaskView.Type
     public final int taskViewType;
 
+    public GroupTask(@NonNull Task task) {
+        this(task, null, null);
+    }
+
     public GroupTask(@NonNull Task t1, @Nullable Task t2, @Nullable SplitBounds splitBounds) {
         this(t1, t2, splitBounds, t2 != null ? TaskView.Type.GROUPED : TaskView.Type.SINGLE);
     }
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
index 59c8263..a89e7e3 100644
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -16,7 +16,9 @@
 package com.android.quickstep.util;
 
 import static com.android.launcher3.util.NavigationMode.NO_BUTTON;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
 
+import android.content.Context;
 import android.view.Surface;
 
 import com.android.launcher3.util.DisplayController.Info;
@@ -27,25 +29,26 @@
  */
 public class NavBarPosition {
 
+    private final boolean mIsLargeScreen;
     private final NavigationMode mMode;
     private final int mDisplayRotation;
 
-    public NavBarPosition(NavigationMode mode, Info info) {
-        mMode = mode;
-        mDisplayRotation = info.rotation;
+    public NavBarPosition(Context context, NavigationMode mode, Info info) {
+        this(context, mode, info.rotation);
     }
 
-    public NavBarPosition(NavigationMode mode, int displayRotation) {
+    public NavBarPosition(Context context, NavigationMode mode, int displayRotation) {
+        mIsLargeScreen = isLargeScreen(context);
         mMode = mode;
         mDisplayRotation = displayRotation;
     }
 
     public boolean isRightEdge() {
-        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
+        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90 && !mIsLargeScreen;
     }
 
     public boolean isLeftEdge() {
-        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270;
+        return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_270 && !mIsLargeScreen;
     }
 
     public float getRotation() {
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
index e189a66..3027f79 100644
--- a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
@@ -16,8 +16,8 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.INSTANT;
 
 import android.view.animation.Interpolator;
 
diff --git a/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
index f1dde53..a38f437 100644
--- a/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/PhoneOverviewToSplitTimings.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 
 import android.view.animation.Interpolator;
 
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
index 7dc1b32..93f2255 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
 
 import android.view.animation.Interpolator;
 
diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
index f5b00cf..d1ec2b6 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 
 import android.view.animation.Interpolator;
 
diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
index cd5edab..9099012 100644
--- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
+++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
@@ -15,11 +15,11 @@
  */
 package com.android.quickstep.util;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
diff --git a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
index a34888f..c82cdb7 100644
--- a/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
+++ b/quickstep/src/com/android/quickstep/util/SystemWindowManagerProxy.java
@@ -28,6 +28,7 @@
 import com.android.launcher3.util.window.CachedDisplayInfo;
 import com.android.launcher3.util.window.WindowManagerProxy;
 
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -53,15 +54,15 @@
     }
 
     @Override
-    public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
+    public ArrayMap<CachedDisplayInfo, List<WindowBounds>> estimateInternalDisplayBounds(
             Context displayInfoContext) {
-        ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
+        ArrayMap<CachedDisplayInfo, List<WindowBounds>> result = new ArrayMap<>();
         WindowManager windowManager = displayInfoContext.getSystemService(WindowManager.class);
         Set<WindowMetrics> possibleMaximumWindowMetrics =
                 windowManager.getPossibleMaximumWindowMetrics(DEFAULT_DISPLAY);
         for (WindowMetrics windowMetrics : possibleMaximumWindowMetrics) {
             CachedDisplayInfo info = getDisplayInfo(windowMetrics, Surface.ROTATION_0);
-            WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
+            List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
             result.put(info, bounds);
         }
         return result;
diff --git a/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
index bf8612a..8804049 100644
--- a/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletHomeToSplitTimings.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
 
 import android.view.animation.Interpolator;
 
diff --git a/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
index cbf46bf..5463d84 100644
--- a/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
+++ b/quickstep/src/com/android/quickstep/util/TabletOverviewToSplitTimings.java
@@ -16,7 +16,7 @@
 
 package com.android.quickstep.util;
 
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
 
 import android.view.animation.Interpolator;
 
@@ -36,8 +36,8 @@
     public int getGridSlideDuration() { return 500; }
 
     public int getDuration() { return TABLET_ENTER_DURATION; }
-    public Interpolator getStagedRectXInterpolator() { return DEACCEL_2; }
-    public Interpolator getStagedRectYInterpolator() { return DEACCEL_2; }
-    public Interpolator getStagedRectScaleXInterpolator() { return DEACCEL_2; }
-    public Interpolator getStagedRectScaleYInterpolator() { return DEACCEL_2; }
+    public Interpolator getStagedRectXInterpolator() { return DECELERATE_2; }
+    public Interpolator getStagedRectYInterpolator() { return DECELERATE_2; }
+    public Interpolator getStagedRectScaleXInterpolator() { return DECELERATE_2; }
+    public Interpolator getStagedRectScaleYInterpolator() { return DECELERATE_2; }
 }
diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
index 0f20e43..1cbded6 100644
--- a/quickstep/src/com/android/quickstep/util/TransformParams.java
+++ b/quickstep/src/com/android/quickstep/util/TransformParams.java
@@ -21,8 +21,8 @@
 import android.util.FloatProperty;
 import android.view.RemoteAnimationTarget;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
 import com.android.quickstep.RemoteAnimationTargets;
 import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
 
@@ -153,7 +153,8 @@
                     // Fade out Assistant overlay.
                     if (activityType == ACTIVITY_TYPE_ASSISTANT && app.isNotInRecents) {
                         float progress = Utilities.boundToRange(getProgress(), 0, 1);
-                        builder.setAlpha(1 - Interpolators.DEACCEL_2_5.getInterpolation(progress));
+                        builder.setAlpha(1 - Interpolators.DECELERATE_QUINT
+                                .getInterpolation(progress));
                     } else {
                         builder.setAlpha(getTargetAlpha());
                     }
diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
index 34fa7f1..ac8862f 100644
--- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
+++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java
@@ -32,11 +32,11 @@
 import android.util.FloatProperty;
 import android.view.View;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.states.StateAnimationConfig;
diff --git a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
index 716d389..fdc8f1f 100644
--- a/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
@@ -15,12 +15,12 @@
  */
 package com.android.quickstep.views;
 
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.OVERSHOOT_1_7;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALL_APPS_EDU_SHOWN;
 
 import android.animation.Animator;
diff --git a/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
new file mode 100644
index 0000000..45a26a5
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/DesktopAppSelectView.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep.views;
+
+import static com.android.app.animation.Interpolators.LINEAR;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+
+/**
+ * Floating view show on launcher home screen that notifies the user that an app will be launched to
+ * the desktop.
+ */
+public class DesktopAppSelectView extends LinearLayout {
+
+    private static final int HIDE_DURATION = 83;
+
+    private final Launcher mLauncher;
+
+    @Nullable
+    private Runnable mOnCloseCallback = null;
+    private boolean mIsHideAnimationRunning;
+
+    public DesktopAppSelectView(Context context) {
+        this(context, null);
+    }
+
+    public DesktopAppSelectView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public DesktopAppSelectView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mLauncher = Launcher.getLauncher(context);
+    }
+
+    /**
+     * Show the popup on launcher home screen
+     *
+     * @param onCloseCallback optional callback that is called when user clicks the close button
+     * @return the created view
+     */
+    public static DesktopAppSelectView show(Launcher launcher, @Nullable Runnable onCloseCallback) {
+        DesktopAppSelectView view = (DesktopAppSelectView) launcher.getLayoutInflater().inflate(
+                R.layout.floating_desktop_app_select, launcher.getDragLayer(), false);
+        view.setOnCloseClickCallback(onCloseCallback);
+        launcher.getDragLayer().addView(view);
+        return view;
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        findViewById(R.id.close_button).setOnClickListener(v -> {
+            if (!mIsHideAnimationRunning) {
+                hide();
+                if (mOnCloseCallback != null) {
+                    mOnCloseCallback.run();
+                }
+            }
+        });
+    }
+
+    /**
+     * Hide the floating view
+     */
+    public void hide() {
+        if (!mIsHideAnimationRunning) {
+            mIsHideAnimationRunning = true;
+            animate().alpha(0).setDuration(HIDE_DURATION).setInterpolator(LINEAR).withEndAction(
+                    () -> {
+                        mLauncher.getDragLayer().removeView(this);
+                        mIsHideAnimationRunning = false;
+                    });
+        }
+    }
+
+    /**
+     * Add a callback that is called when close button is clicked
+     */
+    public void setOnCloseClickCallback(@Nullable Runnable callback) {
+        mOnCloseCallback = callback;
+    }
+}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 75a8ea2..a5652dc 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -1,8 +1,8 @@
 package com.android.quickstep.views;
 
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
 
 import android.animation.ValueAnimator;
 import android.content.Context;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f740d9c..3142c9e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -21,6 +21,16 @@
 import static android.view.View.MeasureSpec.EXACTLY;
 import static android.view.View.MeasureSpec.makeMeasureSpec;
 
+import static com.android.app.animation.Interpolators.ACCELERATE;
+import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.OVERSHOOT_0_75;
+import static com.android.app.animation.Interpolators.clampToProgress;
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
 import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
 import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
@@ -32,16 +42,6 @@
 import static com.android.launcher3.Utilities.mapToRange;
 import static com.android.launcher3.Utilities.squaredHypot;
 import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_GRID_ONLY_OVERVIEW;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCH_FROM_STAGED_APP;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
@@ -1180,7 +1180,7 @@
                     new SurfaceTransactionApplier(mActivity.getDragLayer());
             ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
             appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
-            appAnimator.setInterpolator(ACCEL_DEACCEL);
+            appAnimator.setInterpolator(ACCELERATE_DECELERATE);
             appAnimator.addUpdateListener(valueAnimator -> {
                 float percent = valueAnimator.getAnimatedFraction();
                 SurfaceTransaction transaction = new SurfaceTransaction();
@@ -1631,6 +1631,10 @@
         int[] runningTaskId = getTaskIdsForTaskViewId(mRunningTaskViewId);
         int[] focusedTaskId = getTaskIdsForTaskViewId(mFocusedTaskViewId);
 
+        // Reset the focused task to avoiding initializing TaskViews layout as focused task during
+        // binding. The focused task view will be updated after all the TaskViews are bound.
+        mFocusedTaskViewId = INVALID_TASK_ID;
+
         // Removing views sets the currentPage to 0, so we save this and restore it after
         // the new set of views are added
         int previousCurrentPage = mCurrentPage;
@@ -1737,7 +1741,9 @@
         mFocusedTaskViewId = newFocusedTaskView != null && !ENABLE_GRID_ONLY_OVERVIEW.get()
                 ? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID;
         updateTaskSize();
-        updateChildTaskOrientations();
+        if (newFocusedTaskView != null) {
+            newFocusedTaskView.setOrientationState(mOrientationState);
+        }
 
         TaskView newRunningTaskView = null;
         if (hasAnyValidTaskIds(runningTaskId)) {
@@ -3126,7 +3132,7 @@
         // Use setFloat instead of setViewAlpha as we want to keep the view visible even when it's
         // alpha is set to 0 so that it can be recycled in the view pool properly
         anim.setFloat(taskView, VIEW_ALPHA, 0,
-                clampToProgress(isOnGridBottomRow(taskView) ? ACCEL : FINAL_FRAME, 0, 0.5f));
+                clampToProgress(isOnGridBottomRow(taskView) ? ACCELERATE : FINAL_FRAME, 0, 0.5f));
         FloatProperty<TaskView> secondaryViewTranslate =
                 taskView.getSecondaryDismissTranslationProperty();
         int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
@@ -4279,7 +4285,7 @@
 
     private void updatePageOffsets() {
         float offset = mAdjacentPageHorizontalOffset;
-        float modalOffset = ACCEL_0_75.getInterpolation(mTaskModalness);
+        float modalOffset = ACCELERATE_0_75.getInterpolation(mTaskModalness);
         int count = getChildCount();
         boolean showAsGrid = showAsGrid();
 
@@ -4712,7 +4718,7 @@
 
         // Fade out all other views underneath placeholders
         ObjectAnimator tvFade = ObjectAnimator.ofFloat(this, RecentsView.CONTENT_ALPHA,1, 0);
-        pendingAnimation.add(tvFade, DEACCEL_2, SpringProperty.DEFAULT);
+        pendingAnimation.add(tvFade, DECELERATE_2, SpringProperty.DEFAULT);
         pendingAnimation.buildAnim().start();
         return true;
     }
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 2c9afb4..b4d24e5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -36,12 +36,12 @@
 
 import androidx.annotation.Nullable;
 
+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;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.touch.PagedOrientationHandler;
@@ -256,7 +256,7 @@
 
         final Animator revealAnimator = createOpenCloseOutlineProvider()
                 .createRevealAnimator(this, closing);
-        revealAnimator.setInterpolator(Interpolators.DEACCEL);
+        revealAnimator.setInterpolator(Interpolators.DECELERATE);
         mOpenCloseAnimator.playTogether(revealAnimator,
                 ObjectAnimator.ofFloat(
                         mTaskContainer.getThumbnailView(), DIM_ALPHA,
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 6e7b6dc..200252a 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -20,11 +20,11 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.widget.Toast.LENGTH_SHORT;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherState.BACKGROUND_APP;
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 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.util.Executors.MAIN_EXECUTOR;
@@ -71,11 +71,11 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.popup.SystemShortcut;
@@ -163,7 +163,7 @@
     public static final long SCALE_ICON_DURATION = 120;
     private static final long DIM_ANIM_DURATION = 700;
 
-    private static final Interpolator GRID_INTERPOLATOR = ACCEL_DEACCEL;
+    private static final Interpolator GRID_INTERPOLATOR = ACCELERATE_DECELERATE;
 
     /**
      * This technically can be a vanilla {@link TouchDelegate} class, however that class requires
@@ -580,7 +580,6 @@
                 mIconView, STAGE_POSITION_UNDEFINED);
         mSnapshotView.bind(task);
         setOrientationState(orientedState);
-        mDigitalWellBeingToast.initialize(mTask);
     }
 
     /**
diff --git a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
index 83341cb..b12d98b 100644
--- a/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
+++ b/quickstep/tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java
@@ -20,6 +20,7 @@
 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 static com.android.launcher3.util.TestUtil.runOnExecutorSync;
 import static com.android.launcher3.util.WidgetUtils.createAppWidgetProviderInfo;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -40,11 +41,9 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.icons.ComponentWithLabel;
-import com.android.launcher3.icons.IconCache;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
 import com.android.launcher3.model.QuickstepModelDelegate.PredictorState;
+import com.android.launcher3.util.LauncherLayoutBuilder;
 import com.android.launcher3.util.LauncherModelHelper;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.widget.PendingAddWidgetInfo;
@@ -53,8 +52,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
 
 import java.util.Arrays;
 import java.util.List;
@@ -76,17 +73,9 @@
     private LauncherModelHelper mModelHelper;
     private UserHandle mUserHandle;
 
-    @Mock
-    private IconCache mIconCache;
-
     @Before
     public void setup() throws Exception {
         mModelHelper = new LauncherModelHelper();
-        MockitoAnnotations.initMocks(this);
-        doAnswer(invocation -> {
-            ComponentWithLabel componentWithLabel = invocation.getArgument(0);
-            return componentWithLabel.getComponent().getShortClassName();
-        }).when(mIconCache).getTitleNoCache(any());
 
         mUserHandle = myUserHandle();
         mApp1Provider1 = createAppWidgetProviderInfo(
@@ -114,16 +103,12 @@
                     .collect(Collectors.toList());
         }).when(manager).getInstalledProvidersForPackage(any(), eq(myUserHandle()));
 
-        // 2 widgets, app4/provider1 & app5/provider1, have already been added to the workspace.
-        mModelHelper.initializeData("widgets_predication_update_task_data");
-
+        LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+                .atWorkspace(0, 1, 2).putWidget("app4", "provider1", 1, 1)
+                .atWorkspace(0, 1, 3).putWidget("app5", "provider1", 1, 1);
+        mModelHelper.setupDefaultLayoutProvider(builder);
         MAIN_EXECUTOR.submit(() -> mModelHelper.getModel().addCallbacks(mCallback)).get();
-        MODEL_EXECUTOR.post(() -> mModelHelper.getBgDataModel().widgetsModel.update(
-                LauncherAppState.getInstance(mModelHelper.sandboxContext),
-                /* packageUser= */ null));
-
-        MODEL_EXECUTOR.submit(() -> { }).get();
-        MAIN_EXECUTOR.submit(() -> { }).get();
+        mModelHelper.loadModelSync();
     }
 
     @After
@@ -132,65 +117,72 @@
     }
 
     @Test
-    public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder()
-            throws Exception {
-        // WHEN newPredicationTask is executed with app predication of 5 apps.
-        AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
-                mUserHandle);
-        AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1",
-                mUserHandle);
-        AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className",
-                mUserHandle);
-        AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
-                mUserHandle);
-        AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
-                mUserHandle);
-        mModelHelper.executeTaskForTest(
-                newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1)))
-                .forEach(Runnable::run);
+    public void widgetsRecommendationRan_shouldOnlyReturnNotAddedWidgetsInAppPredictionOrder() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            // WHEN newPredicationTask is executed with app predication of 5 apps.
+            AppTarget app1 = new AppTarget(new AppTargetId("app1"), "app1", "provider1",
+                    mUserHandle);
+            AppTarget app2 = new AppTarget(new AppTargetId("app2"), "app2", "provider1",
+                    mUserHandle);
+            AppTarget app3 = new AppTarget(new AppTargetId("app3"), "app3", "className",
+                    mUserHandle);
+            AppTarget app4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
+                    mUserHandle);
+            AppTarget app5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+                    mUserHandle);
+            mCallback.mRecommendedWidgets = null;
+            mModelHelper.getModel().enqueueModelUpdateTask(
+                    newWidgetsPredicationTask(List.of(app5, app3, app2, app4, app1)));
+            runOnExecutorSync(MAIN_EXECUTOR, () -> { });
 
-        // THEN only 2 widgets are returned because
-        // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
-        //    excluded from the result.
-        // 2. app3 doesn't have a widget.
-        // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
-        List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
-                .stream()
-                .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
-                .collect(Collectors.toList());
-        assertThat(recommendedWidgets).hasSize(2);
-        assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
-        assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+            // THEN only 2 widgets are returned because
+            // 1. app5/provider1 & app4/provider1 have already been added to workspace. They are
+            //    excluded from the result.
+            // 2. app3 doesn't have a widget.
+            // 3. only 1 widget is picked from app1 because we only want to promote one widget per app.
+            List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+                    .stream()
+                    .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+                    .collect(Collectors.toList());
+            assertThat(recommendedWidgets).hasSize(2);
+            assertWidgetInfo(recommendedWidgets.get(0).info, mApp2Provider1);
+            assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+        });
     }
 
     @Test
-    public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty()
-            throws Exception {
+    public void widgetsRecommendationRan_shouldReturnPackageWidgetsWhenEmpty() {
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
 
-        // Not installed widget
-        AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3",
-                mUserHandle);
-        // Not installed app
-        AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
-                mUserHandle);
-        // Workspace added widgets
-        AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
-                mUserHandle);
-        AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
-                mUserHandle);
-        mModelHelper.executeTaskForTest(
-                newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)))
-                .forEach(Runnable::run);
+            // Not installed widget
+            AppTarget widget1 = new AppTarget(new AppTargetId("app1"), "app1", "provider3",
+                    mUserHandle);
+            // Not installed app
+            AppTarget widget3 = new AppTarget(new AppTargetId("app2"), "app3", "provider1",
+                    mUserHandle);
+            // Workspace added widgets
+            AppTarget widget4 = new AppTarget(new AppTargetId("app4"), "app4", "provider1",
+                    mUserHandle);
+            AppTarget widget5 = new AppTarget(new AppTargetId("app5"), "app5", "provider1",
+                    mUserHandle);
 
-        // THEN only 2 widgets are returned because the launcher only filters out non-exist widgets.
-        List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
-                .stream()
-                .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
-                .collect(Collectors.toList());
-        assertThat(recommendedWidgets).hasSize(2);
-        // Another widget from the same package
-        assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
-        assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+            mCallback.mRecommendedWidgets = null;
+            mModelHelper.getModel().enqueueModelUpdateTask(
+                    newWidgetsPredicationTask(List.of(widget5, widget3, widget4, widget1)));
+            runOnExecutorSync(MAIN_EXECUTOR, () -> { });
+
+            // THEN only 2 widgets are returned because the launcher only filters out
+            // non-exist widgets.
+            List<PendingAddWidgetInfo> recommendedWidgets = mCallback.mRecommendedWidgets.items
+                    .stream()
+                    .map(itemInfo -> (PendingAddWidgetInfo) itemInfo)
+                    .collect(Collectors.toList());
+            assertThat(recommendedWidgets).hasSize(2);
+            // Another widget from the same package
+            assertWidgetInfo(recommendedWidgets.get(0).info, mApp4Provider2);
+            assertWidgetInfo(recommendedWidgets.get(1).info, mApp1Provider1);
+        });
     }
 
     private void assertWidgetInfo(
diff --git a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index 9c240f0..298dd6c 100644
--- a/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -53,6 +53,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class OrientationTouchTransformerTest {
@@ -296,7 +298,7 @@
         WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
         doReturn(cachedDisplayInfo).when(wmProxy).getDisplayInfo(any());
         doReturn(windowBounds).when(wmProxy).getRealBounds(any(), any());
-        ArrayMap<CachedDisplayInfo, WindowBounds[]> internalDisplayBounds = new ArrayMap<>();
+        ArrayMap<CachedDisplayInfo, List<WindowBounds>> internalDisplayBounds = new ArrayMap<>();
         doReturn(internalDisplayBounds).when(wmProxy).estimateInternalDisplayBounds(any());
         return new DisplayController.Info(
                 getApplicationContext(), wmProxy, new ArrayMap<>());
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index 7b90ecb..5d820e9 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -42,6 +42,7 @@
 import com.android.launcher3.tapl.Overview;
 import com.android.launcher3.tapl.OverviewActions;
 import com.android.launcher3.tapl.OverviewTask;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
index e8cadab..3317ce1 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
@@ -15,6 +15,7 @@
  */
 package com.android.quickstep;
 
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
@@ -22,6 +23,7 @@
 import android.content.Intent;
 
 import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
 
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 40be480..4ff2f9c 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -20,6 +20,7 @@
 
 import androidx.test.filters.LargeTest;
 
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 
 import org.junit.Test;
diff --git a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
index 83602be..a54dc2d 100644
--- a/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
+++ b/quickstep/tests/src/com/android/quickstep/util/TaskViewSimulatorTest.java
@@ -50,6 +50,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.ArrayList;
+import java.util.List;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class TaskViewSimulatorTest {
@@ -150,7 +153,7 @@
                 WindowBounds wm = new WindowBounds(
                         new Rect(0, 0, mDisplaySize.x, mDisplaySize.y),
                         mDisplayInsets);
-                WindowBounds[] allBounds = new WindowBounds[4];
+                List<WindowBounds> allBounds = new ArrayList<>(4);
                 for (int i = 0; i < 4; i++) {
                     Rect boundsR = new Rect(wm.bounds);
                     Rect insetsR = new Rect(wm.insets);
@@ -158,7 +161,7 @@
                     RotationUtils.rotateRect(insetsR, RotationUtils.deltaRotation(rotation, i));
                     RotationUtils.rotateRect(boundsR, RotationUtils.deltaRotation(rotation, i));
                     boundsR.set(0, 0, Math.abs(boundsR.width()), Math.abs(boundsR.height()));
-                    allBounds[i] = new WindowBounds(boundsR, insetsR);
+                    allBounds.add(new WindowBounds(boundsR, insetsR));
                 }
 
                 WindowManagerProxy wmProxy = mock(WindowManagerProxy.class);
@@ -166,7 +169,7 @@
                 doReturn(wm).when(wmProxy).getRealBounds(any(), any());
                 doReturn(NavigationMode.NO_BUTTON).when(wmProxy).getNavigationMode(any());
 
-                ArrayMap<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache =
+                ArrayMap<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache =
                         new ArrayMap<>();
                 perDisplayBoundsCache.put(cdi.normalize(), allBounds);
 
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index f920d75..05d434e 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -210,7 +210,7 @@
             setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
             setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
             defaultIconSize = grid.iconSizePx;
-            setCenterVertically(grid.isScalableGrid);
+            setCenterVertically(grid.iconCenterVertically);
         } else if (mDisplay == DISPLAY_ALL_APPS) {
             setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
             setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 108e557..3d715e5 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -35,7 +35,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.launcher3.anim.Interpolators;
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragOptions;
@@ -258,7 +258,7 @@
 
         dragLayer.animateView(d.dragView, to, scale, 0.1f, 0.1f,
                 DRAG_VIEW_DROP_DURATION,
-                Interpolators.DEACCEL_2, onAnimationEndRunnable,
+                Interpolators.DECELERATE_2, onAnimationEndRunnable,
                 DragLayer.ANIMATION_END_DISAPPEAR, null);
     }
 
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 61b2748..32421a4 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -18,8 +18,8 @@
 
 import static android.animation.ValueAnimator.areAnimatorsEnabled;
 
+import static com.android.app.animation.Interpolators.DECELERATE_1_5;
 import static com.android.launcher3.LauncherState.EDIT_MODE;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
 import static com.android.launcher3.dragndrop.DraggableView.DRAGGABLE_ICON;
 import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
 import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_REORDER_BOUNCE_OFFSET;
@@ -60,9 +60,9 @@
 import androidx.core.graphics.ColorUtils;
 import androidx.core.view.ViewCompat;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
 import com.android.launcher3.celllayout.CellPosMapper.CellPos;
 import com.android.launcher3.celllayout.ReorderAlgorithm;
@@ -272,7 +272,7 @@
         mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * deviceProfile.iconSizePx);
 
         // Initialize the data structures used for the drag visualization.
-        mEaseOutInterpolator = Interpolators.DEACCEL_2_5; // Quint ease out
+        mEaseOutInterpolator = Interpolators.DECELERATE_QUINT; // Quint ease out
         mDragCell[0] = mDragCell[1] = -1;
         mDragCellSpan[0] = mDragCellSpan[1] = -1;
         for (int i = 0; i < mDragOutlines.length; i++) {
@@ -1606,7 +1606,7 @@
             ValueAnimator va = ObjectAnimator.ofFloat(this, ANIMATION_PROGRESS,
                     animationProgress, 0);
             a = va;
-            a.setInterpolator(DEACCEL_1_5);
+            a.setInterpolator(DECELERATE_1_5);
             a.setDuration(REORDER_ANIMATION_DURATION);
             a.start();
         }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index fb41044..c08dd1d 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -16,13 +16,13 @@
 
 package com.android.launcher3;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 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;
 import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
 import static com.android.launcher3.Utilities.dpiFromPx;
 import static com.android.launcher3.Utilities.pxFromSp;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_MULTI_DISPLAY_PARTIAL_DEPTH;
 import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
 import static com.android.launcher3.icons.GraphicsUtils.getShapePath;
@@ -103,7 +103,7 @@
 
     public final float aspectRatio;
 
-    public final boolean isScalableGrid;
+    private final boolean mIsScalableGrid;
     private final int mTypeIndex;
 
     // Responsive grid
@@ -152,13 +152,14 @@
     public int iconTextSizePx;
     public int iconDrawablePaddingPx;
     public int iconDrawablePaddingOriginalPx;
+    public boolean iconCenterVertically;
 
     public float cellScaleToFit;
     public int cellWidthPx;
     public int cellHeightPx;
     public int workspaceCellPaddingXPx;
 
-    public int cellYPaddingPx;
+    public int cellYPaddingPx = -1;
 
     // Folder
     public float folderLabelTextScale;
@@ -305,7 +306,7 @@
         // TODO(b/241386436): shouldn't change any launcher behaviour
         mIsResponsiveGrid = inv.workspaceSpecsId != INVALID_RESOURCE_HANDLE;
 
-        isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
+        mIsScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode;
         // Determine device posture.
         mInfo = info;
         isTablet = info.isTablet(windowBounds);
@@ -342,14 +343,6 @@
             }
         }
 
-        if (mIsResponsiveGrid) {
-            mWorkspaceSpecs = new WorkspaceSpecs(new ResourceHelper(context, inv.workspaceSpecsId));
-            mResponsiveWidthSpec = mWorkspaceSpecs.getCalculatedWidthSpec(inv.numColumns,
-                    availableWidthPx);
-            mResponsiveHeightSpec = mWorkspaceSpecs.getCalculatedHeightSpec(inv.numRows,
-                    availableHeightPx);
-        }
-
         if (DisplayController.isTransientTaskbar(context)) {
             float invTransientIconSizeDp = inv.transientTaskbarIconSize[mTypeIndex];
             taskbarIconSize = pxFromDp(invTransientIconSizeDp, mMetrics);
@@ -372,8 +365,6 @@
         edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
         workspaceContentScale = res.getFloat(R.dimen.workspace_content_scale);
 
-        desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
-        desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
         gridVisualizationPaddingX = res.getDimensionPixelSize(
                 R.dimen.grid_visualization_horizontal_cell_spacing);
         gridVisualizationPaddingY = res.getDimensionPixelSize(
@@ -406,7 +397,7 @@
 
         folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
 
-        if (isScalableGrid && inv.folderStyle != INVALID_RESOURCE_HANDLE) {
+        if (mIsScalableGrid && inv.folderStyle != INVALID_RESOURCE_HANDLE) {
             TypedArray folderStyle = context.obtainStyledAttributes(inv.folderStyle,
                     R.styleable.FolderStyle);
             // These are re-set in #updateFolderCellSize if the grid is not scalable
@@ -428,8 +419,6 @@
             folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_top_padding_default);
         }
 
-        cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv);
-        cellLayoutBorderSpaceOriginalPx = new Point(cellLayoutBorderSpacePx);
         allAppsBorderSpacePx = new Point(
                 pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].x, mMetrics),
                 pxFromDp(inv.allAppsBorderSpaces[mTypeIndex].y, mMetrics));
@@ -479,7 +468,7 @@
                 || inv.inlineQsb[INDEX_TWO_PANEL_LANDSCAPE]
                 : inv.inlineQsb[INDEX_DEFAULT] || inv.inlineQsb[INDEX_LANDSCAPE])
                 && hotseatQsbHeight > 0;
-        isQsbInline = isScalableGrid && inv.inlineQsb[mTypeIndex] && canQsbInline;
+        isQsbInline = mIsScalableGrid && inv.inlineQsb[mTypeIndex] && canQsbInline;
 
         areNavButtonsInline = isTaskbarPresent && !isGestureMode;
         numShownHotseatIcons =
@@ -534,6 +523,21 @@
             hotseatBarEndOffset = 0;
         }
 
+        // Needs to be calculated after hotseatBarSizePx is correct,
+        // for the available height to be correct
+        if (mIsResponsiveGrid) {
+            mWorkspaceSpecs = new WorkspaceSpecs(new ResourceHelper(context, inv.workspaceSpecsId));
+            mResponsiveWidthSpec = mWorkspaceSpecs.getCalculatedWidthSpec(inv.numColumns,
+                    availableWidthPx);
+            mResponsiveHeightSpec = mWorkspaceSpecs.getCalculatedHeightSpec(inv.numRows,
+                    // don't use availableHeightPx because it subtracts bottom padding,
+                    // but the hotseat go behind it
+                    heightPx - mInsets.top - hotseatBarSizePx);
+        }
+
+        desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
+        desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
+
         overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin);
         overviewTaskIconSizePx = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
         overviewTaskIconDrawableSizePx =
@@ -554,21 +558,7 @@
         // Calculate all of the remaining variables.
         extraSpace = updateAvailableDimensions(res);
 
-        // Now that we have all of the variables calculated, we can tune certain sizes.
-        if (isScalableGrid && inv.devicePaddingId != INVALID_RESOURCE_HANDLE) {
-            // Paddings were created assuming no scaling, so we first unscale the extra space.
-            int unscaledExtraSpace = (int) (extraSpace / cellScaleToFit);
-            DevicePaddings devicePaddings = new DevicePaddings(context, inv.devicePaddingId);
-            DevicePadding padding = devicePaddings.getDevicePadding(unscaledExtraSpace);
-            maxEmptySpace = padding.getMaxEmptySpacePx();
-
-            int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
-            int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
-            int paddingHotseatBottom = padding.getHotseatBottomPadding(unscaledExtraSpace);
-
-            workspaceTopPadding = Math.round(paddingWorkspaceTop * cellScaleToFit);
-            workspaceBottomPadding = Math.round(paddingWorkspaceBottom * cellScaleToFit);
-        }
+        calculateAndSetWorkspaceVerticalPadding(context, inv, extraSpace);
 
         int cellLayoutPadding =
                 isTwoPanels ? cellLayoutBorderSpacePx.x / 2 : res.getDimensionPixelSize(
@@ -649,15 +639,40 @@
     }
 
     private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
+        if (mIsResponsiveGrid) {
+            return mResponsiveWidthSpec.getStartPaddingPx();
+        }
+
         if (isVerticalBarLayout()) {
             return 0;
         }
 
-        return isScalableGrid
+        return mIsScalableGrid
                 ? pxFromDp(idp.horizontalMargin[mTypeIndex], mMetrics)
                 : res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin);
     }
 
+    private void calculateAndSetWorkspaceVerticalPadding(Context context,
+            InvariantDeviceProfile inv,
+            int extraSpace) {
+        if (mIsResponsiveGrid) {
+            workspaceTopPadding = mResponsiveHeightSpec.getStartPaddingPx();
+            workspaceBottomPadding = mResponsiveHeightSpec.getEndPaddingPx();
+        } else if (mIsScalableGrid && inv.devicePaddingId != INVALID_RESOURCE_HANDLE) {
+            // Paddings were created assuming no scaling, so we first unscale the extra space.
+            int unscaledExtraSpace = (int) (extraSpace / cellScaleToFit);
+            DevicePaddings devicePaddings = new DevicePaddings(context, inv.devicePaddingId);
+            DevicePadding padding = devicePaddings.getDevicePadding(unscaledExtraSpace);
+            maxEmptySpace = padding.getMaxEmptySpacePx();
+
+            int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
+            int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
+
+            workspaceTopPadding = Math.round(paddingWorkspaceTop * cellScaleToFit);
+            workspaceBottomPadding = Math.round(paddingWorkspaceBottom * cellScaleToFit);
+        }
+    }
+
     /** Updates hotseatCellHeightPx and hotseatBarSizePx */
     private void updateHotseatSizes(int hotseatIconSizePx) {
         // Ensure there is enough space for folder icons, which have a slightly larger radius.
@@ -682,7 +697,7 @@
      * necessary.
      */
     public void recalculateHotseatWidthAndBorderSpace() {
-        if (!isScalableGrid) return;
+        if (!mIsScalableGrid) return;
 
         int columns = inv.hotseatColumnSpan[mTypeIndex];
         float hotseatWidthPx = getIconToIconWidthForColumns(columns);
@@ -735,12 +750,16 @@
     }
 
     private Point getCellLayoutBorderSpace(InvariantDeviceProfile idp, float scale) {
-        if (!isScalableGrid) {
-            return new Point(0, 0);
-        }
+        int horizontalSpacePx = 0;
+        int verticalSpacePx = 0;
 
-        int horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics, scale);
-        int verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics, scale);
+        if (mIsResponsiveGrid) {
+            horizontalSpacePx = mResponsiveWidthSpec.getGutterPx();
+            verticalSpacePx = mResponsiveHeightSpec.getGutterPx();
+        } else if (mIsScalableGrid) {
+            horizontalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].x, mMetrics, scale);
+            verticalSpacePx = pxFromDp(idp.borderSpaces[mTypeIndex].y, mMetrics, scale);
+        }
 
         return new Point(horizontalSpacePx, verticalSpacePx);
     }
@@ -861,6 +880,7 @@
         float invIconTextSizeSp = inv.iconTextSize[mTypeIndex];
         iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics));
         iconTextSizePx = pxFromSp(invIconTextSizeSp, mMetrics);
+        iconCenterVertically = mIsScalableGrid || mIsResponsiveGrid;
 
         updateIconSize(1f, res);
 
@@ -874,7 +894,7 @@
         boolean shouldScale = scaleY < 1f;
 
         float scaleX = 1f;
-        if (isScalableGrid) {
+        if (mIsScalableGrid) {
             // We scale to fit the cellWidth and cellHeight in the available space.
             // The benefit of scalable grids is that we can get consistent aspect ratios between
             // devices.
@@ -919,8 +939,18 @@
         final boolean isVerticalLayout = isVerticalBarLayout();
         iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * iconScale);
         cellLayoutBorderSpacePx = getCellLayoutBorderSpace(inv, scale);
+        int cellTextAndPaddingHeight =
+                iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx);
 
-        if (isScalableGrid) {
+        if (mIsResponsiveGrid) {
+            int cellContentHeight = iconSizePx + cellTextAndPaddingHeight;
+
+            cellWidthPx = mResponsiveWidthSpec.getCellSizePx();
+            cellHeightPx = mResponsiveHeightSpec.getCellSizePx();
+            cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
+
+            // TODO(b/283929701): decrease icon size if content doesn't fit on cell
+        } else if (mIsScalableGrid) {
             cellWidthPx = pxFromDp(inv.minCellSize[mTypeIndex].x, mMetrics, scale);
             cellHeightPx = pxFromDp(inv.minCellSize[mTypeIndex].y, mMetrics, scale);
 
@@ -942,8 +972,6 @@
                 }
             }
 
-            int cellTextAndPaddingHeight =
-                    iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx);
             int cellContentHeight = iconSizePx + cellTextAndPaddingHeight;
             if (cellHeightPx < cellContentHeight) {
                 // If cellHeight no longer fit iconSize, reduce borderSpace to make cellHeight
@@ -1041,7 +1069,7 @@
                 + allAppsBorderSpacePx.y;
         // but width is just the cell,
         // the border is added in #updateAllAppsContainerWidth
-        if (isScalableGrid) {
+        if (mIsScalableGrid) {
             allAppsIconSizePx = pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics);
             allAppsIconTextSizePx = pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics);
             allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
@@ -1124,7 +1152,7 @@
 
         int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx);
 
-        if (isScalableGrid) {
+        if (mIsScalableGrid) {
             if (inv.folderStyle == INVALID_RESOURCE_HANDLE) {
                 folderCellWidthPx = roundPxValueFromFloat(getCellSize().x * scale);
                 folderCellHeightPx = roundPxValueFromFloat(getCellSize().y * scale);
@@ -1299,10 +1327,12 @@
         } else {
             // Pad the bottom of the workspace with hotseat bar
             // and leave a bit of space in case a widget go all the way down
-            int paddingBottom = hotseatBarSizePx + workspaceBottomPadding
-                    + workspacePageIndicatorHeight - mWorkspacePageIndicatorOverlapWorkspace
-                    - mInsets.bottom;
-            int paddingTop = workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx);
+            int paddingBottom = hotseatBarSizePx + workspaceBottomPadding - mInsets.bottom;
+            if (!mIsResponsiveGrid) {
+                paddingBottom +=
+                        workspacePageIndicatorHeight - mWorkspacePageIndicatorOverlapWorkspace;
+            }
+            int paddingTop = workspaceTopPadding + (mIsScalableGrid ? 0 : edgeMarginPx);
             int paddingSide = desiredWorkspaceHorizontalMarginPx;
 
             padding.set(paddingSide, paddingTop, paddingSide, paddingBottom);
@@ -1378,7 +1408,7 @@
                 hotseatBarPadding.right = endSpacing;
             }
 
-        } else if (isScalableGrid) {
+        } else if (mIsScalableGrid) {
             int sideSpacing = (availableWidthPx - hotseatQsbWidth) / 2;
             hotseatBarPadding.set(sideSpacing,
                     0,
@@ -1598,7 +1628,7 @@
         writer.println(prefix + "\taspectRatio:" + aspectRatio);
 
         writer.println(prefix + "\tisResponsiveGrid:" + mIsResponsiveGrid);
-        writer.println(prefix + "\tisScalableGrid:" + isScalableGrid);
+        writer.println(prefix + "\tisScalableGrid:" + mIsScalableGrid);
 
         writer.println(prefix + "\tinv.numRows: " + inv.numRows);
         writer.println(prefix + "\tinv.numColumns: " + inv.numColumns);
@@ -1752,6 +1782,10 @@
                 getWorkspaceSpringLoadScale(context)));
         writer.println(prefix + pxToDpStr("getCellLayoutHeight()", getCellLayoutHeight()));
         writer.println(prefix + pxToDpStr("getCellLayoutWidth()", getCellLayoutWidth()));
+        if (mIsResponsiveGrid) {
+            writer.println(prefix + "\tmResponsiveHeightSpec:" + mResponsiveHeightSpec.toString());
+            writer.println(prefix + "\tmResponsiveWidthSpec:" + mResponsiveWidthSpec.toString());
+        }
     }
 
     /** Returns a reduced representation of this DeviceProfile. */
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index addcac9..8bdf61a 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -30,7 +30,7 @@
 import android.view.ViewPropertyAnimator;
 import android.widget.FrameLayout;
 
-import com.android.launcher3.anim.Interpolators;
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragController.DragListener;
 import com.android.launcher3.dragndrop.DragOptions;
@@ -42,7 +42,7 @@
         implements DragListener, Insettable {
 
     protected static final int DEFAULT_DRAG_FADE_DURATION = 175;
-    protected static final TimeInterpolator DEFAULT_INTERPOLATOR = Interpolators.ACCEL;
+    protected static final TimeInterpolator DEFAULT_INTERPOLATOR = Interpolators.ACCELERATE;
 
     private final Runnable mFadeAnimationEndRunnable =
             () -> updateVisibility(DropTargetBar.this);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 0b75c45..db5a27a 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -21,6 +21,7 @@
 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
 
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
 import static com.android.launcher3.AbstractFloatingView.TYPE_FOLDER;
 import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE;
@@ -43,7 +44,6 @@
 import static com.android.launcher3.LauncherState.SPRING_LOADED;
 import static com.android.launcher3.Utilities.postAsyncCallback;
 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
 import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
 import static com.android.launcher3.config.FeatureFlags.MULTI_SELECT_EDIT_MODE;
 import static com.android.launcher3.config.FeatureFlags.SHOW_DOT_PAGINATION;
@@ -1928,7 +1928,7 @@
             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                 addAppWidgetFromDrop((PendingAddWidgetInfo) info);
                 break;
-            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                 processShortcutFromDrop((PendingAddShortcutInfo) info);
                 break;
             default:
@@ -2435,7 +2435,6 @@
             final View view;
             switch (item.itemType) {
                 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
-                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                 case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
                     WorkspaceItemInfo info = (WorkspaceItemInfo) item;
                     view = createShortcut(info);
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 4d15ac7..4b7aeeb 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -62,6 +62,7 @@
 
     public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
     public static final String KEY_ICON_STATE = "pref_icon_shape_path";
+    public static final String KEY_ALL_APPS_OVERVIEW_THRESHOLD = "pref_all_apps_overview_threshold";
 
     // We do not need any synchronization for this variable as its only written on UI thread.
     public static final MainThreadInitializedObject<LauncherAppState> INSTANCE =
@@ -104,6 +105,8 @@
         });
 
         mContext.getSystemService(LauncherApps.class).registerCallback(mModel);
+        mOnTerminateCallback.add(() ->
+                mContext.getSystemService(LauncherApps.class).unregisterCallback(mModel));
 
         SimpleBroadcastReceiver modelChangeReceiver =
                 new SimpleBroadcastReceiver(mModel::onBroadcastIntent);
@@ -123,8 +126,9 @@
         mOnTerminateCallback.add(userChangeListener::close);
 
         LockedUserState.get(context).runOnUserUnlocked(() -> {
-            CustomWidgetManager.INSTANCE.get(mContext)
-                    .setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
+            CustomWidgetManager cwm = CustomWidgetManager.INSTANCE.get(mContext);
+            cwm.setWidgetRefreshCallback(mModel::refreshAndBindWidgetsAndShortcuts);
+            mOnTerminateCallback.add(() -> cwm.setWidgetRefreshCallback(null));
 
             IconObserver observer = new IconObserver();
             SafeCloseable iconChangeTracker = mIconProvider.registerIconChangeListener(
@@ -159,6 +163,7 @@
         mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext),
                 iconCacheFileName != null);
         mOnTerminateCallback.add(mIconCache::close);
+        mOnTerminateCallback.add(mModel::destroy);
     }
 
     private void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
@@ -180,9 +185,6 @@
      */
     @Override
     public void close() {
-        mModel.destroy();
-        mContext.getSystemService(LauncherApps.class).unregisterCallback(mModel);
-        CustomWidgetManager.INSTANCE.get(mContext).setWidgetRefreshCallback(null);
         mOnTerminateCallback.executeAllAndDestroy();
     }
 
diff --git a/src/com/android/launcher3/LauncherPrefs.kt b/src/com/android/launcher3/LauncherPrefs.kt
index c98df1b..177f883 100644
--- a/src/com/android/launcher3/LauncherPrefs.kt
+++ b/src/com/android/launcher3/LauncherPrefs.kt
@@ -275,6 +275,9 @@
 
         const val TASKBAR_PINNING_KEY = "TASKBAR_PINNING_KEY"
         @JvmField val ICON_STATE = nonRestorableItem(LauncherAppState.KEY_ICON_STATE, "", true)
+        @JvmField
+        val ALL_APPS_OVERVIEW_THRESHOLD =
+            nonRestorableItem(LauncherAppState.KEY_ALL_APPS_OVERVIEW_THRESHOLD, 200, true)
         @JvmField val THEMED_ICONS = backedUpItem(Themes.KEY_THEMED_ICONS, false, true)
         @JvmField val PROMISE_ICON_IDS = backedUpItem(InstallSessionHelper.PROMISE_ICON_IDS, "")
         @JvmField val WORK_EDU_STEP = backedUpItem(WorkProfileManager.KEY_WORK_EDU_STEP, 0)
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 7fda326..2397429 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -89,7 +89,9 @@
 
         /**
          * The gesture is an application created shortcut
+         * @deprecated This is no longer supported. Use {@link #ITEM_TYPE_DEEP_SHORTCUT} instead
          */
+        @Deprecated
         public static final int ITEM_TYPE_SHORTCUT = 1;
 
         /**
@@ -213,7 +215,6 @@
         public static final String itemTypeToString(int type) {
             switch(type) {
                 case ITEM_TYPE_APPLICATION: return "APP";
-                case ITEM_TYPE_SHORTCUT: return "SHORTCUT";
                 case ITEM_TYPE_FOLDER: return "FOLDER";
                 case ITEM_TYPE_APPWIDGET: return "WIDGET";
                 case ITEM_TYPE_CUSTOM_APPWIDGET: return "CUSTOMWIDGET";
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 8b124dc..05471ad 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -15,8 +15,8 @@
  */
 package com.android.launcher3;
 
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.DECELERATE_2;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
 import static com.android.launcher3.testing.shared.TestProtocol.ALL_APPS_STATE_ORDINAL;
@@ -90,7 +90,7 @@
     public static final float NO_SCALE = 1;
 
     protected static final PageAlphaProvider DEFAULT_ALPHA_PROVIDER =
-            new PageAlphaProvider(ACCEL_2) {
+            new PageAlphaProvider(ACCELERATE_2) {
                 @Override
                 public float getPageAlpha(int pageIndex) {
                     return 1;
@@ -98,7 +98,7 @@
             };
 
     protected static final PageTranslationProvider DEFAULT_PAGE_TRANSLATION_PROVIDER =
-            new PageTranslationProvider(DEACCEL_2) {
+            new PageTranslationProvider(DECELERATE_2) {
                 @Override
                 public float getPageTranslation(int pageIndex) {
                     return 0;
@@ -319,7 +319,7 @@
             return DEFAULT_ALPHA_PROVIDER;
         }
         final int centerPage = launcher.getWorkspace().getNextPage();
-        return new PageAlphaProvider(ACCEL_2) {
+        return new PageAlphaProvider(ACCELERATE_2) {
             @Override
             public float getPageAlpha(int pageIndex) {
                 return pageIndex != centerPage ? 0 : 1f;
@@ -337,7 +337,7 @@
             return DEFAULT_PAGE_TRANSLATION_PROVIDER;
         }
         final float quarterPageSpacing = launcher.getWorkspace().getPageSpacing() / 4f;
-        return new PageTranslationProvider(DEACCEL_2) {
+        return new PageTranslationProvider(DECELERATE_2) {
             @Override
             public float getPageTranslation(int pageIndex) {
                 boolean isRtl = launcher.getWorkspace().mIsRtl;
diff --git a/src/com/android/launcher3/MotionEventsUtils.java b/src/com/android/launcher3/MotionEventsUtils.java
index 40de003..3228ec6 100644
--- a/src/com/android/launcher3/MotionEventsUtils.java
+++ b/src/com/android/launcher3/MotionEventsUtils.java
@@ -30,6 +30,9 @@
     /** {@link MotionEvent#CLASSIFICATION_MULTI_FINGER_SWIPE} is hidden. */
     public static final int CLASSIFICATION_MULTI_FINGER_SWIPE = 4;
 
+    /** {@link MotionEvent#AXIS_GESTURE_SWIPE_FINGER_COUNT} is hidden. */
+    private static final int AXIS_GESTURE_SWIPE_FINGER_COUNT = 53;
+
     @TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
     public static boolean isTrackpadScroll(MotionEvent event) {
         return ENABLE_TRACKPAD_GESTURE.get()
@@ -43,11 +46,13 @@
     }
 
     public static boolean isTrackpadThreeFingerSwipe(MotionEvent event) {
-        return isTrackpadMultiFingerSwipe(event) && event.getPointerCount() == 3;
+        return isTrackpadMultiFingerSwipe(event) && event.getAxisValue(
+                AXIS_GESTURE_SWIPE_FINGER_COUNT) == 3;
     }
 
     public static boolean isTrackpadFourFingerSwipe(MotionEvent event) {
-        return isTrackpadMultiFingerSwipe(event) && event.getPointerCount() == 4;
+        return isTrackpadMultiFingerSwipe(event) && event.getAxisValue(
+                AXIS_GESTURE_SWIPE_FINGER_COUNT) == 4;
     }
 
     public static boolean isTrackpadMotionEvent(MotionEvent event) {
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index af64b3b..4b4a4a5 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -16,7 +16,7 @@
 
 package com.android.launcher3;
 
-import static com.android.launcher3.anim.Interpolators.SCROLL;
+import static com.android.app.animation.Interpolators.SCROLL;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
 import static com.android.launcher3.touch.OverScroll.OVERSCROLL_DAMP_FACTOR;
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index a0ceefb..ba6dc26 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -154,9 +154,10 @@
                     mBorderSpace);
             // Center the icon/folder
             int cHeight = getCellContentHeight();
-            int cellPaddingY = dp.isScalableGrid && mContainerType == WORKSPACE
-                    ? dp.cellYPaddingPx
-                    : (int) Math.max(0, ((lp.height - cHeight) / 2f));
+            int cellPaddingY =
+                    dp.cellYPaddingPx >= 0 && mContainerType == WORKSPACE
+                            ? dp.cellYPaddingPx
+                            : (int) Math.max(0, ((lp.height - cHeight) / 2f));
 
             // No need to add padding when cell layout border spacing is present.
             boolean noPaddingX =
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 73bb828..52755d4 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -67,9 +67,9 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
 import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
 import com.android.launcher3.celllayout.CellPosMapper;
@@ -562,9 +562,9 @@
         // Change the interpolators such that the fade animation plays before the move animation.
         // This prevents empty adjacent pages to overlay during animation
         mLayoutTransition.setInterpolator(LayoutTransition.DISAPPEARING,
-                Interpolators.clampToProgress(Interpolators.ACCEL_DEACCEL, 0, 0.5f));
+                Interpolators.clampToProgress(Interpolators.ACCELERATE_DECELERATE, 0, 0.5f));
         mLayoutTransition.setInterpolator(LayoutTransition.CHANGE_DISAPPEARING,
-                Interpolators.clampToProgress(Interpolators.ACCEL_DEACCEL, 0.5f, 1));
+                Interpolators.clampToProgress(Interpolators.ACCELERATE_DECELERATE, 0.5f, 1));
 
         mLayoutTransition.disableTransitionType(LayoutTransition.APPEARING);
         mLayoutTransition.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
@@ -1840,7 +1840,6 @@
                 != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION);
         boolean willBecomeShortcut =
                 (info.itemType == ITEM_TYPE_APPLICATION ||
-                        info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
                         info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);
 
         return (aboveShortcut && willBecomeShortcut);
@@ -2759,7 +2758,7 @@
             final PendingAddItemInfo pendingInfo = (PendingAddItemInfo) info;
 
             boolean findNearestVacantCell = true;
-            if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+            if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
                 mTargetCell = findNearestArea(touchXY[0], touchXY[1], spanX, spanY,
                         cellLayout, mTargetCell);
                 float distance = cellLayout.getDistanceFromWorkspaceCellVisualCenter(
@@ -2832,8 +2831,7 @@
             View view;
 
             switch (info.itemType) {
-                case ITEM_TYPE_APPLICATION:
-                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+                case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
                 case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                 case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
                     if (info instanceof WorkspaceItemFactory) {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 565d7da..c04cdfd 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -18,6 +18,9 @@
 
 import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE;
 
+import static com.android.app.animation.Interpolators.ACCELERATE_2;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.ZOOM_OUT;
 import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
@@ -30,9 +33,6 @@
 import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.WORKSPACE_PAGE_INDICATOR;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
 import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
 import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
 import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
@@ -201,7 +201,7 @@
 
         propertySetter.setViewBackgroundColor(mLauncher.getScrimView(),
                 state.getWorkspaceScrimColor(mLauncher),
-                config.getInterpolator(ANIM_SCRIM_FADE, ACCEL_2));
+                config.getInterpolator(ANIM_SCRIM_FADE, ACCELERATE_2));
     }
 
     public void applyChildState(LauncherState state, CellLayout cl, int childIndex) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index d4f152a..6ca084a 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -15,14 +15,14 @@
  */
 package com.android.launcher3.allapps;
 
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 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;
@@ -45,6 +45,7 @@
 import androidx.annotation.FloatRange;
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.Launcher;
@@ -53,7 +54,6 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.config.FeatureFlags;
@@ -380,7 +380,7 @@
 
         // need to decide depending on the release velocity
         Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS,
-                config.userControlled ? LINEAR : DEACCEL_1_7);
+                config.userControlled ? LINEAR : DECELERATE_1_7);
         Animator anim = createSpringAnimation(mProgress, targetProgress);
         anim.setInterpolator(verticalProgressInterpolator);
         anim.addListener(getProgressAnimatorListener());
diff --git a/src/com/android/launcher3/allapps/SearchTransitionController.java b/src/com/android/launcher3/allapps/SearchTransitionController.java
index b01ea53..eb1bc0a 100644
--- a/src/com/android/launcher3/allapps/SearchTransitionController.java
+++ b/src/com/android/launcher3/allapps/SearchTransitionController.java
@@ -20,12 +20,12 @@
 
 import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
 
+import static com.android.app.animation.Interpolators.DECELERATE_1_7;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.clampToProgress;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
 import static com.android.launcher3.anim.AnimatorListeners.forSuccessCallback;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
 
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
@@ -48,7 +48,7 @@
     private static final String LOG_TAG = "SearchTransitionCtrl";
 
     // Interpolator when the user taps the QSB while already in All Apps.
-    private static final Interpolator INTERPOLATOR_WITHIN_ALL_APPS = DEACCEL_1_7;
+    private static final Interpolator INTERPOLATOR_WITHIN_ALL_APPS = DECELERATE_1_7;
     // Interpolator when the user taps the QSB from home screen, so transition to all apps is
     // happening simultaneously.
     private static final Interpolator INTERPOLATOR_TRANSITIONING_TO_ALL_APPS = INSTANT;
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index 1cc0c21..d11a51f 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -15,10 +15,10 @@
  */
 package com.android.launcher3.anim;
 
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.Utilities.boundToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
 
 import android.animation.Animator;
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
deleted file mode 100644
index e886543..0000000
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ /dev/null
@@ -1,237 +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.anim;
-
-import android.graphics.Path;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.OvershootInterpolator;
-import android.view.animation.PathInterpolator;
-
-import com.android.launcher3.Utilities;
-
-/**
- * Common interpolators used in Launcher
- */
-public class Interpolators {
-
-    public static final Interpolator LINEAR = new LinearInterpolator();
-
-    public static final Interpolator ACCEL = new AccelerateInterpolator();
-    public static final Interpolator ACCEL_0_5 = new AccelerateInterpolator(0.5f);
-    public static final Interpolator ACCEL_0_75 = new AccelerateInterpolator(0.75f);
-    public static final Interpolator ACCEL_1_5 = new AccelerateInterpolator(1.5f);
-    public static final Interpolator ACCEL_2 = new AccelerateInterpolator(2);
-
-    public static final Interpolator DEACCEL = new DecelerateInterpolator();
-    public static final Interpolator DEACCEL_1_5 = new DecelerateInterpolator(1.5f);
-    public static final Interpolator DEACCEL_1_7 = new DecelerateInterpolator(1.7f);
-    public static final Interpolator DEACCEL_2 = new DecelerateInterpolator(2);
-    public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f);
-    public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f);
-
-    public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator();
-
-    public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
-
-    public static final Interpolator AGGRESSIVE_EASE = new PathInterpolator(0.2f, 0f, 0f, 1f);
-    public static final Interpolator AGGRESSIVE_EASE_IN_OUT = new PathInterpolator(0.6f,0, 0.4f, 1);
-
-    public static final Interpolator DECELERATED_EASE = new PathInterpolator(0, 0, .2f, 1f);
-    public static final Interpolator ACCELERATED_EASE = new PathInterpolator(0.4f, 0, 1f, 1f);
-    public static final Interpolator PREDICTIVE_BACK_DECELERATED_EASE =
-            new PathInterpolator(0, 0, 0, 1f);
-
-    /**
-     * The default emphasized interpolator. Used for hero / emphasized movement of content.
-     */
-    public static final Interpolator EMPHASIZED = createEmphasizedInterpolator();
-    public static final Interpolator EMPHASIZED_ACCELERATE = new PathInterpolator(
-            0.3f, 0f, 0.8f, 0.15f);
-    public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
-            0.05f, 0.7f, 0.1f, 1f);
-
-    public static final Interpolator EXAGGERATED_EASE;
-
-    public static final Interpolator INSTANT = t -> 1;
-    /**
-     * All values of t map to 0 until t == 1. This is primarily useful for setting view visibility,
-     * which should only happen at the very end of the animation (when it's already hidden).
-     */
-    public static final Interpolator FINAL_FRAME = t -> t < 1 ? 0 : 1;
-
-    static {
-        Path exaggeratedEase = new Path();
-        exaggeratedEase.moveTo(0, 0);
-        exaggeratedEase.cubicTo(0.05f, 0f, 0.133333f, 0.08f, 0.166666f, 0.4f);
-        exaggeratedEase.cubicTo(0.225f, 0.94f, 0.5f, 1f, 1f, 1f);
-        EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
-    }
-
-    public static final Interpolator OVERSHOOT_0_75 = new OvershootInterpolator(0.75f);
-    public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
-    public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);
-
-    public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
-            new PathInterpolator(0.3f, 0f, 0.1f, 1f);
-    public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL =
-            v -> ACCEL_DEACCEL.getInterpolation(TOUCH_RESPONSE_INTERPOLATOR.getInterpolation(v));
-
-    /**
-     * Inversion of ZOOM_OUT, compounded with an ease-out.
-     */
-    public static final Interpolator ZOOM_IN = new Interpolator() {
-        @Override
-        public float getInterpolation(float v) {
-            return DEACCEL_3.getInterpolation(1 - ZOOM_OUT.getInterpolation(1 - v));
-        }
-    };
-
-    public static final Interpolator ZOOM_OUT = new Interpolator() {
-
-        private static final float FOCAL_LENGTH = 0.35f;
-
-        @Override
-        public float getInterpolation(float v) {
-            return zInterpolate(v);
-        }
-
-        /**
-         * This interpolator emulates the rate at which the perceived scale of an object changes
-         * as its distance from a camera increases. When this interpolator is applied to a scale
-         * animation on a view, it evokes the sense that the object is shrinking due to moving away
-         * from the camera.
-         */
-        private float zInterpolate(float input) {
-            return (1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + input)) /
-                    (1.0f - FOCAL_LENGTH / (FOCAL_LENGTH + 1.0f));
-        }
-    };
-
-    public static final Interpolator SCROLL = new Interpolator() {
-        @Override
-        public float getInterpolation(float t) {
-            t -= 1.0f;
-            return t*t*t*t*t + 1;
-        }
-    };
-
-    public static final Interpolator SCROLL_CUBIC = new Interpolator() {
-        @Override
-        public float getInterpolation(float t) {
-            t -= 1.0f;
-            return t*t*t + 1;
-        }
-    };
-
-    private static final float FAST_FLING_PX_MS = 10;
-
-    public static Interpolator scrollInterpolatorForVelocity(float velocity) {
-        return Math.abs(velocity) > FAST_FLING_PX_MS ? SCROLL : SCROLL_CUBIC;
-    }
-
-    /**
-     * Create an OvershootInterpolator with tension directly related to the velocity (in px/ms).
-     * @param velocity The start velocity of the animation we want to overshoot.
-     */
-    public static Interpolator overshootInterpolatorForVelocity(float velocity) {
-        return new OvershootInterpolator(Math.min(Math.abs(velocity), 3f));
-    }
-
-    /**
-     * Returns a function that runs the given interpolator such that the entire progress is set
-     * between the given bounds. That is, we set the interpolation to 0 until lowerBound and reach
-     * 1 by upperBound.
-     */
-    public static Interpolator clampToProgress(Interpolator interpolator, float lowerBound,
-            float upperBound) {
-        if (upperBound < lowerBound) {
-            throw new IllegalArgumentException(
-                    String.format("upperBound (%f) must be greater than lowerBound (%f)",
-                            upperBound, lowerBound));
-        }
-        return t -> clampToProgress(interpolator, t, lowerBound, upperBound);
-    }
-
-    /**
-     * Returns the progress value's progress between the lower and upper bounds. That is, the
-     * progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
-     *
-     * Between lowerBound and upperBound, the progress value will be interpolated using the provided
-     * interpolator.
-     */
-    public static float clampToProgress(
-            Interpolator interpolator, float progress, float lowerBound, float upperBound) {
-        if (upperBound < lowerBound) {
-            throw new IllegalArgumentException(
-                    String.format("upperBound (%f) must be greater than lowerBound (%f)",
-                            upperBound, lowerBound));
-        }
-
-        if (progress == lowerBound && progress == upperBound) {
-            return progress == 0f ? 0 : 1;
-        }
-        if (progress < lowerBound) {
-            return 0;
-        }
-        if (progress > upperBound) {
-            return 1;
-        }
-        return interpolator.getInterpolation((progress - lowerBound) / (upperBound - lowerBound));
-    }
-
-    /**
-     * Returns the progress value's progress between the lower and upper bounds. That is, the
-     * progress will be 0f from 0f to lowerBound, and reach 1f by upperBound.
-     */
-    public static float clampToProgress(float progress, float lowerBound, float upperBound) {
-        return clampToProgress(Interpolators.LINEAR, progress, lowerBound, upperBound);
-    }
-
-    /**
-     * Runs the given interpolator such that the interpolated value is mapped to the given range.
-     * This is useful, for example, if we only use this interpolator for part of the animation,
-     * such as to take over a user-controlled animation when they let go.
-     */
-    public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
-            float upperBound) {
-        return t -> Utilities.mapRange(interpolator.getInterpolation(t), lowerBound, upperBound);
-    }
-
-    /**
-     * Returns the reverse of the provided interpolator, following the formula: g(x) = 1 - f(1 - x).
-     * In practice, this means that if f is an interpolator used to model a value animating between
-     * m and n, g is the interpolator to use to obtain the specular behavior when animating from n
-     * to m.
-     */
-    public static Interpolator reverse(Interpolator interpolator) {
-        return t -> 1 - interpolator.getInterpolation(1 - t);
-    }
-
-    // Create the default emphasized interpolator
-    private static PathInterpolator createEmphasizedInterpolator() {
-        Path path = new Path();
-        // Doing the same as fast_out_extra_slow_in
-        path.moveTo(0f, 0f);
-        path.cubicTo(0.05f, 0f, 0.133333f, 0.06f, 0.166666f, 0.4f);
-        path.cubicTo(0.208333f, 0.82f, 0.25f, 1f, 1f, 1f);
-        return new PathInterpolator(path);
-    }
-}
diff --git a/src/com/android/launcher3/anim/SpringAnimationBuilder.java b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
index 40fa0cf..bc7b7f0 100644
--- a/src/com/android/launcher3/anim/SpringAnimationBuilder.java
+++ b/src/com/android/launcher3/anim/SpringAnimationBuilder.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.anim;
 
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.LINEAR;
 
 import android.animation.Animator;
 import android.animation.ValueAnimator;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index f88ff86..8a01ea2 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -82,9 +82,6 @@
      * <p>
      */
     // TODO(Block 1): Clean up flags
-    public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = getReleaseFlag(270394223,
-            "ENABLE_ONE_SEARCH_MOTION", ENABLED, "Enables animations in OneSearch.");
-
     public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
             270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", DISABLED,
             "Enable option to replace decorator-based search result backgrounds with drawables");
@@ -253,6 +250,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 =
+            getDebugFlag(282993230, "ENABLE_LONG_PRESS_NAV_HANDLE", DISABLED,
+                    "Enables long pressing on the bottom bar nav handle to trigger events.");
+
     // TODO(Block 17): Clean up flags
     public static final BooleanFlag ENABLE_TASKBAR_PINNING = getDebugFlag(270396583,
             "ENABLE_TASKBAR_PINNING", DISABLED,
@@ -313,7 +314,7 @@
             "Enable a grid-only overview without a focused task.");
 
     public static final BooleanFlag ENABLE_CURSOR_HOVER_STATES = getDebugFlag(243191650,
-            "ENABLE_CURSOR_HOVER_STATES", DISABLED,
+            "ENABLE_CURSOR_HOVER_STATES", ENABLED,
             "Enables cursor hover states for certain elements.");
 
     // TODO(Block 24): Clean up flags
@@ -381,7 +382,7 @@
             "Enable initiating split screen from workspace to workspace.");
 
     public static final BooleanFlag ENABLE_TRACKPAD_GESTURE = getDebugFlag(271010401,
-            "ENABLE_TRACKPAD_GESTURE", DISABLED, "Enables trackpad gesture.");
+            "ENABLE_TRACKPAD_GESTURE", ENABLED, "Enables trackpad gesture.");
 
     // TODO(Block 29): Clean up flags
     public static final BooleanFlag ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT = getDebugFlag(270393897,
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 9867268..0d51d48 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -28,9 +28,9 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.DragSource;
 import com.android.launcher3.DropTarget;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index 366870b..f18f900 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -19,11 +19,11 @@
 
 import static android.animation.ObjectAnimator.ofFloat;
 
+import static com.android.app.animation.Interpolators.DECELERATE_1_5;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.Utilities.mapRange;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
 import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
 
 import android.animation.Animator;
@@ -42,6 +42,7 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.animation.Interpolator;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DropTargetBar;
 import com.android.launcher3.Launcher;
@@ -49,7 +50,6 @@
 import com.android.launcher3.ShortcutAndWidgetContainer;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.SpringProperty;
 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
@@ -340,14 +340,14 @@
         if (duration < 0) {
             duration = res.getInteger(R.integer.config_dropAnimMaxDuration);
             if (dist < maxDist) {
-                duration *= DEACCEL_1_5.getInterpolation(dist / maxDist);
+                duration *= DECELERATE_1_5.getInterpolation(dist / maxDist);
             }
             duration = Math.max(duration, res.getInteger(R.integer.config_dropAnimMinDuration));
         }
 
         // Fall back to cubic ease out interpolator for the animation if none is specified
         TimeInterpolator interpolator =
-                motionInterpolator == null ? DEACCEL_1_5 : motionInterpolator;
+                motionInterpolator == null ? DECELERATE_1_5 : motionInterpolator;
 
         // Animate the view
         PendingAnimation anim = new PendingAnimation(duration);
@@ -475,7 +475,7 @@
 
     @Override
     public void onOverlayScrollChanged(float progress) {
-        float alpha = 1 - Interpolators.DEACCEL_3.getInterpolation(progress);
+        float alpha = 1 - Interpolators.DECELERATE_3.getInterpolation(progress);
         float transX = getMeasuredWidth() * progress;
 
         if (mIsRtl) {
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index 0d0717e..c26d673 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -55,9 +55,9 @@
 import androidx.dynamicanimation.animation.SpringAnimation;
 import androidx.dynamicanimation.animation.SpringForce;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.data.ItemInfo;
@@ -371,7 +371,7 @@
         AnimatorSet anim = new AnimatorSet();
         anim.play(ObjectAnimator.ofFloat(newContent, VIEW_ALPHA, 0, 1));
         anim.play(ObjectAnimator.ofFloat(mContent, VIEW_ALPHA, 0));
-        anim.setDuration(duration).setInterpolator(Interpolators.DEACCEL_1_5);
+        anim.setDuration(duration).setInterpolator(Interpolators.DECELERATE_1_5);
         anim.start();
     }
 
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 4ae54e6..f38cce1 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -881,7 +881,6 @@
         final ItemInfo item = d.dragInfo;
         final int itemType = item.itemType;
         return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
-                itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
                 itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT));
     }
 
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 2c1100f..d78bfba 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -42,6 +42,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.Alarm;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.CellLayout;
@@ -56,7 +57,6 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.allapps.ActivityAllAppsContainerView;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.celllayout.CellLayoutLayoutParams;
 import com.android.launcher3.dot.FolderDotInfo;
 import com.android.launcher3.dragndrop.BaseItemDragListener;
@@ -260,7 +260,6 @@
     private boolean willAcceptItem(ItemInfo item) {
         final int itemType = item.itemType;
         return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
-                itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
                 itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) &&
                 item != mInfo && !mFolder.isOpen());
     }
@@ -407,7 +406,7 @@
             final int finalIndex = index;
             dragLayer.animateView(animateView, to, finalAlpha,
                     finalScale, finalScale, DROP_IN_ANIMATION_DURATION,
-                    Interpolators.DEACCEL_2,
+                    Interpolators.DECELERATE_2,
                     () -> {
                         mPreviewItemManager.hidePreviewItem(finalIndex, false);
                         mFolder.showItem(item);
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index 47677ea..7241b17 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -34,13 +34,9 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.Context;
 import android.content.ContextWrapper;
-import android.content.Intent;
 import android.content.res.TypedArray;
-import android.graphics.Color;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.graphics.drawable.AdaptiveIconDrawable;
-import android.graphics.drawable.ColorDrawable;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -78,8 +74,6 @@
 import com.android.launcher3.celllayout.CellPosMapper;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.folder.FolderIcon;
-import com.android.launcher3.icons.BaseIconFactory;
-import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -183,7 +177,6 @@
     private final DeviceProfile mDp;
     private final DeviceProfile mDpOrig;
     private final Rect mInsets;
-    private final WorkspaceItemInfo mWorkspaceItemInfo;
     private final LayoutInflater mHomeElementInflater;
     private final InsettableFrameLayout mRootView;
     private final Hotseat mHotseat;
@@ -221,19 +214,6 @@
                 mDp.isTaskbarPresent ? 0 : currentWindowInsets.getSystemWindowInsetBottom());
         mDp.updateInsets(mInsets);
 
-        BaseIconFactory iconFactory =
-                new BaseIconFactory(context, mIdp.fillResIconDpi, mIdp.iconBitmapSize) { };
-        BitmapInfo iconInfo = iconFactory.createBadgedIconBitmap(
-                new AdaptiveIconDrawable(
-                        new ColorDrawable(Color.WHITE),
-                        new ColorDrawable(Color.WHITE)));
-
-        mWorkspaceItemInfo = new WorkspaceItemInfo();
-        mWorkspaceItemInfo.bitmap = iconInfo;
-        mWorkspaceItemInfo.intent = new Intent();
-        mWorkspaceItemInfo.contentDescription = mWorkspaceItemInfo.title =
-                context.getString(R.string.label_application);
-
         mHomeElementInflater = LayoutInflater.from(
                 new ContextThemeWrapper(this, R.style.HomeScreenElementTheme));
         mHomeElementInflater.setFactory2(this);
@@ -483,7 +463,6 @@
         for (ItemInfo itemInfo : currentWorkspaceItems) {
             switch (itemInfo.itemType) {
                 case Favorites.ITEM_TYPE_APPLICATION:
-                case Favorites.ITEM_TYPE_SHORTCUT:
                 case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                     inflateAndAddIcon((WorkspaceItemInfo) itemInfo);
                     break;
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index d366c4a..c5c74ac 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,8 +17,8 @@
 
 package com.android.launcher3.graphics;
 
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V3;
 
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 27d1f78..5e86bd6 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -91,8 +91,7 @@
             List<ItemInfo> filteredItems = new ArrayList<>();
             for (Pair<ItemInfo, Object> entry : mItemList) {
                 ItemInfo item = entry.first;
-                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
-                        item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
+                if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
                     // Short-circuit this logic if the icon exists somewhere on the workspace
                     if (shortcutExists(dataModel, item.getIntent(), item.user)) {
                         continue;
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 0861e9d..5b0da5b 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -210,7 +210,6 @@
                     // Fall through.
                 }
                 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
-                case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                     workspaceItems.remove(item);
                     break;
                 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -245,7 +244,6 @@
                 break;
             case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
-            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                 if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
                         item.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                     workspaceItems.add(item);
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index 9a6cde6..9d16610 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -455,7 +455,6 @@
                 try {
                     // calculate weight
                     switch (entry.itemType) {
-                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                         case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                         case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
                             entry.mIntent = c.getString(indexIntent);
@@ -531,7 +530,6 @@
                 try {
                     // calculate weight
                     switch (entry.itemType) {
-                        case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                         case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                         case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: {
                             entry.mIntent = c.getString(indexIntent);
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index fa0511c..9a3abd4 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -286,7 +286,6 @@
 
                     final WorkspaceItemInfo si = new WorkspaceItemInfo();
                     si.user = user;
-                    si.itemType = ITEM_TYPE_APPLICATION;
 
                     LauncherActivityInfo lai;
                     boolean usePackageIcon = laiList.isEmpty();
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 2054d93..33332f0 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -193,9 +193,7 @@
 
     public IconRequestInfo<WorkspaceItemInfo> createIconRequestInfo(
             WorkspaceItemInfo wai, boolean useLowResIcon) {
-        byte[] iconBlob = itemType == Favorites.ITEM_TYPE_SHORTCUT
-                || itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
-                || restoreFlag != 0
+        byte[] iconBlob = itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT || restoreFlag != 0
                 ? getIconBlob() : null;
 
         return new IconRequestInfo<>(wai, mActivityInfo, iconBlob, useLowResIcon);
@@ -347,7 +345,6 @@
         }
 
         final WorkspaceItemInfo info = new WorkspaceItemInfo();
-        info.itemType = Favorites.ITEM_TYPE_APPLICATION;
         info.user = user;
         info.intent = newIntent;
 
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 1a8cf24..d2a8174 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -503,7 +503,6 @@
 
             boolean allowMissingTarget = false;
             switch (c.itemType) {
-                case Favorites.ITEM_TYPE_SHORTCUT:
                 case Favorites.ITEM_TYPE_APPLICATION:
                 case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                     Intent intent = c.parseIntent();
@@ -517,9 +516,8 @@
                     ComponentName cn = intent.getComponent();
                     String targetPkg = cn == null ? intent.getPackage() : cn.getPackageName();
 
-                    if (TextUtils.isEmpty(targetPkg)
-                            && c.itemType != Favorites.ITEM_TYPE_SHORTCUT) {
-                        c.markDeleted("Only legacy shortcuts can have null package");
+                    if (TextUtils.isEmpty(targetPkg)) {
+                        c.markDeleted("Shortcuts can't have null package");
                         return;
                     }
 
diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java
index ddb8b05..f2afaeb 100644
--- a/src/com/android/launcher3/model/ModelWriter.java
+++ b/src/com/android/launcher3/model/ModelWriter.java
@@ -498,7 +498,6 @@
                                 modelItem.container == Favorites.CONTAINER_HOTSEAT)) {
                     switch (modelItem.itemType) {
                         case Favorites.ITEM_TYPE_APPLICATION:
-                        case Favorites.ITEM_TYPE_SHORTCUT:
                         case Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                         case Favorites.ITEM_TYPE_FOLDER:
                             if (!mBgDataModel.workspaceItems.contains(modelItem)) {
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index bfb80b3..1c68292 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -30,7 +30,6 @@
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_TASK;
 import static com.android.launcher3.logger.LauncherAtom.ContainerInfo.ContainerCase.CONTAINER_NOT_SET;
 import static com.android.launcher3.shortcuts.ShortcutKey.EXTRA_SHORTCUT_ID;
@@ -87,7 +86,6 @@
 
     /**
      * One of {@link Favorites#ITEM_TYPE_APPLICATION},
-     * {@link Favorites#ITEM_TYPE_SHORTCUT},
      * {@link Favorites#ITEM_TYPE_DEEP_SHORTCUT}
      * {@link Favorites#ITEM_TYPE_FOLDER},
      * {@link Favorites#ITEM_TYPE_APP_PAIR},
@@ -361,13 +359,6 @@
                                 })
                                 .orElse(LauncherAtom.Shortcut.newBuilder()));
                 break;
-            case ITEM_TYPE_SHORTCUT:
-                itemBuilder
-                        .setShortcut(nullableComponent
-                                .map(component -> LauncherAtom.Shortcut.newBuilder()
-                                        .setShortcutName(component.flattenToShortString()))
-                                .orElse(LauncherAtom.Shortcut.newBuilder()));
-                break;
             case ITEM_TYPE_APPWIDGET:
                 itemBuilder
                         .setWidget(nullableComponent
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 01606d4..3ce194d 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -96,7 +96,7 @@
 
 
     public WorkspaceItemInfo() {
-        itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+        itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
     }
 
     public WorkspaceItemInfo(WorkspaceItemInfo info) {
@@ -205,8 +205,8 @@
     @Override
     public ComponentName getTargetComponent() {
         ComponentName cn = super.getTargetComponent();
-        if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT || hasStatusFlag(
-                FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON))) {
+        if (cn == null && hasStatusFlag(
+                FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON)) {
             // Legacy shortcuts and promise icons with web UI may not have a componentName but just
             // a packageName. In that case create a empty componentName instead of adding additional
             // check everywhere.
diff --git a/src/com/android/launcher3/notification/NotificationContainer.java b/src/com/android/launcher3/notification/NotificationContainer.java
index 9eb05cd..7cc9ad3 100644
--- a/src/com/android/launcher3/notification/NotificationContainer.java
+++ b/src/com/android/launcher3/notification/NotificationContainer.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.notification;
 
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
 
 import android.animation.Animator;
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index 16a4057..ecd018b 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -16,8 +16,8 @@
 
 package com.android.launcher3.notification;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Utilities.mapToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DISMISSED;
 
 import android.animation.AnimatorSet;
diff --git a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
index b24ee34..06da8c5 100644
--- a/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
+++ b/src/com/android/launcher3/pm/ShortcutConfigActivityInfo.java
@@ -72,7 +72,7 @@
     }
 
     public int getItemType() {
-        return LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+        return LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
     }
 
     @Override
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index 72f99cb..08be026 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -18,11 +18,11 @@
 
 import static androidx.core.content.ContextCompat.getColorStateList;
 
-import static com.android.launcher3.anim.Interpolators.ACCELERATED_EASE;
-import static com.android.launcher3.anim.Interpolators.DECELERATED_EASE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.ACCELERATED_EASE;
+import static com.android.app.animation.Interpolators.DECELERATED_EASE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_MATERIAL_U_POPUP;
 
 import android.animation.Animator;
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index e62ccbc..0bb018d 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.testing;
 
 import static com.android.launcher3.allapps.AllAppsStore.DEFER_UPDATES_TEST;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_TRACKPAD_GESTURE;
 import static com.android.launcher3.config.FeatureFlags.FOLDABLE_SINGLE_PAGE;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
@@ -229,7 +230,13 @@
             }
 
             case TestProtocol.REQUEST_HAS_TIS: {
-                response.putBoolean(TestProtocol.REQUEST_HAS_TIS, false);
+                response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD, false);
+                return response;
+            }
+
+            case TestProtocol.REQUEST_IS_TRACKPAD_GESTURE_ENABLED: {
+                response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
+                        ENABLE_TRACKPAD_GESTURE.get());
                 return response;
             }
 
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index c499e35..8bc1c37 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.touch;
 
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
@@ -22,7 +23,6 @@
 import static com.android.launcher3.LauncherState.NORMAL;
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.anim.AnimatorListeners.forEndCallback;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index d028f24..b672bde 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -15,15 +15,15 @@
  */
 package com.android.launcher3.touch;
 
+import static com.android.app.animation.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED_ACCELERATE;
+import static com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.app.animation.Interpolators.FINAL_FRAME;
+import static com.android.app.animation.Interpolators.INSTANT;
+import static com.android.app.animation.Interpolators.LINEAR;
+import static com.android.app.animation.Interpolators.clampToProgress;
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
-import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
-import static com.android.launcher3.anim.Interpolators.INSTANT;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.clampToProgress;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_BOTTOM_SHEET_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
@@ -40,11 +40,11 @@
 import android.view.MotionEvent;
 import android.view.animation.Interpolator;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.states.StateAnimationConfig;
 
 /**
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 6647d0d..a7c94bb 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -54,8 +54,8 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -106,7 +106,8 @@
 
     private final LauncherPrefs mPrefs;
 
-    private DisplayController(Context context) {
+    @VisibleForTesting
+    protected DisplayController(Context context) {
         mContext = context;
         mDM = context.getSystemService(DisplayManager.class);
         mPrefs = LauncherPrefs.get(context);
@@ -127,8 +128,7 @@
         Context displayInfoContext = getDisplayInfoContext(display);
         mInfo = new Info(displayInfoContext, wmProxy,
                 wmProxy.estimateInternalDisplayBounds(displayInfoContext));
-        mInfo.mPerDisplayBounds.forEach((key, value) -> FileLog.i(TAG,
-                "(CTOR) perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
+        FileLog.i(TAG, "(CTOR) perDisplayBounds: " + mInfo.mPerDisplayBounds);
     }
 
     /**
@@ -286,9 +286,8 @@
         if (!newInfo.supportedBounds.equals(oldInfo.supportedBounds)
                 || !newInfo.mPerDisplayBounds.equals(oldInfo.mPerDisplayBounds)) {
             change |= CHANGE_SUPPORTED_BOUNDS;
-            newInfo.mPerDisplayBounds.forEach((key, value) -> FileLog.w(TAG,
-                    "(CHANGE_SUPPORTED_BOUNDS) perDisplayBounds - " + key + ": "
-                            + Arrays.deepToString(value)));
+            FileLog.w(TAG,
+                    "(CHANGE_SUPPORTED_BOUNDS) perDisplayBounds: " + newInfo.mPerDisplayBounds);
         }
         if (DEBUG) {
             Log.d(TAG, "handleInfoChange - change: " + getChangeFlagsString(change));
@@ -329,7 +328,7 @@
         // WindowBounds
         public final WindowBounds realBounds;
         public final Set<WindowBounds> supportedBounds = new ArraySet<>();
-        private final ArrayMap<CachedDisplayInfo, WindowBounds[]> mPerDisplayBounds =
+        private final ArrayMap<CachedDisplayInfo, List<WindowBounds>> mPerDisplayBounds =
                 new ArrayMap<>();
 
         public Info(Context displayInfoContext) {
@@ -340,7 +339,7 @@
         // Used for testing
         public Info(Context displayInfoContext,
                 WindowManagerProxy wmProxy,
-                Map<CachedDisplayInfo, WindowBounds[]> perDisplayBoundsCache) {
+                Map<CachedDisplayInfo, List<WindowBounds>> perDisplayBoundsCache) {
             CachedDisplayInfo displayInfo = wmProxy.getDisplayInfo(displayInfoContext);
             normalizedDisplayInfo = displayInfo.normalize();
             rotation = displayInfo.rotation;
@@ -354,16 +353,14 @@
             navigationMode = wmProxy.getNavigationMode(displayInfoContext);
 
             mPerDisplayBounds.putAll(perDisplayBoundsCache);
-            WindowBounds[] cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
+            List<WindowBounds> cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
 
             realBounds = wmProxy.getRealBounds(displayInfoContext, displayInfo);
             if (cachedValue == null) {
                 // Unexpected normalizedDisplayInfo is found, recreate the cache
                 FileLog.e(TAG, "Unexpected normalizedDisplayInfo found, invalidating cache: "
                         + normalizedDisplayInfo);
-                mPerDisplayBounds.forEach((key, value) -> FileLog.e(TAG,
-                        "(Invalid Cache) perDisplayBounds - " + key + ": " + Arrays.deepToString(
-                                value)));
+                FileLog.e(TAG, "(Invalid Cache) perDisplayBounds : " + mPerDisplayBounds);
                 mPerDisplayBounds.clear();
                 mPerDisplayBounds.putAll(wmProxy.estimateInternalDisplayBounds(displayInfoContext));
                 cachedValue = mPerDisplayBounds.get(normalizedDisplayInfo);
@@ -376,22 +373,19 @@
 
             if (cachedValue != null) {
                 // Verify that the real bounds are a match
-                WindowBounds expectedBounds = cachedValue[displayInfo.rotation];
+                WindowBounds expectedBounds = cachedValue.get(displayInfo.rotation);
                 if (!realBounds.equals(expectedBounds)) {
-                    WindowBounds[] clone = new WindowBounds[4];
-                    System.arraycopy(cachedValue, 0, clone, 0, 4);
-                    clone[displayInfo.rotation] = realBounds;
+                    List<WindowBounds> clone = new ArrayList<>(cachedValue);
+                    clone.set(displayInfo.rotation, realBounds);
                     mPerDisplayBounds.put(normalizedDisplayInfo, clone);
                 }
             }
-            mPerDisplayBounds.values().forEach(
-                    windowBounds -> Collections.addAll(supportedBounds, windowBounds));
+            mPerDisplayBounds.values().forEach(supportedBounds::addAll);
             if (DEBUG) {
                 Log.d(TAG, "displayInfo: " + displayInfo);
                 Log.d(TAG, "realBounds: " + realBounds);
                 Log.d(TAG, "normalizedDisplayInfo: " + normalizedDisplayInfo);
-                mPerDisplayBounds.forEach((key, value) -> Log.d(TAG,
-                        "perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
+                Log.d(TAG, "perDisplayBounds: " + mPerDisplayBounds);
             }
         }
 
@@ -448,7 +442,7 @@
         pw.println("  navigationMode=" + info.navigationMode.name());
         pw.println("  currentSize=" + info.currentSize);
         info.mPerDisplayBounds.forEach((key, value) -> pw.println(
-                "  perDisplayBounds - " + key + ": " + Arrays.deepToString(value)));
+                "  perDisplayBounds - " + key + ": " + value));
     }
 
     /**
diff --git a/src/com/android/launcher3/util/IntArray.java b/src/com/android/launcher3/util/IntArray.java
index 1c78795..2498242 100644
--- a/src/com/android/launcher3/util/IntArray.java
+++ b/src/com/android/launcher3/util/IntArray.java
@@ -250,6 +250,11 @@
         return b.toString();
     }
 
+    @Override
+    public String toString() {
+        return "IntArray [" + toConcatString() + "]";
+    }
+
     public static IntArray fromConcatString(String concatString) {
         StringTokenizer tokenizer = new StringTokenizer(concatString, ",");
         int[] array = new int[tokenizer.countTokens()];
diff --git a/src/com/android/launcher3/util/LockedUserState.kt b/src/com/android/launcher3/util/LockedUserState.kt
index 1231604..0a87594 100644
--- a/src/com/android/launcher3/util/LockedUserState.kt
+++ b/src/com/android/launcher3/util/LockedUserState.kt
@@ -1,3 +1,18 @@
+/*
+ * 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.util
 
 import android.content.Context
diff --git a/src/com/android/launcher3/util/MainThreadInitializedObject.java b/src/com/android/launcher3/util/MainThreadInitializedObject.java
index 6a4e528..1cb9994 100644
--- a/src/com/android/launcher3/util/MainThreadInitializedObject.java
+++ b/src/com/android/launcher3/util/MainThreadInitializedObject.java
@@ -48,8 +48,8 @@
     }
 
     public T get(Context context) {
-        if (context instanceof SandboxContext) {
-            return ((SandboxContext) context).getObject(this, mProvider);
+        if (context instanceof SandboxContext sc) {
+            return sc.getObject(this);
         }
 
         if (mValue == null) {
@@ -131,23 +131,22 @@
          * Find a cached object from mObjectMap if we have already created one. If not, generate
          * an object using the provider.
          */
-        private <T> T getObject(MainThreadInitializedObject<T> object, ObjectProvider<T> provider) {
+        protected <T> T getObject(MainThreadInitializedObject<T> object) {
             synchronized (mDestroyLock) {
                 if (mDestroyed) {
                     Log.e(TAG, "Static object access with a destroyed context");
                 }
-
                 T t = (T) mObjectMap.get(object);
                 if (t != null) {
                     return t;
                 }
                 if (Looper.myLooper() == Looper.getMainLooper()) {
-                    t = createObject(provider);
+                    t = createObject(object);
                     // Check if we've explicitly allowed the object or if it's a SafeCloseable,
                     // it will get destroyed in onDestroy()
                     if (!mAllowedObjects.contains(object) && !(t instanceof SafeCloseable)) {
-                        throw new IllegalStateException(
-                                "Leaking unknown objects " + object + "  " + provider + " " + t);
+                        throw new IllegalStateException("Leaking unknown objects "
+                                + object + "  " + object.mProvider + " " + t);
                     }
                     mObjectMap.put(object, t);
                     mOrderedObjects.add(t);
@@ -156,15 +155,15 @@
             }
 
             try {
-                return MAIN_EXECUTOR.submit(() -> getObject(object, provider)).get();
+                return MAIN_EXECUTOR.submit(() -> getObject(object)).get();
             } catch (InterruptedException | ExecutionException e) {
                 throw new RuntimeException(e);
             }
         }
 
         @UiThread
-        protected <T> T createObject(ObjectProvider<T> provider) {
-            return provider.get(this);
+        protected <T> T createObject(MainThreadInitializedObject<T> object) {
+            return object.mProvider.get(this);
         }
     }
 }
diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
index 4ac6bc4..b97b889 100644
--- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
+++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
@@ -15,9 +15,9 @@
 
 import androidx.annotation.AnyThread;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
-import com.android.launcher3.anim.Interpolators;
 
 /**
  * Utility class to handle wallpaper scrolling along with workspace.
@@ -237,7 +237,7 @@
 
         public OffsetHandler(Context context) {
             super(UI_HELPER_EXECUTOR.getLooper());
-            mInterpolator = Interpolators.DEACCEL_1_5;
+            mInterpolator = Interpolators.DECELERATE_1_5;
             mWM = WallpaperManager.getInstance(context);
         }
 
diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java
index 4093bc9..278a37e 100644
--- a/src/com/android/launcher3/util/window/WindowManagerProxy.java
+++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java
@@ -57,6 +57,9 @@
 import com.android.launcher3.util.ResourceBasedOverride;
 import com.android.launcher3.util.WindowBounds;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Utility class for mocking some window manager behaviours
  */
@@ -90,11 +93,11 @@
      * Returns a map of normalized info of internal displays to estimated window bounds
      * for that display
      */
-    public ArrayMap<CachedDisplayInfo, WindowBounds[]> estimateInternalDisplayBounds(
+    public ArrayMap<CachedDisplayInfo, List<WindowBounds>> estimateInternalDisplayBounds(
             Context displayInfoContext) {
         CachedDisplayInfo info = getDisplayInfo(displayInfoContext).normalize();
-        WindowBounds[] bounds = estimateWindowBounds(displayInfoContext, info);
-        ArrayMap<CachedDisplayInfo, WindowBounds[]> result = new ArrayMap<>();
+        List<WindowBounds> bounds = estimateWindowBounds(displayInfoContext, info);
+        ArrayMap<CachedDisplayInfo, List<WindowBounds>> result = new ArrayMap<>();
         result.put(info, bounds);
         return result;
     }
@@ -200,7 +203,8 @@
     /**
      * Returns a list of possible WindowBounds for the display keyed on the 4 surface rotations
      */
-    protected WindowBounds[] estimateWindowBounds(Context context, CachedDisplayInfo displayInfo) {
+    protected List<WindowBounds> estimateWindowBounds(Context context,
+            CachedDisplayInfo displayInfo) {
         int densityDpi = context.getResources().getConfiguration().densityDpi;
         int rotation = displayInfo.rotation;
         Rect safeCutout = displayInfo.cutout;
@@ -243,7 +247,7 @@
                 ? 0
                 : getDimenByName(systemRes, NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
 
-        WindowBounds[] result = new WindowBounds[4];
+        List<WindowBounds> result = new ArrayList<>(4);
         Point tempSize = new Point();
         for (int i = 0; i < 4; i++) {
             int rotationChange = deltaRotation(rotation, i);
@@ -274,7 +278,7 @@
             } else {
                 insets.right = Math.max(insets.right, navbarWidth);
             }
-            result[i] = new WindowBounds(bounds, insets, i);
+            result.add(new WindowBounds(bounds, insets, i));
         }
         return result;
     }
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index ec7ec0b..91eb109 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -17,11 +17,11 @@
 
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
+import static com.android.app.animation.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.TABLET_BOTTOM_SHEET_SUCCESS_TRANSITION_PROGRESS;
 import static com.android.launcher3.allapps.AllAppsTransitionController.REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS;
-import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
 import static com.android.launcher3.util.ScrollableLayoutManager.PREDICTIVE_BACK_MIN_SCALE;
 
 import android.animation.Animator;
@@ -47,10 +47,10 @@
 import androidx.annotation.Px;
 import androidx.annotation.RequiresApi;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.touch.BaseSwipeDetector;
 import com.android.launcher3.touch.SingleAxisSwipeDetector;
 
@@ -310,7 +310,7 @@
                     TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
             mOpenCloseAnimator.setDuration(
                     BaseSwipeDetector.calculateDuration(velocity, mTranslationShift))
-                    .setInterpolator(Interpolators.DEACCEL);
+                    .setInterpolator(Interpolators.DECELERATE);
             mOpenCloseAnimator.start();
         }
     }
@@ -357,7 +357,7 @@
     }
 
     protected Interpolator getIdleInterpolator() {
-        return Interpolators.ACCEL;
+        return Interpolators.ACCELERATE;
     }
 
     protected void onCloseComplete() {
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
index 4b319e5..67f24aa 100644
--- a/src/com/android/launcher3/views/ActivityContext.java
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -338,6 +338,12 @@
             return null;
         }
 
+        boolean isShortcut = (item instanceof WorkspaceItemInfo)
+                && item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
+                && !((WorkspaceItemInfo) item).isPromise();
+        if (isShortcut && GO_DISABLE_WIDGETS) {
+            return null;
+        }
         ActivityOptionsWrapper options = v != null ? getActivityLaunchOptions(v, item)
                 : makeDefaultActivityOptions(item != null && item.animationType == DEFAULT_NO_ICON
                         ? SPLASH_SCREEN_STYLE_SOLID_COLOR : -1 /* SPLASH_SCREEN_STYLE_UNDEFINED */);
@@ -349,13 +355,11 @@
             intent.setSourceBounds(Utilities.getViewBounds(v));
         }
         try {
-            boolean isShortcut = (item instanceof WorkspaceItemInfo)
-                    && (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT
-                    || item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
-                    && !((WorkspaceItemInfo) item).isPromise();
             if (isShortcut) {
-                // Shortcuts need some special checks due to legacy reasons.
-                startShortcutIntentSafely(intent, optsBundle, item);
+                String id = ((WorkspaceItemInfo) item).getDeepShortcutId();
+                String packageName = intent.getPackage();
+                ((Context) this).getSystemService(LauncherApps.class).startShortcut(
+                        packageName, id, intent.getSourceBounds(), optsBundle, user);
             } else if (user == null || user.equals(Process.myUserHandle())) {
                 // Could be launching some bookkeeping activity
                 context.startActivity(intent, optsBundle);
@@ -430,55 +434,6 @@
         return new ActivityOptionsWrapper(options, new RunnableList());
     }
 
-    /**
-     * Safely launches an intent for a shortcut.
-     *
-     * @param intent Intent to start.
-     * @param optsBundle Optional launch arguments.
-     * @param info Shortcut information.
-     */
-    default void startShortcutIntentSafely(Intent intent, Bundle optsBundle, ItemInfo info) {
-        try {
-            StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
-            try {
-                // Temporarily disable deathPenalty on all default checks. For eg, shortcuts
-                // containing file Uri's would cause a crash as penaltyDeathOnFileUriExposure
-                // is enabled by default on NYC.
-                StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
-                        .penaltyLog().build());
-
-                if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
-                    String id = ((WorkspaceItemInfo) info).getDeepShortcutId();
-                    String packageName = intent.getPackage();
-                    startShortcut(packageName, id, intent.getSourceBounds(), optsBundle, info.user);
-                } else {
-                    // Could be launching some bookkeeping activity
-                    ((Context) this).startActivity(intent, optsBundle);
-                }
-            } finally {
-                StrictMode.setVmPolicy(oldPolicy);
-            }
-        } catch (SecurityException e) {
-            throw e;
-        }
-    }
-
-    /**
-     * A wrapper around the platform method with Launcher specific checks.
-     */
-    default void startShortcut(String packageName, String id, Rect sourceBounds,
-            Bundle startActivityOptions, UserHandle user) {
-        if (GO_DISABLE_WIDGETS) {
-            return;
-        }
-        try {
-            ((Context) this).getSystemService(LauncherApps.class).startShortcut(packageName, id,
-                    sourceBounds, startActivityOptions, user);
-        } catch (SecurityException | IllegalStateException e) {
-            Log.e(TAG, "Failed to start shortcut", e);
-        }
-    }
-
     default CellPosMapper getCellPosMapper() {
         return CellPosMapper.DEFAULT;
     }
diff --git a/src/com/android/launcher3/views/ArrowTipView.java b/src/com/android/launcher3/views/ArrowTipView.java
index 73c5ad4..d905aaa 100644
--- a/src/com/android/launcher3/views/ArrowTipView.java
+++ b/src/com/android/launcher3/views/ArrowTipView.java
@@ -35,11 +35,11 @@
 import androidx.annotation.Px;
 import androidx.core.content.ContextCompat;
 
+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.Interpolators;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.graphics.TriangleShape;
 
@@ -95,7 +95,7 @@
                         .withLayer()
                         .setStartDelay(0)
                         .setDuration(HIDE_DURATION_MS)
-                        .setInterpolator(Interpolators.ACCEL)
+                        .setInterpolator(Interpolators.ACCELERATE)
                         .withEndAction(() -> mActivity.getDragLayer().removeView(this))
                         .start();
             } else {
@@ -191,7 +191,7 @@
                 .withLayer()
                 .setStartDelay(SHOW_DELAY_MS)
                 .setDuration(SHOW_DURATION_MS)
-                .setInterpolator(Interpolators.DEACCEL)
+                .setInterpolator(Interpolators.DECELERATE)
                 .start();
         return this;
     }
@@ -339,7 +339,7 @@
                 .withLayer()
                 .setStartDelay(SHOW_DELAY_MS)
                 .setDuration(SHOW_DURATION_MS)
-                .setInterpolator(Interpolators.DEACCEL)
+                .setInterpolator(Interpolators.DECELERATE)
                 .start();
         return this;
     }
diff --git a/src/com/android/launcher3/views/ClipIconView.java b/src/com/android/launcher3/views/ClipIconView.java
index 694dead..87e496e 100644
--- a/src/com/android/launcher3/views/ClipIconView.java
+++ b/src/com/android/launcher3/views/ClipIconView.java
@@ -15,9 +15,9 @@
  */
 package com.android.launcher3.views;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Utilities.boundToRange;
 import static com.android.launcher3.Utilities.mapToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
 
 import static java.lang.Math.max;
diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java
index 4d0e2af..3b05221 100644
--- a/src/com/android/launcher3/views/FloatingIconView.java
+++ b/src/com/android/launcher3/views/FloatingIconView.java
@@ -17,10 +17,10 @@
 
 import static android.view.Gravity.LEFT;
 
+import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Utilities.getBadge;
 import static com.android.launcher3.Utilities.getFullDrawable;
 import static com.android.launcher3.Utilities.mapToRange;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 import static com.android.launcher3.views.IconLabelDotView.setIconAndDotVisible;
 
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 4641e31..aebf752 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -290,7 +290,6 @@
     static WorkspaceItemInfo placeholderInfo(Intent intent) {
         WorkspaceItemInfo placeholderInfo = new WorkspaceItemInfo();
         placeholderInfo.intent = intent;
-        placeholderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
         placeholderInfo.container = LauncherSettings.Favorites.CONTAINER_SETTINGS;
         return placeholderInfo;
     }
diff --git a/src/com/android/launcher3/views/Snackbar.java b/src/com/android/launcher3/views/Snackbar.java
index 8d5838e..2d81db8 100644
--- a/src/com/android/launcher3/views/Snackbar.java
+++ b/src/com/android/launcher3/views/Snackbar.java
@@ -30,10 +30,10 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.app.animation.Interpolators;
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.compat.AccessibilityManagerCompat;
 import com.android.launcher3.dragndrop.DragLayer;
 
@@ -159,7 +159,7 @@
                 .scaleX(1)
                 .scaleY(1)
                 .setDuration(SHOW_DURATION_MS)
-                .setInterpolator(Interpolators.ACCEL_DEACCEL)
+                .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
                 .start();
         int timeout = AccessibilityManagerCompat.getRecommendedTimeoutMillis(activity,
                 TIMEOUT_DURATION_MS, FLAG_CONTENT_TEXT | FLAG_CONTENT_CONTROLS);
@@ -174,7 +174,7 @@
                         .withLayer()
                         .setStartDelay(0)
                         .setDuration(HIDE_DURATION_MS)
-                        .setInterpolator(Interpolators.ACCEL)
+                        .setInterpolator(Interpolators.ACCELERATE)
                         .withEndAction(this::onClosed)
                         .start();
             } else {
diff --git a/src/com/android/launcher3/views/WidgetsEduView.java b/src/com/android/launcher3/views/WidgetsEduView.java
index c2947c7..9180781 100644
--- a/src/com/android/launcher3/views/WidgetsEduView.java
+++ b/src/com/android/launcher3/views/WidgetsEduView.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.views;
 
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
 
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
diff --git a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
index 9442734..473abf1 100644
--- a/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/AddItemWidgetsBottomSheet.java
@@ -16,8 +16,8 @@
 
 package com.android.launcher3.widget;
 
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.Utilities.ATLEAST_R;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 
 import android.animation.PropertyValuesHolder;
 import android.annotation.SuppressLint;
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 049131e..dcc86a1 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.widget;
 
-import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
+import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
 
 import android.content.Context;
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 846dafd..93f7cb3 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -16,8 +16,8 @@
 
 package com.android.launcher3.widget;
 
+import static com.android.app.animation.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_BOTTOM_WIDGETS_TRAY;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
diff --git a/src/com/android/launcher3/workspace/WorkspaceSpecs.kt b/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
index ac0a166..dc5ae47 100644
--- a/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
+++ b/src/com/android/launcher3/workspace/WorkspaceSpecs.kt
@@ -231,6 +231,13 @@
         if (workspaceSpec.cellSize.ofRemainderSpace > 0)
             cellSizePx = (workspaceSpec.cellSize.ofRemainderSpace * remainderSpace).roundToInt()
     }
+
+    override fun toString(): String {
+        return "CalculatedWorkspaceSpec(availableSpace=$availableSpace, " +
+            "cells=$cells, startPaddingPx=$startPaddingPx, endPaddingPx=$endPaddingPx, " +
+            "gutterPx=$gutterPx, cellSizePx=$cellSizePx, " +
+            "workspaceSpec.maxAvailableSize=${workspaceSpec.maxAvailableSize})"
+    }
 }
 
 data class WorkspaceSpec(
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 772a995..b62dbd1 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -15,7 +15,7 @@
  */
 package com.android.launcher3.uioverrides.states;
 
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+import static com.android.app.animation.Interpolators.DECELERATE;
 import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
 
 import android.content.Context;
@@ -80,7 +80,7 @@
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
         PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
-        return new PageAlphaProvider(DEACCEL_2) {
+        return new PageAlphaProvider(DECELERATE) {
             @Override
             public float getPageAlpha(int pageIndex) {
                 return launcher.getDeviceProfile().isTablet
diff --git a/tests/res/raw/cache_data_updated_task_data.txt b/tests/res/raw/cache_data_updated_task_data.txt
deleted file mode 100644
index 603dbe3..0000000
--- a/tests/res/raw/cache_data_updated_task_data.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-# Model data used by CacheDataUpdatedTaskTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Auto install app shortcut
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-
-# Custom shortcuts
-bgItem s itemType=1 title=app1-shrt intent=component=app1/class3 id=7
-bgItem s itemType=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Restored custom shortcut
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=9
-bgItem s itemType=1 status=1 title=app5-shrt intent=component=app5/class1 id=10
-
-allApps componentName=app1/class1 intent=component=app1/class1
-allApps componentName=app1/class2 intent=component=app1/class2
-allApps componentName=app2/class1 intent=component=app2/class1
-allApps componentName=app2/class2 intent=component=app2/class2
\ No newline at end of file
diff --git a/tests/res/raw/package_install_state_change_task_data.txt b/tests/res/raw/package_install_state_change_task_data.txt
deleted file mode 100644
index e82ea9d..0000000
--- a/tests/res/raw/package_install_state_change_task_data.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# Model data used by PackageInstallStateChangeTaskTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Promise icons for app3
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
-
-# Promise icon for app4
-bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Widget
-bgItem w providerName=app4/provider1 id=9
-bgItem w providerName=app5/provider1 id=10
\ No newline at end of file
diff --git a/tests/res/raw/widgets_predication_update_task_data.txt b/tests/res/raw/widgets_predication_update_task_data.txt
deleted file mode 100644
index 941d195..0000000
--- a/tests/res/raw/widgets_predication_update_task_data.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-# Model data used by WidgetsPredictionUpdateTasksTest
-
-classMap s com.android.launcher3.model.data.WorkspaceItemInfo
-classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
-
-# Items for the BgDataModel
-
-# App shortcuts
-bgItem s itemType=0 title=app1-class1 intent=component=app1/class1 id=1
-bgItem s itemType=0 title=app1-class2 intent=component=app1/class2 id=2
-bgItem s itemType=0 title=app2-class1 intent=component=app2/class1 id=3
-bgItem s itemType=0 title=app2-class2 intent=component=app2/class2 id=4
-
-# Promise icons for app3
-bgItem s itemType=0 status=2 title=app3-class1 intent=component=app3/class1 id=5
-bgItem s itemType=0 status=2 title=app3-class2 intent=component=app3/class2 id=6
-bgItem s itemType=1 status=1 title=app3-shrt intent=component=app3/class3 id=7
-
-# Promise icon for app4
-bgItem s itemType=1 status=1 title=app4-shrt intent=component=app4/class1 id=8
-
-# Widget
-bgItem w providerName=app4/provider1 id=9
-bgItem w providerName=app5/provider1 id=10
\ No newline at end of file
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index b7c3aca..0809eb8 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -122,6 +122,7 @@
             "get-activities-created-count";
     public static final String REQUEST_GET_ACTIVITIES = "get-activities";
     public static final String REQUEST_HAS_TIS = "has-touch-interaction-service";
+    public static final String REQUEST_IS_TRACKPAD_GESTURE_ENABLED = "is-trackpad-gesture-enabled";
     public static final String REQUEST_TASKBAR_ALL_APPS_TOP_PADDING =
             "taskbar-all-apps-top-padding";
     public static final String REQUEST_ALL_APPS_TOP_PADDING = "all-apps-top-padding";
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index 3de4d55..6dec67e 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -196,7 +196,7 @@
         isGestureMode: Boolean,
         naturalX: Int,
         naturalY: Int
-    ): Array<WindowBounds> {
+    ): List<WindowBounds> {
         val buttonsNavHeight = Utilities.dpToPx(48f, deviceSpec.densityDpi)
 
         val rotation0Insets =
@@ -231,7 +231,7 @@
                 if (isGestureMode) deviceSpec.gesturePx else 0
             )
 
-        return arrayOf(
+        return listOf(
             WindowBounds(Rect(0, 0, naturalX, naturalY), rotation0Insets, Surface.ROTATION_0),
             WindowBounds(Rect(0, 0, naturalY, naturalX), rotation90Insets, Surface.ROTATION_90),
             WindowBounds(Rect(0, 0, naturalX, naturalY), rotation180Insets, Surface.ROTATION_180),
@@ -243,11 +243,11 @@
         deviceSpec: DeviceSpec,
         naturalX: Int,
         naturalY: Int
-    ): Array<WindowBounds> {
+    ): List<WindowBounds> {
         val naturalInsets = Rect(0, deviceSpec.statusBarNaturalPx, 0, 0)
         val rotatedInsets = Rect(0, deviceSpec.statusBarRotatedPx, 0, 0)
 
-        return arrayOf(
+        return listOf(
             WindowBounds(Rect(0, 0, naturalX, naturalY), naturalInsets, Surface.ROTATION_0),
             WindowBounds(Rect(0, 0, naturalY, naturalX), rotatedInsets, Surface.ROTATION_90),
             WindowBounds(Rect(0, 0, naturalX, naturalY), naturalInsets, Surface.ROTATION_180),
@@ -256,7 +256,7 @@
     }
 
     private fun initializeCommonVars(
-        perDisplayBoundsCache: Map<CachedDisplayInfo, Array<WindowBounds>>,
+        perDisplayBoundsCache: Map<CachedDisplayInfo, List<WindowBounds>>,
         displayInfo: CachedDisplayInfo,
         rotation: Int,
         isGestureMode: Boolean = true,
diff --git a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
index 03352fe..98191fe 100644
--- a/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
+++ b/tests/src/com/android/launcher3/model/AbstractWorkspaceModelTest.kt
@@ -17,17 +17,18 @@
 
 import android.content.ComponentName
 import android.content.Context
-import android.content.Intent
 import android.graphics.Rect
 import com.android.launcher3.InvariantDeviceProfile
 import com.android.launcher3.LauncherAppState
-import com.android.launcher3.LauncherSettings
+import com.android.launcher3.model.data.AppInfo
 import com.android.launcher3.model.data.WorkspaceItemInfo
-import com.android.launcher3.util.ContentWriter
 import com.android.launcher3.util.GridOccupancy
 import com.android.launcher3.util.IntArray
 import com.android.launcher3.util.IntSparseArrayMap
+import com.android.launcher3.util.LauncherLayoutBuilder
 import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY
+import com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE
 import java.util.UUID
 
 /** Base class for workspace related tests. */
@@ -38,6 +39,7 @@
         val nonEmptyScreenSpaces = listOf(Rect(1, 2, 3, 4))
     }
 
+    protected lateinit var mLayoutBuilder: LauncherLayoutBuilder
     protected lateinit var mTargetContext: Context
     protected lateinit var mIdp: InvariantDeviceProfile
     protected lateinit var mAppState: LauncherAppState
@@ -47,6 +49,7 @@
     protected lateinit var mScreenOccupancy: IntSparseArrayMap<GridOccupancy>
 
     open fun setup() {
+        mLayoutBuilder = LauncherLayoutBuilder()
         mModelHelper = LauncherModelHelper()
         mTargetContext = mModelHelper.sandboxContext
         mIdp = InvariantDeviceProfile.INSTANCE[mTargetContext]
@@ -64,10 +67,11 @@
 
     /** Sets up workspaces with the given screen IDs with some items and a 2x2 space. */
     fun setupWorkspaces(screenIdsWithItems: List<Int>) {
-        var nextItemId = 1
-        screenIdsWithItems.forEach { screenId ->
-            nextItemId = setupWorkspace(nextItemId, screenId, nonEmptyScreenSpaces)
-        }
+        screenIdsWithItems.forEach { screenId -> setupWorkspace(screenId, nonEmptyScreenSpaces) }
+        mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
+        mIdp.numRows = 5
+        mIdp.numColumns = mIdp.numRows
+        mModelHelper.loadModelSync()
     }
 
     /**
@@ -78,30 +82,23 @@
         screen1: List<Rect>? = null,
         screen2: List<Rect>? = null,
         screen3: List<Rect>? = null,
-    ) = listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
+    ) {
+        listOf(screen0, screen1, screen2, screen3).let(this::setupWithSpaces)
+        mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder)
+        mIdp.numRows = 5
+        mIdp.numColumns = mIdp.numRows
+        mModelHelper.loadModelSync()
+    }
 
     private fun setupWithSpaces(workspaceSpaces: List<List<Rect>?>) {
-        var nextItemId = 1
         workspaceSpaces.forEachIndexed { screenId, spaces ->
             if (spaces != null) {
-                nextItemId = setupWorkspace(nextItemId, screenId, spaces)
+                setupWorkspace(screenId, spaces)
             }
         }
     }
 
-    private fun setupWorkspace(startId: Int, screenId: Int, spaces: List<Rect>): Int {
-        return mModelHelper.executeSimpleTask { dataModel ->
-            writeWorkspaceWithSpaces(dataModel, startId, screenId, spaces)
-        }
-    }
-
-    private fun writeWorkspaceWithSpaces(
-        bgDataModel: BgDataModel,
-        itemStartId: Int,
-        screenId: Int,
-        spaces: List<Rect>,
-    ): Int {
-        var itemId = itemStartId
+    private fun setupWorkspace(screenId: Int, spaces: List<Rect>) {
         val occupancy = GridOccupancy(mIdp.numColumns, mIdp.numRows)
         occupancy.markCells(0, 0, mIdp.numColumns, mIdp.numRows, true)
         spaces.forEach { spaceRect -> occupancy.markCells(spaceRect, false) }
@@ -109,35 +106,22 @@
         mScreenOccupancy.append(screenId, occupancy)
         for (x in 0 until mIdp.numColumns) {
             for (y in 0 until mIdp.numRows) {
-                if (!occupancy.cells[x][y]) {
-                    continue
+                if (occupancy.cells[x][y]) {
+                    mLayoutBuilder.atWorkspace(x, y, screenId).putApp(TEST_PACKAGE, TEST_ACTIVITY)
                 }
-                val info = getExistingItem()
-                info.id = itemId++
-                info.screenId = screenId
-                info.cellX = x
-                info.cellY = y
-                info.container = LauncherSettings.Favorites.CONTAINER_DESKTOP
-                bgDataModel.addItem(mTargetContext, info, false)
-                val writer = ContentWriter(mTargetContext)
-                info.writeToValues(writer)
-                writer.put(LauncherSettings.Favorites._ID, info.id)
-                mTargetContext.contentResolver.insert(
-                    LauncherSettings.Favorites.CONTENT_URI,
-                    writer.getValues(mTargetContext)
-                )
             }
         }
-        return itemId
     }
 
     fun getExistingItem() =
-        WorkspaceItemInfo().apply { intent = Intent().setComponent(ComponentName("a", "b")) }
+        WorkspaceItemInfo().apply {
+            intent = AppInfo.makeLaunchIntent(ComponentName(TEST_PACKAGE, TEST_ACTIVITY))
+        }
 
     fun getNewItem(): WorkspaceItemInfo {
         val itemPackage = UUID.randomUUID().toString()
         return WorkspaceItemInfo().apply {
-            intent = Intent().setComponent(ComponentName(itemPackage, itemPackage))
+            intent = AppInfo.makeLaunchIntent(ComponentName(itemPackage, itemPackage))
         }
     }
 }
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
index 6636b8a..1155227 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.kt
@@ -23,7 +23,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo
 import com.android.launcher3.util.Executors
 import com.android.launcher3.util.IntArray
-import com.android.launcher3.util.IntSet
+import com.android.launcher3.util.TestUtil.runOnExecutorSync
 import com.android.launcher3.util.any
 import com.android.launcher3.util.eq
 import com.android.launcher3.util.same
@@ -32,8 +32,6 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
@@ -46,11 +44,7 @@
 @RunWith(AndroidJUnit4::class)
 class AddWorkspaceItemsTaskTest : AbstractWorkspaceModelTest() {
 
-    @Captor private lateinit var mAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
-    @Captor private lateinit var mNotAnimatedItemArgumentCaptor: ArgumentCaptor<ArrayList<ItemInfo>>
-
-    @Mock private lateinit var mDataModelCallbacks: BgDataModel.Callbacks
+    private lateinit var mDataModelCallbacks: MyCallbacks
 
     @Mock private lateinit var mWorkspaceItemSpaceFinder: WorkspaceItemSpaceFinder
 
@@ -58,7 +52,7 @@
     override fun setup() {
         super.setup()
         MockitoAnnotations.initMocks(this)
-        whenever(mDataModelCallbacks.getPagesToBindSynchronously(any())).thenReturn(IntSet())
+        mDataModelCallbacks = MyCallbacks()
         Executors.MAIN_EXECUTOR.submit { mModelHelper.model.addCallbacks(mDataModelCallbacks) }
             .get()
     }
@@ -105,7 +99,7 @@
         val addedItems = testAddItems(nonEmptyScreenIds, itemToAdd)
 
         assertThat(addedItems.size).isEqualTo(0)
-        verifyZeroInteractions(mWorkspaceItemSpaceFinder, mDataModelCallbacks)
+        verifyZeroInteractions(mWorkspaceItemSpaceFinder)
     }
 
     @Test
@@ -191,22 +185,14 @@
     ): List<AddedItem> {
         setupWorkspaces(nonEmptyScreenIds)
         val task = newTask(*itemsToAdd)
-        var updateCount = 0
-        mModelHelper.executeTaskForTest(task).forEach {
-            updateCount++
-            it.run()
-        }
 
         val addedItems = mutableListOf<AddedItem>()
-        if (updateCount > 0) {
-            verify(mDataModelCallbacks)
-                .bindAppsAdded(
-                    any(),
-                    mNotAnimatedItemArgumentCaptor.capture(),
-                    mAnimatedItemArgumentCaptor.capture()
-                )
-            addedItems.addAll(mAnimatedItemArgumentCaptor.value.map { AddedItem(it, true) })
-            addedItems.addAll(mNotAnimatedItemArgumentCaptor.value.map { AddedItem(it, false) })
+
+        runOnExecutorSync(Executors.MODEL_EXECUTOR) {
+            mDataModelCallbacks.addedItems.clear()
+            mModelHelper.model.enqueueModelUpdateTask(task)
+            runOnExecutorSync(Executors.MAIN_EXECUTOR) {}
+            addedItems.addAll(mDataModelCallbacks.addedItems)
         }
 
         return addedItems
@@ -224,3 +210,17 @@
 }
 
 private data class AddedItem(val itemInfo: ItemInfo, val isAnimated: Boolean)
+
+private class MyCallbacks : BgDataModel.Callbacks {
+
+    val addedItems = mutableListOf<AddedItem>()
+
+    override fun bindAppsAdded(
+        newScreens: IntArray?,
+        addNotAnimated: ArrayList<ItemInfo>,
+        addAnimated: ArrayList<ItemInfo>
+    ) {
+        addedItems.addAll(addAnimated.map { AddedItem(it, true) })
+        addedItems.addAll(addNotAnimated.map { AddedItem(it, false) })
+    }
+}
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index f55b244..f771052 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -1,32 +1,31 @@
 package com.android.launcher3.model;
 
+import static android.os.Process.myUserHandle;
+
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertTrue;
 
-import android.content.ComponentName;
 import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Color;
-import android.os.Process;
-import android.os.UserHandle;
-import android.os.UserManager;
 
-import androidx.annotation.NonNull;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.icons.BitmapInfo;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.icons.cache.CachingLogic;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LauncherLayoutBuilder;
 import com.android.launcher3.util.LauncherModelHelper;
+import com.android.launcher3.util.PackageUserKey;
 
 import org.junit.After;
 import org.junit.Before;
@@ -35,6 +34,7 @@
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.List;
 
 /**
  * Tests for {@link CacheDataUpdatedTask}
@@ -43,49 +43,40 @@
 @RunWith(AndroidJUnit4.class)
 public class CacheDataUpdatedTaskTest {
 
-    private static final String NEW_LABEL_PREFIX = "new-label-";
+    private static final String PENDING_APP_1 = TEST_PACKAGE + ".pending1";
+    private static final String PENDING_APP_2 = TEST_PACKAGE + ".pending2";
 
     private LauncherModelHelper mModelHelper;
+    private Context mContext;
+
+    private int mSession1;
 
     @Before
     public void setup() throws Exception {
         mModelHelper = new LauncherModelHelper();
-        mModelHelper.initializeData("cache_data_updated_task_data");
+        mContext = mModelHelper.sandboxContext;
+        mSession1 = mModelHelper.createInstallerSession(PENDING_APP_1);
+        mModelHelper.createInstallerSession(PENDING_APP_2);
 
-        // Add placeholder entries in the cache to simulate update
-        Context context = mModelHelper.sandboxContext;
-        IconCache iconCache = LauncherAppState.getInstance(context).getIconCache();
-        CachingLogic<ItemInfo> placeholderLogic = new CachingLogic<ItemInfo>() {
-            @Override
-            @NonNull
-            public ComponentName getComponent(@NonNull ItemInfo info) {
-                return info.getTargetComponent();
-            }
+        LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+                .atHotseat(1).putFolder("MyFolder")
+                .addApp(TEST_PACKAGE, TEST_ACTIVITY)    // 2
+                .addApp(TEST_PACKAGE, TEST_ACTIVITY2)   // 3
+                .addApp(TEST_PACKAGE, TEST_ACTIVITY3)   // 4
 
-            @NonNull
-            @Override
-            public UserHandle getUser(@NonNull ItemInfo info) {
-                return info.user;
-            }
+                // Pending App 1
+                .addApp(PENDING_APP_1, TEST_ACTIVITY)   // 5
+                .addApp(PENDING_APP_1, TEST_ACTIVITY2)  // 6
+                .addApp(PENDING_APP_1, TEST_ACTIVITY3)  // 7
 
-            @NonNull
-            @Override
-            public CharSequence getLabel(@NonNull ItemInfo info) {
-                return NEW_LABEL_PREFIX + info.id;
-            }
-
-            @NonNull
-            @Override
-            public BitmapInfo loadIcon(@NonNull Context context, @NonNull ItemInfo info) {
-                return BitmapInfo.of(Bitmap.createBitmap(1, 1, Config.ARGB_8888), Color.RED);
-            }
-        };
-
-        UserManager um = context.getSystemService(UserManager.class);
-        for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
-            iconCache.addIconToDBAndMemCache(info, placeholderLogic, new PackageInfo(),
-                    um.getSerialNumberForUser(info.user), true);
-        }
+                // Pending App 2
+                .addApp(PENDING_APP_2, TEST_ACTIVITY)   // 8
+                .addApp(PENDING_APP_2, TEST_ACTIVITY2)  // 9
+                .addApp(PENDING_APP_2, TEST_ACTIVITY3)  // 10
+                .build();
+        mModelHelper.setupDefaultLayoutProvider(builder);
+        mModelHelper.loadModelSync();
+        assertEquals(10, mModelHelper.getBgDataModel().itemsIdMap.size());
     }
 
     @After
@@ -94,27 +85,63 @@
     }
 
     private CacheDataUpdatedTask newTask(int op, String... pkg) {
-        return new CacheDataUpdatedTask(op, Process.myUserHandle(),
+        return new CacheDataUpdatedTask(op, myUserHandle(),
                 new HashSet<>(Arrays.asList(pkg)));
     }
 
     @Test
-    public void testCacheUpdate_update_apps() throws Exception {
-        // Clear all icons from apps list so that its easy to check what was updated
-        for (AppInfo info : mModelHelper.getAllAppsList().data) {
-            info.bitmap = BitmapInfo.LOW_RES_INFO;
-        }
+    public void testCacheUpdate_update_apps() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            // Clear all icons from apps list so that its easy to check what was updated
+            allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
 
-        mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, "app1"));
+            mModelHelper.getModel().enqueueModelUpdateTask(
+                    newTask(CacheDataUpdatedTask.OP_CACHE_UPDATE, TEST_PACKAGE));
 
-        // Verify that only the app icons of app1 (id 1 & 2) are updated. Custom shortcut (id 7)
-        // is not updated
-        verifyUpdate(1, 2);
+            // Verify that only the app icons of TEST_PACKAGE (id 2, 3, 4) are updated.
+            verifyUpdate(2, 3, 4);
+        });
+    }
 
-        // Verify that only app1 var updated in allAppsList
-        assertFalse(mModelHelper.getAllAppsList().data.isEmpty());
-        for (AppInfo info : mModelHelper.getAllAppsList().data) {
-            if (info.componentName.getPackageName().equals("app1")) {
+    @Test
+    public void testSessionUpdate_ignores_normal_apps() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            // Clear all icons from apps list so that its easy to check what was updated
+            allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
+
+            mModelHelper.getModel().enqueueModelUpdateTask(
+                    newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, TEST_PACKAGE));
+
+            // TEST_PACKAGE has no restored shortcuts. Verify that nothing was updated.
+            verifyUpdate();
+        });
+    }
+
+    @Test
+    public void testSessionUpdate_updates_pending_apps() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            LauncherAppState.getInstance(mContext).getIconCache().updateSessionCache(
+                    new PackageUserKey(PENDING_APP_1, myUserHandle()),
+                    mContext.getPackageManager().getPackageInstaller().getSessionInfo(mSession1));
+
+            // Clear all icons from apps list so that its easy to check what was updated
+            allItems().forEach(wi -> wi.bitmap = BitmapInfo.LOW_RES_INFO);
+
+            mModelHelper.getModel().enqueueModelUpdateTask(
+                    newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, PENDING_APP_1));
+
+            // Only restored apps from PENDING_APP_1 (id 5, 6, 7) are updated
+            verifyUpdate(5, 6, 7);
+        });
+    }
+
+    private void verifyUpdate(int... idsUpdated) {
+        IntSet updates = IntSet.wrap(idsUpdated);
+        for (WorkspaceItemInfo info : allItems()) {
+            if (updates.contains(info.id)) {
                 assertFalse(info.bitmap.isNullOrLowRes());
             } else {
                 assertTrue(info.bitmap.isNullOrLowRes());
@@ -122,33 +149,7 @@
         }
     }
 
-    @Test
-    public void testSessionUpdate_ignores_normal_apps() throws Exception {
-        mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app1"));
-
-        // app1 has no restored shortcuts. Verify that nothing was updated.
-        verifyUpdate();
-    }
-
-    @Test
-    public void testSessionUpdate_updates_pending_apps() throws Exception {
-        mModelHelper.executeTaskForTest(newTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, "app3"));
-
-        // app3 has only restored apps (id 5, 6) and shortcuts (id 9). Verify that only apps were
-        // were updated
-        verifyUpdate(5, 6);
-    }
-
-    private void verifyUpdate(Integer... idsUpdated) {
-        HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
-        for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
-            if (updates.contains(info.id)) {
-                assertEquals(NEW_LABEL_PREFIX + info.id, info.title);
-                assertFalse(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
-            } else {
-                assertNotSame(NEW_LABEL_PREFIX + info.id, info.title);
-                assertTrue(((WorkspaceItemInfo) info).bitmap.isNullOrLowRes());
-            }
-        }
+    private List<WorkspaceItemInfo> allItems() {
+        return ((FolderInfo) mModelHelper.getBgDataModel().itemsIdMap.get(1)).contents;
     }
 }
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 3b480ca..4fa5352 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -24,7 +24,6 @@
 import android.os.Process
 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.LauncherPrefs
 import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
@@ -108,8 +107,8 @@
     fun testMigration() {
         // Src Hotseat icons
         addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
-        addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
-        addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
         addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
         // Src grid icons
         // _ _ _ _ _
@@ -124,7 +123,7 @@
         addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE)
 
         // Dest hotseat icons
-        addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
         // Dest grid icons
         addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10)
 
@@ -219,8 +218,8 @@
         // Hotseat items in grid A
         // 1 2 _ 3 4
         addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
-        addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
-        addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
         addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
         // Workspace items in grid A
         // _ _ _ _ _
@@ -235,7 +234,7 @@
 
         // Hotseat items in grid B
         // 2 _ _ _
-        addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
         // Workspace items in grid B
         // _ _ _ _
         // _ _ _ 10
@@ -291,7 +290,7 @@
                 null
             )
                 ?: throw IllegalStateException()
-        var locMap = parseLocMap(context, c)
+        var locMap = parseLocMap(c)
         // Expected items in grid B
         // _ _ _ _
         // 5 6 7 8
@@ -348,7 +347,7 @@
                 null
             )
                 ?: throw IllegalStateException()
-        locMap = parseLocMap(context, c)
+        locMap = parseLocMap(c)
         // Expected workspace items in grid A
         // _ _ _ _ _
         // _ _ _ _ 5
@@ -410,7 +409,7 @@
                 null
             )
                 ?: throw IllegalStateException()
-        locMap = parseLocMap(context, c)
+        locMap = parseLocMap(c)
         // Expected workspace items in grid B
         // _ _ _ _
         // 5 6 _ 8
@@ -436,7 +435,7 @@
         c.close()
     }
 
-    private fun parseLocMap(context: Context, c: Cursor): Map<String, Triple<Int, Int, Int>> {
+    private fun parseLocMap(c: Cursor): Map<String, Triple<Int, Int, Int>> {
         // Check workspace items
         val intentIndex = c.getColumnIndex(INTENT)
         val screenIndex = c.getColumnIndex(SCREEN)
@@ -465,7 +464,16 @@
                     1,
                     TMP_TABLE
                 ),
-                addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE),
+                addItem(
+                    ITEM_TYPE_DEEP_SHORTCUT,
+                    1,
+                    CONTAINER_HOTSEAT,
+                    0,
+                    0,
+                    testPackage2,
+                    2,
+                    TMP_TABLE
+                ),
                 addItem(
                     ITEM_TYPE_APPLICATION,
                     2,
@@ -476,7 +484,16 @@
                     3,
                     TMP_TABLE
                 ),
-                addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+                addItem(
+                    ITEM_TYPE_DEEP_SHORTCUT,
+                    3,
+                    CONTAINER_HOTSEAT,
+                    0,
+                    0,
+                    testPackage4,
+                    4,
+                    TMP_TABLE
+                )
             )
         val numSrcDatabaseHotseatIcons = srcHotseatItems.size
         idp.numDatabaseHotseatIcons = 6
@@ -532,9 +549,9 @@
     @Test
     fun migrateFromLargerHotseat() {
         addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
-        addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
         addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
-        addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+        addItem(ITEM_TYPE_DEEP_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
         addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
 
         idp.numDatabaseHotseatIcons = 4
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 78812c0..544ed6b 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -30,7 +30,7 @@
 import static com.android.launcher3.LauncherSettings.Favorites.INTENT;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
 import static com.android.launcher3.LauncherSettings.Favorites.OPTIONS;
 import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID;
 import static com.android.launcher3.LauncherSettings.Favorites.RANK;
@@ -158,13 +158,13 @@
 
     @Test
     public void loadSimpleShortcut() {
-        initCursor(ITEM_TYPE_SHORTCUT, "my-shortcut");
+        initCursor(ITEM_TYPE_DEEP_SHORTCUT, "my-shortcut");
         assertTrue(mLoaderCursor.moveToNext());
 
         WorkspaceItemInfo info = mLoaderCursor.loadSimpleWorkspaceItem();
         assertTrue(mApp.getIconCache().isDefaultIcon(info.bitmap, info.user));
         assertEquals("my-shortcut", info.title);
-        assertEquals(ITEM_TYPE_SHORTCUT, info.itemType);
+        assertEquals(ITEM_TYPE_DEEP_SHORTCUT, info.itemType);
     }
 
     @Test
diff --git a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
index 519191e..4ba61ac 100644
--- a/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/PackageInstallStateChangedTaskTest.java
@@ -1,5 +1,12 @@
 package com.android.launcher3.model;
 
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY2;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY3;
+import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
+
 import static org.junit.Assert.assertEquals;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -9,6 +16,8 @@
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.PackageInstallInfo;
+import com.android.launcher3.util.IntSet;
+import com.android.launcher3.util.LauncherLayoutBuilder;
 import com.android.launcher3.util.LauncherModelHelper;
 
 import org.junit.After;
@@ -16,9 +25,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.Arrays;
-import java.util.HashSet;
-
 /**
  * Tests for {@link PackageInstallStateChangedTask}
  */
@@ -26,12 +32,36 @@
 @RunWith(AndroidJUnit4.class)
 public class PackageInstallStateChangedTaskTest {
 
+    private static final String PENDING_APP_1 = TEST_PACKAGE + ".pending1";
+    private static final String PENDING_APP_2 = TEST_PACKAGE + ".pending2";
+
     private LauncherModelHelper mModelHelper;
+    private IntSet mDownloadingApps;
 
     @Before
     public void setup() throws Exception {
         mModelHelper = new LauncherModelHelper();
-        mModelHelper.initializeData("package_install_state_change_task_data");
+        mModelHelper.createInstallerSession(PENDING_APP_1);
+        mModelHelper.createInstallerSession(PENDING_APP_2);
+
+        LauncherLayoutBuilder builder = new LauncherLayoutBuilder()
+                .atWorkspace(0, 0, 1).putApp(TEST_PACKAGE, TEST_ACTIVITY)               // 1
+                .atWorkspace(0, 0, 2).putApp(TEST_PACKAGE, TEST_ACTIVITY2)              // 2
+                .atWorkspace(0, 0, 3).putApp(TEST_PACKAGE, TEST_ACTIVITY3)              // 3
+
+                .atWorkspace(0, 0, 4).putApp(PENDING_APP_1, TEST_ACTIVITY)              // 4
+                .atWorkspace(0, 0, 5).putApp(PENDING_APP_1, TEST_ACTIVITY2)             // 5
+                .atWorkspace(0, 0, 6).putApp(PENDING_APP_1, TEST_ACTIVITY3)             // 6
+                .atWorkspace(0, 0, 7).putWidget(PENDING_APP_1, "pending.widget", 1, 1)  // 7
+
+                .atWorkspace(0, 0, 8).putApp(PENDING_APP_2, TEST_ACTIVITY)              // 8
+                .atWorkspace(0, 0, 9).putApp(PENDING_APP_2, TEST_ACTIVITY2)             // 9
+                .atWorkspace(0, 0, 10).putApp(PENDING_APP_2, TEST_ACTIVITY3);           // 10
+
+        mDownloadingApps = IntSet.wrap(4, 5, 6, 7, 8, 9, 10);
+        mModelHelper.setupDefaultLayoutProvider(builder);
+        mModelHelper.loadModelSync();
+        assertEquals(10, mModelHelper.getBgDataModel().itemsIdMap.size());
     }
 
     @After
@@ -47,36 +77,45 @@
     }
 
     @Test
-    public void testSessionUpdate_ignore_installed() throws Exception {
-        mModelHelper.executeTaskForTest(newTask("app1", 30));
+    public void testSessionUpdate_ignore_installed() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            mModelHelper.getModel().enqueueModelUpdateTask(newTask(TEST_PACKAGE, 30));
 
-        // No shortcuts were updated
-        verifyProgressUpdate(0);
+            // No shortcuts were updated
+            verifyProgressUpdate(0);
+        });
     }
 
     @Test
-    public void testSessionUpdate_shortcuts_updated() throws Exception {
-        mModelHelper.executeTaskForTest(newTask("app3", 30));
+    public void testSessionUpdate_shortcuts_updated() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            mModelHelper.getModel().enqueueModelUpdateTask(newTask(PENDING_APP_1, 30));
 
-        verifyProgressUpdate(30, 5, 6, 7);
+            verifyProgressUpdate(30, 4, 5, 6, 7);
+        });
     }
 
     @Test
-    public void testSessionUpdate_widgets_updated() throws Exception {
-        mModelHelper.executeTaskForTest(newTask("app4", 30));
+    public void testSessionUpdate_widgets_updated() {
+        // Run on model executor so that no other task runs in the middle.
+        runOnExecutorSync(MODEL_EXECUTOR, () -> {
+            mModelHelper.getModel().enqueueModelUpdateTask(newTask(PENDING_APP_2, 30));
 
-        verifyProgressUpdate(30, 8, 9);
+            verifyProgressUpdate(30, 8, 9, 10);
+        });
     }
 
-    private void verifyProgressUpdate(int progress, Integer... idsUpdated) {
-        HashSet<Integer> updates = new HashSet<>(Arrays.asList(idsUpdated));
+    private void verifyProgressUpdate(int progress, int... idsUpdated) {
+        IntSet updates = IntSet.wrap(idsUpdated);
         for (ItemInfo info : mModelHelper.getBgDataModel().itemsIdMap) {
-            if (info instanceof WorkspaceItemInfo) {
-                assertEquals(updates.contains(info.id) ? progress: 100,
-                        ((WorkspaceItemInfo) info).getProgressLevel());
+            int expectedProgress = updates.contains(info.id) ? progress
+                    : (mDownloadingApps.contains(info.id) ? 0 : 100);
+            if (info instanceof WorkspaceItemInfo wi) {
+                assertEquals(expectedProgress, wi.getProgressLevel());
             } else {
-                assertEquals(updates.contains(info.id) ? progress: -1,
-                        ((LauncherAppWidgetInfo) info).installProgress);
+                assertEquals(expectedProgress, ((LauncherAppWidgetInfo) info).installProgress);
             }
         }
     }
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index d7c4ae3..352447f 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -82,10 +82,6 @@
 import org.junit.rules.TestRule;
 
 import java.io.IOException;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -209,12 +205,6 @@
         mTargetContext.unregisterReceiver(broadcastReceiver);
     }
 
-    // Annotation for tests that need to be run in portrait and landscape modes.
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
-    protected @interface PortraitLandscape {
-    }
-
     protected TestRule getRulesInsideActivityMonitor() {
         final ViewCaptureRule viewCaptureRule = new ViewCaptureRule();
         final RuleChain inner = RuleChain
diff --git a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
index 266f0ae..f0875f8 100644
--- a/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
+++ b/tests/src/com/android/launcher3/ui/PortraitLandscapeRunner.java
@@ -9,10 +9,21 @@
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-class PortraitLandscapeRunner implements TestRule {
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+public class PortraitLandscapeRunner implements TestRule {
     private static final String TAG = "PortraitLandscapeRunner";
     private AbstractLauncherUiTest mTest;
 
+    // Annotation for tests that need to be run in portrait and landscape modes.
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface PortraitLandscape {
+    }
+
     public PortraitLandscapeRunner(AbstractLauncherUiTest test) {
         mTest = test;
     }
@@ -20,7 +31,7 @@
     @Override
     public Statement apply(Statement base, Description description) {
         if (!TestHelpers.isInLauncherProcess() ||
-                description.getAnnotation(AbstractLauncherUiTest.PortraitLandscape.class) == null) {
+                description.getAnnotation(PortraitLandscape.class) == null) {
             return base;
         }
 
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 9676cb3..a12d10b 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -55,6 +55,7 @@
 import com.android.launcher3.tapl.HomeAppIconMenuItem;
 import com.android.launcher3.tapl.Widgets;
 import com.android.launcher3.tapl.Workspace;
+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.ScreenRecord;
diff --git a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
index e9a2b0f..3806648 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddConfigWidgetTest.java
@@ -34,6 +34,7 @@
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.testcomponent.WidgetConfigActivity;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TestViewHelpers;
 import com.android.launcher3.util.Wait;
 import com.android.launcher3.util.rule.ShellCommandRule;
diff --git a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
index 6d858e0..028b9b6 100644
--- a/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/AddWidgetTest.java
@@ -30,6 +30,7 @@
 import com.android.launcher3.tapl.Widget;
 import com.android.launcher3.tapl.WidgetResizeFrame;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TestViewHelpers;
 import com.android.launcher3.util.rule.ShellCommandRule;
 import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
diff --git a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
index c4b6d43..0b2f335 100644
--- a/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/TwoPanelWorkspaceTest.java
@@ -29,6 +29,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.tapl.Workspace;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
 import com.android.launcher3.ui.TaplTestsLauncher3;
 import com.android.launcher3.util.LauncherLayoutBuilder;
 import com.android.launcher3.util.TestUtil;
diff --git a/tests/src/com/android/launcher3/util/DisplayControllerTest.kt b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
new file mode 100644
index 0000000..8e4e998
--- /dev/null
+++ b/tests/src/com/android/launcher3/util/DisplayControllerTest.kt
@@ -0,0 +1,159 @@
+/*
+ * 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.util
+
+import android.content.Context
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.graphics.Point
+import android.graphics.Rect
+import android.hardware.display.DisplayManager
+import android.util.ArrayMap
+import android.util.DisplayMetrics
+import android.view.Display
+import android.view.Surface
+import androidx.test.annotation.UiThreadTest
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.LauncherPrefs
+import com.android.launcher3.util.DisplayController.CHANGE_DENSITY
+import com.android.launcher3.util.DisplayController.CHANGE_ROTATION
+import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener
+import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext
+import com.android.launcher3.util.window.CachedDisplayInfo
+import com.android.launcher3.util.window.WindowManagerProxy
+import kotlin.math.min
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+import org.mockito.stubbing.Answer
+
+/** Unit tests for {@link DisplayController} */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DisplayControllerTest {
+
+    private val appContext: Context = ApplicationProvider.getApplicationContext()
+
+    @Mock private lateinit var context: SandboxContext
+    @Mock private lateinit var windowManagerProxy: WindowManagerProxy
+    @Mock private lateinit var launcherPrefs: LauncherPrefs
+    @Mock private lateinit var displayManager: DisplayManager
+    @Mock private lateinit var display: Display
+    @Mock private lateinit var resources: Resources
+    @Mock private lateinit var displayInfoChangeListener: DisplayInfoChangeListener
+
+    private lateinit var displayController: DisplayController
+
+    private val width = 2208
+    private val height = 1840
+    private val inset = 110
+    private val densityDpi = 420
+    private val density = densityDpi / DisplayMetrics.DENSITY_DEFAULT.toFloat()
+    private val bounds =
+        arrayOf(
+            WindowBounds(Rect(0, 0, width, height), Rect(0, inset, 0, 0), Surface.ROTATION_0),
+            WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_90),
+            WindowBounds(Rect(0, 0, width, height), Rect(0, inset, 0, 0), Surface.ROTATION_180),
+            WindowBounds(Rect(0, 0, height, width), Rect(0, inset, 0, 0), Surface.ROTATION_270)
+        )
+    private val configuration =
+        Configuration(appContext.resources.configuration).apply {
+            densityDpi = this@DisplayControllerTest.densityDpi
+            screenWidthDp = (bounds[0].bounds.width() / density).toInt()
+            screenHeightDp = (bounds[0].bounds.height() / density).toInt()
+            smallestScreenWidthDp = min(screenWidthDp, screenHeightDp)
+        }
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        whenever(context.getObject(eq(WindowManagerProxy.INSTANCE))).thenReturn(windowManagerProxy)
+        whenever(context.getObject(eq(LauncherPrefs.INSTANCE))).thenReturn(launcherPrefs)
+
+        // Mock WindowManagerProxy
+        val displayInfo =
+            CachedDisplayInfo(Point(width, height), Surface.ROTATION_0, Rect(0, 0, 0, 0))
+        whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo)
+        whenever(windowManagerProxy.estimateInternalDisplayBounds(any()))
+            .thenAnswer(
+                Answer {
+                    // Always create a new copy of bounds
+                    val perDisplayBounds = ArrayMap<CachedDisplayInfo, List<WindowBounds>>()
+                    perDisplayBounds[displayInfo] = bounds.toList()
+                    return@Answer perDisplayBounds
+                }
+            )
+        whenever(windowManagerProxy.getRealBounds(any(), any())).thenAnswer { i ->
+            bounds[i.getArgument<CachedDisplayInfo>(1).rotation]
+        }
+
+        // Mock context
+        whenever(context.createWindowContext(any(), any(), nullable())).thenReturn(context)
+        whenever(context.getSystemService(eq(DisplayManager::class.java)))
+            .thenReturn(displayManager)
+        doNothing().`when`(context).registerComponentCallbacks(any())
+
+        // Mock display
+        whenever(display.rotation).thenReturn(displayInfo.rotation)
+        whenever(context.display).thenReturn(display)
+        whenever(displayManager.getDisplay(any())).thenReturn(display)
+
+        // Mock resources
+        whenever(resources.configuration).thenReturn(configuration)
+        whenever(context.resources).thenReturn(resources)
+
+        // Initialize DisplayController
+        displayController = DisplayController(context)
+        displayController.addChangeListener(displayInfoChangeListener)
+    }
+
+    @Test
+    @UiThreadTest
+    fun testRotation() {
+        val displayInfo =
+            CachedDisplayInfo(Point(height, width), Surface.ROTATION_90, Rect(0, 0, 0, 0))
+        whenever(windowManagerProxy.getDisplayInfo(any())).thenReturn(displayInfo)
+        whenever(display.rotation).thenReturn(displayInfo.rotation)
+        val configuration =
+            Configuration(configuration).apply {
+                screenWidthDp = configuration.screenHeightDp
+                screenHeightDp = configuration.screenWidthDp
+            }
+        whenever(resources.configuration).thenReturn(configuration)
+
+        displayController.onConfigurationChanged(configuration)
+
+        verify(displayInfoChangeListener).onDisplayInfoChanged(any(), any(), eq(CHANGE_ROTATION))
+    }
+
+    @Test
+    @UiThreadTest
+    fun testFontScale() {
+        val configuration = Configuration(configuration).apply { fontScale = 1.2f }
+        whenever(resources.configuration).thenReturn(configuration)
+
+        displayController.onConfigurationChanged(configuration)
+
+        verify(displayInfoChangeListener).onDisplayInfoChanged(any(), any(), eq(CHANGE_DENSITY))
+    }
+}
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 976afcd..9dc04a1 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -15,34 +15,31 @@
  */
 package com.android.launcher3.util;
 
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL;
+
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
-import static com.android.launcher3.LauncherSettings.Favorites.CONTENT_URI;
+import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import static com.android.launcher3.util.TestUtil.runOnExecutorSync;
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
 
-import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.SessionParams;
 import android.content.pm.PackageManager;
 import android.content.pm.ProviderInfo;
-import android.content.res.Resources;
-import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Color;
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
-import android.os.Process;
 import android.provider.Settings;
 import android.test.mock.MockContentResolver;
 import android.util.ArrayMap;
@@ -57,13 +54,10 @@
 import com.android.launcher3.LauncherModel.ModelUpdateTask;
 import com.android.launcher3.LauncherPrefs;
 import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.model.AllAppsList;
 import com.android.launcher3.model.BgDataModel;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.ItemInstallQueue;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.pm.UserCache;
 import com.android.launcher3.testing.TestInformationProvider;
@@ -72,37 +66,25 @@
 import com.android.launcher3.util.window.WindowManagerProxy;
 import com.android.launcher3.widget.custom.CustomWidgetManager;
 
-import org.mockito.ArgumentCaptor;
-
-import java.io.BufferedReader;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.InputStreamReader;
+import java.io.IOException;
 import java.io.OutputStreamWriter;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executor;
-import java.util.function.Function;
 
 /**
  * Utility class to help manage Launcher Model and related objects for test.
  */
 public class LauncherModelHelper {
 
-    public static final int DESKTOP = LauncherSettings.Favorites.CONTAINER_DESKTOP;
-    public static final int HOTSEAT = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
-
-    public static final int APP_ICON = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-    public static final int SHORTCUT = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
-    public static final int NO__ICON = -1;
-
-    public static final String TEST_PACKAGE = testContext().getPackageName();
+    public static final String TEST_PACKAGE = getInstrumentation().getContext().getPackageName();
     public static final String TEST_ACTIVITY = "com.android.launcher3.tests.Activity2";
+    public static final String TEST_ACTIVITY2 = "com.android.launcher3.tests.Activity3";
+    public static final String TEST_ACTIVITY3 = "com.android.launcher3.tests.Activity4";
 
     // Authority for providing a test default-workspace-layout data.
     private static final String TEST_PROVIDER_AUTHORITY =
@@ -110,39 +92,18 @@
     private static final int DEFAULT_BITMAP_SIZE = 10;
     private static final int DEFAULT_GRID_SIZE = 4;
 
-    private final HashMap<Class, HashMap<String, Field>> mFieldCache = new HashMap<>();
-    private final MockContentResolver mMockResolver = new MockContentResolver();
-    public final TestLauncherProvider provider;
     public final SandboxModelContext sandboxContext;
 
-    public final long defaultProfileId;
+    private final RunnableList mDestroyTask = new RunnableList();
 
     private BgDataModel mDataModel;
-    private AllAppsList mAllAppsList;
 
     public LauncherModelHelper() {
-        Context context = getApplicationContext();
-        // System settings cache content provider. Ensure that they are statically initialized
-        Settings.Secure.getString(context.getContentResolver(), "test");
-        Settings.System.getString(context.getContentResolver(), "test");
-        Settings.Global.getString(context.getContentResolver(), "test");
-
-        provider = new TestLauncherProvider();
         sandboxContext = new SandboxModelContext();
-        defaultProfileId = UserCache.INSTANCE.get(sandboxContext)
-                .getSerialNumberForUser(Process.myUserHandle());
-        setupProvider(LauncherProvider.AUTHORITY, provider);
     }
 
     public void setupProvider(String authority, ContentProvider provider) {
-        ProviderInfo providerInfo = new ProviderInfo();
-        providerInfo.authority = authority;
-        providerInfo.applicationInfo = sandboxContext.getApplicationInfo();
-        provider.attachInfo(sandboxContext, providerInfo);
-        mMockResolver.addProvider(providerInfo.authority, provider);
-        doReturn(providerInfo)
-                .when(sandboxContext.mPm)
-                .resolveContentProvider(eq(authority), anyInt());
+        sandboxContext.setupProvider(authority, provider);
     }
 
     public LauncherModel getModel() {
@@ -151,16 +112,35 @@
 
     public synchronized BgDataModel getBgDataModel() {
         if (mDataModel == null) {
-            mDataModel = ReflectionHelpers.getField(getModel(), "mBgDataModel");
+            getModel().enqueueModelUpdateTask(new ModelUpdateTask() {
+                @Override
+                public void init(@NonNull LauncherAppState app, @NonNull LauncherModel model,
+                        @NonNull BgDataModel dataModel, @NonNull AllAppsList allAppsList,
+                        @NonNull Executor uiExecutor) {
+                    mDataModel = dataModel;
+                }
+
+                @Override
+                public void run() { }
+            });
         }
         return mDataModel;
     }
 
-    public synchronized AllAppsList getAllAppsList() {
-        if (mAllAppsList == null) {
-            mAllAppsList = ReflectionHelpers.getField(getModel(), "mBgAllAppsList");
-        }
-        return mAllAppsList;
+    /**
+     * Creates a installer session for the provided package.
+     */
+    public int createInstallerSession(String pkg) throws IOException {
+        SessionParams sp = new SessionParams(MODE_FULL_INSTALL);
+        sp.setAppPackageName(pkg);
+        Bitmap icon = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+        icon.eraseColor(Color.RED);
+        sp.setAppIcon(icon);
+        sp.setAppLabel(pkg);
+        PackageInstaller pi = sandboxContext.getPackageManager().getPackageInstaller();
+        int sessionId = pi.createSession(sp);
+        mDestroyTask.add(() -> pi.abandonSession(sessionId));
+        return sessionId;
     }
 
     public void destroy() {
@@ -175,6 +155,8 @@
         waitOrThrow(l1);
         sandboxContext.onDestroy();
         l2.countDown();
+
+        mDestroyTask.executeAllAndDestroy();
     }
 
     private void waitOrThrow(CountDownLatch latch) {
@@ -186,184 +168,6 @@
     }
 
     /**
-     * Synchronously executes the task and returns all the UI callbacks posted.
-     */
-    public List<Runnable> executeTaskForTest(ModelUpdateTask task) throws Exception {
-        LauncherModel model = getModel();
-        if (!model.isModelLoaded()) {
-            ReflectionHelpers.setField(model, "mModelLoaded", true);
-        }
-        Executor mockExecutor = mock(Executor.class);
-        model.enqueueModelUpdateTask(new ModelUpdateTask() {
-            @Override
-            public void init(@NonNull final LauncherAppState app,
-                    @NonNull final LauncherModel model, @NonNull final BgDataModel dataModel,
-                    @NonNull final AllAppsList allAppsList, @NonNull final Executor uiExecutor) {
-                task.init(app, model, dataModel, allAppsList, mockExecutor);
-            }
-
-            @Override
-            public void run() {
-                task.run();
-            }
-        });
-        MODEL_EXECUTOR.submit(() -> null).get();
-
-        ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
-        verify(mockExecutor, atLeast(0)).execute(captor.capture());
-        return captor.getAllValues();
-    }
-
-    /**
-     * Synchronously executes a task on the model
-     */
-    public <T> T executeSimpleTask(Function<BgDataModel, T> task) throws Exception {
-        BgDataModel dataModel = getBgDataModel();
-        return MODEL_EXECUTOR.submit(() -> task.apply(dataModel)).get();
-    }
-
-    /**
-     * Initializes mock data for the test.
-     */
-    public void initializeData(String resourceName) throws Exception {
-        BgDataModel bgDataModel = getBgDataModel();
-        AllAppsList allAppsList = getAllAppsList();
-
-        MODEL_EXECUTOR.submit(() -> {
-            // Copy apk from resources to a local file and install from there.
-            Resources resources = testContext().getResources();
-            int resId = resources.getIdentifier(
-                    resourceName, "raw", testContext().getPackageName());
-            try (BufferedReader reader = new BufferedReader(new InputStreamReader(
-                    resources.openRawResource(resId)))) {
-                String line;
-                HashMap<String, Class> classMap = new HashMap<>();
-                while ((line = reader.readLine()) != null) {
-                    line = line.trim();
-                    if (line.startsWith("#") || line.isEmpty()) {
-                        continue;
-                    }
-                    String[] commands = line.split(" ");
-                    switch (commands[0]) {
-                        case "classMap":
-                            classMap.put(commands[1], Class.forName(commands[2]));
-                            break;
-                        case "bgItem":
-                            bgDataModel.addItem(sandboxContext,
-                                    (ItemInfo) initItem(classMap.get(commands[1]), commands, 2),
-                                    false);
-                            break;
-                        case "allApps":
-                            allAppsList.add((AppInfo) initItem(AppInfo.class, commands, 1), null);
-                            break;
-                    }
-                }
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }).get();
-    }
-
-    private Object initItem(Class clazz, String[] fieldDef, int startIndex) throws Exception {
-        HashMap<String, Field> cache = mFieldCache.get(clazz);
-        if (cache == null) {
-            cache = new HashMap<>();
-            Class c = clazz;
-            while (c != null) {
-                for (Field f : c.getDeclaredFields()) {
-                    f.setAccessible(true);
-                    cache.put(f.getName(), f);
-                }
-                c = c.getSuperclass();
-            }
-            mFieldCache.put(clazz, cache);
-        }
-
-        Object item = clazz.newInstance();
-        for (int i = startIndex; i < fieldDef.length; i++) {
-            String[] fieldData = fieldDef[i].split("=", 2);
-            Field f = cache.get(fieldData[0]);
-            Class type = f.getType();
-            if (type == int.class || type == long.class) {
-                f.set(item, Integer.parseInt(fieldData[1]));
-            } else if (type == CharSequence.class || type == String.class) {
-                f.set(item, fieldData[1]);
-            } else if (type == Intent.class) {
-                if (!fieldData[1].startsWith("#Intent")) {
-                    fieldData[1] = "#Intent;" + fieldData[1] + ";end";
-                }
-                f.set(item, Intent.parseUri(fieldData[1], 0));
-            } else if (type == ComponentName.class) {
-                f.set(item, ComponentName.unflattenFromString(fieldData[1]));
-            } else {
-                throw new Exception("Added parsing logic for "
-                        + f.getName() + " of type " + f.getType());
-            }
-        }
-        return item;
-    }
-
-    public int addItem(int type, int screen, int container, int x, int y) {
-        return addItem(type, screen, container, x, y, defaultProfileId, TEST_PACKAGE);
-    }
-
-    public int addItem(int type, int screen, int container, int x, int y, long profileId) {
-        return addItem(type, screen, container, x, y, profileId, TEST_PACKAGE);
-    }
-
-    public int addItem(int type, int screen, int container, int x, int y, String packageName) {
-        return addItem(type, screen, container, x, y, defaultProfileId, packageName);
-    }
-
-    public int addItem(int type, int screen, int container, int x, int y, String packageName,
-            int id, Uri contentUri) {
-        addItem(type, screen, container, x, y, defaultProfileId, packageName, id, contentUri);
-        return id;
-    }
-
-    /**
-     * Adds a mock item in the DB.
-     * @param type {@link #APP_ICON} or {@link #SHORTCUT} or >= 2 for
-     *             folder (where the type represents the number of items in the folder).
-     */
-    public int addItem(int type, int screen, int container, int x, int y, long profileId,
-            String packageName) {
-        int id = LauncherSettings.Settings.call(sandboxContext.getContentResolver(),
-                LauncherSettings.Settings.METHOD_NEW_ITEM_ID)
-                .getInt(LauncherSettings.Settings.EXTRA_VALUE);
-        addItem(type, screen, container, x, y, profileId, packageName, id, CONTENT_URI);
-        return id;
-    }
-
-    public void addItem(int type, int screen, int container, int x, int y, long profileId,
-            String packageName, int id, Uri contentUri) {
-        ContentValues values = new ContentValues();
-        values.put(LauncherSettings.Favorites._ID, id);
-        values.put(LauncherSettings.Favorites.CONTAINER, container);
-        values.put(LauncherSettings.Favorites.SCREEN, screen);
-        values.put(LauncherSettings.Favorites.CELLX, x);
-        values.put(LauncherSettings.Favorites.CELLY, y);
-        values.put(LauncherSettings.Favorites.SPANX, 1);
-        values.put(LauncherSettings.Favorites.SPANY, 1);
-        values.put(LauncherSettings.Favorites.PROFILE_ID, profileId);
-
-        if (type == APP_ICON || type == SHORTCUT) {
-            values.put(LauncherSettings.Favorites.ITEM_TYPE, type);
-            values.put(LauncherSettings.Favorites.INTENT,
-                    new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
-        } else {
-            values.put(LauncherSettings.Favorites.ITEM_TYPE,
-                    LauncherSettings.Favorites.ITEM_TYPE_FOLDER);
-            // Add folder items.
-            for (int i = 0; i < type; i++) {
-                addItem(APP_ICON, 0, id, 0, 0, profileId);
-            }
-        }
-
-        sandboxContext.getContentResolver().insert(contentUri, values);
-    }
-
-    /**
      * Sets up a mock provider to load the provided layout by default, next time the layout loads
      */
     public LauncherModelHelper setupDefaultLayoutProvider(LauncherLayoutBuilder builder)
@@ -394,6 +198,9 @@
             }
         };
         setupProvider(TEST_PROVIDER_AUTHORITY, cp);
+        mDestroyTask.add(() -> runOnExecutorSync(MODEL_EXECUTOR, () ->
+                UiDevice.getInstance(getInstrumentation()).executeShellCommand(
+                        "settings delete secure launcher3.layout.provider")));
         return this;
     }
 
@@ -402,46 +209,16 @@
      */
     public void loadModelSync() throws ExecutionException, InterruptedException {
         Callbacks mockCb = new Callbacks() { };
-        Executors.MAIN_EXECUTOR.submit(() -> getModel().addCallbacksAndLoad(mockCb)).get();
+        MAIN_EXECUTOR.submit(() -> getModel().addCallbacksAndLoad(mockCb)).get();
 
         Executors.MODEL_EXECUTOR.submit(() -> { }).get();
-        Executors.MAIN_EXECUTOR.submit(() -> { }).get();
-        Executors.MAIN_EXECUTOR.submit(() -> getModel().removeCallbacks(mockCb)).get();
+        MAIN_EXECUTOR.submit(() -> { }).get();
+        MAIN_EXECUTOR.submit(() -> getModel().removeCallbacks(mockCb)).get();
     }
 
-    /**
-     * An extension of LauncherProvider backed up by in-memory database.
-     */
-    public static class TestLauncherProvider extends LauncherProvider {
+    public static class SandboxModelContext extends SandboxContext {
 
-        @Override
-        public boolean onCreate() {
-            return true;
-        }
-
-        public SQLiteDatabase getDb() {
-            return getModelDbController().getDb();
-        }
-    }
-
-    public static boolean deleteContents(File dir) {
-        File[] files = dir.listFiles();
-        boolean success = true;
-        if (files != null) {
-            for (File file : files) {
-                if (file.isDirectory()) {
-                    success &= deleteContents(file);
-                }
-                if (!file.delete()) {
-                    success = false;
-                }
-            }
-        }
-        return success;
-    }
-
-    public class SandboxModelContext extends SandboxContext {
-
+        private final MockContentResolver mMockResolver = new MockContentResolver();
         private final ArrayMap<String, Object> mSpiedServices = new ArrayMap<>();
         private final PackageManager mPm;
         private final File mDbDir;
@@ -453,8 +230,31 @@
                     DisplayController.INSTANCE, CustomWidgetManager.INSTANCE,
                     SettingsCache.INSTANCE, PluginManagerWrapper.INSTANCE, LockedUserState.INSTANCE,
                     ItemInstallQueue.INSTANCE, WindowManagerProxy.INSTANCE);
+
+            // System settings cache content provider. Ensure that they are statically initialized
+            Settings.Secure.getString(
+                    ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+            Settings.System.getString(
+                    ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+            Settings.Global.getString(
+                    ApplicationProvider.getApplicationContext().getContentResolver(), "test");
+
             mPm = spy(getBaseContext().getPackageManager());
             mDbDir = new File(getCacheDir(), UUID.randomUUID().toString());
+            setupProvider(LauncherProvider.AUTHORITY, new LauncherProvider() {
+                @Override
+                public boolean onCreate() {
+                    return true;
+                }
+            });
+        }
+
+        @Override
+        protected <T> T createObject(MainThreadInitializedObject<T> object) {
+            if (object == LauncherAppState.INSTANCE) {
+                return (T) new LauncherAppState(this, null /* iconCacheFileName */);
+            }
+            return super.createObject(object);
         }
 
         public SandboxModelContext allow(MainThreadInitializedObject object) {
@@ -505,9 +305,30 @@
             mSpiedServices.put(name, result);
             return result;
         }
-    }
 
-    private static Context testContext() {
-        return getInstrumentation().getContext();
+        public void setupProvider(String authority, ContentProvider provider) {
+            ProviderInfo providerInfo = new ProviderInfo();
+            providerInfo.authority = authority;
+            providerInfo.applicationInfo = getApplicationInfo();
+            provider.attachInfo(this, providerInfo);
+            mMockResolver.addProvider(providerInfo.authority, provider);
+            doReturn(providerInfo).when(mPm).resolveContentProvider(eq(authority), anyInt());
+        }
+
+        private static boolean deleteContents(File dir) {
+            File[] files = dir.listFiles();
+            boolean success = true;
+            if (files != null) {
+                for (File file : files) {
+                    if (file.isDirectory()) {
+                        success &= deleteContents(file);
+                    }
+                    if (!file.delete()) {
+                        success = false;
+                    }
+                }
+            }
+            return success;
+        }
     }
 }
diff --git a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt b/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
index 84156e7..92ab2cb 100644
--- a/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
+++ b/tests/src/com/android/launcher3/util/LockedUserStateTest.kt
@@ -32,7 +32,7 @@
 import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
 
-/** Unit tests for {@link LockedUserUtil} */
+/** Unit tests for {@link LockedUserState} */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 class LockedUserStateTest {
@@ -49,40 +49,31 @@
     @Test
     fun runOnUserUnlocked_runs_action_immediately_if_already_unlocked() {
         `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
-        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
         val action: Runnable = mock()
-
-        LockedUserState.get(context).runOnUserUnlocked(action)
+        LockedUserState(context).runOnUserUnlocked(action)
         verify(action).run()
     }
 
     @Test
     fun runOnUserUnlocked_waits_to_run_action_until_user_is_unlocked() {
         `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
-        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
         val action: Runnable = mock()
-
-        LockedUserState.get(context).runOnUserUnlocked(action)
+        val state = LockedUserState(context)
+        state.runOnUserUnlocked(action)
         verifyZeroInteractions(action)
-
-        LockedUserState.get(context)
-            .mUserUnlockedReceiver
-            .onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
-
+        state.mUserUnlockedReceiver.onReceive(context, Intent(Intent.ACTION_USER_UNLOCKED))
         verify(action).run()
     }
 
     @Test
     fun isUserUnlocked_returns_true_when_user_is_unlocked() {
         `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(true)
-        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
-        assertThat(LockedUserState.get(context).isUserUnlocked).isTrue()
+        assertThat(LockedUserState(context).isUserUnlocked).isTrue()
     }
 
     @Test
     fun isUserUnlocked_returns_false_when_user_is_locked() {
         `when`(userManager.isUserUnlocked(Process.myUserHandle())).thenReturn(false)
-        LockedUserState.INSTANCE.initializeForTesting(LockedUserState(context))
-        assertThat(LockedUserState.get(context).isUserUnlocked).isFalse()
+        assertThat(LockedUserState(context).isUserUnlocked).isFalse()
     }
 }
diff --git a/tests/src/com/android/launcher3/util/TestUtil.java b/tests/src/com/android/launcher3/util/TestUtil.java
index f8cd995..14bc8b9 100644
--- a/tests/src/com/android/launcher3/util/TestUtil.java
+++ b/tests/src/com/android/launcher3/util/TestUtil.java
@@ -53,6 +53,7 @@
 import java.io.OutputStream;
 import java.security.MessageDigest;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
 import java.util.function.Predicate;
 import java.util.function.ToIntFunction;
 
@@ -159,6 +160,30 @@
             Settings.Secure.putString(context.getContentResolver(), LAYOUT_DIGEST_KEY, null);
     }
 
+    /**
+     * Utility method to run a task synchronously which converts any exceptions to RuntimeException
+     */
+    public static void runOnExecutorSync(ExecutorService executor, UncheckedRunnable task) {
+        try {
+            executor.submit(() -> {
+                try {
+                    task.run();
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }).get();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** Interface to indicate a runnable which can throw any exception. */
+    public interface UncheckedRunnable {
+        /** Method to run the task */
+        void run() throws Exception;
+    }
+
+
     private static class PackageInstallCheck extends LauncherApps.Callback
             implements AutoCloseable {
 
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 5a96d95..31e9aa2 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -18,6 +18,8 @@
 
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
 
+import static com.android.launcher3.tapl.LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS;
+import static com.android.launcher3.tapl.LauncherInstrumentation.EVENT_TOUCH_UP_TIS;
 import static com.android.launcher3.tapl.OverviewTask.TASK_START_EVENT;
 import static com.android.launcher3.testing.shared.TestProtocol.OVERVIEW_STATE_ORDINAL;
 
@@ -138,6 +140,10 @@
                     mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
                             LauncherInstrumentation.EVENT_TOUCH_UP);
                 }
+                if (mLauncher.isTrackpadGestureEnabled()) {
+                    mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+                    mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                }
                 mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
                 mLauncher.runToState(
                         () -> mLauncher.waitForNavigationUiObject("recent_apps").click(),
@@ -280,6 +286,10 @@
                         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
                                 LauncherInstrumentation.EVENT_TOUCH_UP);
                     }
+                    if (mLauncher.isTrackpadGestureEnabled()) {
+                        mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+                        mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                    }
                     mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
                     mLauncher.runToState(() -> recentsButton.click(), OVERVIEW_STATE_ORDINAL,
                             "clicking Recents button for the first time");
@@ -290,6 +300,10 @@
                         mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
                                 LauncherInstrumentation.EVENT_TOUCH_UP);
                     }
+                    if (mLauncher.isTrackpadGestureEnabled()) {
+                        mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+                        mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                    }
                     mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
                     mLauncher.executeAndWaitForEvent(
                             () -> recentsButton.click(),
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2adfc98..0aefd68 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1035,6 +1035,10 @@
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
                 }
+                if (isTrackpadGestureEnabled()) {
+                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                }
 
                 runToState(
                         waitForNavigationUiObject("home")::click,
@@ -1074,6 +1078,10 @@
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP);
                 }
+                if (isTrackpadGestureEnabled()) {
+                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+                    expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+                }
             }
             if (launcherVisible) {
                 if (getContext().getApplicationInfo().isOnBackInvokedCallbackEnabled()) {
@@ -1646,9 +1654,14 @@
     }
 
     private boolean hasTIS() {
-        return getTestInfo(TestProtocol.REQUEST_HAS_TIS).getBoolean(TestProtocol.REQUEST_HAS_TIS);
+        return getTestInfo(TestProtocol.REQUEST_HAS_TIS).getBoolean(
+                TestProtocol.TEST_INFO_RESPONSE_FIELD);
     }
 
+    boolean isTrackpadGestureEnabled() {
+        return getTestInfo(TestProtocol.REQUEST_IS_TRACKPAD_GESTURE_ENABLED).getBoolean(
+                TestProtocol.TEST_INFO_RESPONSE_FIELD);
+    }
 
     public void sendPointer(long downTime, long currentTime, int action, Point point,
             GestureScope gestureScope) {
@@ -1660,7 +1673,8 @@
                         && gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
                     expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
                 }
-                if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
+                if (hasTIS && (isTrackpadGestureEnabled()
+                        || getNavigationModel() != NavigationModel.THREE_BUTTON)) {
                     expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
                 }
                 break;
@@ -1679,7 +1693,8 @@
                                     || gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
                                     ? EVENT_TOUCH_UP : EVENT_TOUCH_CANCEL);
                 }
-                if (hasTIS && getNavigationModel() != NavigationModel.THREE_BUTTON) {
+                if (hasTIS && (isTrackpadGestureEnabled()
+                        || getNavigationModel() != NavigationModel.THREE_BUTTON)) {
                     expectEvent(TestProtocol.SEQUENCE_TIS,
                             gestureScope == GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
                                     || gestureScope == GestureScope.OUTSIDE_WITH_KEYCODE
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
index 386deac..2f7596e 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewActions.java
@@ -51,7 +51,7 @@
                     "clicked screenshot button")) {
                 UiObject2 closeScreenshot = mLauncher.waitForSystemUiObject(
                         "screenshot_dismiss_image");
-                if (mLauncher.getNavigationModel()
+                if (mLauncher.isTrackpadGestureEnabled() || mLauncher.getNavigationModel()
                         != LauncherInstrumentation.NavigationModel.THREE_BUTTON) {
                     mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS,
                             LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS);