Merge "Make all apps text focusable by accessibility." into 24D1-dev
diff --git a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
index a1bcad0..b004dfd 100644
--- a/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/redesigned_gesture_tutorial_fragment.xml
@@ -134,11 +134,12 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
+        android:layout_above="@id/gesture_tutorial_fragment_action_button"
         android:layout_centerHorizontal="true"
         android:background="@android:color/transparent"
-        android:paddingEnd="24dp"
-        android:paddingStart="24dp"
-        android:paddingTop="24dp">
+        android:paddingTop="24dp"
+        android:paddingHorizontal="24dp"
+        android:layout_marginBottom="16dp">
 
         <TextView
             android:id="@+id/gesture_tutorial_fragment_feedback_title"
@@ -169,7 +170,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
 
-            app:layout_constraintBottom_toBottomOf="@id/gesture_tutorial_fragment_action_button"
+            app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
@@ -193,7 +194,7 @@
             android:id="@+id/checkmark_animation"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginBottom="44dp"
+            android:layout_marginBottom="28dp"
             android:gravity="center"
             android:scaleType="centerCrop"
             app:lottie_loop="false"
@@ -204,19 +205,6 @@
             app:layout_constraintTop_toBottomOf="@id/gesture_tutorial_fragment_feedback_subtitle"
             app:layout_constraintBottom_toBottomOf="parent" />
 
-        <Button
-            android:id="@+id/gesture_tutorial_fragment_action_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:background="@drawable/gesture_tutorial_action_button_background"
-            android:stateListAnimator="@null"
-            android:text="@string/gesture_tutorial_action_button_label"
-            android:visibility="invisible"
-            android:layout_marginBottom="60dp"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/checkmark_animation" />
 
     </androidx.constraintlayout.widget.ConstraintLayout>
 
@@ -228,4 +216,18 @@
         android:src="@drawable/gesture_tutorial_finger_dot"
         android:visibility="gone" />
 
+    <Button
+        android:id="@+id/gesture_tutorial_fragment_action_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="@dimen/gesture_tutorial_done_button_end_margin"
+        android:layout_marginBottom="@dimen/gesture_tutorial_done_button_bottom_margin"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentEnd="true"
+        android:background="@drawable/gesture_tutorial_action_button_background"
+        android:stateListAnimator="@null"
+        android:text="@string/gesture_tutorial_action_button_label"
+        android:visibility="invisible"
+         />
+
 </com.android.quickstep.interaction.RootSandboxLayout>
\ No newline at end of file
diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml
index efdab4a..4d9aacc 100644
--- a/quickstep/res/values-de/strings.xml
+++ b/quickstep/res/values-de/strings.xml
@@ -94,7 +94,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Einstellungen der Systemsteuerung"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Teilen"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Screenshot"</string>
-    <string name="action_split" msgid="2098009717623550676">"Teilen"</string>
+    <string name="action_split" msgid="2098009717623550676">"Splitscreen"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"App-Paar speichern"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Für Splitscreen auf weitere App tippen"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Für Splitscreen andere App auswählen"</string>
diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml
index 7ca8314..53d9904 100644
--- a/quickstep/res/values-es/strings.xml
+++ b/quickstep/res/values-es/strings.xml
@@ -117,7 +117,7 @@
     <string name="taskbar_edu_pinning_title" msgid="210102174154211712">"Mostrar siempre la barra de tareas"</string>
     <string name="taskbar_edu_pinning_standalone" msgid="2636919474366410467">"Para mostrar siempre la barra de tareas en la parte inferior, mantén pulsada la línea divisoria"</string>
     <string name="taskbar_search_edu_title" msgid="5569194922234364530">"Mantén pulsada la tecla de acción para buscar lo que ves en pantalla"</string>
