Merge "[Search][Motion] Separate AllApps scrim and content interpolation" into sc-dev
diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml
index c1a746f..9b22c62 100644
--- a/quickstep/res/values-as/strings.xml
+++ b/quickstep/res/values-as/strings.xml
@@ -30,7 +30,7 @@
     <string name="time_left_for_app" msgid="3111996412933644358">"আজি <xliff:g id="TIME">%1$s</xliff:g> বাকী আছ"</string>
     <string name="title_app_suggestions" msgid="4185902664111965088">"এপ চাজেশ্বন"</string>
     <string name="all_apps_label" msgid="8542784161730910663">"সকলো এপ্"</string>
-    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"আপোনাৰ অনুমানিক এপ্"</string>
+    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"আপোনাৰ প্ৰয়োজন হ\'ব পৰা এপ্"</string>
     <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"আপোনাৰ গৃহ স্ক্ৰীনৰ একেবাৰে তলৰ শাৰীটোত এপৰ পৰামর্শসমূহ পাওক"</string>
     <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"আপোনাৰ গৃহ স্ক্ৰীনৰ প্ৰিয় সমলৰ শাৰীটোত এপৰ পৰামর্শসমূহ পাওক"</string>
     <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"আপোনাৰ সকলোতকৈ বেছিকৈ ব্যৱহৃত এপ্‌সমূহ গৃহ স্ক্ৰীনতে সহজে এক্সেছ কৰক। আপোনাৰ ৰুটিনসমূহৰ ভিত্তিত পৰামর্শসমূহ সলনি হ\'ব। একেবাৰে তলৰ শাৰীটোত থকা এপ্‌সমূহ ওপৰৰ আপোনাৰ গৃহ স্ক্ৰীনলৈ যাব।"</string>
diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml
index 846f68a..9310d71 100644
--- a/quickstep/res/values-gl/strings.xml
+++ b/quickstep/res/values-gl/strings.xml
@@ -30,7 +30,7 @@
     <string name="time_left_for_app" msgid="3111996412933644358">"Tempo restante hoxe <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="title_app_suggestions" msgid="4185902664111965088">"Suxestións de aplicacións"</string>
     <string name="all_apps_label" msgid="8542784161730910663">"Todas as aplicacións"</string>
-    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"As túas aplicacións preditas"</string>
+    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Previsión das túas aplicacións"</string>
     <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Recibe suxestións de aplicacións na fila inferior da pantalla de inicio"</string>
     <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Recibe suxestións de aplicacións na fila de Favoritos da pantalla de inicio"</string>
     <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Accede facilmente desde a pantalla de inicio ás aplicacións que máis usas. As suxestións irán cambiando en función das túas rutinas. As aplicacións da fila inferior pasarán á pantalla de inicio."</string>
diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml
index 1ec2709..496d33b 100644
--- a/quickstep/res/values-gu/strings.xml
+++ b/quickstep/res/values-gu/strings.xml
@@ -78,8 +78,7 @@
     <string name="action_screenshot" msgid="8171125848358142917">"સ્ક્રીનશૉટ"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ઍપ કે તમારી સંસ્થા દ્વારા આ ક્રિયા કરવાની મંજૂરી નથી"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"નૅવિગેશન ટ્યૂટૉરિઅલ છોડી દઈએ?"</string>
-    <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
-    <skip />
+    <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"તમે આને પછીથી <xliff:g id="NAME">%1$s</xliff:g> ઍપમાં જોઈ શકો છો"</string>
     <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"રદ કરો"</string>
     <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"છોડો"</string>
 </resources>
diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml
index 31182b6..8fdba69 100644
--- a/quickstep/res/values-kn/strings.xml
+++ b/quickstep/res/values-kn/strings.xml
@@ -30,7 +30,7 @@
     <string name="time_left_for_app" msgid="3111996412933644358">"ಇಂದು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಉಳಿದಿದೆ"</string>
     <string name="title_app_suggestions" msgid="4185902664111965088">"ಆ್ಯಪ್ ಸಲಹೆಗಳು"</string>
     <string name="all_apps_label" msgid="8542784161730910663">"ಎಲ್ಲಾ ಆ್ಯಪ್‌ಗಳು"</string>
-    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"ನಿಮ್ಮ ಸಂಭವನೀಯ ಆ್ಯಪ್‌ಗಳು"</string>
+    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"ನಿಮ್ಮ ಮುನ್ಸೂಚಿತ ಆ್ಯಪ್‌ಗಳು"</string>
     <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ನ ಕೆಳಭಾಗದ ಸಾಲಿನಲ್ಲಿ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ"</string>
     <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ನ ಮೆಚ್ಚಿನವುಗಳ ಸಾಲಿನಲ್ಲಿ ಆ್ಯಪ್ ಸಲಹೆಗಳನ್ನು ಪಡೆಯಿರಿ"</string>
     <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿಯೇ ನೀವು ಹೆಚ್ಚು ಬಳಸಿದ ಆ್ಯಪ್‌ಗಳನ್ನು ಸುಲಭವಾಗಿ ಪ್ರವೇಶಿಸಿ. ನಿಮ್ಮ ದಿನಚರಿಯನ್ನು ಆಧರಿಸಿ ಸಲಹೆಗಳು ಬದಲಾಗುತ್ತವೆ. ಕೆಳಭಾಗದ ಸಾಲಿನಲ್ಲಿನ ಆ್ಯಪ್‌ಗಳು ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ ಚಲಿಸುತ್ತವೆ."</string>
@@ -78,8 +78,7 @@
     <string name="action_screenshot" msgid="8171125848358142917">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ಆ್ಯಪ್ ಅಥವಾ ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಕ್ರಿಯೆಯನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"ನ್ಯಾವಿಗೇಷನ್ ಟ್ಯುಟೋರಿಯಲ್ ಸ್ಕಿಪ್ ಮಾಡಿ?"</string>
-    <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
-    <skip />
+    <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್‌ನಲ್ಲಿ ಇದನ್ನು ನಂತರ ಕಾಣಬಹುದು"</string>
     <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"ರದ್ದುಮಾಡಿ"</string>
     <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"ಸ್ಕಿಪ್ ಮಾಡಿ"</string>
 </resources>
diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml
index d31b03a..c576cf1 100644
--- a/quickstep/res/values-mr/strings.xml
+++ b/quickstep/res/values-mr/strings.xml
@@ -78,8 +78,7 @@
     <string name="action_screenshot" msgid="8171125848358142917">"स्क्रीनशॉट"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"अ‍ॅप किंवा तुमच्या संस्थेद्वारे ही क्रिया करण्याची अनुमती नाही"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"नेव्हिगेशन ट्युटोरियल वगळायचे आहे का?"</string>
-    <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
-    <skip />
+    <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तुम्हाला हे नंतर <xliff:g id="NAME">%1$s</xliff:g> ॲपमध्ये मिळेल"</string>
     <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"रद्द करा"</string>
     <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"वगळा"</string>
 </resources>
diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml
index 6d31422..99ad814 100644
--- a/quickstep/res/values-ne/strings.xml
+++ b/quickstep/res/values-ne/strings.xml
@@ -30,7 +30,7 @@
     <string name="time_left_for_app" msgid="3111996412933644358">"आज: <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
     <string name="title_app_suggestions" msgid="4185902664111965088">"एपसम्बन्धी सुझावहरू"</string>
     <string name="all_apps_label" msgid="8542784161730910663">"सबै एपहरू"</string>
-    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"तपाईंका पूर्वानुमानित एपहरू"</string>
+    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"तपाईंलाई चाहिने एपहरू"</string>
     <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"तपाईंको गृह स्क्रिनको पुछारको पङ्क्तिमा सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्"</string>
     <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"आफ्नो होम स्क्रिनको मन पर्ने नामक पङ्क्तिमा सिफारिस गरिएका एपहरू प्राप्त गर्नुहोस्"</string>
     <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"गृह स्क्रिनबाटै आफूले सबैभन्दा बढी प्रयोग गर्ने एप सजिलै चलाउनुहोस्। सिफारिस गरिने एपहरूको क्रम तपाईंले एप प्रयोग गर्ने समयतालिकाअनुसार बदलिने छ। फेदको पङ्क्तिमा रहेका एपहरू तपाईंको गृह स्क्रिनको सिरानमा सर्ने छन्।"</string>
@@ -108,8 +108,7 @@
     <string name="blocked_by_policy" msgid="2071401072261365546">"यो एप वा तपाईंको सङ्गठनले यो कारबाही गर्ने अनुमति दिँदैन"</string>
     <!-- no translation found for skip_tutorial_dialog_title (2725643161260038458) -->
     <skip />
-    <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
-    <skip />
+    <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"तपाईं पछि <xliff:g id="NAME">%1$s</xliff:g> एपमा गई यो ट्युटोरियल भेट्टाउन सक्नुहुन्छ"</string>
     <!-- no translation found for gesture_tutorial_action_button_label_cancel (3809842569351264108) -->
     <skip />
     <!-- no translation found for gesture_tutorial_action_button_label_skip (394452764989751960) -->
diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml
index d1e30a2..c73c83e 100644
--- a/quickstep/res/values-te/strings.xml
+++ b/quickstep/res/values-te/strings.xml
@@ -78,8 +78,7 @@
     <string name="action_screenshot" msgid="8171125848358142917">"స్క్రీన్‌షాట్"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ఈ చర్యను యాప్ గానీ, మీ సంస్థ గానీ అనుమతించవు"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"నావిగేషన్ ట్యుటోరియల్‌ను స్కిప్ చేయాలా?"</string>
-    <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
-    <skip />
+    <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"<xliff:g id="NAME">%1$s</xliff:g> యాప్‌లో మీరు తర్వాత కనుగొనవచ్చు"</string>
     <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"రద్దు చేయి"</string>
     <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"స్కిప్ చేయి"</string>
 </resources>
diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml
index bfcc897..5ce95ad 100644
--- a/quickstep/res/values-ur/strings.xml
+++ b/quickstep/res/values-ur/strings.xml
@@ -78,8 +78,7 @@
     <string name="action_screenshot" msgid="8171125848358142917">"اسکرین شاٹ"</string>
     <string name="blocked_by_policy" msgid="2071401072261365546">"ایپ یا آپ کی تنظیم کی جانب سے اس کارروائی کی اجازت نہیں ہے"</string>
     <string name="skip_tutorial_dialog_title" msgid="2725643161260038458">"نیویگیشن کا ٹیوٹوریل نظر انداز کریں؟"</string>
-    <!-- no translation found for skip_tutorial_dialog_subtitle (544063326241955662) -->
-    <skip />
+    <string name="skip_tutorial_dialog_subtitle" msgid="544063326241955662">"آپ اسے بعد میں <xliff:g id="NAME">%1$s</xliff:g> ایپ میں تلاش کر سکتے ہیں"</string>
     <string name="gesture_tutorial_action_button_label_cancel" msgid="3809842569351264108">"منسوخ کریں"</string>
     <string name="gesture_tutorial_action_button_label_skip" msgid="394452764989751960">"نظر انداز کریں"</string>
 </resources>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 9d39100..fe5e553d 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -30,7 +30,7 @@
     <string name="time_left_for_app" msgid="3111996412933644358">"今天还可使用 <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="title_app_suggestions" msgid="4185902664111965088">"应用建议"</string>
     <string name="all_apps_label" msgid="8542784161730910663">"所有应用"</string>
-    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"您的预测应用"</string>
+    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"您可能想要使用的应用"</string>
     <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"在主屏幕底部获取应用建议"</string>
     <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"在主屏幕的收藏行获取应用建议"</string>
     <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"直接在主屏幕上轻松访问您最常用的应用。系统会根据您的日常安排提供不同的建议。最下面一排中的应用会向上移动到主屏幕中。"</string>
diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml
index a118f1d..2ffaecf 100644
--- a/quickstep/res/values-zu/strings.xml
+++ b/quickstep/res/values-zu/strings.xml
@@ -30,7 +30,7 @@
     <string name="time_left_for_app" msgid="3111996412933644358">"<xliff:g id="TIME">%1$s</xliff:g> esele namhlanje"</string>
     <string name="title_app_suggestions" msgid="4185902664111965088">"Iziphakamiso zohlelo lokusebenza"</string>
     <string name="all_apps_label" msgid="8542784161730910663">"Zonke izinhlelo zokusebenza"</string>
-    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Izinhlelo zakho zokusebenza eziqagelwe"</string>
+    <string name="all_apps_prediction_tip" msgid="2672336544844936186">"Ama-app akho aqagelwe"</string>
     <string name="hotseat_edu_title_migrate" msgid="306578144424489980">"Thola iziphakamiso ze-app emgqeni ongezansi wesikrini sakho sasekhaya"</string>
     <string name="hotseat_edu_title_migrate_landscape" msgid="3633942953997845243">"Thola iziphakamiso zohlelo lokusebenza kumugqa wezintandokazi Zesikrini sakho sasekhaya"</string>
     <string name="hotseat_edu_message_migrate" msgid="8927179260533775320">"Finyelela kalula izinhlelo zakho zokusebenza ezisetshenziswa kakhulu khona kusikrini sasekhaya. Iziphakamiso zizoshintsha ngokususelwe kwimijikelezo yakho. Izinhlelo zokusebenza ezisemgqeni ongezansi zizoya phezulu kusikrini sakho sasekhaya."</string>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index fb9765c..7aae38c 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -26,6 +26,8 @@
 
 import android.animation.AnimatorSet;
 import android.animation.ValueAnimator;
+import android.app.ActivityOptions;
+import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.os.Bundle;
@@ -37,6 +39,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.model.WellbeingModel;
+import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.popup.SystemShortcut;
 import com.android.launcher3.proxy.ProxyActivityStarter;
 import com.android.launcher3.proxy.StartActivityParams;
@@ -50,6 +53,7 @@
 import com.android.launcher3.uioverrides.RecentsViewStateController;
 import com.android.launcher3.util.ActivityOptionsWrapper;
 import com.android.launcher3.util.DisplayController;
+import com.android.launcher3.util.ObjectWrapper;
 import com.android.launcher3.util.UiThreadHelper;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.SysUINavigationMode;
@@ -233,8 +237,9 @@
     }
 
     @Override
-    public void onDisplayInfoChanged(DisplayController.Info info, int flags) {
-        super.onDisplayInfoChanged(info, flags);
+    public void onDisplayInfoChanged(Context context, DisplayController.Info info,
+            int flags) {
+        super.onDisplayInfoChanged(context, info, flags);
         if ((flags & CHANGE_SIZE) != 0) {
             addTaskbarIfNecessary();
         }
@@ -418,18 +423,38 @@
     }
 
     @Override
-    public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
+    public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
         ActivityOptionsWrapper activityOptions =
                 mAppTransitionManager.hasControlRemoteAppTransitionPermission()
                         ? mAppTransitionManager.getActivityLaunchOptions(this, v)
-                        : super.getActivityLaunchOptions(v);
+                        : super.getActivityLaunchOptions(v, item);
         if (mLastTouchUpTime > 0) {
             ActivityOptionsCompat.setLauncherSourceInfo(
                     activityOptions.options, mLastTouchUpTime);
         }
+        addLaunchCookie(item, activityOptions.options);
         return activityOptions;
     }
 
+    /**
+     * Adds a new launch cookie for the activity launch of the given {@param info} if supported.
+     */
+    public void addLaunchCookie(ItemInfo info, ActivityOptions opts) {
+        if (info == null) {
+            return;
+        }
+        switch (info.itemType) {
+            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+                // Fall through and continue if it's an app or shortcut
+                break;
+            default:
+                return;
+        }
+        opts.setLaunchCookie(ObjectWrapper.wrap(new Integer(info.id)));
+    }
+
     public void setHintUserWillBeActive() {
         addActivityFlags(ACTIVITY_STATE_USER_WILL_BE_ACTIVE);
     }
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 827eb7d..5b1b59b 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -110,7 +110,7 @@
     private static final String TAG = "QuickstepTransition";
 
     private static final boolean ENABLE_SHELL_STARTING_SURFACE =
-            SystemProperties.getBoolean("persist.debug.shell_starting_surface", false);
+            SystemProperties.getBoolean("persist.debug.shell_starting_surface", true);
 
     /** Duration of status bar animations. */
     public static final int STATUS_BAR_TRANSITION_DURATION = 120;
@@ -172,6 +172,8 @@
     private final float mClosingWindowTransY;
     private final float mMaxShadowRadius;
 
+    private final StartingWindowListener mStartingWindowListener = new StartingWindowListener();
+
     private DeviceProfile mDeviceProfile;
 
     private RemoteAnimationProvider mRemoteAnimationProvider;
@@ -221,13 +223,9 @@
                 }
             };
 
+            mStartingWindowListener.setTransitionManager(this);
             SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
-                    new IStartingWindowListener.Stub() {
-                        @Override
-                        public void onTaskLaunching(int taskId, int supportedType) {
-                            mTypeForTaskId.put(taskId, supportedType);
-                        }
-                    });
+                    mStartingWindowListener);
         }
     }
 
@@ -566,7 +564,6 @@
         // Set the crop here so we can calculate the corner radius below.
         crop.set(left, top, right, bottom);
 
-        RectF targetBounds = new RectF(windowTargetBounds);
         RectF floatingIconBounds = new RectF();
         RectF tmpRectF = new RectF();
         Point tmpPos = new Point();
@@ -655,12 +652,8 @@
                 tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]);
                 tmpRectF.offset(mDx.value, mDy.value);
                 Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value);
-                float windowTransX0 = tmpRectF.left - offsetX;
-                float windowTransY0 = tmpRectF.top - offsetY;
-                if (hasSplashScreen) {
-                    windowTransX0 -= crop.left * scale;
-                    windowTransY0 -= crop.top * scale;
-                }
+                float windowTransX0 = tmpRectF.left - offsetX - crop.left * scale;
+                float windowTransY0 = tmpRectF.top - offsetY - crop.top * scale;
 
                 // Calculate the icon position.
                 floatingIconBounds.set(launcherIconBounds);
@@ -819,6 +812,7 @@
     public void onActivityDestroyed() {
         unregisterRemoteAnimations();
         unregisterRemoteTransitions();
+        mStartingWindowListener.setTransitionManager(null);
         SystemUiProxy.INSTANCE.getNoCreate().setStartingWindowListener(null);
     }
 
@@ -1213,25 +1207,16 @@
             alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION
                     : APP_LAUNCH_ALPHA_DOWN_DURATION;
 
-            if (hasSplashScreen) {
-                iconAlphaStart = 0;
+            iconAlphaStart = hasSplashScreen ? 0 : 1f;
 
-                // TOOD: Share value from shell when available.
-                final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
+            // TOOD: Share value from shell when available.
+            final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
 
-                cropCenterXStart = windowTargetBounds.centerX();
-                cropCenterYStart = windowTargetBounds.centerY();
+            cropCenterXStart = windowTargetBounds.centerX();
+            cropCenterYStart = windowTargetBounds.centerY();
 
-                cropWidthStart = (int) windowIconSize;
-                cropHeightStart = (int) windowIconSize;
-            } else {
-                iconAlphaStart = 1;
-
-                cropWidthStart = cropHeightStart =
-                        Math.min(windowTargetBounds.width(), windowTargetBounds.height());
-                cropCenterXStart = cropCenterYStart =
-                        Math.min(windowTargetBounds.centerX(), windowTargetBounds.centerY());
-            }
+            cropWidthStart = (int) windowIconSize;
+            cropHeightStart = (int) windowIconSize;
 
             cropWidthEnd = windowTargetBounds.width();
             cropHeightEnd = windowTargetBounds.height();
@@ -1240,4 +1225,17 @@
             cropCenterYEnd = windowTargetBounds.centerY();
         }
     }
+
+    private static class StartingWindowListener extends IStartingWindowListener.Stub {
+        private QuickstepTransitionManager mTransitionManager;
+
+        public void setTransitionManager(QuickstepTransitionManager transitionManager) {
+            mTransitionManager = transitionManager;
+        }
+
+        @Override
+        public void onTaskLaunching(int taskId, int supportedType) {
+            mTransitionManager.mTypeForTaskId.put(taskId, supportedType);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index b4aa596..5ba1fe1 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -15,12 +15,11 @@
  */
 package com.android.launcher3.uioverrides;
 
-import static com.android.launcher3.graphics.IconShape.getShape;
-
 import android.content.Context;
 import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.Rect;
@@ -37,6 +36,7 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
 import com.android.launcher3.graphics.IconPalette;
+import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.icons.IconNormalizer;
 import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -58,9 +58,13 @@
     private final DeviceProfile mDeviceProfile;
     private final Paint mIconRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
     private final Path mRingPath = new Path();
-    private boolean mIsPinned = false;
-    private final int mNormalizedIconRadius;
+    private final int mNormalizedIconSize;
+    private final Path mShapePath;
+    private final Matrix mTmpMatrix = new Matrix();
+
     private final BlurMaskFilter mShadowFilter;
+
+    private boolean mIsPinned = false;
     private int mPlateColor;
     boolean mDrawForDrag = false;
 
@@ -75,24 +79,18 @@
     public PredictedAppIcon(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mDeviceProfile = ActivityContext.lookupContext(context).getDeviceProfile();
-        mNormalizedIconRadius = IconNormalizer.getNormalizedCircleSize(getIconSize()) / 2;
+        mNormalizedIconSize = IconNormalizer.getNormalizedCircleSize(getIconSize());
         int shadowSize = context.getResources().getDimensionPixelSize(
                 R.dimen.blur_size_thin_outline);
         mShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.OUTER);
+        mShapePath = GraphicsUtils.getShapePath(mNormalizedIconSize);
     }
 
     @Override
     public void onDraw(Canvas canvas) {
         int count = canvas.save();
         if (!mIsPinned) {
-            boolean isBadged = false;
-            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;
-            }
-            drawEffect(canvas, isBadged);
+            drawEffect(canvas);
             canvas.translate(getWidth() * RING_EFFECT_RATIO, getHeight() * RING_EFFECT_RATIO);
             canvas.scale(1 - 2 * RING_EFFECT_RATIO, 1 - 2 * RING_EFFECT_RATIO);
         }
@@ -161,33 +159,58 @@
     }
 
     private int getOutlineOffsetX() {
-        return (getMeasuredWidth() / 2) - mNormalizedIconRadius;
+        return (getMeasuredWidth() - mNormalizedIconSize) / 2;
     }
 
     private int getOutlineOffsetY() {
         if (mDisplay != DISPLAY_TASKBAR) {
             return getPaddingTop() + mDeviceProfile.folderIconOffsetYPx;
         }
-        return (getMeasuredHeight() / 2) - mNormalizedIconRadius;
+        return (getMeasuredHeight() - mNormalizedIconSize) / 2;
     }
 
