Merge "Detect potential WindowConfiguration change at onApplyWindowInsets" into tm-qpr-dev
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 6bc3d38..c85e71c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -277,6 +277,7 @@
 
     <!--  Taskbar 3 button spacing  -->
     <dimen name="taskbar_button_space_inbetween">24dp</dimen>
+    <dimen name="taskbar_button_space_inbetween_phone">40dp</dimen>
     <dimen name="taskbar_button_margin_5_5">26dp</dimen>
     <dimen name="taskbar_button_margin_6_5">75dp</dimen>
     <dimen name="taskbar_button_margin_4_5">47dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index d251f3e..d65de51 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1416,7 +1416,7 @@
         animation.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationStart(Animator animation) {
-                anim.start(mLauncher, velocityPxPerS);
+                anim.start(mLauncher, mDeviceProfile, velocityPxPerS);
             }
         });
         return anim;
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 55c3c20..f1f18c1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -15,15 +15,20 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
 import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
+import static com.android.launcher3.taskbar.TaskbarManager.isPhoneButtonNavMode;
+import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
 import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_KEYGUARD;
+import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_SMALL_SCREEN;
 import static com.android.launcher3.taskbar.Utilities.appendFlag;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
@@ -109,6 +114,7 @@
     private static final int FLAG_NOTIFICATION_SHADE_EXPANDED = 1 << 10;
     private static final int FLAG_SCREEN_PINNING_ACTIVE = 1 << 11;
     private static final int FLAG_VOICE_INTERACTION_WINDOW_SHOWING = 1 << 12;
+    private static final int FLAG_SMALL_SCREEN = 1 << 13;
 
     private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
 
@@ -122,7 +128,7 @@
 
     private final TaskbarActivityContext mContext;
     private final FrameLayout mNavButtonsView;
-    private final ViewGroup mNavButtonContainer;
+    private final LinearLayout mNavButtonContainer;
     // Used for IME+A11Y buttons
     private final ViewGroup mEndContextualContainer;
     private final ViewGroup mStartContextualContainer;
@@ -180,9 +186,13 @@
      */
     public void init(TaskbarControllers controllers) {
         mControllers = controllers;
-        mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
-
         boolean isThreeButtonNav = mContext.isThreeButtonNav();
+        DeviceProfile deviceProfile = mContext.getDeviceProfile();
+        Resources resources = mContext.getResources();
+        mNavButtonsView.getLayoutParams().height = !isPhoneMode(deviceProfile) ?
+                deviceProfile.taskbarSize :
+                resources.getDimensionPixelSize(R.dimen.taskbar_size);
+
         mIsImeRenderingNavButtons =
                 InputMethodService.canImeRenderGesturalNavButtons() && mContext.imeDrawsImeNavBar();
         if (!mIsImeRenderingNavButtons) {
@@ -201,6 +211,11 @@
                 flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0
                         && (flags & FLAG_SCREEN_PINNING_ACTIVE) == 0));
 
+        mPropertyHolders.add(new StatePropertyHolder(
+                mControllers.taskbarViewController.getTaskbarIconAlpha()
+                        .getProperty(ALPHA_INDEX_SMALL_SCREEN),
+                flags -> (flags & FLAG_SMALL_SCREEN) == 0));
+
         mPropertyHolders.add(new StatePropertyHolder(mControllers.taskbarDragLayerController
                 .getKeyguardBgTaskbar(), flags -> (flags & FLAG_KEYGUARD_VISIBLE) == 0));
 
@@ -231,7 +246,7 @@
             initButtons(mNavButtonContainer, mEndContextualContainer,
                     mControllers.navButtonController);
             updateButtonLayoutSpacing();