-    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"El producto usa la parte seleccionada de tu pantalla para hacer búsquedas. Se aplican la <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de Privacidad<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> y los <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Términos del Servicio<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google."</string>
+    <string name="taskbar_edu_search_disclosure" msgid="8734536088447779686">"Este producto usa la parte seleccionada de tu pantalla para hacer búsquedas. Se aplican la <xliff:g id="BEGIN_PRIVACY_LINK">&lt;a href="%1$s"&gt;</xliff:g>Política de Privacidad<xliff:g id="END_PRIVACY_LINK">&lt;/a&gt;</xliff:g> y los <xliff:g id="BEGIN_TOS_LINK">&lt;a href="%2$s"&gt;</xliff:g>Términos del Servicio<xliff:g id="END_TOS_LINK">&lt;/a&gt;</xliff:g> de Google."</string>
     <string name="taskbar_edu_close" msgid="887022990168191073">"Cerrar"</string>
     <string name="taskbar_edu_done" msgid="6880178093977704569">"Hecho"</string>
     <string name="taskbar_button_home" msgid="2151398979630664652">"Inicio"</string>
diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml
index 2043aff..d1b5bfc 100644
--- a/quickstep/res/values-et/strings.xml
+++ b/quickstep/res/values-et/strings.xml
@@ -94,7 +94,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Süsteemi navigeerimisseaded"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Jaga"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Ekraanipilt"</string>
-    <string name="action_split" msgid="2098009717623550676">"Eralda"</string>
+    <string name="action_split" msgid="2098009717623550676">"Jaga pooleks"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"Salvesta rakendusepaar"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Jagatud ekraanikuva kasutamiseks puudutage muud rakendust"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Valige jagatud ekraanikuva jaoks muu rakendus."</string>
diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml
index fd136ed..8673f78 100644
--- a/quickstep/res/values-fi/strings.xml
+++ b/quickstep/res/values-fi/strings.xml
@@ -94,7 +94,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"Järjestelmän navigointiasetukset"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"Jaa"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"Kuvakaappaus"</string>
-    <string name="action_split" msgid="2098009717623550676">"Jaa"</string>
+    <string name="action_split" msgid="2098009717623550676">"Jaettu näyttö"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"Tallenna pari"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"Avaa jaettu näyttö napauttamalla toista sovellusta"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"Käytä jaettua näyttöä valitsemalla toinen sovellus"</string>
diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml
index 0cfaac3..9573602 100644
--- a/quickstep/res/values-my/strings.xml
+++ b/quickstep/res/values-my/strings.xml
@@ -94,7 +94,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"စနစ် လမ်းညွှန် ဆက်တင်များ"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"မျှဝေရန်"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
-    <string name="action_split" msgid="2098009717623550676">"ခွဲထုတ်ရန်"</string>
+    <string name="action_split" msgid="2098009717623550676">"ခွဲရန်"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"အက်ပ်အတွဲ သိမ်းရန်"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"မျက်နှာပြင် ခွဲ၍ပြသရန် အက်ပ်နောက်တစ်ခုကို တို့ပါ"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"မျက်နှာပြင် ခွဲ၍ပြသခြင်းသုံးရန် နောက်အက်ပ်တစ်ခုရွေးပါ"</string>
diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml
index 4ccb3c6..4242141 100644
--- a/quickstep/res/values-zh-rCN/strings.xml
+++ b/quickstep/res/values-zh-rCN/strings.xml
@@ -94,7 +94,7 @@
     <string name="allset_navigation_settings" msgid="4713404605961476027"><annotation id="link">"系统导航设置"</annotation></string>
     <string name="action_share" msgid="2648470652637092375">"分享"</string>
     <string name="action_screenshot" msgid="8171125848358142917">"屏幕截图"</string>