-    private void drawEffect(Canvas canvas, boolean isBadged) {
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        updateRingPath();
+    }
+
+    @Override
+    public void setTag(Object tag) {
+        super.setTag(tag);
+        updateRingPath();
+    }
+
+    private void updateRingPath() {
+        boolean isBadged = false;
+        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;
+        }
+
+        mRingPath.reset();
+        mTmpMatrix.setTranslate(getOutlineOffsetX(), getOutlineOffsetY());
+
+        mRingPath.addPath(mShapePath, mTmpMatrix);
+        if (isBadged) {
+            float outlineSize = mNormalizedIconSize * RING_EFFECT_RATIO;
+            float iconSize = getIconSize() * (1 - 2 * RING_EFFECT_RATIO);
+            float badgeSize = LauncherIcons.getBadgeSizeForIconSize((int) iconSize) + outlineSize;
+            float scale = badgeSize / mNormalizedIconSize;
+            mTmpMatrix.postTranslate(mNormalizedIconSize, mNormalizedIconSize);
+            mTmpMatrix.preScale(scale, scale);
+            mTmpMatrix.preTranslate(-mNormalizedIconSize, -mNormalizedIconSize);
+            mRingPath.addPath(mShapePath, mTmpMatrix);
+        }
+    }
+
+    private void drawEffect(Canvas canvas) {
         // Don't draw ring effect if item is about to be dragged.
         if (mDrawForDrag) {
             return;
         }
-        mRingPath.reset();
-        getShape().addToPath(mRingPath, getOutlineOffsetX(), getOutlineOffsetY(),
-                mNormalizedIconRadius);
-        if (isBadged) {
-            float outlineSize = mNormalizedIconRadius * RING_EFFECT_RATIO * 2;
-            float iconSize = getIconSize() * (1 - 2 * RING_EFFECT_RATIO);
-            float badgeSize = LauncherIcons.getBadgeSizeForIconSize((int) iconSize) + outlineSize;
-            float badgeInset = mNormalizedIconRadius * 2 - badgeSize;
-            getShape().addToPath(mRingPath, getOutlineOffsetX() + badgeInset,
-                    getOutlineOffsetY() + badgeInset, badgeSize / 2);
-
-        }
         mIconRingPaint.setColor(RING_SHADOW_COLOR);
         mIconRingPaint.setMaskFilter(mShadowFilter);
         canvas.drawPath(mRingPath, mIconRingPaint);
@@ -249,8 +272,10 @@
          */
         @Override
         public void drawUnderItem(Canvas canvas) {
-            getShape().drawShape(canvas, mIcon.getOutlineOffsetX(), mIcon.getOutlineOffsetY(),
-                    mIcon.mNormalizedIconRadius, mOutlinePaint);
+            canvas.save();
+            canvas.translate(mIcon.getOutlineOffsetX(), mIcon.getOutlineOffsetY());
+            canvas.drawPath(mIcon.mShapePath, mOutlinePaint);
+            canvas.restore();
         }
 
         /**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 9097c8b..0652d48 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -113,7 +113,7 @@
                         ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
 
         float splitPlaceholderAlpha = state.areElementsVisible(mLauncher, SPLIT_PLACHOLDER_VIEW) ?
-                0.7f : 0;
+                0.85f : 0;
         propertySetter.setFloat(mRecentsView.getSplitPlaceholder(), ALPHA_FLOAT,
                 splitPlaceholderAlpha, LINEAR);
     }
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 43cc7fc..53f1fd0 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -66,6 +66,7 @@
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.SystemClock;
 import android.view.MotionEvent;
 import android.view.View;
@@ -1046,7 +1047,8 @@
                 interpolator, target, velocityPxPerMs));
     }
 
-    protected abstract HomeAnimationFactory createHomeAnimationFactory(long duration);
+    protected abstract HomeAnimationFactory createHomeAnimationFactory(
+            ArrayList<IBinder> launchCookies, long duration);
 
     private final TaskStackChangeListener mActivityRestartListener = new TaskStackChangeListener() {
         @Override
@@ -1087,7 +1089,8 @@
             final RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets != null
                     ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
                     : null;
-            HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration);
+            HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(
+                    runningTaskTarget.taskInfo.launchCookies, duration);
             mIsSwipingPipToHome = homeAnimFactory.supportSwipePipToHome()
                     && runningTaskTarget != null
                     && runningTaskTarget.taskInfo.pictureInPictureParams != null
@@ -1509,9 +1512,8 @@
             SystemUiProxy.INSTANCE.get(mContext).stopSwipePipToHome(
                     mSwipePipToHomeAnimator.getComponentName(),
                     mSwipePipToHomeAnimator.getDestinationBounds());
-            mRecentsAnimationController.setFinishTaskBounds(
+            mRecentsAnimationController.setFinishTaskTransaction(
                     mSwipePipToHomeAnimator.getTaskId(),
-                    mSwipePipToHomeAnimator.getDestinationBounds(),
                     mSwipePipToHomeAnimator.getFinishTransaction());
             mIsSwipingPipToHome = false;
         }
diff --git a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
index f5698f7..9846ee7 100644
--- a/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
+++ b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
@@ -38,6 +38,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -68,6 +69,7 @@
 import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.UUID;
 import java.util.function.Consumer;
 
@@ -126,7 +128,8 @@
     }
 
     @Override
-    protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
+    protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
+            long duration) {
         mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
         ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
         Intent intent = new Intent(mGestureState.getHomeIntent());
diff --git a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
index 5ecd385..dd35d68 100644
--- a/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
+++ b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
@@ -31,6 +31,7 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.RectF;
+import android.os.IBinder;
 import android.os.UserHandle;
 import android.view.View;
 
@@ -47,6 +48,7 @@
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.states.StateAnimationConfig;
 import com.android.launcher3.util.DynamicResource;
+import com.android.launcher3.util.ObjectWrapper;
 import com.android.launcher3.views.FloatingIconView;
 import com.android.quickstep.util.AppCloseConfig;
 import com.android.quickstep.util.RectFSpringAnim;
@@ -56,6 +58,8 @@
 import com.android.systemui.plugins.ResourceProvider;
 import com.android.systemui.shared.system.InputConsumerController;
 
+import java.util.ArrayList;
+
 /**
  * Temporary class to allow easier refactoring
  */
@@ -71,20 +75,12 @@
 
 
     @Override
-    protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
+    protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
+            long duration) {
         HomeAnimationFactory homeAnimFactory;
         if (mActivity != null) {
-            final TaskView runningTaskView = mRecentsView.getRunningTaskView();
-            final View workspaceView;
-            if (runningTaskView != null
-                    && !mIsSwipingPipToHome
-                    && runningTaskView.getTask().key.getComponent() != null) {
-                workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
-                        runningTaskView.getTask().key.getComponent().getPackageName(),
-                        UserHandle.of(runningTaskView.getTask().key.userId));
-            } else {
-                workspaceView = null;
-            }
+            final View workspaceView = findWorkspaceView(launchCookies,
+                    mRecentsView.getRunningTaskView());
             boolean canUseWorkspaceView =
                     workspaceView != null && workspaceView.isAttachedToWindow();
 
@@ -232,6 +228,37 @@
         return homeAnimFactory;
     }
 