-
+            updateStateForFlag(FLAG_SMALL_SCREEN, isPhoneButtonNavMode(mContext));
             if (isInSetup) {
                 // Since setup wizard only has back button enabled, it looks strange to be
                 // end-aligned, so start-align instead.
@@ -244,18 +259,18 @@
 
                 // TODO(b/210906568) Dark intensity is currently not propagated during setup, so set
                 //  it based on dark theme for now.
-                int mode = mContext.getResources().getConfiguration().uiMode
+                int mode = resources.getConfiguration().uiMode
                         & Configuration.UI_MODE_NIGHT_MASK;
                 boolean isDarkTheme = mode == Configuration.UI_MODE_NIGHT_YES;
                 mTaskbarNavButtonDarkIntensity.updateValue(isDarkTheme ? 0 : 1);
             } else if (isInKidsMode) {
-                int iconSize = mContext.getResources().getDimensionPixelSize(
+                int iconSize = resources.getDimensionPixelSize(
                         R.dimen.taskbar_icon_size_kids);
-                int buttonWidth = mContext.getResources().getDimensionPixelSize(
+                int buttonWidth = resources.getDimensionPixelSize(
                         R.dimen.taskbar_nav_buttons_width_kids);
-                int buttonHeight = mContext.getResources().getDimensionPixelSize(
+                int buttonHeight = resources.getDimensionPixelSize(
                         R.dimen.taskbar_nav_buttons_height_kids);
-                int buttonRadius = mContext.getResources().getDimensionPixelSize(
+                int buttonRadius = resources.getDimensionPixelSize(
                         R.dimen.taskbar_nav_buttons_corner_radius_kids);
                 int paddingleft = (buttonWidth - iconSize) / 2;
                 int paddingRight = paddingleft;
@@ -277,7 +292,7 @@
                         buttonWidth,
                         buttonHeight
                 );
-                int homeButtonLeftMargin = mContext.getResources().getDimensionPixelSize(
+                int homeButtonLeftMargin = resources.getDimensionPixelSize(
                         R.dimen.taskbar_home_button_left_margin_kids);
                 homeLayoutparams.setMargins(homeButtonLeftMargin, 0, 0, 0);
                 mHomeButton.setLayoutParams(homeLayoutparams);
@@ -287,7 +302,7 @@
                         buttonWidth,
                         buttonHeight
                 );
-                int backButtonLeftMargin = mContext.getResources().getDimensionPixelSize(
+                int backButtonLeftMargin = resources.getDimensionPixelSize(
                         R.dimen.taskbar_back_button_left_margin_kids);
                 backLayoutParams.setMargins(backButtonLeftMargin, 0, 0, 0);
                 mBackButton.setLayoutParams(backLayoutParams);
@@ -342,7 +357,7 @@
             if (!mIsImeRenderingNavButtons) {
                 View imeDownButton = addButton(R.drawable.ic_sysbar_back, BUTTON_BACK,
                         mStartContextualContainer, mControllers.navButtonController, R.id.back);
-                imeDownButton.setRotation(Utilities.isRtl(mContext.getResources()) ? 90 : -90);
+                imeDownButton.setRotation(Utilities.isRtl(resources) ? 90 : -90);
                 // Only show when IME is visible.
                 mPropertyHolders.add(new StatePropertyHolder(imeDownButton,
                         flags -> (flags & FLAG_IME_VISIBLE) != 0));
@@ -614,6 +629,9 @@
     }
 
     private void updateNavButtonTranslationY() {
+        if (isPhoneButtonNavMode(mContext)) {
+            return;
+        }
         final float normalTranslationY = mTaskbarNavButtonTranslationY.value;
         final float imeAdjustmentTranslationY = mTaskbarNavButtonTranslationYForIme.value;
         TaskbarUIController uiController = mControllers.uiController;
@@ -683,12 +701,22 @@
         if (!mContext.isThreeButtonNav() || mContext.isNavBarKidsModeActive()) {
             return;
         }
+
+        if (isPhoneButtonNavMode(mContext)) {
+            updatePhoneButtonSpacing();
+            return;
+        }
+
         DeviceProfile dp = mContext.getDeviceProfile();
         Resources res = mContext.getResources();
 
         // Add spacing after the end of the last nav button
         FrameLayout.LayoutParams navButtonParams =
                 (FrameLayout.LayoutParams) mNavButtonContainer.getLayoutParams();
+        navButtonParams.gravity = Gravity.END;
+        navButtonParams.width = FrameLayout.LayoutParams.WRAP_CONTENT;
+        navButtonParams.height = MATCH_PARENT;
+
         int navMarginEnd = (int) res.getDimension(dp.inv.inlineNavButtonsEndSpacing);
         int contextualWidth = mEndContextualContainer.getWidth();
         // If contextual buttons are showing, we check if the end margin is enough for the
@@ -706,6 +734,39 @@
             View navButton = mNavButtonContainer.getChildAt(i);
             LinearLayout.LayoutParams buttonLayoutParams =
                     (LinearLayout.LayoutParams) navButton.getLayoutParams();
+            buttonLayoutParams.weight = 0;
+            if (i == 0) {
+                buttonLayoutParams.setMarginEnd(spaceInBetween / 2);
+            } else if (i == mNavButtonContainer.getChildCount() - 1) {
+                buttonLayoutParams.setMarginStart(spaceInBetween / 2);
+            } else {
+                buttonLayoutParams.setMarginStart(spaceInBetween / 2);
+                buttonLayoutParams.setMarginEnd(spaceInBetween / 2);
+            }
+        }
+    }
+
+    /** Uniformly spaces out the 3 button nav for smaller phone screens */
+    private void updatePhoneButtonSpacing() {
+        DeviceProfile dp = mContext.getDeviceProfile();
+        Resources res = mContext.getResources();
+
+        // TODO: Polish pending, this is just to make it usable
+        FrameLayout.LayoutParams navContainerParams =
+                (FrameLayout.LayoutParams) mNavButtonContainer.getLayoutParams();
+        int endStartMargins = res.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size);
+        navContainerParams.gravity = Gravity.CENTER;
+        navContainerParams.setMarginEnd(endStartMargins);
+        navContainerParams.setMarginStart(endStartMargins);
+        mNavButtonContainer.setLayoutParams(navContainerParams);
+
+        // Add the spaces in between the nav buttons
+        int spaceInBetween = res.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween_phone);
+        for (int i = 0; i < mNavButtonContainer.getChildCount(); i++) {
+            View navButton = mNavButtonContainer.getChildAt(i);
+            LinearLayout.LayoutParams buttonLayoutParams =
+                    (LinearLayout.LayoutParams) navButton.getLayoutParams();
+            buttonLayoutParams.weight = 1;
             if (i == 0) {
                 buttonLayoutParams.setMarginEnd(spaceInBetween / 2);
             } else if (i == mNavButtonContainer.getChildCount() - 1) {
@@ -725,6 +786,8 @@
         }
 
         moveNavButtonsBackToTaskbarWindow();
+        mNavButtonContainer.removeAllViews();
+        mAllButtons.clear();
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 0652463..6b67b50 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -15,8 +15,6 @@
  */
 package com.android.launcher3.taskbar;
 
-import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
-
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
@@ -96,7 +94,7 @@
         mControllers = controllers;
         DeviceProfile deviceProfile = mActivity.getDeviceProfile();
         Resources resources = mActivity.getResources();
-        if (isPhoneMode(mActivity.getDeviceProfile())) {
+        if (isPhoneGestureNavMode(mActivity.getDeviceProfile())) {
             mStashedHandleView.getLayoutParams().height =
                     resources.getDimensionPixelSize(R.dimen.taskbar_size);
             mStashedHandleWidth =
@@ -108,7 +106,7 @@
         }
 
         mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_STASHED).setValue(
-                isPhoneMode(deviceProfile) ? 1 : 0);
+                isPhoneGestureNavMode(deviceProfile) ? 1 : 0);
         mTaskbarStashedHandleHintScale.updateValue(1f);
 
         final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
@@ -136,7 +134,7 @@
             view.setPivotY(stashedCenterY);
         });
         initRegionSampler();
-        if (isPhoneMode(deviceProfile)) {
+        if (isPhoneGestureNavMode(deviceProfile)) {
             onIsStashedChanged(true);
         }
     }
@@ -164,6 +162,10 @@
         mRegionSamplingHelper = null;
     }
 