-    <string name="action_split" msgid="2098009717623550676">"拆分"</string>
+    <string name="action_split" msgid="2098009717623550676">"分屏"</string>
     <string name="action_save_app_pair" msgid="5974823919237645229">"保存应用组合"</string>
     <string name="toast_split_select_app" msgid="8464310533320556058">"点按另一个应用即可使用分屏"</string>
     <string name="toast_contextual_split_select_app" msgid="433510957123687090">"另外选择一个应用才可使用分屏模式"</string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index cdb257a..dbcba49 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -175,6 +175,8 @@
     <dimen name="gesture_tutorial_menu_done_button_top_spacing">0dp</dimen>
     <dimen name="gesture_tutorial_menu_back_shape_bottom_margin">0dp</dimen>
     <dimen name="gesture_tutorial_menu_done_button_spacing">72dp</dimen>
+    <dimen name="gesture_tutorial_done_button_bottom_margin">40dp</dimen>
+    <dimen name="gesture_tutorial_done_button_end_margin">24dp</dimen>
 
     <!-- Gesture Tutorial mock conversations -->
     <dimen name="gesture_tutorial_message_icon_size">44dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
index b36fd66..3e9272d 100644
--- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
@@ -37,7 +37,6 @@
 import com.android.launcher3.allapps.FloatingHeaderRow;
 import com.android.launcher3.allapps.FloatingHeaderView;
 import com.android.launcher3.anim.AlphaUpdateListener;
-import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.keyboard.FocusIndicatorHelper;
 import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
 import com.android.launcher3.model.data.ItemInfo;
@@ -45,6 +44,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.views.ActivityContext;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -281,4 +281,11 @@
         return getChildAt(0);
     }
 
+    public void dump(String prefix, PrintWriter writer) {
+        writer.println(prefix + this.getClass().getSimpleName());
+        writer.println(prefix + "\tmPredictionsEnabled: " + mPredictionsEnabled);
+        writer.println(prefix + "\tmPredictionUiUpdatePaused: " + mPredictionUiUpdatePaused);
+        writer.println(prefix + "\tmNumPredictedAppsPerRow: " + mNumPredictedAppsPerRow);
+        writer.println(prefix + "\tmPredictedApps: " + mPredictedApps);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
index 672bd1d..6493234 100644
--- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -29,6 +29,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.ComponentName;
+import android.util.Log;
 import android.view.HapticFeedbackConstants;
 import android.view.View;
 import android.view.ViewGroup;
@@ -80,6 +81,7 @@
         SystemShortcut.Factory<QuickstepLauncher>, DeviceProfile.OnDeviceProfileChangeListener,
         DragSource, ViewGroup.OnHierarchyChangeListener {
 
+    private static final String TAG = "HotseatPredictionController";
     private static final int FLAG_UPDATE_PAUSED = 1 << 0;
     private static final int FLAG_DRAG_IN_PROGRESS = 1 << 1;
     private static final int FLAG_FILL_IN_PROGRESS = 1 << 2;
@@ -292,6 +294,16 @@
     }
 
     /**
+     * Ensures that if the flag FLAG_UPDATE_PAUSED is active we set it to false.
+     */
+    public void verifyUIUpdateNotPaused() {
+        if ((mPauseFlags & FLAG_UPDATE_PAUSED) != 0) {
+            setPauseUIUpdate(false);
+            Log.e(TAG, "FLAG_UPDATE_PAUSED should not be set to true (see b/339700174)");
+        }
+    }
+
+    /**
      * Sets or updates the predicted items
      */
     public void setPredictedItems(FixedContainerItems items) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 3654e5f..abb763a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -376,6 +376,7 @@
                             (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0 ||
                             (flags & FLAG_KEYGUARD_OCCLUDED) != 0;
                     return (flags & FLAG_DISABLE_BACK) == 0
+                            && (!mContext.isGestureNav() || !mContext.isUserSetupComplete())
                             && ((flags & FLAG_KEYGUARD_VISIBLE) == 0 || showingOnKeyguard);
                 }));
         // Hide back button in SUW if keyboard is showing (IME draws its own back).
