Merge "[Toast] Remove feature flag for rich answer, use all apps flag instead." into tm-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
index 7cf8201..c65fa5f 100644
--- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
+++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java
@@ -19,6 +19,8 @@
 import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition;
 import static com.android.quickstep.util.SplitAnimationTimings.TABLET_HOME_TO_SPLIT;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
@@ -115,13 +117,19 @@
 
             PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration());
             RectF startingTaskRect = new RectF();
-            FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
-                    source.view, null /* thumbnail */,
-                    source.drawable, startingTaskRect);
+            final FloatingTaskView floatingTaskView = FloatingTaskView.getFloatingTaskView(mTarget,
+                    source.view, null /* thumbnail */, source.drawable, startingTaskRect);
             floatingTaskView.setAlpha(1);
             floatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
                     false /* fadeWithThumbnail */, true /* isStagedTask */);
             controller.setFirstFloatingTaskView(floatingTaskView);
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationCancel(Animator animation) {
+                    mTarget.getDragLayer().removeView(floatingTaskView);
+                    controller.resetState();
+                }
+            });
             anim.buildAnim().start();
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 875327d..2435236 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -210,7 +210,7 @@
         DeviceProfile deviceProfile = mContext.getDeviceProfile();
         Resources resources = mContext.getResources();
         Point p = !mContext.isUserSetupComplete()
-                ? new Point(0, resources.getDimensionPixelSize(R.dimen.taskbar_suw_frame))
+                ? new Point(0, controllers.taskbarActivityContext.getSetupWindowHeight())
                 : DimensionUtils.getTaskbarPhoneDimensions(deviceProfile, resources,
                         TaskbarManager.isPhoneMode(deviceProfile));
         mNavButtonsView.getLayoutParams().height = p.y;
@@ -691,8 +691,9 @@
                         (resources.getDimensionPixelSize(R.dimen.taskbar_nav_buttons_size) / 2);
         navButtonsLayoutParams.setMarginEnd(0);
         navButtonsLayoutParams.gravity = Gravity.START;
+        mNavButtonsView.getLayoutParams().height =
+                mControllers.taskbarActivityContext.getSetupWindowHeight();
         mNavButtonContainer.setLayoutParams(navButtonsLayoutParams);
-        mNavButtonContainer.requestLayout();
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 13ca58d..d9d46d4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -341,6 +341,9 @@
 
     public void onConfigurationChanged(@Config int configChanges) {
         mControllers.onConfigurationChanged(configChanges);
+        if (!mIsUserSetupComplete) {
+            setTaskbarWindowHeight(getSetupWindowHeight());
+        }
     }
 
     public boolean isThreeButtonNav() {
@@ -673,7 +676,7 @@
         }
 
         if (!isUserSetupComplete()) {
-            return resources.getDimensionPixelSize(R.dimen.taskbar_suw_frame);
+            return getSetupWindowHeight();
         }
 
         if (DisplayController.isTransientTaskbar(this)) {
@@ -685,6 +688,10 @@
         return mDeviceProfile.taskbarSize + Math.max(getLeftCornerRadius(), getRightCornerRadius());
     }
 