+    private boolean isPhoneGestureNavMode(DeviceProfile deviceProfile) {
+        return TaskbarManager.isPhoneMode(deviceProfile) && !mActivity.isThreeButtonNav();
+    }
+
     public MultiValueAlpha getStashedHandleAlpha() {
         return mTaskbarStashedHandleAlpha;
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index f5fe77a..e1bcbe2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -119,7 +119,7 @@
     // The size we should return to when we call setTaskbarWindowFullscreen(false)
     private int mLastRequestedNonFullscreenHeight;
 
-    private final NavigationMode mNavMode;
+    private NavigationMode mNavMode;
     private final boolean mImeDrawsImeNavBar;
     private final ViewCache mViewCache = new ViewCache();
 
@@ -235,7 +235,8 @@
     }
 
     /** Updates {@link DeviceProfile} instances for any Taskbar windows. */
-    public void updateDeviceProfile(DeviceProfile dp) {
+    public void updateDeviceProfile(DeviceProfile dp, NavigationMode navMode) {
+        mNavMode = navMode;
         mControllers.taskbarAllAppsController.updateDeviceProfile(dp);
         mDeviceProfile = dp.copy(this);
         updateIconSize(getResources());
@@ -608,7 +609,10 @@
      */
     public int getDefaultTaskbarWindowHeight() {
         if (FLAG_HIDE_NAVBAR_WINDOW && mDeviceProfile.isPhone) {
-            return getResources().getDimensionPixelSize(R.dimen.taskbar_stashed_size);
+            Resources resources = getResources();
+            return isThreeButtonNav() ?
+                    resources.getDimensionPixelSize(R.dimen.taskbar_size) :
+                    resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
         }
         return mDeviceProfile.taskbarSize + Math.max(getLeftCornerRadius(), getRightCornerRadius());
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 77ef83c..ec9760c 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -18,6 +18,7 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.util.TouchController;
 import com.android.quickstep.AnimatedFloat;
@@ -173,7 +174,15 @@
          * Returns how tall the background should be drawn at the bottom of the screen.
          */
         public int getTaskbarBackgroundHeight() {
-            return mActivity.getDeviceProfile().taskbarSize;
+            DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+            if (TaskbarManager.isPhoneMode(deviceProfile)) {
+                Resources resources = mActivity.getResources();
+                return mActivity.isThreeButtonNav() ?
+                        resources.getDimensionPixelSize(R.dimen.taskbar_size) :
+                        resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
+            } else {
+                return deviceProfile.taskbarSize;
+            }
         }
 
         /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 85e76b2..0bda3cd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -32,6 +32,7 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseQuickstepLauncher;
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.QuickstepTransitionManager;
 import com.android.launcher3.Utilities;
@@ -48,6 +49,7 @@
 import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.StringJoiner;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 /**
@@ -92,6 +94,15 @@
     // We skip any view synchronizations during init/destroy.
     private boolean mCanSyncViews;
 
+    private final Consumer<Float> mIconAlphaForHomeConsumer = alpha -> {
+        mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1);
+        mLauncher.getHotseat().setQsbAlpha(
+                mLauncher.getDeviceProfile().isQsbInline && alpha > 0 ? 0 : 1);
+    };
+
+    private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
+            dp -> mIconAlphaForHomeConsumer.accept(mIconAlphaForHome.getValue());
+
     private final StateManager.StateListener<LauncherState> mStateListener =
             new StateManager.StateListener<LauncherState>() {
 
@@ -131,13 +142,7 @@
                 .getTaskbarBackgroundAlpha();
         MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
         mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
-        mIconAlphaForHome.setConsumer(
-                alpha -> {
-                    mLauncher.getHotseat().setIconsAlpha(alpha > 0 ? 0 : 1);
-                    if (mLauncher.getDeviceProfile().isQsbInline) {
-                        mLauncher.getHotseat().setQsbAlpha(alpha > 0 ? 0 : 1);
-                    }
-                });
+        mIconAlphaForHome.setConsumer(mIconAlphaForHomeConsumer);
 
         mIconAlignmentForResumedState.finishAnimation();
         onIconAlignmentRatioChangedForAppAndHomeTransition();
@@ -150,6 +155,7 @@
         applyState(0);
 
         mCanSyncViews = true;
+        mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
     }
 
     public void onDestroy() {
@@ -164,6 +170,7 @@
         mLauncher.getStateManager().removeStateListener(mStateListener);
 
         mCanSyncViews = true;
+        mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
     }
 
     public Animator createAnimToLauncher(@NonNull LauncherState toState,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 353bf89..1212c61 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -82,6 +82,7 @@
     // It's destruction/creation will be managed by the activity.
     private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
             new NonDestroyableScopedUnfoldTransitionProgressProvider();
+    private DisplayController.NavigationMode mNavMode;
 
     private TaskbarActivityContext mTaskbarActivityContext;
     private StatefulActivity mActivity;
@@ -132,9 +133,11 @@
                         | ActivityInfo.CONFIG_SCREEN_SIZE;
                 boolean requiresRecreate = (configDiff & configsRequiringRecreate) != 0;
                 if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
-                        && mTaskbarActivityContext != null && dp != null) {
+                        && mTaskbarActivityContext != null && dp != null
+                        && !isPhoneMode(dp)) {
                     // Additional check since this callback gets fired multiple times w/o
                     // screen size changing, or when simply rotating the device.
+                    // In the case of phone device rotation, we do want to call recreateTaskbar()
                     DeviceProfile oldDp = mTaskbarActivityContext.getDeviceProfile();
                     boolean isOrientationChange =
                             (configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0;
@@ -152,7 +155,7 @@
                     // Config change might be handled without re-creating the taskbar
                     if (mTaskbarActivityContext != null) {
                         if (dp != null && isTaskbarPresent(dp)) {
-                            mTaskbarActivityContext.updateDeviceProfile(dp);
+                            mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode);
                         }
                         mTaskbarActivityContext.onConfigurationChanged(configDiff);
                     }
@@ -167,9 +170,11 @@
                 destroyExistingTaskbar());
         mDispInfoChangeListener = (context, info, flags) -> {
             if ((flags & CHANGE_FLAGS) != 0) {
+                mNavMode = info.navigationMode;
                 recreateTaskbar();
             }
         };
+        mNavMode = mDisplayController.getInfo().navigationMode;
         mDisplayController.addChangeListener(mDispInfoChangeListener);
         SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI,
                 mUserSetupCompleteListener);
@@ -289,7 +294,7 @@
             mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp, mNavButtonController,
                     mUnfoldProgressProvider);
         } else {
-            mTaskbarActivityContext.updateDeviceProfile(dp);
+            mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode);
         }
         mTaskbarActivityContext.init(mSharedState);
 
@@ -324,6 +329,14 @@
         return TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW && deviceProfile.isPhone;
     }
 
+    /**
+     * @return {@code true} if {@link #isPhoneMode(DeviceProfile)} is true and we're using
+     *                      3 button-nav
+     */
+    public static boolean isPhoneButtonNavMode(TaskbarActivityContext context) {
+        return isPhoneMode(context.getDeviceProfile()) && context.isThreeButtonNav();
+    }
+
     private boolean isTaskbarPresent(DeviceProfile deviceProfile) {
         return FLAG_HIDE_NAVBAR_WINDOW || deviceProfile.isTaskbarPresent;
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 114ab4e..3ea9173 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -20,7 +20,6 @@
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
-import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
 import static com.android.launcher3.taskbar.Utilities.appendFlag;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
@@ -180,7 +179,7 @@
         mActivity = activity;
         mPrefs = Utilities.getPrefs(mActivity);
         mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
-        if (isPhoneMode(mActivity.getDeviceProfile())) {
+        if (isPhoneMode()) {
             // DeviceProfile's taskbar vars aren't initialized w/ the flag off
             Resources resources = mActivity.getResources();
             mUnstashedHeight = resources.getDimensionPixelSize(R.dimen.taskbar_size);
@@ -217,7 +216,8 @@
         updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
         updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
         updateStateForFlag(FLAG_IN_SETUP, isInSetup);
-        updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode(mActivity.getDeviceProfile()));
+        updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode()
+                && !mActivity.isThreeButtonNav());
         applyState();
 
         notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
@@ -229,7 +229,7 @@
      */
     public boolean supportsVisualStashing() {
         return mControllers.uiController.supportsVisualStashing() ||
-                isPhoneMode(mActivity.getDeviceProfile());
+                (isPhoneMode() && !mActivity.isThreeButtonNav());
     }
 
     /**
@@ -286,6 +286,13 @@
         return (hasAnyFlag(FLAG_IN_STASHED_LAUNCHER_STATE) && supportsVisualStashing());
     }
 
+    /**
+     * @return {@code true} if we're not on a large screen AND using gesture nav
+     */
+    private boolean isPhoneMode() {
+        return TaskbarManager.isPhoneMode(mActivity.getDeviceProfile());
+    }
+
     private boolean hasAnyFlag(int flagMask) {
         return hasAnyFlag(mState, flagMask);
     }
@@ -312,7 +319,7 @@
      * @see WindowInsets.Type#systemBars()
      */
     public int getContentHeightToReportToApps() {
-        if (isPhoneMode(mActivity.getDeviceProfile())) {
+        if (isPhoneMode() && !mActivity.isThreeButtonNav()) {
             return getStashedHeight();
         }
 
@@ -431,7 +438,7 @@
         }
         mAnimator = new AnimatorSet();
         addJankMonitorListener(mAnimator, /* appearing= */ !mIsStashed);
-        final float stashTranslation = isPhoneMode(mActivity.getDeviceProfile()) ? 0 :
+        final float stashTranslation = isPhoneMode() ? 0 :
                 (mUnstashedHeight - mStashedHeight) / 2f;
 
         if (!supportsVisualStashing()) {
@@ -477,7 +484,7 @@
 
             firstHalfAnimatorSet.playTogether(
                     mIconAlphaForStash.animateToValue(0),
-                    mIconScaleForStash.animateToValue(isPhoneMode(mActivity.getDeviceProfile()) ?
+                    mIconScaleForStash.animateToValue(isPhoneMode() ?
                             0 : STASHED_TASKBAR_SCALE)
             );
             secondHalfAnimatorSet.playTogether(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 929dc20..992aa4b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -71,7 +71,8 @@
     public static final int ALPHA_INDEX_NOTIFICATION_EXPANDED = 4;
     public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 5;
     public static final int ALPHA_INDEX_IME_BUTTON_NAV = 6;
-    private static final int NUM_ALPHA_CHANNELS = 7;
+    public static final int ALPHA_INDEX_SMALL_SCREEN = 7;
+    private static final int NUM_ALPHA_CHANNELS = 8;
 
     private final TaskbarActivityContext mActivity;
     private final TaskbarView mTaskbarView;
@@ -390,7 +391,8 @@
                 "ALPHA_INDEX_RECENTS_DISABLED",
                 "ALPHA_INDEX_NOTIFICATION_EXPANDED",
                 "ALPHA_INDEX_ASSISTANT_INVOKED",
-                "ALPHA_INDEX_IME_BUTTON_NAV");
+                "ALPHA_INDEX_IME_BUTTON_NAV",
+                "ALPHA_INDEX_SMALL_SCREEN");
 
         mModelCallbacks.dumpLogs(prefix + "\t", pw);
     }
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 8f1872b..8dee10a 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1330,7 +1330,8 @@
                 if (windowAnimation == null) {
                     continue;
                 }
-                windowAnimation.start(mContext, velocityPxPerMs);
+                DeviceProfile dp = mActivity == null ? null : mActivity.getDeviceProfile();
+                windowAnimation.start(mContext, dp, velocityPxPerMs);
                 mRunningWindowAnim[i] = RunningWindowAnim.wrap(windowAnimation);
             }
             homeAnimFactory.setSwipeVelocity(velocityPxPerMs.y);
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
index 51ae56b..c602324 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java
@@ -16,7 +16,6 @@
 package com.android.quickstep;
 
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
 
 import android.graphics.Rect;
 import android.util.ArraySet;
@@ -97,18 +96,6 @@
             RemoteAnimationTargetCompat[] appTargets,
             RemoteAnimationTargetCompat[] wallpaperTargets,
             Rect homeContentInsets, Rect minimizedHomeBounds) {
-        // Convert appTargets to type RemoteAnimationTarget for all apps except Home app
-        RemoteAnimationTarget[] nonHomeApps = Arrays.stream(appTargets)
-                .filter(remoteAnimationTarget ->
-                        remoteAnimationTarget.activityType != ACTIVITY_TYPE_HOME)
-                .map(RemoteAnimationTargetCompat::unwrap)
-                .toArray(RemoteAnimationTarget[]::new);
-
-        RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(nonHomeApps);
-
-        RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
-                wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets),
-                homeContentInsets, minimizedHomeBounds);
         mController = new RecentsAnimationController(animationController,
                 mAllowMinimizeSplitScreen, this::onAnimationFinished);
 
@@ -116,6 +103,13 @@
             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
                     mController::finishAnimationToApp);
         } else {
+            final RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(
+                    Arrays.stream(appTargets).map(RemoteAnimationTargetCompat::unwrap)
+                            .toArray(RemoteAnimationTarget[]::new));
+            final RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
+                    wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets),
+                    homeContentInsets, minimizedHomeBounds);
+
             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
                 for (RecentsAnimationListener listener : getListeners()) {
                     listener.onRecentsAnimationStart(mController, targets);
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index fd7e367..0314761 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -45,7 +45,7 @@
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
 
-import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 
 public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
@@ -156,30 +156,21 @@
             public void onTasksAppeared(RemoteAnimationTargetCompat[] appearedTaskTargets) {
                 RemoteAnimationTargetCompat appearedTaskTarget = appearedTaskTargets[0];
                 BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
-                // Convert appTargets to type RemoteAnimationTarget for all apps except Home app
-                final ArrayList<RemoteAnimationTargetCompat> tmpNonHomeApps = new ArrayList<>();
-                final ArrayList<RemoteAnimationTargetCompat> tmpHomeApps = new ArrayList<>();
+
                 for (RemoteAnimationTargetCompat compat : appearedTaskTargets) {
-                    if (compat.activityType != ACTIVITY_TYPE_HOME) {
-                        tmpNonHomeApps.add(compat);
-                    } else {
-                        tmpHomeApps.add(compat);
+                    if (compat.activityType == ACTIVITY_TYPE_HOME
+                            && activityInterface.getCreatedActivity() instanceof RecentsActivity) {
+                        // When receive opening home activity while recents is running, enter home
+                        // and dismiss recents.
+                        ((RecentsActivity) activityInterface.getCreatedActivity()).startHome();
+                        return;
                     }
                 }
-                RemoteAnimationTarget[] nonHomeApps = tmpNonHomeApps.stream()
-                        .map(RemoteAnimationTargetCompat::unwrap)
-                        .toArray(RemoteAnimationTarget[]::new);
-                RemoteAnimationTarget[] homeApps = tmpHomeApps.stream()
-                        .map(RemoteAnimationTargetCompat::unwrap)
-                        .toArray(RemoteAnimationTarget[]::new);
-                if (homeApps.length > 0
-                        && activityInterface.getCreatedActivity() instanceof RecentsActivity) {
-                    ((RecentsActivity) activityInterface.getCreatedActivity()).startHome();
-                    return;
-                }
 
-                RemoteAnimationTarget[] nonAppTargets =
-                        SystemUiProxy.INSTANCE.getNoCreate().onStartingSplitLegacy(nonHomeApps);
+                RemoteAnimationTarget[] nonAppTargets = SystemUiProxy.INSTANCE.getNoCreate()
+                        .onStartingSplitLegacy(Arrays.stream(appearedTaskTargets)
+                                .map(RemoteAnimationTargetCompat::unwrap)
+                                .toArray(RemoteAnimationTarget[]::new));
 
                 if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
                         && activityInterface.getCreatedActivity() != null) {
diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
index b70c411..fa7bc04 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -358,7 +358,7 @@
             };
             RectFSpringAnim windowAnim = createWindowAnimationToHome(startShift,
                     homeAnimFactory)[0];
-            windowAnim.start(mContext, velocityPxPerMs);
+            windowAnim.start(mContext, mDp, velocityPxPerMs);
             return windowAnim;
         }
     }