@@ -406,8 +407,8 @@
         mPropertyHolders.add(
                 new StatePropertyHolder(mHomeButtonAlpha.get(
                         ALPHA_INDEX_KEYGUARD_OR_DISABLE),
-                flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 &&
-                        (flags & FLAG_DISABLE_HOME) == 0));
+                        flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0
+                                && (flags & FLAG_DISABLE_HOME) == 0 && !mContext.isGestureNav()));
 
         // Recents button
         mRecentsButton = addButton(R.drawable.ic_sysbar_recent, BUTTON_RECENTS,
@@ -425,7 +426,7 @@
         });
         mPropertyHolders.add(new StatePropertyHolder(mRecentsButton,
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0 && (flags & FLAG_DISABLE_RECENTS) == 0
-                        && !mContext.isNavBarKidsModeActive()));
+                        && !mContext.isNavBarKidsModeActive() && !mContext.isGestureNav()));
 
         // A11y button
         mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y,
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
index 83e4571..94e2244 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
@@ -15,9 +15,12 @@
  */
 package com.android.launcher3.taskbar;
 
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Rect;
@@ -111,4 +114,17 @@
             setBackgroundColor(newColor);
         }
     }
+
+    /**
+     * Updates the handle scale.
+     *
+     * @param scale target scale to animate towards (starting from current scale)
+     * @param durationMs milliseconds for the animation to take
+     */
+    public void animateScale(float scale, long durationMs) {
+        ObjectAnimator scaleAnim = ObjectAnimator.ofPropertyValuesHolder(this,
+                PropertyValuesHolder.ofFloat(SCALE_PROPERTY, scale));
+        scaleAnim.setDuration(durationMs).setAutoCancel(true);
+        scaleAnim.start();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index f258b47..36e054a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -57,6 +57,10 @@
     public static final int ALPHA_INDEX_HIDDEN_WHILE_DREAMING = 3;
     private static final int NUM_ALPHA_CHANNELS = 4;
 
+    // Values for long press animations, picked to most closely match navbar spec.
+    private static final float SCALE_TOUCH_ANIMATION_SHRINK = 0.85f;
+    private static final float SCALE_TOUCH_ANIMATION_EXPAND = 1.18f;
+
     /**
      * The SharedPreferences key for whether the stashed handle region is dark.
      */
@@ -324,7 +328,13 @@
 
     @Override
     public void animateNavBarLongPress(boolean isTouchDown, boolean shrink, long durationMs) {
-        // TODO(b/308693847): Animate similarly to NavigationHandle.java (SysUI).
+        float targetScale;
+        if (isTouchDown) {
+            targetScale = shrink ? SCALE_TOUCH_ANIMATION_SHRINK : SCALE_TOUCH_ANIMATION_EXPAND;
+        } else {
+            targetScale = 1f;
+        }
+        mStashedHandleView.animateScale(targetScale, durationMs);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index bc71cae..4cefd3c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -951,7 +951,9 @@
                 mWindowLayoutParams.paramsForRotation[rot].height = size;
             }
         }
-        mControllers.taskbarInsetsController.onTaskbarOrBubblebarWindowHeightOrInsetsChanged();
+        mControllers.runAfterInit(
+                mControllers.taskbarInsetsController
+                        ::onTaskbarOrBubblebarWindowHeightOrInsetsChanged);
         notifyUpdateLayoutParams();
     }
 
@@ -1416,7 +1418,7 @@
         });
     }
 
-    protected boolean isUserSetupComplete() {
+    public boolean isUserSetupComplete() {
         return mIsUserSetupComplete;
     }
 
@@ -1452,7 +1454,8 @@
             ((LauncherTaskbarUIController) uiController).addLauncherVisibilityChangedAnimation(
                     fullAnimation, duration);
         }