+    public int getSetupWindowHeight() {
+        return getResources().getDimensionPixelSize(R.dimen.taskbar_suw_frame);
+    }
+
     /**
      * Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
      * window.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 32c1972..b388512 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -149,7 +149,8 @@
         if (context.dragLayer.alpha < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) {
             // Let touches pass through us.
             insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
-        } else if (controllers.navbarButtonsViewController.isImeVisible) {
+        } else if (controllers.navbarButtonsViewController.isImeVisible
+                && controllers.taskbarStashController.isStashed()) {
             insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
         } else if (!controllers.uiController.isTaskbarTouchable) {
             // Let touches pass through us.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 11755d9..e62e533 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -375,11 +375,11 @@
 
         if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
             DeviceProfile dp = mActivity.getDeviceProfile();
-            if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent && !dp.isLandscape) {
+            if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent) {
                 // We always show the back button in SUW but in portrait the SUW layout may not
-                // be wide enough to support overlapping the nav bar with its content.  For now,
-                // just inset by the bar height.
-                return mUnstashedHeight;
+                // be wide enough to support overlapping the nav bar with its content.
+                // We're sending different res values in portrait vs landscape
+                return mActivity.getResources().getDimensionPixelSize(R.dimen.taskbar_suw_insets);
             }
             boolean isAnimating = mAnimator != null && mAnimator.isStarted();
             if (!mControllers.stashedHandleViewController.isStashedHandleVisible()
@@ -393,10 +393,6 @@
             return mStashedHeight;
         }
 
-        if (!mActivity.isUserSetupComplete()) {
-            // Special insets for SUW.
-            return mActivity.getResources().getDimensionPixelSize(R.dimen.taskbar_suw_insets);
-        }
         return mUnstashedHeight;
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 9936d27..b5e6fac 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -193,7 +193,8 @@
      * Should be called when the IME visibility changes, so we can make Taskbar not steal touches.
      */
     public void setImeIsVisible(boolean isImeVisible) {
-        mTaskbarView.setTouchesEnabled(!isImeVisible);
+        mTaskbarView.setTouchesEnabled(!isImeVisible
+                || DisplayController.isTransientTaskbar(mActivity));
     }
 
     /**
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 0ef4597..0a155cb 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -342,6 +342,10 @@
                 return;
             }
 
+            if (mItemInfo == null) {
+                return;
+            }
+
             if (mItemInfo.container < 0 || appState == null) {
                 // Write log on the model thread so that logs do not go out of order
                 // (for eg: drop comes after drag)
diff --git a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
index e8a4b0a..e5c74dc 100644
--- a/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java
@@ -19,21 +19,39 @@
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Intent;
+import android.graphics.Rect;
+import android.graphics.RectF;
 import android.view.View;
 
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.quickstep.views.FloatingTaskView;
+import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 
 /** Handles when the stage split lands on the home screen. */
 public class SplitToWorkspaceController {
 
     private final Launcher mLauncher;
+    private final DeviceProfile mDP;
     private final SplitSelectStateController mController;
 
+    private final int mHalfDividerSize;
+
     public SplitToWorkspaceController(Launcher launcher, SplitSelectStateController controller) {
         mLauncher = launcher;
+        mDP = mLauncher.getDeviceProfile();
         mController = controller;
+
+        mHalfDividerSize = mLauncher.getResources().getDimensionPixelSize(
+                R.dimen.multi_window_task_divider_size) / 2;
     }
 
     /**
@@ -48,19 +66,74 @@
         }
         Object tag = view.getTag();
         Intent intent;
+        BitmapInfo bitmapInfo;
         if (tag instanceof WorkspaceItemInfo) {
             final WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) tag;
             intent = workspaceItemInfo.intent;
+            bitmapInfo = workspaceItemInfo.bitmap;
         } else if (tag instanceof com.android.launcher3.model.data.AppInfo) {
             final com.android.launcher3.model.data.AppInfo appInfo =
                     (com.android.launcher3.model.data.AppInfo) tag;
             intent = appInfo.intent;
+            bitmapInfo = appInfo.bitmap;
         } else {
             return false;
         }
+
         mController.setSecondTask(intent);
-        mController.launchSplitTasks(aBoolean -> mLauncher.getDragLayer().removeView(
-                mController.getFirstFloatingTaskView()));
+
+        boolean isTablet = mLauncher.getDeviceProfile().isTablet;
+        SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
+        PendingAnimation pendingAnimation = new PendingAnimation(timings.getDuration());
+
+        Rect firstTaskStartingBounds = new Rect();
+        Rect firstTaskEndingBounds = new Rect();
+        RectF secondTaskStartingBounds = new RectF();
+        Rect secondTaskEndingBounds = new Rect();
+
+        RecentsView recentsView = mLauncher.getOverviewPanel();
+        recentsView.getPagedOrientationHandler().getFinalSplitPlaceholderBounds(mHalfDividerSize,
+                mDP, mController.getActiveSplitStagePosition(), firstTaskEndingBounds,
+                secondTaskEndingBounds);
+
+        FloatingTaskView firstFloatingTaskView = mController.getFirstFloatingTaskView();
+        firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
+        firstFloatingTaskView.addConfirmAnimation(pendingAnimation,
+                new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
+                false /* fadeWithThumbnail */, true /* isStagedTask */);
+
+        FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher,
+                view, null /* thumbnail */, bitmapInfo.newIcon(mLauncher),
+                secondTaskStartingBounds);
+        secondFloatingTaskView.setAlpha(1);
+        secondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
+                secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
+
+        pendingAnimation.addListener(new AnimatorListenerAdapter() {
+            private boolean mIsCancelled = false;
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                mIsCancelled = true;
+                cleanUp();
+            }
+
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (!mIsCancelled) {
+                    mController.launchSplitTasks(aBoolean -> cleanUp());
+                    InteractionJankMonitorWrapper.end(
+                            InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
+                }
+            }
+
+            private void cleanUp() {
+                mLauncher.getDragLayer().removeView(firstFloatingTaskView);
+                mLauncher.getDragLayer().removeView(secondFloatingTaskView);
+                mController.resetState();
+            }
+        });
+        pendingAnimation.buildAnim().start();
         return true;
     }
 }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 72209c6..88654b7 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -330,6 +330,10 @@
             "HOME_GARDENING_WORKSPACE_BUTTONS", false,
             "Change workspace edit buttons to reflect home gardening");
 