+    /**
+     * Returns the associated view on the workspace matching one of the launch cookies, or the app
+     * associated with the running task.
+     */
+    @Nullable
+    private View findWorkspaceView(ArrayList<IBinder> launchCookies, TaskView runningTaskView) {
+        if (mIsSwipingPipToHome) {
+            // Disable if swiping to PIP
+            return null;
+        }
+        if (runningTaskView == null || runningTaskView.getTask() == null
+                || runningTaskView.getTask().key.getComponent() == null) {
+            // Disable if it's an invalid task
+            return null;
+        }
+
+        // Find the associated item info for the launch cookie (if available)
+        int launchCookieItemId = -1;
+        for (IBinder cookie : launchCookies) {
+            Integer itemId = ObjectWrapper.unwrap(cookie);
+            if (itemId != null) {
+                launchCookieItemId = itemId;
+                break;
+            }
+        }
+
+        return mActivity.getWorkspace().getFirstMatchForAppClose(launchCookieItemId,
+                runningTaskView.getTask().key.getComponent().getPackageName(),
+                UserHandle.of(runningTaskView.getTask().key.userId));
+    }
+
     @Override
     protected void finishRecentsControllerToHome(Runnable callback) {
         mRecentsAnimationController.finish(
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 7c453e7..ec224ed 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -37,6 +37,8 @@
 import android.os.Looper;
 import android.view.View;
 
+import androidx.annotation.Nullable;
+
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.InvariantDeviceProfile;
@@ -48,6 +50,7 @@
 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;
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
@@ -177,9 +180,9 @@
     }
 
     @Override
-    public ActivityOptionsWrapper getActivityLaunchOptions(final View v) {
+    public ActivityOptionsWrapper getActivityLaunchOptions(final View v, @Nullable ItemInfo item) {
         if (!(v instanceof TaskView)) {
-            return super.getActivityLaunchOptions(v);
+            return super.getActivityLaunchOptions(v, item);
         }
 
         final TaskView taskView = (TaskView) v;
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
index 82e8a93..4560735 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java
@@ -19,7 +19,6 @@
 import static com.android.launcher3.util.Executors.THREAD_POOL_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
 
-import android.graphics.Rect;
 import android.window.PictureInPictureSurfaceTransaction;
 
 import androidx.annotation.NonNull;
@@ -145,18 +144,16 @@
     }
 
     /**
-     * Sets the final bounds on a Task. This is used by Launcher to notify the system that
-     * animating Activity to PiP has completed and the associated task surface should be updated
-     * accordingly. This should be called before `finish`
+     * Sets the final surface transaction on a Task. This is used by Launcher to notify the system
+     * that animating Activity to PiP has completed and the associated task surface should be
+     * updated accordingly. This should be called before `finish`
      * @param taskId for which the leash should be updated
-     * @param destinationBounds bounds of the final PiP window
      * @param finishTransaction leash operations for the final transform.
      */
-    public void setFinishTaskBounds(int taskId, Rect destinationBounds,
+    public void setFinishTaskTransaction(int taskId,
             PictureInPictureSurfaceTransaction finishTransaction) {
         UI_HELPER_EXECUTOR.execute(
-                () -> mController.setFinishTaskBounds(taskId, destinationBounds,
-                        finishTransaction));
+                () -> mController.setFinishTaskTransaction(taskId, finishTransaction));
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 6cf12a3..b4f1330 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -241,7 +241,7 @@
     public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
         mDisplayController.removeChangeListener(this);
         mDisplayController.addChangeListener(this);
-        onDisplayInfoChanged(mDisplayController.getInfo(), CHANGE_ALL);
+        onDisplayInfoChanged(mContext, mDisplayController.getInfo(), CHANGE_ALL);
 
         if (newMode == NO_BUTTON) {
             mExclusionListener.register();
@@ -254,7 +254,7 @@
     }
 
     @Override
-    public void onDisplayInfoChanged(Info info, int flags) {
+    public void onDisplayInfoChanged(Context context, Info info, int flags) {
         if (info.id != getDisplayId() || flags == CHANGE_FRAME_DELAY) {
             // ignore displays that aren't running launcher and frame refresh rate changes
             return;
diff --git a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
index a1af77d..edc3ab2 100644
--- a/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
+++ b/quickstep/src/com/android/quickstep/RemoteAnimationTargets.java
@@ -17,6 +17,8 @@
 
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
 
+import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
+
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
 import java.util.ArrayList;
@@ -97,6 +99,10 @@
     }
 
     public void release() {
+        if (ENABLE_SHELL_TRANSITIONS) {
+            mReleaseChecks.clear();
+            return;
+        }
         if (mReleased) {
             return;
         }
diff --git a/quickstep/src/com/android/quickstep/RotationTouchHelper.java b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
index d4ad176..f4688a1 100644
--- a/quickstep/src/com/android/quickstep/RotationTouchHelper.java
+++ b/quickstep/src/com/android/quickstep/RotationTouchHelper.java
@@ -225,7 +225,7 @@
     public void onNavigationModeChanged(SysUINavigationMode.Mode newMode) {
         mDisplayController.removeChangeListener(this);
         mDisplayController.addChangeListener(this);
-        onDisplayInfoChanged(mDisplayController.getInfo(), CHANGE_ALL);
+        onDisplayInfoChanged(mContext, mDisplayController.getInfo(), CHANGE_ALL);
 
         mOrientationTouchTransformer.setNavigationMode(newMode, mDisplayController.getInfo(),
             mContext.getResources());
@@ -243,7 +243,7 @@
     }
 
     @Override
-    public void onDisplayInfoChanged(Info info, int flags) {
+    public void onDisplayInfoChanged(Context context, Info info, int flags) {
         if (info.id != mDisplayId|| flags == CHANGE_FRAME_DELAY) {
             // ignore displays that aren't running launcher and frame refresh rate changes
             return;
diff --git a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
index 351adf4..c527be3 100644
--- a/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
+++ b/quickstep/src/com/android/quickstep/util/NavigationModeFeatureFlag.java
@@ -46,7 +46,8 @@
     }
 
     public boolean get() {
-        return mBasePredicate.get() && mSupported && mObserver.isHomeAndOverviewSame();
+        return mBasePredicate.get() && mSupported && mObserver != null
+                && mObserver.isHomeAndOverviewSame();
     }
 
     public void initialize(Context context) {
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index c1c8c1b..01d51f8 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -16,16 +16,20 @@
 
 package com.android.quickstep.util;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
 
 import android.animation.AnimatorSet;
 import android.app.ActivityOptions;
+import android.content.res.Resources;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
 import android.util.Pair;
+import android.view.Gravity;
 import android.view.SurfaceControl;
 import android.window.TransitionInfo;
 
@@ -33,7 +37,10 @@
 
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.InsettableFrameLayout;
 import com.android.launcher3.LauncherAnimationRunner;
+import com.android.launcher3.R;
 import com.android.launcher3.WrappedAnimationRunnerImpl;
 import com.android.launcher3.WrappedLauncherAnimationRunner;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
@@ -115,6 +122,26 @@
         resetState();
     }
 
+    /**
+     * @return {@link InsettableFrameLayout.LayoutParams} to correctly position the
+     * split placeholder view
+     */
+    public InsettableFrameLayout.LayoutParams getLayoutParamsForActivePosition(Resources resources,
+            DeviceProfile deviceProfile) {
+        InsettableFrameLayout.LayoutParams params =
+                new InsettableFrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
+        boolean topLeftPosition = mInitialPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT;
+        if (deviceProfile.isLandscape) {
+            params.width = (int) resources.getDimension(R.dimen.split_placeholder_size);
+            params.gravity = topLeftPosition ? Gravity.START : Gravity.END;
+        } else {
+            params.height = (int) resources.getDimension(R.dimen.split_placeholder_size);
+            params.gravity = Gravity.TOP;
+        }
+
+        return params;
+    }
+
     @Nullable
     public SplitPositionOption getActiveSplitPositionOption() {
         return mInitialPosition;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index db651a8..41076f3 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -142,9 +142,9 @@
 import com.android.quickstep.TaskViewUtils;
 import com.android.quickstep.ViewUtils;
 import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.MultiValueUpdateListener;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.quickstep.util.SplitScreenBounds;
+import com.android.quickstep.util.SplitSelectStateController;
 import com.android.quickstep.util.SurfaceTransactionApplier;
 import com.android.quickstep.util.TaskViewSimulator;
 import com.android.quickstep.util.TransformParams;
@@ -327,6 +327,8 @@
     private float mFullscreenScale;
 
     private static final int DISMISS_TASK_DURATION = 300;
+    private static final int DISMISS_TASK_TRANSLATION_DURATION = 200;
+    private static final int ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION = 75;
     private static final int ADDITION_TASK_DURATION = 200;
     // The threshold at which we update the SystemUI flags when animating from the task into the app
     public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f;
@@ -364,15 +366,13 @@
     protected float mTaskViewsPrimaryTranslation = 0;
     // Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
     private float mGridProgress = 0;
+    private final IntSet mTopRowIdSet = new IntSet();
 
     // The GestureEndTarget that is still in progress.
     protected GestureState.GestureEndTarget mCurrentGestureEndTarget;
 
-    IntSet mTopIdSet = new IntSet();
-
     private int mOverScrollShift = 0;
 
-
     /**
      * TODO: Call reloadIdNeeded in onTaskStackChanged.
      */
@@ -824,18 +824,16 @@
             ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
             appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
             appAnimator.setInterpolator(ACCEL_DEACCEL);
-            appAnimator.addUpdateListener(new MultiValueUpdateListener() {
-                @Override
-                public void onUpdate(float percent) {
-                    SurfaceParams.Builder builder = new SurfaceParams.Builder(
-                            apps[apps.length - 1].leash);
-                    Matrix matrix = new Matrix();
-                    matrix.postScale(percent, percent);
-                    matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
-                            mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
-                    builder.withAlpha(percent).withMatrix(matrix);
-                    surfaceApplier.scheduleApply(builder.build());
-                }
+            appAnimator.addUpdateListener(valueAnimator -> {
+                float percent = valueAnimator.getAnimatedFraction();
+                SurfaceParams.Builder builder = new SurfaceParams.Builder(
+                        apps[apps.length - 1].leash);
+                Matrix matrix = new Matrix();
+                matrix.postScale(percent, percent);
+                matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
+                        mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
+                builder.withAlpha(percent).withMatrix(matrix);
+                surfaceApplier.scheduleApply(builder.build());
             });
             anim.play(appAnimator);
             anim.addListener(new AnimatorListenerAdapter() {
@@ -1298,7 +1296,7 @@
         }
         mClearAllButton.setFullscreenTranslationPrimary(accumulatedTranslationX);
 
-        updateGridProperties(/*isTaskDismissal=*/false);
+        updateGridProperties();
     }
 
     public void getTaskSize(Rect outRect) {
@@ -1515,7 +1513,14 @@
         mTaskListChangeId = -1;
         mFocusedTaskId = -1;
 
-        mRecentsAnimationController = null;
+        if (mRecentsAnimationController != null) {
+            if (LIVE_TILE.get() && mEnableDrawingLiveTile) {
+                // We are still drawing the live tile, finish it now to clean up.
+                finishRecentsAnimation(true /* toRecents */, null);
+            } else {
+                mRecentsAnimationController = null;
+            }
+        }
         mLiveTileParams.setTargetSet(null);
         mLiveTileTaskViewSimulator.setDrawsBelowRecents(true);
 
@@ -1651,7 +1656,7 @@
             // When switching to tasks in quick switch, ensures the snapped page's scroll maintain
             // invariant between quick switch and overview grid, to ensure a smooth animation
             // transition.
-            updateGridProperties(/*isTaskDismissal=*/false);
+            updateGridProperties();
         }
     }
 
@@ -1824,13 +1829,26 @@
         }
     }
 
+    /** Updates TaskView and ClearAllButtion scaling and translation required to turn into grid
+     * layout.
+     * This method is used when no task dismissal has occurred.
+     */
+    private void updateGridProperties() {
+        updateGridProperties(null, -1);
+    }
+
     /**
      * Updates TaskView and ClearAllButton scaling and translation required to turn into grid
      * layout.
      * This method only calculates the potential position and depends on {@link #setGridProgress} to
-     * apply the actual scaling and translation.
+     * apply the actual scaling and translation. This adds task translation animations in the case
+     * of task dismissals: e.g. when dismissedTask is not null.
+     *
+     * @param dismissedTask the TaskView dismissed, possibly null
+     * @param dismissedIndex the index at which the dismissedTask was prior to dismissal, if no
+     *                       dismissal occurred, this is unused
      */
-    private void updateGridProperties(boolean isTaskDismissal) {
+    private void updateGridProperties(TaskView dismissedTask, int dismissedIndex) {
         int taskCount = getTaskViewCount();
         if (taskCount == 0) {
             return;
@@ -1857,8 +1875,12 @@
         int snappedPage = getNextPage();
         TaskView snappedTaskView = getTaskViewAtByAbsoluteIndex(snappedPage);
 
+        boolean isTaskDismissal = dismissedTask != null;
+        float dismissedTaskWidth =
+                isTaskDismissal ? dismissedTask.getLayoutParams().width + mPageSpacing : 0;
+
         if (!isTaskDismissal) {
-            mTopIdSet.clear();
+            mTopRowIdSet.clear();
         }
         for (int i = 0; i < taskCount; i++) {
             TaskView taskView = getTaskViewAt(i);
@@ -1893,13 +1915,14 @@
                     // calculate the distance focused task need to shift.
                     focusedTaskShift += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
                 }
-                boolean isTopRow = isTaskDismissal ? mTopIdSet.contains(taskView.getTask().key.id)
+                int taskId = taskView.getTask().key.id;
+                boolean isTopRow = isTaskDismissal ? mTopRowIdSet.contains(taskId)
                         : topRowWidth <= bottomRowWidth;
                 if (isTopRow) {
                     gridTranslations[i] += topAccumulatedTranslationX;
                     topRowWidth += taskWidthAndSpacing;
                     topSet.add(i);
-                    mTopIdSet.add(taskView.getTask().key.id);
+                    mTopRowIdSet.add(taskId);
 
                     taskView.setGridTranslationY(taskGridVerticalDiff);
 
@@ -1953,17 +1976,55 @@
             snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex];
         }
 
-
+        // Animate task dismissTranslationX for tasks with index >= dismissed index and in the
+        // same row as the dismissed index, or if the dismissed task was the focused task. Offset
+        // successive task dismissal durations for a staggered effect.
+        ArrayList<Animator> gridTranslationAnimators = new ArrayList<>();
+        boolean isFocusedTaskDismissed =
+                isTaskDismissal && dismissedTask.getTask().key.id == mFocusedTaskId;
         for (int i = 0; i < taskCount; i++) {
             TaskView taskView = getTaskViewAt(i);
+            if (isFocusedTaskDismissed || (i >= dismissedIndex && isSameGridRow(dismissedTask,
+                    taskView))) {
+                Animator taskDismissAnimator = ObjectAnimator.ofFloat(taskView,
+                        taskView.getPrimaryDismissTranslationProperty(),
+                        mIsRtl ? -dismissedTaskWidth : dismissedTaskWidth, 0f);
+                int additionalTranslationDuration =
+                        i >= dismissedIndex ? (ADDITIONAL_DISMISS_TASK_TRANSLATION_DURATION * (
+                                (i - dismissedIndex) / 2)) : 0;
+                taskDismissAnimator.setDuration(
+                        DISMISS_TASK_TRANSLATION_DURATION + additionalTranslationDuration);
+                gridTranslationAnimators.add(taskDismissAnimator);
+            }
             taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX);
             taskView.setNonFullscreenTranslationX(snappedTaskFullscreenScrollAdjustment);
         }
+        AnimatorSet gridTranslationAnimatorSet = new AnimatorSet();
+        gridTranslationAnimatorSet.playTogether(gridTranslationAnimators);
+        gridTranslationAnimatorSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            // Allow the actions view to display again once in focus mode
+            public void onAnimationEnd(Animator animation) {
+                super.onAnimationEnd(animation);
+                if (getFocusedTaskView() == null) {
+                    mActionsView.getScrollAlpha().setValue(1);
+                }
+            }
 
-        // Use the accumulated translation of the longer row.
-        float clearAllAccumulatedTranslation = mIsRtl ? Math.max(topAccumulatedTranslationX,
-                bottomAccumulatedTranslationX) : Math.min(topAccumulatedTranslationX,
-                bottomAccumulatedTranslationX);
+            @Override
+            // Hide the actions view if not in focus mode
+            public void onAnimationStart(Animator animation) {
+                super.onAnimationStart(animation);
+                if (getFocusedTaskView() == null) {
+                    mActionsView.getScrollAlpha().setValue(0);
+                }
+            }
+        });
+        gridTranslationAnimatorSet.start();
+
+        // Use the accumulated translation of the row containing the last task.
+        float clearAllAccumulatedTranslation = topSet.contains(taskCount - 1)
+                ? topAccumulatedTranslationX : bottomAccumulatedTranslationX;
 
         // If the last task is on the shorter row, ClearAllButton will embed into the shorter row
         // which is not what we want. Compensate the width difference of the 2 rows in that case.
@@ -1981,13 +2042,14 @@
                 mIsRtl ? -shorterRowCompensation : shorterRowCompensation;
 
         // If the total width is shorter than one grid's width, move ClearAllButton further away
-        // accordingly.
+        // accordingly. Update longRowWidth if ClearAllButton has been moved.
         float clearAllShortTotalCompensation = 0;
         int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
         if (longRowWidth < mLastComputedGridSize.width()) {
             float shortTotalCompensation = mLastComputedGridSize.width() - longRowWidth;
             clearAllShortTotalCompensation =
                     mIsRtl ? -shortTotalCompensation : shortTotalCompensation;
+            longRowWidth = mLastComputedGridSize.width();
         }
 
         float clearAllTotalTranslationX =
@@ -2020,6 +2082,19 @@
         setGridProgress(mGridProgress);
     }
 
+    private boolean isSameGridRow(TaskView taskView1, TaskView taskView2) {
+        if (taskView1 == null || taskView2 == null) {
+            return false;
+        }
+        int taskId1 = taskView1.getTask().key.id;
+        int taskId2 = taskView2.getTask().key.id;
+        if (taskId1 == mFocusedTaskId || taskId2 == mFocusedTaskId) {
+            return false;
+        }
+        return (mTopRowIdSet.contains(taskId1) && mTopRowIdSet.contains(taskId2)) || (
+                !mTopRowIdSet.contains(taskId1) && !mTopRowIdSet.contains(taskId2));
+    }
+
     /**
      * Moves TaskView and ClearAllButton between carousel and 2 row grid.
      *
@@ -2230,8 +2305,12 @@
                     }
 
                     int pageToSnapTo = mCurrentPage;
-                    if (draggedIndex < pageToSnapTo ||
-                            pageToSnapTo == (getTaskViewCount() - 1)) {
+                    // Snap to start if focused task was dismissed, as after quick switch it could
+                    // be at any page but the focused task always displays at the start.
+                    if (taskView.getTask().key.id == mFocusedTaskId) {
+                        pageToSnapTo = mTaskViewStartIndex;
+                    } else if (draggedIndex < pageToSnapTo || pageToSnapTo == (getTaskViewCount()
+                            - 1)) {
                         pageToSnapTo -= 1;
                     }
                     removeViewInLayout(taskView);
@@ -2242,7 +2321,7 @@
                     } else {
                         snapToPageImmediately(pageToSnapTo);
                         // Grid got messed up, reapply.
-                        updateGridProperties(/*isTaskDismissal=*/true);
+                        updateGridProperties(taskView, draggedIndex - mTaskViewStartIndex);
                         if (showAsGrid() && getFocusedTaskView() == null) {
                             animateActionsViewOut();
                         }
@@ -2251,7 +2330,9 @@
                     // immediately available.
                     onLayout(false /*  changed */, getLeft(), getTop(), getRight(), getBottom());
                 }
-                resetTaskVisuals();
+                if (!showAsGrid()) {
+                    resetTaskVisuals();
+                }
                 onDismissAnimationEnds();
                 mPendingAnimation = null;
             }
@@ -2434,15 +2515,6 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        if (LIVE_TILE.get() && mRunningTaskId != -1) {
-            switchToScreenshot(
-                    () -> finishRecentsAnimation(true, this::onConfigurationChangedInternal));
-        } else {
-            onConfigurationChangedInternal();
-        }
-    }
-
-    private void onConfigurationChangedInternal() {
         final int rotation = mActivity.getDisplay().getRotation();
         if (mOrientationState.setRecentsRotation(rotation)) {
             updateOrientationHandler();
@@ -2620,6 +2692,10 @@
                     ? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
                     : mOrientationHandler.getPrimaryViewTranslate();
             translationProperty.set(child, totalTranslation);
+            if (LIVE_TILE.get() && mEnableDrawingLiveTile && i == getRunningTaskIndex()) {
+                mLiveTileTaskViewSimulator.taskPrimaryTranslation.value = totalTranslation;
+                redrawLiveTile();
+            }
         }
         updateCurveProperties();
     }
@@ -2753,9 +2829,14 @@
 
     public void initiateSplitSelect(TaskView taskView, SplitPositionOption splitPositionOption) {
         mSplitHiddenTaskView = taskView;
-        mSplitPlaceholderView.getSplitController().setInitialTaskSelect(taskView,
+        SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
+        splitController.setInitialTaskSelect(taskView,
                 splitPositionOption);
         mSplitHiddenTaskViewIndex = indexOfChild(taskView);
+        mSplitPlaceholderView.setLayoutParams(
+                splitController.getLayoutParamsForActivePosition(getResources(),
+                        mActivity.getDeviceProfile()));
+        mSplitPlaceholderView.setIcon(taskView.getIconView());
     }
 
     public PendingAnimation createSplitSelectInitAnimation() {
@@ -3163,7 +3244,6 @@
         }
 
         mRecentsAnimationController.finish(toRecents, () -> {
-            mRecentsAnimationController = null;
             if (onFinishComplete != null) {
                 onFinishComplete.run();
             }
@@ -3173,6 +3253,7 @@
             // typical example of this is (1) user swipes up from app to Overview (2) user
             // taps on QSB (3) user goes back to Overview and launch the most recent task.
             setCurrentTask(-1);
+            mRecentsAnimationController = null;
         });
     }
 
@@ -3235,8 +3316,8 @@
     @Override
     protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren,
             ComputePageScrollsLogic scrollLogic) {
-        boolean pageScrollChanged = super.getPageScrolls(outPageScrolls, layoutChildren,
-                scrollLogic);
+        int[] newPageScrolls = new int[outPageScrolls.length];
+        super.getPageScrolls(newPageScrolls, layoutChildren, scrollLogic);
         boolean showAsFullscreen = showAsFullscreen();
         boolean showAsGrid = showAsGrid();
 
@@ -3248,6 +3329,7 @@
             mClearAllButton.setScrollOffsetPrimary(mIsRtl ? clearAllWidthDiff : -clearAllWidthDiff);
         }
 
+        boolean pageScrollChanged = false;
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
@@ -3259,9 +3341,10 @@
                         showAsGrid);
             }
 
