Merge "Add logs for widget picker image test" into udc-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index b5b453b..6cc54ca 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -676,7 +676,6 @@
                     hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
             mAnimator.addListener(AnimatorListeners.forEndCallback(() -> {
                 mAnimator = null;
-                mIsStashed = isStashed;
             }));
             return;
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 08ce794..dc160cc 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -203,6 +203,10 @@
 
     public static final boolean ENABLE_PIP_KEEP_CLEAR_ALGORITHM =
             SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", true);
+    private static final boolean TRACE_LAYOUTS =
+            SystemProperties.getBoolean("persist.debug.trace_layouts", false);
+    private static final String TRACE_RELAYOUT_CLASS =
+            SystemProperties.get("persist.debug.trace_request_layout_class", null);
 
     public static final boolean GO_LOW_RAM_RECENTS_ENABLED = false;
 
@@ -615,6 +619,8 @@
             mViewCapture = SettingsAwareViewCapture.getInstance(this).startCapture(getWindow());
         }
         getWindow().addPrivateFlags(PRIVATE_FLAG_OPTIMIZE_MEASURE);
+        View.setTraceLayoutSteps(TRACE_LAYOUTS);
+        View.setTracedRequestLayoutClassClass(TRACE_RELAYOUT_CLASS);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 2d5b8db..af49774 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -413,20 +413,14 @@
     }
 
     /**
-     * TODO: This doesn't animate at present. Feel free to blow out everyhing in this method
-     * if needed
+     * If {@param launchingTaskView} is not null, then this will play the tasks launch animation
+     * from the position of the GroupedTaskView (when user taps on the TaskView to start it).
+     * Technically this case should be taken care of by
+     * {@link #composeRecentsSplitLaunchAnimatorLegacy} below, but the way we launch tasks whether
+     * it's a single task or multiple tasks results in different entry-points.
      *
-     * We could manually try to animate the just the bounds for the leashes we get back, but we try
-     * to do it through TaskViewSimulator(TVS) since that handles a lot of the recents UI stuff for
-     * us.
-     *
-     * First you have to call TVS#setPreview() to indicate which leash it will operate one
-     * Then operations happen in TVS#apply() on each frame callback.
-     *
-     * TVS uses DeviceProfile to try to figure out things like task height and such based on if the
-     * device is in multiWindowMode or not. It's unclear given the two calls to startTask() when the
-     * device is considered in multiWindowMode and things like insets and stuff change
-     * and calculations have to be adjusted in the animations for that
+     * If it is null, then it will simply fade in the starting apps and fade out launcher (for the
+     * case where launcher handles animating starting split tasks from app icon)
      */
     public static void composeRecentsSplitLaunchAnimator(GroupedTaskView launchingTaskView,
             @NonNull StateManager stateManager, @Nullable DepthController depthController,
@@ -461,9 +455,9 @@
             return;
         }
 
-        // TODO: consider initialTaskPendingIntent
         TransitionInfo.Change splitRoot1 = null;
         TransitionInfo.Change splitRoot2 = null;
+        final ArrayList<SurfaceControl> openingTargets = new ArrayList<>();
         for (int i = 0; i < transitionInfo.getChanges().size(); ++i) {
             final TransitionInfo.Change change = transitionInfo.getChanges().get(i);
             if (change.getTaskInfo() == null) {
@@ -484,32 +478,48 @@
             if (taskId == initialTaskId) {
                 splitRoot1 = change.getParent() == null ? change :
                         transitionInfo.getChange(change.getParent());
+                openingTargets.add(splitRoot1.getLeash());
             }
             if (taskId == secondTaskId) {
                 splitRoot2 = change.getParent() == null ? change :
                         transitionInfo.getChange(change.getParent());
+                openingTargets.add(splitRoot2.getLeash());
             }
         }
 
-        // This is where we should animate the split roots. For now, though, just make them visible.
-        animateSplitRoot(t, splitRoot1);
-        animateSplitRoot(t, splitRoot2);
+        SurfaceControl.Transaction animTransaction = new SurfaceControl.Transaction();
+        ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
+        animator.setDuration(SPLIT_LAUNCH_DURATION);
+        animator.addUpdateListener(valueAnimator -> {
+            float progress = valueAnimator.getAnimatedFraction();
+            for (SurfaceControl leash: openingTargets) {
+                animTransaction.setAlpha(leash, progress);
+            }
+            animTransaction.apply();
+        });
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                for (SurfaceControl leash: openingTargets) {
+                    animTransaction.show(leash)
+                            .setAlpha(leash, 0.0f);
+                }
+                animTransaction.apply();
+            }
 
-        // This contains the initial state (before animation), so apply this at the beginning of
-        // the animation.
-        t.apply();
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                finishCallback.run();
+            }
+        });
 
-        // Once there is an animation, this should be called AFTER the animation completes.
-        finishCallback.run();
-    }
-
-    private static void animateSplitRoot(SurfaceControl.Transaction t,
-            TransitionInfo.Change splitRoot) {
-        testLogD(LAUNCH_SPLIT_PAIR, "animateSplitRoot: " + splitRoot);
-        if (splitRoot != null) {
-            t.show(splitRoot.getLeash());
-            t.setAlpha(splitRoot.getLeash(), 1.f);
+        if (splitRoot1 != null && splitRoot1.getParent() != null) {
+            // Set the highest level split root alpha; we could technically use the parent of either
+            // splitRoot1 or splitRoot2
+            t.setAlpha(transitionInfo.getChange(splitRoot1.getParent()).getLeash(), 1f);
         }
+        t.apply();
+        animator.start();
     }
 
     /**
@@ -522,7 +532,9 @@
      * it's a single task or multiple tasks results in different entry-points.
      *
      * If it is null, then it will simply fade in the starting apps and fade out launcher (for the
-     * case where launcher handles animating starting split tasks from app icon) */
+     * case where launcher handles animating starting split tasks from app icon)
+     * @deprecated with shell transitions
+     */
     public static void composeRecentsSplitLaunchAnimatorLegacy(
             @Nullable GroupedTaskView launchingTaskView, int initialTaskId, int secondTaskId,
             @NonNull RemoteAnimationTarget[] appTargets,
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 5565139..0c89766 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -592,9 +592,8 @@
                             if (mSuccessCallback != null) {
                                 mSuccessCallback.accept(true);
                             }
+                            resetState();
                         });