+    public static final BooleanFlag ENABLE_DOWNLOAD_APP_UX_V2 = getDebugFlag(
+            "ENABLE_DOWNLOAD_APP_UX_V2", false, "Updates the download app UX"
+                    + " to have better visuals");
+
     public static final BooleanFlag ENABLE_TASKBAR_REVISED_THRESHOLDS = getDebugFlag(
             "ENABLE_TASKBAR_REVISED_THRESHOLDS", false,
             "Uses revised thresholds for transient taskbar.");
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index b4be061..098cf80 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -28,6 +28,7 @@
 
 import android.app.AlertDialog;
 import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -315,10 +316,16 @@
      */
     public static void onClickSearchAction(Launcher launcher, SearchActionItemInfo itemInfo) {
         if (itemInfo.getIntent() != null) {
-            if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
-                launcher.startActivityForResult(itemInfo.getIntent(), 0);
-            } else {
-                launcher.startActivity(itemInfo.getIntent());
+            try {
+                if (itemInfo.hasFlags(SearchActionItemInfo.FLAG_SHOULD_START_FOR_RESULT)) {
+                    launcher.startActivityForResult(itemInfo.getIntent(), 0);
+                } else {
+                    launcher.startActivity(itemInfo.getIntent());
+                }
+            } catch (ActivityNotFoundException e) {
+                Toast.makeText(launcher,
+                        launcher.getResources().getText(R.string.shortcut_not_available),
+                        Toast.LENGTH_SHORT).show();
             }
         } else if (itemInfo.getPendingIntent() != null) {
             try {
diff --git a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
index 57731d0..93329fa 100644
--- a/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
+++ b/tests/src/com/android/launcher3/ui/workspace/ThemeIconsTest.java
@@ -35,6 +35,8 @@
 import com.android.launcher3.tapl.HomeAppIconMenuItem;
 import com.android.launcher3.ui.AbstractLauncherUiTest;
 import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 
 import org.junit.Test;
 
@@ -109,6 +111,7 @@
     }
 
     @Test
+    @ScreenRecord // b/260722220
     public void testShortcutIconWithTheme() throws Exception {
         setThemeEnabled(true);
         TaplTestsLauncher3.initialize(this);
@@ -128,6 +131,13 @@
     }
 
     private void verifyIconTheme(String title, ViewGroup parent, boolean isThemed) {
+        // Wait for Launcher model to be completed
+        try {
+            Executors.MODEL_EXECUTOR.submit(() -> { }).get();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
         // Find the app icon
         Queue<View> viewQueue = new ArrayDeque<>();
         viewQueue.add(parent);
diff --git a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
index ddeeac2..bddb593 100644
--- a/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
+++ b/tests/tapl/com/android/launcher3/tapl/SearchResultFromQsb.java
@@ -20,6 +20,8 @@
 import androidx.test.uiautomator.By;
 import androidx.test.uiautomator.UiObject2;
 
+import java.util.ArrayList;
+
 /**
  * Operations on search result page opened from home screen qsb.
  */
@@ -27,6 +29,9 @@
     // The input resource id in the search box.
     private static final String INPUT_RES = "input";
     private static final String BOTTOM_SHEET_RES_ID = "bottom_sheet_background";
+
+    // This particular ID change should happen with caution
+    private static final String SEARCH_CONTAINER_RES_ID = "search_results_list_view";
     private final LauncherInstrumentation mLauncher;
 
     SearchResultFromQsb(LauncherInstrumentation launcher) {
@@ -49,6 +54,33 @@
         return new AllAppsAppIcon(mLauncher, icon);
     }
 
+    /** Find the web suggestion from search suggestion's title text */
+    public void findWebSuggest(String text) {
+        ArrayList<UiObject2> goldenGateResults =
+                new ArrayList<>(mLauncher.waitForObjectsInContainer(
+                        mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),
+                        By.clazz(TextView.class)));
+        boolean found = false;
+        for(UiObject2 uiObject: goldenGateResults) {
+            String currentString = uiObject.getText();
+            if (currentString.equals(text)) {
+                found = true;
+            }
+        }
+        if (!found) {
+            throw new IllegalStateException("Web suggestion title: " + text + " not found");
+        }
+    }
+
+    /** Find the total amount of views being displayed and return the size */
+    public int getSearchResultItemSize() {
+        ArrayList<UiObject2> searchResultItems =
+                new ArrayList<>(mLauncher.waitForObjectsInContainer(
+                        mLauncher.waitForSystemLauncherObject(SEARCH_CONTAINER_RES_ID),
+                        By.clazz(TextView.class)));
+        return searchResultItems.size();
+    }
+
     /**
      * Taps outside bottom sheet to dismiss and return to workspace. Available on tablets only.
      * @param tapRight Tap on the right of bottom sheet if true, or left otherwise.