-            if (scrollDiff != 0) {
-                outPageScrolls[i] += scrollDiff;
+            final int pageScroll = newPageScrolls[i] + (int) scrollDiff;
+            if (outPageScrolls[i] != pageScroll) {
                 pageScrollChanged = true;
+                outPageScrolls[i] = pageScroll;
             }
         }
         return pageScrollChanged;
diff --git a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
index fb9be81..bb8bc11 100644
--- a/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
+++ b/quickstep/src/com/android/quickstep/views/SplitPlaceholderView.java
@@ -19,11 +19,12 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
-import android.view.View;
+import android.view.Gravity;
+import android.widget.FrameLayout;
 
 import com.android.quickstep.util.SplitSelectStateController;
 
-public class SplitPlaceholderView extends View {
+public class SplitPlaceholderView extends FrameLayout {
 
     public static final FloatProperty<SplitPlaceholderView> ALPHA_FLOAT =
             new FloatProperty<SplitPlaceholderView>("SplitViewAlpha") {
@@ -40,6 +41,7 @@
             };
 
     private SplitSelectStateController mSplitController;
+    private IconView mIcon;
 
     public SplitPlaceholderView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -52,4 +54,15 @@
     public SplitSelectStateController getSplitController() {
         return mSplitController;
     }
+
+    public void setIcon(IconView icon) {
+        if (mIcon == null) {
+            mIcon = new IconView(getContext());
+            addView(mIcon);
+        }
+        mIcon.setDrawable(icon.getDrawable());
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(icon.getLayoutParams());
+        params.gravity = Gravity.CENTER;
+        mIcon.setLayoutParams(params);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 2bb14d2..35acdd1 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -523,7 +523,7 @@
         if (mTask != null) {
             TestLogging.recordEvent(
                     TestProtocol.SEQUENCE_MAIN, "startActivityFromRecentsAsync", mTask);
-            ActivityOptionsWrapper opts =  mActivity.getActivityLaunchOptions(this);
+            ActivityOptionsWrapper opts =  mActivity.getActivityLaunchOptions(this, null);
             if (ActivityManagerWrapper.getInstance()
                     .startActivityFromRecents(mTask.key, opts.options)) {
                 return opts.onEndCallback;
diff --git a/res/color-night-v31/widgets_picker_surface.xml b/res/color-night-v31/widgets_picker_surface.xml
new file mode 100644
index 0000000..fbc9e43
--- /dev/null
+++ b/res/color-night-v31/widgets_picker_surface.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<selector
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/system_neutral1_800" />
+</selector>
diff --git a/res/color-v31/widgets_picker_surface.xml b/res/color-v31/widgets_picker_surface.xml
new file mode 100644
index 0000000..30f3032
--- /dev/null
+++ b/res/color-v31/widgets_picker_surface.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<selector
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/system_neutral1_500" android:lStar="98"/>
+</selector>
diff --git a/res/color/widgets_picker_surface.xml b/res/color/widgets_picker_surface.xml
new file mode 100644
index 0000000..6150110
--- /dev/null
+++ b/res/color/widgets_picker_surface.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<selector
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="?android:attr/colorBackgroundFloating" />
+</selector>
diff --git a/res/drawable/widgets_list_bottom_ripple.xml b/res/drawable/widgets_list_bottom_ripple.xml
index 3a26091..72262d4 100644
--- a/res/drawable/widgets_list_bottom_ripple.xml
+++ b/res/drawable/widgets_list_bottom_ripple.xml
@@ -30,7 +30,7 @@
     </item>
     <item android:id="@android:id/background">
         <shape android:shape="rectangle">
-            <solid android:color="?android:attr/colorBackground" />
+            <solid android:color="@color/widgets_picker_surface" />
             <corners
                 android:topLeftRadius="@dimen/widget_list_content_corner_radius"
                 android:topRightRadius="@dimen/widget_list_content_corner_radius"
diff --git a/res/drawable/widgets_list_middle_ripple.xml b/res/drawable/widgets_list_middle_ripple.xml
index da025d7..1136bea 100644
--- a/res/drawable/widgets_list_middle_ripple.xml
+++ b/res/drawable/widgets_list_middle_ripple.xml
@@ -31,7 +31,7 @@
 
     <item android:id="@android:id/background">
         <shape android:shape="rectangle">
-            <solid android:color="?android:attr/colorBackground" />
+            <solid android:color="@color/widgets_picker_surface" />
             <corners
                 android:topLeftRadius="@dimen/widget_list_content_corner_radius"
                 android:topRightRadius="@dimen/widget_list_content_corner_radius"
diff --git a/res/drawable/widgets_list_single_item_ripple.xml b/res/drawable/widgets_list_single_item_ripple.xml
index b8b6f42..a82918e 100644
--- a/res/drawable/widgets_list_single_item_ripple.xml
+++ b/res/drawable/widgets_list_single_item_ripple.xml
@@ -30,7 +30,7 @@
     </item>
     <item android:id="@android:id/background">
         <shape android:shape="rectangle">
-            <solid android:color="?android:attr/colorBackground" />
+            <solid android:color="@color/widgets_picker_surface" />
             <corners
                 android:topLeftRadius="@dimen/widget_list_top_bottom_corner_radius"
                 android:topRightRadius="@dimen/widget_list_top_bottom_corner_radius"
diff --git a/res/drawable/widgets_list_top_ripple.xml b/res/drawable/widgets_list_top_ripple.xml
index 6efc3e1..4ad185c 100644
--- a/res/drawable/widgets_list_top_ripple.xml
+++ b/res/drawable/widgets_list_top_ripple.xml
@@ -31,7 +31,7 @@
 
     <item android:id="@android:id/background">
         <shape android:shape="rectangle">
-            <solid android:color="?android:attr/colorBackground" />
+            <solid android:color="@color/widgets_picker_surface" />
             <corners
                 android:topLeftRadius="@dimen/widget_list_top_bottom_corner_radius"
                 android:topRightRadius="@dimen/widget_list_top_bottom_corner_radius"
diff --git a/res/drawable/widgets_recommendation_background.xml b/res/drawable/widgets_recommendation_background.xml
new file mode 100644
index 0000000..b59de27
--- /dev/null
+++ b/res/drawable/widgets_recommendation_background.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2021, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<shape android:shape="rectangle"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="@color/widgets_picker_surface" />
+    <corners android:radius="@dimen/widget_list_top_bottom_corner_radius"/>
+</shape>
\ No newline at end of file
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index 172284b..a01aa2c 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -25,7 +25,7 @@
         android:id="@+id/container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="?android:attr/colorBackgroundFloating"
+        android:background="?android:attr/colorBackground"
         android:elevation="4dp">
 
         <TextView
diff --git a/res/layout/widgets_full_sheet_search_and_recommendations.xml b/res/layout/widgets_full_sheet_search_and_recommendations.xml
index e5df175..e322c6c 100644
--- a/res/layout/widgets_full_sheet_search_and_recommendations.xml
+++ b/res/layout/widgets_full_sheet_search_and_recommendations.xml
@@ -20,7 +20,8 @@
     android:layout_height="wrap_content"
     android:paddingHorizontal="16dp"
     android:layout_marginBottom="16dp"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:clipToPadding="false">
     <View
         android:id="@+id/collapse_handle"
         android:layout_width="48dp"
@@ -44,6 +45,8 @@
         android:id="@+id/recommended_widget_table"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:background="@drawable/widgets_recommendation_background"
+        android:paddingVertical="8dp"
         android:layout_marginTop="16dp"
-        android:visibility="gone" />
+        android:visibility="gone"/>
 </LinearLayout>
diff --git a/res/layout/widgets_list_row_header.xml b/res/layout/widgets_list_row_header.xml
index 8259c16..f4b4130 100644
--- a/res/layout/widgets_list_row_header.xml
+++ b/res/layout/widgets_list_row_header.xml
@@ -19,7 +19,7 @@
     android:id="@+id/widgets_list_header"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginHorizontal="8dp"
+    android:layout_marginHorizontal="16dp"
     android:background="@drawable/widgets_list_middle_ripple"
     android:layout_marginBottom="@dimen/widget_list_entry_bottom_margin"
     android:paddingVertical="@dimen/widget_list_header_view_vertical_padding"
diff --git a/res/layout/widgets_table_container.xml b/res/layout/widgets_table_container.xml
index 0b5f0b9..e63483d 100644
--- a/res/layout/widgets_table_container.xml
+++ b/res/layout/widgets_table_container.xml
@@ -18,6 +18,6 @@
     android:id="@+id/widgets_table"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginHorizontal="8dp"
+    android:layout_marginHorizontal="16dp"
     android:background="@drawable/widgets_list_middle_ripple"
     android:layout_marginBottom="@dimen/widget_list_entry_bottom_margin"/>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index 08605ef..31ac27f 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -97,8 +97,8 @@
     <string name="folder_name_format_exact" msgid="8626242716117004803">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> টা বস্তু"</string>
     <string name="folder_name_format_overflow" msgid="4270108890534995199">"ফ’ল্ডাৰ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> টা অথবা তাতকৈ অধিক বস্তু"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"ৱালপেপাৰসমূহ"</string>
-    <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ষ্টাইল &amp; ৱালপেপাৰ"</string>
-    <string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিংসমূহ"</string>
+    <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"শৈলী আৰু ৱালপেপাৰ"</string>
+    <string name="settings_button_text" msgid="8873672322605444408">"গৃহ ছেটিং"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে"</string>
     <string name="allow_rotation_title" msgid="7728578836261442095">"গৃহ স্ক্ৰীণ ঘূৰোৱাৰ অনুমতি দিয়ক"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"ফ\'নটো যেতিয়া ঘূৰোৱা হয়"</string>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 20821d3..c2d9946 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -115,7 +115,7 @@
     <string name="msg_missing_notification_access" msgid="281113995110910548">"Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="title_change_settings" msgid="1376365968844349552">"Змяніць налады"</string>
     <string name="notification_dots_service_title" msgid="4284221181793592871">"Паказваць значкі апавяшчэнняў"</string>
-    <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Дадаць значкі праграм на Галоўны экран"</string>
+    <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Дадаваць значкі праграм на Галоўны экран"</string>
     <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Для новых праграм"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Невядома"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Выдаліць"</string>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index a38c3d2..a485a14 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -66,7 +66,7 @@
     <string name="all_apps_button_work_label" msgid="7270707118948892488">"Laneko aplikazioen zerrenda"</string>
     <string name="remove_drop_target_label" msgid="7812859488053230776">"Kendu"</string>
     <string name="uninstall_drop_target_label" msgid="4722034217958379417">"Desinstalatu"</string>
-    <string name="app_info_drop_target_label" msgid="692894985365717661">"Aplikazioaren datuak"</string>
+    <string name="app_info_drop_target_label" msgid="692894985365717661">"Aplikazioaren informazioa"</string>
     <string name="install_drop_target_label" msgid="2539096853673231757">"Instalatu"</string>
     <string name="dismiss_prediction_label" msgid="3357562989568808658">"Ez iradoki aplikazioa"</string>
     <string name="pin_prediction" msgid="4196423321649756498">"Ainguratu iragarpena"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index d7e3a5b..34ed9e0 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -103,7 +103,7 @@
     <string name="allow_rotation_title" msgid="7728578836261442095">"Salli aloitusnäytön kiertäminen"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Kun puhelinta kierretään"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"Pistemerkit"</string>
-    <string name="notification_dots_desc_on" msgid="1679848116452218908">"Käytössä"</string>
+    <string name="notification_dots_desc_on" msgid="1679848116452218908">"Päällä"</string>
     <string name="notification_dots_desc_off" msgid="1760796511504341095">"Ei päällä"</string>
     <string name="title_missing_notification_access" msgid="7503287056163941064">"Ilmoituksien käyttöoikeus tarvitaan"</string>
     <string name="msg_missing_notification_access" msgid="281113995110910548">"<xliff:g id="NAME">%1$s</xliff:g> tarvitsee ilmoitusten käyttöoikeuden, jotta pistemerkkejä voidaan näyttää."</string>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 7d65a14..382f6ff 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -27,7 +27,7 @@
     <string name="safemode_widget_error" msgid="4863470563535682004">"Os widgets están desactivados no modo seguro"</string>
     <string name="shortcut_not_available" msgid="2536503539825726397">"O atallo non está dispoñible"</string>
     <string name="home_screen" msgid="5629429142036709174">"Inicio"</string>
-    <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Dividir pantalla"</string>
+    <string name="recent_task_option_split_screen" msgid="6690461455618725183">"Pantalla dividida"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"Mantén premido un widget para movelo."</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"Toca dúas veces un widget e manteno premido para movelo ou utiliza accións personalizadas."</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
@@ -108,7 +108,7 @@
     <string name="title_missing_notification_access" msgid="7503287056163941064">"Necesítase acceso ás notificacións"</string>
     <string name="msg_missing_notification_access" msgid="281113995110910548">"Para que se mostren os puntos de notificacións, activa as notificacións da aplicación <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="title_change_settings" msgid="1376365968844349552">"Cambiar configuración"</string>
-    <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostrar puntos de notificacións"</string>
+    <string name="notification_dots_service_title" msgid="4284221181793592871">"Mostra puntos de notificacións"</string>
     <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Engadir iconas de aplicacións á pantalla de inicio"</string>
     <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"Para novas aplicacións"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Descoñecido"</string>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 2397e92..104b4ac 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -100,7 +100,7 @@
     <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stílar og veggfóður"</string>
     <string name="settings_button_text" msgid="8873672322605444408">"Heimastillingar"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Gert óvirkt af kerfisstjóra"</string>
-    <string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning fyrir heimaskjá"</string>
+    <string name="allow_rotation_title" msgid="7728578836261442095">"Leyfa snúning á heimaskjá"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Þegar símanum er snúið"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"Tilkynningapunktar"</string>
     <string name="notification_dots_desc_on" msgid="1679848116452218908">"Kveikt"</string>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 967a22e..3ce2c20 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -98,7 +98,7 @@
     <string name="folder_name_format_overflow" msgid="4270108890534995199">"ໂຟນເດີ: <xliff:g id="NAME">%1$s</xliff:g>, <xliff:g id="SIZE">%2$d</xliff:g> ຫຼື ລາຍການເພີ່ມເຕີມ"</string>
     <string name="wallpaper_button_text" msgid="8404103075899945851">"ພາບພື້ນຫຼັງ"</string>
     <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"ຮູບແບບ ແລະ ຮູບພື້ນຫຼັງ"</string>
-    <string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າ Home"</string>
+    <string name="settings_button_text" msgid="8873672322605444408">"ການຕັ້ງຄ່າໜ້າຫຼັກ"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ"</string>
     <string name="allow_rotation_title" msgid="7728578836261442095">"ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍຢູ່ໜ້າຫຼັກໄດ້"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"ເມື່ອໝຸນໂທລະສັບ"</string>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 247144d..ce79bde 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -109,7 +109,7 @@
     <string name="msg_missing_notification_access" msgid="281113995110910548">"За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="title_change_settings" msgid="1376365968844349552">"Промени ги поставките"</string>
     <string name="notification_dots_service_title" msgid="4284221181793592871">"Прикажувај точки за известување"</string>
-    <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додавај икони за апликации на почетен екран"</string>
+    <string name="auto_add_shortcuts_label" msgid="3698776050751790653">"Додавај икони за апликации на почетниот екран"</string>
     <string name="auto_add_shortcuts_description" msgid="7117251166066978730">"За нови апликации"</string>
     <string name="package_state_unknown" msgid="7592128424511031410">"Непознато"</string>
     <string name="abandoned_clean_this" msgid="7610119707847920412">"Отстрани"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 03519ba..8505c8e 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -27,7 +27,7 @@
     <string name="safemode_widget_error" msgid="4863470563535682004">"ନିରାପଦ ମୋଡରେ ୱିଜେଟ୍‌ ଅକ୍ଷମ କରାଗଲା"</string>
     <string name="shortcut_not_available" msgid="2536503539825726397">"ଶର୍ଟକଟ୍‌ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="home_screen" msgid="5629429142036709174">"ମୂଳପୃଷ୍ଠା"</string>
-    <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍ପ୍ଲିଟ୍ ସ୍କ୍ରିନ୍"</string>
+    <string name="recent_task_option_split_screen" msgid="6690461455618725183">"ସ୍କ୍ରିନ‌କୁ ସ୍ପ୍ଲିଟ୍ କରନ୍ତୁ"</string>
     <string name="long_press_widget_to_add" msgid="3587712543577675817">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।"</string>
     <string name="long_accessible_way_to_add" msgid="2733588281439571974">"ଏକ ୱିଜେଟକୁ ମୁଭ୍ କରିବା ପାଇଁ ଦୁଇଥର-ଟାପ୍ କରି ଧରି ରଖନ୍ତୁ କିମ୍ବା କଷ୍ଟମ୍ କାର୍ଯ୍ୟଗୁଡ଼ିକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="widget_dims_format" msgid="2370757736025621599">"%1$d × %2$d"</string>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 5879f91..9e60efb 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -106,7 +106,7 @@
     <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Slogi in ozadja"</string>
     <string name="settings_button_text" msgid="8873672322605444408">"Domače nastavitve"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Onemogočil skrbnik."</string>
-    <string name="allow_rotation_title" msgid="7728578836261442095">"Omogočanje sukanja začetnega zaslona"</string>
+    <string name="allow_rotation_title" msgid="7728578836261442095">"Omogoči sukanje začetnega zaslona"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Ko se telefon zasuka"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"Obvestilne pike"</string>
     <string name="notification_dots_desc_on" msgid="1679848116452218908">"Vklopljeno"</string>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index f2c16b4..1ed8070 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -100,7 +100,7 @@
     <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"Stilet dhe imazhet e sfondit"</string>
     <string name="settings_button_text" msgid="8873672322605444408">"Cilësimet e ekranit bazë"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"Çaktivizuar nga administratori"</string>
-    <string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit kryesor"</string>
+    <string name="allow_rotation_title" msgid="7728578836261442095">"Lejo rrotullimin e ekranit bazë"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"Kur telefoni rrotullohet"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"Pikat e njoftimeve"</string>
     <string name="notification_dots_desc_on" msgid="1679848116452218908">"Aktiv"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index a3c7256..344f455 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -100,7 +100,7 @@
     <string name="styles_wallpaper_button_text" msgid="4342122323125579619">"స్ట‌యిల్స్‌ &amp; వాల్‌పేపర్‌లు"</string>
     <string name="settings_button_text" msgid="8873672322605444408">"హోమ్ సెట్టింగ్‌లు"</string>
     <string name="msg_disabled_by_admin" msgid="6898038085516271325">"మీ నిర్వాహకులు నిలిపివేసారు"</string>
-    <string name="allow_rotation_title" msgid="7728578836261442095">"హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి"</string>
+    <string name="allow_rotation_title" msgid="7728578836261442095">"హోమ్ స్క్రీన్ రొటేషన్‌ను అనుమతించండి"</string>
     <string name="allow_rotation_desc" msgid="8662546029078692509">"ఫోన్‌‌ను తిప్పినప్పుడు"</string>
     <string name="notification_dots_title" msgid="9062440428204120317">"నోటిఫికేషన్ డాట్‌లు"</string>
     <string name="notification_dots_desc_on" msgid="1679848116452218908">"ఆన్"</string>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index e9412d9..4c5f9f2 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -21,6 +21,7 @@
 
 import android.app.ActivityOptions;
 import android.content.ActivityNotFoundException;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.LauncherApps;
 import android.content.res.Configuration;
@@ -165,7 +166,7 @@
     }
 
     @NonNull
-    public ActivityOptionsWrapper getActivityLaunchOptions(View v) {
+    public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
         int left = 0, top = 0;
         int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
         if (v instanceof BubbleTextView) {
@@ -192,7 +193,7 @@
             return false;
         }
 
-        Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v).toBundle() : null;
+        Bundle optsBundle = (v != null) ? getActivityLaunchOptions(v, item).toBundle() : null;
         UserHandle user = item == null ? null : item.user;
 
         // Prepare intent
@@ -296,7 +297,7 @@
     }
 
     @Override
-    public void onDisplayInfoChanged(Info info, int flags) {
+    public void onDisplayInfoChanged(Context context, Info info, int flags) {
         if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.updateIsSeascape(this)) {
             reapplyUi();
         }
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d333b49..2ace796 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher3;
 
-import static com.android.launcher3.graphics.IconShape.getShape;
 import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
 
@@ -26,16 +25,13 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
-import android.graphics.BlurMaskFilter;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
-import android.graphics.Path;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.os.Process;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
 import android.util.Property;
@@ -50,7 +46,6 @@
 import androidx.annotation.UiThread;
 
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.dragndrop.DraggableView;
 import com.android.launcher3.folder.FolderIcon;
@@ -60,7 +55,6 @@
 import com.android.launcher3.icons.DotRenderer;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
-import com.android.launcher3.icons.LauncherIcons;
 import com.android.launcher3.icons.PlaceHolderIconDrawable;
 import com.android.launcher3.icons.cache.HandlerRunnable;
 import com.android.launcher3.model.data.AppInfo;
@@ -97,11 +91,6 @@
 
     private float mScaleForReorderBounce = 1f;
 
-    protected final Paint mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
-    private final Path mHighlightPath = new Path();
-    protected int mHighlightColor = Color.TRANSPARENT;
-    private final BlurMaskFilter mHighlightShadowFilter;
-
     private static final Property<BubbleTextView, Float> DOT_SCALE_PROPERTY
             = new Property<BubbleTextView, Float>(Float.TYPE, "dotScale") {
         @Override
@@ -220,10 +209,6 @@
         setEllipsize(TruncateAt.END);
         setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
         setTextAlpha(1f);
-
-        int shadowSize = context.getResources().getDimensionPixelSize(
-                R.dimen.blur_size_click_shadow);
-        mHighlightShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.INNER);
     }
 
     @Override
@@ -451,41 +436,10 @@
 
     @Override
     public void onDraw(Canvas canvas) {
-        if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mHighlightColor != Color.TRANSPARENT) {
-            int count = canvas.save();
-            drawFocusHighlight(canvas);
-            canvas.restoreToCount(count);
-        }
         super.onDraw(canvas);
         drawDotIfNecessary(canvas);
     }
 
-    protected void drawFocusHighlight(Canvas canvas) {
-        boolean isBadged = getTag() instanceof ItemInfo && !Process.myUserHandle().equals(
-                ((ItemInfo) getTag()).user);
-        float insetScale = (HIGHLIGHT_SCALE - 1) / 2;
-        canvas.translate(-getIconSize() * insetScale, -insetScale * getIconSize());
-        float outlineSize = getIconSize() * HIGHLIGHT_SCALE;
-        mHighlightPath.reset();
-        mHighlightPaint.reset();
-        getIconBounds(mDotParams.iconBounds);
-        getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left, mDotParams.iconBounds.top,
-                outlineSize / 2);
-        if (isBadged) {
-            float borderSize = outlineSize - getIconSize();
-            float badgeSize = LauncherIcons.getBadgeSizeForIconSize(getIconSize()) + borderSize;
-            float badgeInset = outlineSize - badgeSize;
-            getShape().addToPath(mHighlightPath, mDotParams.iconBounds.left + badgeInset,
-                    mDotParams.iconBounds.top + badgeInset, badgeSize / 2);
-        }
-        mHighlightPaint.setMaskFilter(mHighlightShadowFilter);
-        mHighlightPaint.setColor(mDotParams.color);
-        canvas.drawPath(mHighlightPath, mHighlightPaint);
-        mHighlightPaint.setMaskFilter(null);
-        mHighlightPaint.setColor(mHighlightColor);
-        canvas.drawPath(mHighlightPath, mHighlightPaint);
-    }
-
     /**
      * Draws the notification dot in the top right corner of the icon bounds.
      *
@@ -921,11 +875,9 @@
 
     @Override
     public SafeCloseable prepareDrawDragView() {
-        int highlightColor = mHighlightColor;
-        mHighlightColor = Color.TRANSPARENT;
         resetIconScale();
         setForceHideDot(true);
-        return () -> mHighlightColor = highlightColor;
+        return () -> { };
     }
 
     private void resetIconScale() {
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index a6fc0f3..fd97936 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -38,8 +39,8 @@
 import com.android.launcher3.CellLayout.ContainerType;
 import com.android.launcher3.DevicePaddings.DevicePadding;
 import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.graphics.IconShape;
 import com.android.launcher3.icons.DotRenderer;
+import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.icons.IconNormalizer;
 import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.DisplayController;
@@ -54,6 +55,7 @@
     private static final float TABLET_MIN_DPS = 600;
     private static final float LARGE_TABLET_MIN_DPS = 720;
 
+    private static final int DEFAULT_DOT_SIZE = 100;
 
     public final InvariantDeviceProfile inv;
     private final Info mInfo;
@@ -366,11 +368,10 @@
         updateWorkspacePadding();
 
         // This is done last, after iconSizePx is calculated above.
-        mDotRendererWorkSpace = new DotRenderer(iconSizePx, IconShape.getShapePath(),
-                IconShape.DEFAULT_PATH_SIZE);
+        Path dotPath = GraphicsUtils.getShapePath(DEFAULT_DOT_SIZE);
+        mDotRendererWorkSpace = new DotRenderer(iconSizePx, dotPath, DEFAULT_DOT_SIZE);
         mDotRendererAllApps = iconSizePx == allAppsIconSizePx ? mDotRendererWorkSpace :
-                new DotRenderer(allAppsIconSizePx, IconShape.getShapePath(),
-                        IconShape.DEFAULT_PATH_SIZE);
+                new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
     }
 
     private void setCellLayoutBorderSpacing(int borderSpacing) {
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 11dc0c4..1332e14 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -203,9 +203,9 @@
                 .apply();
 
         DisplayController.INSTANCE.get(context).addChangeListener(
-                (info, flags) -> {
+                (displayContext, info, flags) -> {
                     if ((flags & (CHANGE_SIZE | CHANGE_DENSITY)) != 0) {
-                        onConfigChanged(context);
+                        onConfigChanged(displayContext);
                     }
                 });
         mOverlayMonitor = new OverlayMonitor(context);
@@ -226,7 +226,7 @@
      */
     public InvariantDeviceProfile(Context context, Display display) {
         // Ensure that the main device profile is initialized
-        InvariantDeviceProfile originalProfile = INSTANCE.get(context);
+        INSTANCE.get(context);
         String gridName = getCurrentGridName(context);
 
         // Get the display info based on default display and interpolate it to existing display
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 1579df5..0c3a356 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2939,20 +2939,30 @@
      * Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
      * animation.
      *
+     * @param preferredItemId The id of the preferred item to match to if it exists.
      * @param packageName The package name of the app to match.
      * @param user The user of the app to match.
      */
-    public View getFirstMatchForAppClose(String packageName, UserHandle user) {
-        List<CellLayout> cellLayouts = new ArrayList<>(getPanelCount() + 1);
-        cellLayouts.add(getHotseat());
-        getVisiblePages().forEach(page -> cellLayouts.add((CellLayout) page));
-
-        final Workspace.ItemOperator packageAndUser = (ItemInfo info, View view) -> info != null
-                && info.getTargetComponent() != null
-                && TextUtils.equals(info.getTargetComponent().getPackageName(), packageName)
-                && info.user.equals(user);
+    public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user) {
+        final Workspace.ItemOperator preferredItem = (ItemInfo info, View view) ->
+                info != null && info.id == preferredItemId;
+        final Workspace.ItemOperator preferredItemInFolder = (info, view) -> {
+            if (info instanceof FolderInfo) {
+                FolderInfo folderInfo = (FolderInfo) info;
+                for (WorkspaceItemInfo shortcutInfo : folderInfo.contents) {
+                    if (preferredItem.evaluate(shortcutInfo, view)) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        };
         final Workspace.ItemOperator packageAndUserAndApp = (ItemInfo info, View view) ->
-                packageAndUser.evaluate(info, view) && info.itemType == ITEM_TYPE_APPLICATION;
+                info != null
+                        && info.getTargetComponent() != null
+                        && TextUtils.equals(info.getTargetComponent().getPackageName(), packageName)
+                        && info.user.equals(user)
+                        && info.itemType == ITEM_TYPE_APPLICATION;
         final Workspace.ItemOperator packageAndUserAndAppInFolder = (info, view) -> {
             if (info instanceof FolderInfo) {
                 FolderInfo folderInfo = (FolderInfo) info;
@@ -2965,13 +2975,18 @@
             return false;
         };
 
+        List<CellLayout> cellLayouts = new ArrayList<>(getPanelCount() + 1);
+        cellLayouts.add(getHotseat());
+        getVisiblePages().forEach(page -> cellLayouts.add((CellLayout) page));
+
         // Order: App icons, app in folder. Items in hotseat get returned first.
         if (ADAPTIVE_ICON_WINDOW_ANIM.get()) {
-            return getFirstMatch(cellLayouts, packageAndUserAndApp, packageAndUserAndAppInFolder);
+            return getFirstMatch(cellLayouts, preferredItem, preferredItemInFolder,
+                    packageAndUserAndApp, packageAndUserAndAppInFolder);
         } else {
             // Do not use Folder as a criteria, since it'll cause a crash when trying to draw
             // FolderAdaptiveIcon as the background.
-            return getFirstMatch(cellLayouts, packageAndUserAndApp);
+            return getFirstMatch(cellLayouts, preferredItem, packageAndUserAndApp);
         }
     }
 
diff --git a/src/com/android/launcher3/graphics/IconShape.java b/src/com/android/launcher3/graphics/IconShape.java
index b208a40..2da679c 100644
--- a/src/com/android/launcher3/graphics/IconShape.java
+++ b/src/com/android/launcher3/graphics/IconShape.java
@@ -37,20 +37,14 @@
 import android.graphics.drawable.ColorDrawable;
 import android.os.Build;
 import android.util.AttributeSet;
-import android.util.SparseArray;
-import android.util.TypedValue;
 import android.util.Xml;
 import android.view.View;
 import android.view.ViewOutlineProvider;
 
-import androidx.annotation.Nullable;
-
 import com.android.launcher3.R;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.icons.IconNormalizer;
-import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ClipPathView;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -66,30 +60,16 @@
 public abstract class IconShape {
 
     private static IconShape sInstance = new Circle();
-    private static Path sShapePath;
     private static float sNormalizationScale = ICON_VISIBLE_AREA_FACTOR;
 
-    public static final int DEFAULT_PATH_SIZE = 100;
-
     public static IconShape getShape() {
         return sInstance;
     }
 
-    public static Path getShapePath() {
-        if (sShapePath == null) {
-            Path p = new Path();
-            getShape().addToPath(p, 0, 0, DEFAULT_PATH_SIZE * 0.5f);
-            sShapePath = p;
-        }
-        return sShapePath;
-    }
-
     public static float getNormalizationScale() {
         return sNormalizationScale;
     }
 
-    private SparseArray<TypedValue> mAttrs;
-
     public boolean enableShapeDetection(){
         return false;
     };
@@ -102,11 +82,6 @@
     public abstract <T extends View & ClipPathView> Animator createRevealAnimator(T target,
             Rect startRect, Rect endRect, float endRadius, boolean isReversed);
 
-    @Nullable
-    public TypedValue getAttrValue(int attr) {
-        return mAttrs == null ? null : mAttrs.get(attr);
-    }
-
     /**
      * Abstract shape where the reveal animation is a derivative of a round rect animation
      */
@@ -410,7 +385,6 @@
 
             final int depth = parser.getDepth();
             int[] radiusAttr = new int[] {R.attr.folderIconRadius};
-            IntArray keysToIgnore = new IntArray(0);
 
             while (((type = parser.next()) != XmlPullParser.END_TAG ||
                     parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
@@ -421,7 +395,6 @@
                     IconShape shape = getShapeDefinition(parser.getName(), a.getFloat(0, 1));
                     a.recycle();
 
-                    shape.mAttrs = Themes.createValueMap(context, attrs, keysToIgnore);
                     result.add(shape);
                 }
             }
@@ -467,8 +440,6 @@
         }
 
         // Initialize shape properties
-        drawable.setBounds(0, 0, DEFAULT_PATH_SIZE, DEFAULT_PATH_SIZE);
-        sShapePath = new Path(drawable.getIconMask());
         sNormalizationScale = IconNormalizer.normalizeAdaptiveIcon(drawable, size, null);
     }
 }
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index ac0ec5f..13ae866 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,9 +17,6 @@
 
 package com.android.launcher3.graphics;
 
-import static com.android.launcher3.graphics.IconShape.DEFAULT_PATH_SIZE;
-import static com.android.launcher3.graphics.IconShape.getShapePath;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -39,6 +36,7 @@
 
 import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.icons.FastBitmapDrawable;
+import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.util.Themes;
 
@@ -62,6 +60,7 @@
                 }
             };
 
+    private static final int DEFAULT_PATH_SIZE = 100;
     private static final float PROGRESS_WIDTH = 7;
     private static final float PROGRESS_GAP = 2;
     private static final int MAX_PAINT_ALPHA = 255;
@@ -132,7 +131,7 @@
             boolean isDarkMode) {
         super(info.bitmap);
         mItem = info;
-        mShapePath = getShapePath();
+        mShapePath = GraphicsUtils.getShapePath(DEFAULT_PATH_SIZE);
         mScaledTrackPath = new Path();
         mScaledProgressPath = new Path();
 
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index 2e54904..ce7dc07 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -180,7 +180,7 @@
                 LauncherApps launcherApps = launcher.getSystemService(LauncherApps.class);
                 try {
                     launcherApps.startPackageInstallerSessionDetailsActivity(sessionInfo, null,
-                            launcher.getActivityLaunchOptions(v).toBundle());
+                            launcher.getActivityLaunchOptions(v, item).toBundle());
                     return;
                 } catch (Exception e) {
                     Log.e(TAG, "Unable to launch market intent for package=" + packageName, e);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index b2cc31b..31586e7 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -311,21 +311,31 @@
     @Override
     public List<SplitPositionOption> getSplitPositionOptions(DeviceProfile dp) {
         List<SplitPositionOption> options = new ArrayList<>(1);
+        // Add both left and right options if we're in tablet mode
         // TODO: Add in correct icons
-        if (dp.isSeascape()) { // or seascape
-            // Add left/right options
+        if (dp.isTablet && dp.isLandscape) {
             options.add(new SplitPositionOption(
                     R.drawable.ic_split_screen, R.string.split_screen_position_right,
-                    STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
-        } else if (dp.isLandscape) {
+                    STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
             options.add(new SplitPositionOption(
                     R.drawable.ic_split_screen, R.string.split_screen_position_left,
                     STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
         } else {
-            // Only add top option
-            options.add(new SplitPositionOption(
-                    R.drawable.ic_split_screen, R.string.split_screen_position_top,
-                    STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+            if (dp.isSeascape()) {
+                // Add left/right options
+                options.add(new SplitPositionOption(
+                        R.drawable.ic_split_screen, R.string.split_screen_position_right,
+                        STAGE_POSITION_BOTTOM_OR_RIGHT, STAGE_TYPE_MAIN));
+            } else if (dp.isLandscape) {
+                options.add(new SplitPositionOption(
+                        R.drawable.ic_split_screen, R.string.split_screen_position_left,
+                        STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+            } else {
+                // Only add top option
+                options.add(new SplitPositionOption(
+                        R.drawable.ic_split_screen, R.string.split_screen_position_top,
+                        STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
+            }
         }
         return options;
     }
diff --git a/src/com/android/launcher3/util/ActivityTracker.java b/src/com/android/launcher3/util/ActivityTracker.java
index 59266b4..b5b9c2f 100644
--- a/src/com/android/launcher3/util/ActivityTracker.java
+++ b/src/com/android/launcher3/util/ActivityTracker.java
@@ -75,9 +75,8 @@
     private boolean handleIntent(T activity, Intent intent, boolean alreadyOnHome) {
         if (intent != null && intent.getExtras() != null) {
             IBinder stateBinder = intent.getExtras().getBinder(EXTRA_SCHEDULER_CALLBACK);
-            if (stateBinder instanceof ObjectWrapper) {
-                SchedulerCallback<T> handler =
-                        ((ObjectWrapper<SchedulerCallback>) stateBinder).get();
+            SchedulerCallback<T> handler = ObjectWrapper.unwrap(stateBinder);
+            if (handler != null) {
                 if (!handler.init(activity, alreadyOnHome)) {
                     intent.getExtras().remove(EXTRA_SCHEDULER_CALLBACK);
                 }
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 07c89b9..75c089e 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -87,7 +87,7 @@
                     new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
         }
 
-        mInfo = createInfo(display);
+        mInfo = new Info(getContext(display), display);
         mDM.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
     }
 
@@ -125,7 +125,13 @@
      */
     public interface DisplayInfoChangeListener {
 
-        void onDisplayInfoChanged(Info info, int flags);
+        /**
+         * Invoked when display info has changed.
+         * @param context updated context associated with the display.
+         * @param info updated display information.
+         * @param flags bitmask indicating type of change.
+         */
+        void onDisplayInfoChanged(Context context, Info info, int flags);
     }
 
     /**
@@ -172,14 +178,15 @@
         return mInfo;
     }
 
-    private Info createInfo(Display display) {
-        return new Info(mContext.createDisplayContext(display), display);
+    private Context getContext(Display display) {
+        return Utilities.ATLEAST_S ? mWindowContext : mContext.createDisplayContext(display);
     }
 
     @AnyThread
     private void handleInfoChange(Display display) {
         Info oldInfo = mInfo;
-        Info newInfo = createInfo(display);
+        Context context = getContext(display);
+        Info newInfo = new Info(context, display);
         int change = 0;
         if (newInfo.hasDifferentSize(oldInfo)) {
             change |= CHANGE_SIZE;
@@ -197,13 +204,13 @@
         if (change != 0) {
             mInfo = newInfo;
             final int flags = change;
-            MAIN_EXECUTOR.execute(() -> notifyChange(flags));
+            MAIN_EXECUTOR.execute(() -> notifyChange(context, flags));
         }
     }
 
-    private void notifyChange(int flags) {
+    private void notifyChange(Context context, int flags) {
         for (int i = mListeners.size() - 1; i >= 0; i--) {
-            mListeners.get(i).onDisplayInfoChanged(mInfo, flags);
+            mListeners.get(i).onDisplayInfoChanged(context, mInfo, flags);
         }
     }
 
diff --git a/src/com/android/launcher3/util/ObjectWrapper.java b/src/com/android/launcher3/util/ObjectWrapper.java
index e5b4707..a715821 100644
--- a/src/com/android/launcher3/util/ObjectWrapper.java
+++ b/src/com/android/launcher3/util/ObjectWrapper.java
@@ -42,4 +42,11 @@
     public static IBinder wrap(Object obj) {
         return new ObjectWrapper<>(obj);
     }
+
+    public static <T> T unwrap(IBinder binder) {
+        if (binder instanceof ObjectWrapper) {
+            return ((ObjectWrapper<T>) binder).get();
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index f13484f..e2e3be7 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -158,7 +158,7 @@
         if (mContract == null) {
             return;
         }
-        View icon = mLauncher.getWorkspace().getFirstMatchForAppClose(
+        View icon = mLauncher.getWorkspace().getFirstMatchForAppClose(-1,
                 mContract.componentName.getPackageName(), mContract.user);
 
         boolean iconChanged = mIcon != icon;
diff --git a/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java b/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
index 2366609..42896ba 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsDiffReporter.java
@@ -181,8 +181,8 @@
         }
         if (newRow instanceof WidgetsListSearchHeaderEntry
                 && curRow instanceof WidgetsListSearchHeaderEntry) {
-            return ((WidgetsListSearchHeaderEntry) newRow).hasEntryUpdated()
-                    || !curRow.equals(newRow);
+            // Always refresh search header entries to reset rounded corners in their view holder.
+            return true;
         }
         return false;
     }
diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
index 1aefe41..18f1be3 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java
@@ -43,6 +43,7 @@
     private static final float DOWN_SCALE_RATIO = 0.9f;
     private static final float MAX_DOWN_SCALE_RATIO = 0.5f;
     private final float mWidgetCellTextViewsHeight;
+    private final float mWidgetPreviewPadding;
 
     private float mRecommendationTableMaxHeight = Float.MAX_VALUE;
     @Nullable private OnLongClickListener mWidgetCellOnLongClickListener;
@@ -57,6 +58,8 @@
         super(context, attrs);
         // There are 1 row for title, 1 row for dimension and 2 rows for description.
         mWidgetCellTextViewsHeight = 4 * getResources().getDimension(R.dimen.widget_cell_font_size);
+        mWidgetPreviewPadding = 2 * getResources()
+                .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding);
     }
 
     /** Sets a {@link android.view.View.OnLongClickListener} for all widget cells in this table. */
@@ -147,7 +150,7 @@
             float rowHeight = 0;
             for (int j = 0; j < widgetItems.size(); j++) {
                 float previewHeight = widgetItems.get(j).spanY * deviceProfile.cellHeightPx
-                        * previewScale;
+                        * previewScale + mWidgetPreviewPadding;
                 rowHeight = Math.max(rowHeight, previewHeight + mWidgetCellTextViewsHeight);
             }
             totalHeight += rowHeight;