-                // After successful launch, call resetState
-                resetState();
             });
         }
 
diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
index 5127190..20aa410 100644
--- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
+++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java
@@ -16,14 +16,17 @@
 
 package com.android.quickstep;
 
+import static com.android.launcher3.util.rule.TestStabilityRule.LOCAL;
+import static com.android.launcher3.util.rule.TestStabilityRule.PLATFORM_POSTSUBMIT;
+
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.launcher3.ui.TaplTestsLauncher3;
+import com.android.launcher3.util.rule.TestStabilityRule.Stability;
 import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -44,9 +47,9 @@
         startTestActivity(2);
     }
 
-    @Ignore
     @Test
     @NavigationModeSwitch
+    @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/187761685
     public void testStressPressHome() {
         for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
             // Destroy Launcher activity.
@@ -57,9 +60,9 @@
         }
     }
 
-    @Ignore
     @Test
     @NavigationModeSwitch
+    @Stability(flavors = LOCAL | PLATFORM_POSTSUBMIT) // b/187761685
     public void testStressSwipeToOverview() {
         for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) {
             // Destroy Launcher activity.
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index f94a3c5..3c90408 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -21,6 +21,7 @@
 import android.graphics.Rect;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.DragEvent;
 import android.view.KeyEvent;
 import android.view.inputmethod.InputMethodManager;
@@ -37,6 +38,8 @@
  * Note: AppCompatEditText doesn't fully support #displayCompletions and #onCommitCompletion
  */
 public class ExtendedEditText extends EditText {
+    private static final String TAG = "ExtendedEditText";
+
     private final Set<OnFocusChangeListener> mOnFocusChangeListeners = new HashSet<>();
 
     private boolean mForceDisableSuggestions = false;
@@ -89,9 +92,17 @@
         return false;
     }
 
-    public void showKeyboard() {
+    /**
+     * Synchronously shows the soft input method.
+     *
+     * @param shouldFocus whether this EditText should also request focus.
+     * @return true if the keyboard is shown correctly and focus is given to this view (if
+     *     applicable).
+     */
+    public boolean showKeyboard(boolean shouldFocus) {
         onKeyboardShown();
-        showSoftInput();
+        boolean focusResult = !shouldFocus || requestFocus();
+        return focusResult && showSoftInputInternal();
     }
 
     public void hideKeyboard() {
@@ -104,10 +115,15 @@
                 .keyboardStateManager().setKeyboardState(SHOW);
     }
 
-    private boolean showSoftInput() {
-        return requestFocus() &&
-                getContext().getSystemService(InputMethodManager.class)
-                    .showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
+    private boolean showSoftInputInternal() {
+        boolean result = false;
+        InputMethodManager imm = getContext().getSystemService(InputMethodManager.class);
+        if (imm != null) {
+            result = imm.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
+        } else {
+            Log.w(TAG, "Failed to retrieve InputMethodManager from the system.");
+        }
+        return result;
     }
 
     public void dispatchBackKey() {
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 4427a49..ecbc7a9 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -160,7 +160,7 @@
      * Focuses the search field to handle key events.
      */
     public void focusSearchField() {
-        mInput.showKeyboard();
+        mInput.showKeyboard(true /* shouldFocus */);
     }
 
     /**
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 83431dc..7ca6c70 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -83,11 +83,11 @@
      */
     // TODO(Block 1): Clean up flags
     public static final BooleanFlag ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES = getReleaseFlag(
-            270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", TEAMFOOD,
+            270394041, "ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES", ENABLED,
             "Enable option to replace decorator-based search result backgrounds with drawables");
 
     public static final BooleanFlag ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION = getReleaseFlag(
-            270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", TEAMFOOD,
+            270394392, "ENABLE_SEARCH_RESULT_LAUNCH_TRANSITION", ENABLED,
             "Enable option to launch search results using the new view container transitions");
 
     // TODO(Block 2): Clean up flags
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index f38cce1..55a539a 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -535,7 +535,7 @@
                     mFolderName.selectAll();
                 }
             }
-            mFolderName.showKeyboard();
+            mFolderName.showKeyboard(true /* shouldFocus */);
             mFolderName.displayCompletions(
                     Stream.of(mInfo.suggestedFolderNames.getLabels())
                             .filter(Objects::nonNull)
diff --git a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
index 38de2fa..83d9f4a 100644
--- a/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
+++ b/tests/src/com/android/launcher3/util/viewcapture_analysis/AlphaJumpDetector.java
@@ -110,6 +110,7 @@
             DRAG_LAYER + "WidgetsTwoPaneSheet|SpringRelativeLayout:id/container",
             CONTENT + "LauncherRootView:id/launcher|FloatingIconView",
             RECENTS_DRAG_LAYER + "ArrowTipView",
+            DRAG_LAYER + "ArrowTipView",
             DRAG_LAYER + "FallbackRecentsView:id/overview_panel",
             RECENTS_DRAG_LAYER + "FallbackRecentsView:id/overview_panel",
             DRAG_LAYER