diff --git a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
index c4909de..68739ba 100644
--- a/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
+++ b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
@@ -214,7 +214,7 @@
      * @param context The activity context.
      * @param velocityPxPerMs Velocity of swipe in px/ms.
      */
-    public void start(Context context, PointF velocityPxPerMs) {
+    public void start(Context context, @Nullable DeviceProfile profile, PointF velocityPxPerMs) {
         // Only tell caller that we ended if both x and y animations have ended.
         OnAnimationEndListener onXEndListener = ((animation, canceled, centerX, velocityX) -> {
             mRectXAnimEnded = true;
@@ -252,7 +252,13 @@
         float minVisibleChange = Math.abs(1f / mStartRect.height());
         ResourceProvider rp = DynamicResource.provider(context);
         float damping = rp.getFloat(R.dimen.swipe_up_rect_scale_damping_ratio);
-        float stiffness = rp.getFloat(R.dimen.swipe_up_rect_scale_stiffness);
+
+        // Increase the stiffness for devices where we want the window size to transform quicker.
+        boolean shouldUseHigherStiffness = profile != null
+                && (profile.isLandscape || profile.isTablet);
+        float stiffness = shouldUseHigherStiffness
+                ? rp.getFloat(R.dimen.swipe_up_rect_scale_higher_stiffness)
+                : rp.getFloat(R.dimen.swipe_up_rect_scale_stiffness);
 
         mRectScaleAnim = new SpringAnimation(this, RECT_SCALE_PROGRESS)
                 .setSpring(new SpringForce(1f)
diff --git a/res/values/config.xml b/res/values/config.xml
index 3f94c34..1415ed0 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -156,6 +156,7 @@
 
     <item name="swipe_up_rect_scale_damping_ratio" type="dimen" format="float">0.75</item>
     <item name="swipe_up_rect_scale_stiffness" type="dimen" format="float">200</item>
+    <item name="swipe_up_rect_scale_higher_stiffness" type="dimen" format="float">400</item>
 
     <item name="swipe_up_rect_xy_fling_friction" type="dimen" format="float">1.5</item>
 
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index f27eb79..418df37 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -399,7 +399,7 @@
         // Add a bit of space between nav bar and hotseat in vertical bar layout.
         hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
         updateHotseatSizes(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
-        if (areNavButtonsInline) {
+        if (areNavButtonsInline && !isPhone) {
             /*
              * 3 nav buttons +
              * Spacing between nav buttons +
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2bc5e64..4c9542d 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -2122,7 +2122,8 @@
                 final ItemInfo info = (ItemInfo) cell.getTag();
                 boolean isWidget = info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
                         || info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
-                if (isWidget) {
+                if (isWidget && dropTargetLayout != null) {
+                    // animate widget to a valid place
                     int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
                             ANIMATE_INTO_POSITION_AND_DISAPPEAR;
                     animateWidgetDrop(info, parent, d.dragView, null, animationType, cell, false);
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index bdab03f..ecc9d7e 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -232,7 +232,15 @@
                 // Reset pull back progress and alpha after switching states.
                 ALL_APPS_PULL_BACK_TRANSLATION.set(this, 0f);
                 ALL_APPS_PULL_BACK_ALPHA.set(this, 1f);
-                mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
+
+                // We only want to close the keyboard if the animation has completed successfully.
+                // The reason is that with keyboard sync, if the user swipes down from All Apps with
+                // the keyboard open and then changes their mind and swipes back up, we want the
+                // keyboard to remain open. However an onCancel signal is sent to the listeners
+                // (success = false), so we need to check for that.
+                if (success) {
+                    mLauncher.getAppsView().getSearchUiManager().getEditText().hideKeyboard();
+                }
             });
         }