-        mControllers.taskbarStashController.addUnstashToHotseatAnimation(fullAnimation, duration);
+        mControllers.taskbarStashController.addUnstashToHotseatAnimationFromSuw(fullAnimation,
+                duration);
 
         View allAppsButton = mControllers.taskbarViewController.getAllAppsButtonView();
         if (allAppsButton != null && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get()) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index a6988ee..102fe2a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -357,7 +357,6 @@
         boolean hideTaskbar = isVisible || !mActivity.isUserSetupComplete();
         updateStateForFlag(FLAG_IN_SETUP, hideTaskbar);
         updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, hideTaskbar);
-        updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, mActivity.isPhoneGestureNavMode());
         applyState(hideTaskbar ? 0 : getStashDuration());
     }
 
@@ -549,11 +548,12 @@
      *                            sub-animations are properly coordinated. This duration should not
      *                            actually be used since this animation tracks a swipe progress.
      */
-    protected void addUnstashToHotseatAnimation(AnimatorSet animation, int placeholderDuration) {
+    protected void addUnstashToHotseatAnimationFromSuw(AnimatorSet animation,
+            int placeholderDuration) {
         // Defer any UI updates now to avoid the UI becoming stale when the animation plays.
         mControllers.taskbarViewController.setDeferUpdatesForSUW(true);
         createAnimToIsStashed(
-                /* isStashed= */ false,
+                /* isStashed= */ mActivity.isPhoneMode(),
                 placeholderDuration,
                 TRANSITION_UNSTASH_SUW_MANUAL,
                 /* jankTag= */ "SUW_MANUAL");
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
index 8ad2493..e487f9f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/AbstractNavButtonLayoutter.kt
@@ -24,8 +24,10 @@
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.Space
+import com.android.launcher3.DeviceProfile
 import com.android.launcher3.R
 import com.android.launcher3.Utilities
+import com.android.launcher3.taskbar.TaskbarActivityContext
 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter
 
 /**
@@ -73,6 +75,23 @@
         return params
     }
 
+    fun adjustForSetupInPhoneMode(
+        navButtonsLayoutParams: FrameLayout.LayoutParams,
+        navButtonsViewLayoutParams: FrameLayout.LayoutParams,
+        deviceProfile: DeviceProfile
+    ) {
+        val phoneOrPortraitSetupMargin =
+            resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
+        navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
+        navButtonsLayoutParams.bottomMargin =
+            if (!deviceProfile.isLandscape) 0
+            else
+                phoneOrPortraitSetupMargin -
+                        resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
+        navButtonsViewLayoutParams.height =
+            resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
+    }
+
     open fun repositionContextualContainer(
         contextualContainer: ViewGroup,
         buttonSize: Int,
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
index 1e9f09b..2497fbb 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/NavButtonLayoutFactory.kt
@@ -116,6 +116,7 @@
                 isPhoneGestureMode -> {
                     PhoneGestureLayoutter(
                         resources,
+                        navButtonsView,
                         navButtonContainer,
                         endContextualContainer,
                         startContextualContainer,
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
index 8d91f2c..390ec34 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/PhoneGestureLayoutter.kt
@@ -17,15 +17,19 @@
 package com.android.launcher3.taskbar.navbutton
 
 import android.content.res.Resources
+import android.view.Gravity
 import android.view.ViewGroup
+import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.LinearLayout
 import android.widget.Space
+import com.android.launcher3.DeviceProfile
 import com.android.launcher3.taskbar.TaskbarActivityContext
 
 /** Layoutter for showing gesture navigation on phone screen. No buttons here, no-op container */
 class PhoneGestureLayoutter(
     resources: Resources,
+    navButtonsView: NearestTouchFrame,
     navBarContainer: LinearLayout,
     endContextualContainer: ViewGroup,
     startContextualContainer: ViewGroup,
@@ -42,8 +46,31 @@
         a11yButton,
         space
     ) {
+    private val mNavButtonsView = navButtonsView
 
     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
+        // TODO: look into if we should use SetupNavLayoutter instead.
+        if (!context.isUserSetupComplete) {
+            // Since setup wizard only has back button enabled, it looks strange to be
+            // end-aligned, so start-align instead.
+            val navButtonsLayoutParams = navButtonContainer.layoutParams as FrameLayout.LayoutParams
+            val navButtonsViewLayoutParams =
+                mNavButtonsView.layoutParams as FrameLayout.LayoutParams
+            val deviceProfile: DeviceProfile = context.deviceProfile
+
+            navButtonsLayoutParams.marginEnd = 0
+            navButtonsLayoutParams.gravity = Gravity.START
+            context.setTaskbarWindowSize(context.setupWindowSize)
+
+            adjustForSetupInPhoneMode(
+                navButtonsLayoutParams,
+                navButtonsViewLayoutParams,
+                deviceProfile
+            )
+            mNavButtonsView.layoutParams = navButtonsViewLayoutParams
+            navButtonContainer.layoutParams = navButtonsLayoutParams
+        }
+
         endContextualContainer.removeAllViews()
         startContextualContainer.removeAllViews()
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
index 91042c3..22a3630 100644
--- a/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/navbutton/SetupNavLayoutter.kt
@@ -77,16 +77,11 @@
             navButtonsLayoutParams.height =
                 resources.getDimensionPixelSize(R.dimen.taskbar_back_button_suw_height)
         } else {
-            val phoneOrPortraitSetupMargin =
-                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_margin)
-            navButtonsLayoutParams.marginStart = phoneOrPortraitSetupMargin
-            navButtonsLayoutParams.bottomMargin =
-                if (!deviceProfile.isLandscape) 0
-                else
-                    phoneOrPortraitSetupMargin -
-                        resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2
-            navButtonsViewLayoutParams.height =
-                resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_suw_height)
+            adjustForSetupInPhoneMode(
+                navButtonsLayoutParams,
+                navButtonsViewLayoutParams,
+                deviceProfile
+            )
         }
         mNavButtonsView.layoutParams = navButtonsViewLayoutParams
         navButtonContainer.layoutParams = navButtonsLayoutParams
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 10a7ff6..702997c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -390,6 +390,12 @@
     }
 
     @Override
+    public void startBinding() {
+        super.startBinding();
+        mHotseatPredictionController.verifyUIUpdateNotPaused();
+    }
+
+    @Override
     protected void onActivityFlagsChanged(int changeBits) {
         if ((changeBits & ACTIVITY_STATE_STARTED) != 0) {
             mDepthController.setActivityStarted(isStarted());
@@ -1414,6 +1420,10 @@
         if (mHotseatPredictionController != null) {
             mHotseatPredictionController.dump(prefix, writer);
         }
+        PredictionRowView<?> predictionRowView =
+                getAppsView().getFloatingHeaderView().findFixedRowByType(
+                        PredictionRowView.class);
+        predictionRowView.dump(prefix, writer);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 1152de2..273b944 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -244,7 +244,7 @@
         if (mSplitBounds == null) {
             mStagePosition = STAGE_POSITION_UNDEFINED;
         } else {
-            mStagePosition = mThumbnailPosition.equals(splitInfo.leftTopBounds)
+            mStagePosition = runningTarget.taskId == splitInfo.leftTopTaskId
                     ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
             mPositionHelper.setSplitBounds(convertLauncherSplitBoundsToShell(mSplitBounds),
                     mStagePosition);
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index fd38af3..b615850 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -181,6 +181,9 @@
                 }
             }
         }
+        if (intent.`package` == null) {
+            intent.`package` = targetPkg
+        }
         // else if cn == null => can't infer much, leave it
         // else if !validPkg => could be restored icon or missing sd-card
         when {
diff --git a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
index 30957fc..2f0f2eb 100644
--- a/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
+++ b/tests/src/com/android/launcher3/model/WorkspaceItemProcessorTest.kt
@@ -64,13 +64,13 @@
     @Mock private lateinit var mockBgDataModel: BgDataModel
     @Mock private lateinit var mockContext: Context
     @Mock private lateinit var mockAppState: LauncherAppState
-    @Mock private lateinit var mockIntent: Intent
     @Mock private lateinit var mockPmHelper: PackageManagerHelper
     @Mock private lateinit var mockLauncherApps: LauncherApps
     @Mock private lateinit var mockCursor: LoaderCursor
     @Mock private lateinit var mockUserManagerState: UserManagerState
     @Mock private lateinit var mockWidgetInflater: WidgetInflater
 
+    private lateinit var intent: Intent
     private lateinit var userHandle: UserHandle
     private lateinit var iconRequestInfos: MutableList<IconRequestInfo<WorkspaceItemInfo>>
     private lateinit var componentName: ComponentName
@@ -90,11 +90,11 @@
         mockBgDataModel = mock<BgDataModel>()
         componentName = ComponentName("package", "class")
         unlockedUsersArray = LongSparseArray<Boolean>(1).apply { put(101, true) }
-        mockIntent =
-            mock<Intent>().apply {
-                whenever(component).thenReturn(componentName)
-                whenever(`package`).thenReturn("pkg")
-                whenever(getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID)).thenReturn("")
+        intent =
+            Intent().apply {
+                component = componentName
+                `package` = "pkg"
+                putExtra(ShortcutKey.EXTRA_SHORTCUT_ID, "")
             }
         mockContext =
             mock<Context>().apply {
@@ -110,7 +110,7 @@
         mockPmHelper =
             mock<PackageManagerHelper>().apply {
                 whenever(getAppLaunchIntent(componentName.packageName, userHandle))
-                    .thenReturn(mockIntent)
+                    .thenReturn(intent)
             }
         mockLauncherApps =
             mock<LauncherApps>().apply {
@@ -124,10 +124,9 @@
                 id = 1
                 restoreFlag = 1
                 serialNumber = 101
-                whenever(parseIntent()).thenReturn(mockIntent)
+                whenever(parseIntent()).thenReturn(intent)
                 whenever(markRestored()).doAnswer { restoreFlag = 0 }
-                whenever(updater().put(Favorites.INTENT, mockIntent.toUri(0)).commit())
-                    .thenReturn(1)
+                whenever(updater().put(Favorites.INTENT, intent.toUri(0)).commit()).thenReturn(1)
                 whenever(getAppShortcutInfo(any(), any(), any(), any()))
                     .thenReturn(mockWorkspaceInfo)
                 whenever(createIconRequestInfo(any(), any())).thenReturn(mockIconRequestInfo)
@@ -185,9 +184,11 @@
     fun `When user is null then mark item deleted`() {
         // Given
         mockCursor = mock<LoaderCursor>().apply { id = 1 }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
+
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
+
         // Then
         verify(mockCursor).markDeleted("User has been deleted for item id=1", PROFILE_DELETED)
         verify(mockCursor, times(0)).checkAndAddItem(any(), any(), anyOrNull())
@@ -197,8 +198,9 @@
     fun `When app has null intent then mark deleted`() {
         // Given
         mockCursor.apply { whenever(parseIntent()).thenReturn(null) }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
+
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
         // Then
         verify(mockCursor).markDeleted("Null intent from db for item id=1", MISSING_INFO)
@@ -209,13 +211,13 @@
     fun `When app has null target package then mark deleted`() {
 
         // Given
-        mockIntent.apply {
-            whenever(component).thenReturn(null)
-            whenever(`package`).thenReturn(null)
+        intent.apply {
+            component = null
+            `package` = null
         }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -228,11 +230,11 @@
 
         // Given
         componentName = ComponentName("", "")
-        whenever(mockIntent.component).thenReturn(componentName)
-        whenever(mockCursor.parseIntent()).thenReturn(mockIntent)
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
+        intent.component = componentName
+        intent.`package` = ""
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -243,10 +245,8 @@
     @Test
     fun `When valid app then mark restored`() {
 
-        // Given
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
-
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -271,18 +271,18 @@
         mockPmHelper =
             mock<PackageManagerHelper>().apply {
                 whenever(getAppLaunchIntent(componentName.packageName, userHandle))
-                    .thenReturn(mockIntent)
+                    .thenReturn(intent)
             }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
         assertWithMessage("item restoreFlag should be set to 0")
             .that(mockCursor.restoreFlag)
             .isEqualTo(0)
-        verify(mockCursor.updater().put(Favorites.INTENT, mockIntent.toUri(0))).commit()
+        verify(mockCursor.updater().put(Favorites.INTENT, intent.toUri(0))).commit()
         assertThat(iconRequestInfos).containsExactly(mockIconRequestInfo)
         verify(mockCursor).checkAndAddItem(mockWorkspaceInfo, mockBgDataModel, null)
     }
@@ -300,9 +300,9 @@
             mock<PackageManagerHelper>().apply {
                 whenever(getAppLaunchIntent(componentName.packageName, userHandle)).thenReturn(null)
             }
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -336,13 +336,13 @@
                 whenever(disabledReason).thenReturn(0)
                 whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
             }
-        val shortcutKey = ShortcutKey.fromIntent(mockIntent, mockCursor.user)
+        val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user)
         keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
         iconRequestInfos = mutableListOf()
-        itemProcessorUnderTest =
-            createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
 
         // When
+        itemProcessorUnderTest =
+            createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -362,9 +362,9 @@
         mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT
         iconRequestInfos = mutableListOf()
         keyToPinnedShortcutsMap = hashMapOf()
-        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
 
         // When
+        itemProcessorUnderTest = createWorkspaceItemProcessorUnderTest()
         itemProcessorUnderTest.processItem()
 
         // Then
@@ -381,6 +381,45 @@
     }
 
     @Test
+    fun `When valid Pinned Deep Shortcut with null intent package then use targetPkg`() {
+
+        // Given
+        mockCursor.itemType = ITEM_TYPE_DEEP_SHORTCUT
+        val expectedShortcutInfo =
+            mock<ShortcutInfo>().apply {
+                whenever(id).thenReturn("")
+                whenever(`package`).thenReturn("")
+                whenever(activity).thenReturn(mock())
+                whenever(longLabel).thenReturn("")
+                whenever(isEnabled).thenReturn(true)
+                whenever(disabledMessage).thenReturn("")
+                whenever(disabledReason).thenReturn(0)
+                whenever(persons).thenReturn(EMPTY_PERSON_ARRAY)
+            }
+        iconRequestInfos = mutableListOf()
+        // Make sure shortcuts map has expected key from expected package
+        intent.`package` = componentName.packageName
+        val shortcutKey = ShortcutKey.fromIntent(intent, mockCursor.user)
+        keyToPinnedShortcutsMap[shortcutKey] = expectedShortcutInfo
+        // set intent package back to null to test scenario
+        intent.`package` = null
+
+        // When
+        itemProcessorUnderTest =
+            createWorkspaceItemProcessorUnderTest(allDeepShortcuts = allDeepShortcuts)
+        itemProcessorUnderTest.processItem()
+
+        // Then
+        assertWithMessage("item restoreFlag should be set to 0")
+            .that(mockCursor.restoreFlag)
+            .isEqualTo(0)
+        assertThat(iconRequestInfos).isEmpty()
+        assertThat(allDeepShortcuts).containsExactly(expectedShortcutInfo)
+        verify(mockCursor).markRestored()
+        verify(mockCursor).checkAndAddItem(any(), any(), anyOrNull())
+    }
+
+    @Test
     fun `When processing Folder then create FolderInfo and mark restored`() {
         val actualFolderInfo = FolderInfo()
         mockBgDataModel =