Merge changes Ie55bd70e,I69bcfa97,I222522bc into tm-qpr-dev

* changes:
  Fix taskbar stash state not persisting properly across recreate
  Add support to Tapl to recreateTaskbar
  Don't rely on QuickstepLauncher instance for tests
diff --git a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
index 2ffb28e..0c1f05f 100644
--- a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
+++ b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java
@@ -25,12 +25,14 @@
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.R;
-import com.android.launcher3.taskbar.LauncherTaskbarUIController;
 import com.android.launcher3.testing.DebugTestInformationHandler;
 import com.android.launcher3.testing.shared.TestProtocol;
-import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.quickstep.TouchInteractionService.TISBinder;
+import com.android.quickstep.util.TISBindHelper;
 
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
 
 /**
  * Class to handle requests from tests, including debug ones, to Quickstep Launcher builds.
@@ -49,29 +51,26 @@
         Bundle response = new Bundle();
         switch (method) {
             case TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING:
-                runOnUIThread(l -> {
-                    enableManualTaskbarStashing(l, true);
+                runOnTISBinder(tisBinder -> {
+                    enableManualTaskbarStashing(tisBinder, true);
                 });
                 return response;
 
             case TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING:
-                runOnUIThread(l -> {
-                    enableManualTaskbarStashing(l, false);
+                runOnTISBinder(tisBinder -> {
+                    enableManualTaskbarStashing(tisBinder, false);
                 });
                 return response;
 
             case TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED:
-                runOnUIThread(l -> {
-                    enableManualTaskbarStashing(l, true);
-
-                    QuickstepLauncher quickstepLauncher = (QuickstepLauncher) l;
-                    LauncherTaskbarUIController taskbarUIController =
-                            quickstepLauncher.getTaskbarUIController();
+                runOnTISBinder(tisBinder -> {
+                    enableManualTaskbarStashing(tisBinder, true);
 
                     // Allow null-pointer to catch illegal states.
-                    taskbarUIController.unstashTaskbarIfStashed();
+                    tisBinder.getTaskbarManager().getCurrentActivityContext()
+                            .unstashTaskbarIfStashed();
 
-                    enableManualTaskbarStashing(l, false);
+                    enableManualTaskbarStashing(tisBinder, false);
                 });
                 return response;
 
@@ -82,6 +81,11 @@
                 return response;
             }
 
+            case TestProtocol.REQUEST_RECREATE_TASKBAR:
+                // Allow null-pointer to catch illegal states.
+                runOnTISBinder(tisBinder -> tisBinder.getTaskbarManager().recreateTaskbar());
+                return response;
+
             default:
                 response = super.call(method, arg, extras);
                 if (response != null) return response;
@@ -89,24 +93,26 @@
         }
     }
 
-    private void enableManualTaskbarStashing(Launcher launcher, boolean enable) {
-        QuickstepLauncher quickstepLauncher = (QuickstepLauncher) launcher;
-        LauncherTaskbarUIController taskbarUIController =
-                quickstepLauncher.getTaskbarUIController();
-
+    private void enableManualTaskbarStashing(TISBinder tisBinder, boolean enable) {
         // Allow null-pointer to catch illegal states.
-        taskbarUIController.enableManualStashingForTests(enable);
+        tisBinder.getTaskbarManager().getCurrentActivityContext().enableManualStashingForTests(
+                enable);
     }
 
     /**
-     * Runs the given command on the UI thread.
+     * Runs the given command on the UI thread, after ensuring we are connected to
+     * TouchInteractionService.
      */
-    private static void runOnUIThread(UIThreadCommand command) {
+    private void runOnTISBinder(Consumer<TISBinder> connectionCallback) {
         try {
-            MAIN_EXECUTOR.submit(() -> {
-                command.execute(Launcher.ACTIVITY_TRACKER.getCreatedActivity());
-                return null;
-            }).get();
+            CountDownLatch countDownLatch = new CountDownLatch(1);
+            TISBindHelper helper = MAIN_EXECUTOR.submit(() ->
+                    new TISBindHelper(mContext, tisBinder -> {
+                        connectionCallback.accept(tisBinder);
+                        countDownLatch.countDown();
+                    })).get();
+            countDownLatch.await();
+            MAIN_EXECUTOR.submit(helper::onDestroy);
         } catch (ExecutionException | InterruptedException e) {
             throw new RuntimeException(e);
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
index d69b8d2..9393b0f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java
@@ -43,8 +43,8 @@
         mLauncher.getHotseat().setIconsAlpha(1f);
     }
 
-    @Override
     /** Disable taskbar stashing in desktop environment. */
+    @Override
     public boolean supportsVisualStashing() {
         return false;
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 6c740ba..6e0b71d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -30,7 +30,6 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherState;
@@ -124,24 +123,6 @@
     }
 
     /**
-     * Enables manual taskbar stashing. This method should only be used for tests that need to
-     * stash/unstash the taskbar.
-     */
-    @VisibleForTesting
-    public void enableManualStashingForTests(boolean enableManualStashing) {
-        mControllers.taskbarStashController.enableManualStashingForTests(enableManualStashing);
-    }
-
-    /**
-     * Unstashes the Taskbar if it is stashed. This method should only be used to unstash the
-     * taskbar at the end of a test.
-     */
-    @VisibleForTesting
-    public void unstashTaskbarIfStashed() {
-        mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
-    }
-
-    /**
      * Adds the Launcher resume animator to the given animator set.
      *
      * This should be used to run a Launcher resume animation whose progress matches a
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index e1bcbe2..3b1e677 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -773,6 +773,24 @@
         mControllers.taskbarStashController.startUnstashHint(animateForward);
     }
 
+    /**
+     * Enables manual taskbar stashing. This method should only be used for tests that need to
+     * stash/unstash the taskbar.
+     */
+    @VisibleForTesting
+    public void enableManualStashingForTests(boolean enableManualStashing) {
+        mControllers.taskbarStashController.enableManualStashingForTests(enableManualStashing);
+    }
+
+    /**
+     * Unstashes the Taskbar if it is stashed. This method should only be used to unstash the
+     * taskbar at the end of a test.
+     */
+    @VisibleForTesting
+    public void unstashTaskbarIfStashed() {
+        mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
+    }
+
     protected boolean isUserSetupComplete() {
         return mIsUserSetupComplete;
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 35c5b96..80b3c1d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -36,6 +36,7 @@
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.LauncherAppState;
@@ -277,7 +278,8 @@
      * we fully want to destroy an existing taskbar and create a new one.
      * In other case (folding/unfolding) we don't need to remove and add window.
      */
-    private void recreateTaskbar() {
+    @VisibleForTesting
+    public void recreateTaskbar() {
         DeviceProfile dp = mUserUnlocked ?
                 LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 3ea9173..d9d55e7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -210,7 +210,10 @@
                 StashedHandleViewController.ALPHA_INDEX_STASHED);
         mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale();
 
-        boolean isManuallyStashedInApp = supportsManualStashing()
+        // We use supportsVisualStashing() here instead of supportsManualStashing() because we want
+        // it to work properly for tests that recreate taskbar. This check is here just to ensure
+        // that taskbar unstashes when going to 3 button mode (supportsVisualStashing() false).
+        boolean isManuallyStashedInApp = supportsVisualStashing()
                 && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
         boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible;
         updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
@@ -218,7 +221,10 @@
         updateStateForFlag(FLAG_IN_SETUP, isInSetup);
         updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode()
                 && !mActivity.isThreeButtonNav());
-        applyState();
+        // For now, assume we're in an app, since LauncherTaskbarUIController won't be able to tell
+        // us that we're paused until a bit later. This avoids flickering upon recreating taskbar.
+        updateStateForFlag(FLAG_IN_APP, true);
+        applyState(/* duration = */ 0);
 
         notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
     }
@@ -228,8 +234,7 @@
      * state.
      */
     public boolean supportsVisualStashing() {
-        return mControllers.uiController.supportsVisualStashing() ||
-                (isPhoneMode() && !mActivity.isThreeButtonNav());
+        return !mActivity.isThreeButtonNav() && mControllers.uiController.supportsVisualStashing();
     }
 
     /**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index fcc34c6..114bfec 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -49,9 +49,13 @@
         return true;
     }
 
+    /**
+     * This should only be called by TaskbarStashController so that a TaskbarUIController can
+     * disable stashing. All other controllers should use
+     * {@link TaskbarStashController#supportsVisualStashing()} as the source of truth.
+     */
     public boolean supportsVisualStashing() {
-        if (mControllers == null) return false;
-        return !mControllers.taskbarActivityContext.isThreeButtonNav();
+        return true;
     }
 
     protected void onStashedInAppChanged() { }
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
index 1df9c02..9337cb5 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java
@@ -68,6 +68,13 @@
     }
 
     @Test
+    public void testHideTaskbarPersistsOnRecreate() {
+        getTaskbar().hide();
+        mLauncher.recreateTaskbar();
+        mLauncher.getLaunchedAppState().assertTaskbarHidden();
+    }
+
+    @Test
     public void testLaunchApp() throws Exception {
         getTaskbar().getAppIcon(TEST_APP_NAME).launch(TEST_APP_PACKAGE);
     }
diff --git a/src/com/android/launcher3/testing/shared/TestProtocol.java b/src/com/android/launcher3/testing/shared/TestProtocol.java
index 67efb58..5116b01 100644
--- a/src/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/src/com/android/launcher3/testing/shared/TestProtocol.java
@@ -86,6 +86,7 @@
     public static final String REQUEST_DISABLE_MANUAL_TASKBAR_STASHING = "disable-taskbar-stashing";
     public static final String REQUEST_UNSTASH_TASKBAR_IF_STASHED = "unstash-taskbar-if-stashed";
     public static final String REQUEST_STASHED_TASKBAR_HEIGHT = "stashed-taskbar-height";
+    public static final String REQUEST_RECREATE_TASKBAR = "recreate-taskbar";
     public static final String REQUEST_APP_LIST_FREEZE_FLAGS = "app-list-freeze-flags";
     public static final String REQUEST_APPS_LIST_SCROLL_Y = "apps-list-scroll-y";
     public static final String REQUEST_WIDGETS_SCROLL_Y = "widgets-scroll-y";
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 04167839..a17651b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.tapl;
 
+import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID;
 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT;
@@ -54,13 +55,23 @@
     public Taskbar getTaskbar() {
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to get the taskbar")) {
-            mLauncher.waitForLauncherObject("taskbar_view");
+            mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
 
             return new Taskbar(mLauncher);
         }
     }
 
     /**
+     * Waits for the taskbar to be hidden, or fails.
+     */
+    public void assertTaskbarHidden() {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "waiting for taskbar to be hidden")) {
+            mLauncher.waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+        }
+    }
+
+    /**
      * Returns the Taskbar in a visible state.
      *
      * The taskbar must already be hidden when calling this method.
@@ -71,7 +82,7 @@
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
              LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
                      "want to show the taskbar")) {
-            mLauncher.waitUntilLauncherObjectGone("taskbar_view");
+            mLauncher.waitUntilLauncherObjectGone(TASKBAR_RES_ID);
 
             final long downTime = SystemClock.uptimeMillis();
             final int unstashTargetY = mLauncher.getRealDisplaySize().y
@@ -85,7 +96,7 @@
             LauncherInstrumentation.log("showTaskbar: sent down");
 
             try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
-                mLauncher.waitForLauncherObject("taskbar_view");
+                mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
                 mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
                         LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
 
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index fa7e8e9..1fb8cc7 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -168,7 +168,7 @@
     private static final String OVERVIEW_RES_ID = "overview_panel";
     private static final String WIDGETS_RES_ID = "primary_widgets_list_view";
     private static final String CONTEXT_MENU_RES_ID = "popup_container";
-    private static final String TASKBAR_RES_ID = "taskbar_view";
+    static final String TASKBAR_RES_ID = "taskbar_view";
     private static final String SPLIT_PLACEHOLDER_RES_ID = "split_placeholder";
     public static final int WAIT_TIME_MS = 30000;
     private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
@@ -1755,6 +1755,15 @@
         getTestInfo(TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED);
     }
 
+    /**
+     * Recreates the taskbar (outside of tests this is done for certain configuration changes).
+     * The expected behavior is that the taskbar retains its current state after being recreated.
+     * For example, if taskbar is currently stashed, it should still be stashed after recreating.
+     */
+    public void recreateTaskbar() {
+        getTestInfo(TestProtocol.REQUEST_RECREATE_TASKBAR);
+    }
+
     public List<String> getHotseatIconNames() {
         return getTestInfo(TestProtocol.REQUEST_HOTSEAT_ICON_NAMES)
                 .getStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD);
diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
index 5d9be36..0f9d5f5 100644
--- a/tests/tapl/com/android/launcher3/tapl/Taskbar.java
+++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.tapl;
 
+import static com.android.launcher3.tapl.LauncherInstrumentation.TASKBAR_RES_ID;
 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
 import static com.android.launcher3.testing.shared.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
 
@@ -51,7 +52,7 @@
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to get a taskbar icon")) {
             return new TaskbarAppIcon(mLauncher, mLauncher.waitForObjectInContainer(
-                    mLauncher.waitForLauncherObject("taskbar_view"),
+                    mLauncher.waitForLauncherObject(TASKBAR_RES_ID),
                     AppIcon.getAppIconSelector(appName, mLauncher)));
         }
     }
@@ -67,7 +68,7 @@
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to hide the taskbar");
              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            mLauncher.waitForLauncherObject("taskbar_view");
+            mLauncher.waitForLauncherObject(TASKBAR_RES_ID);
 
             final long downTime = SystemClock.uptimeMillis();
             Point stashTarget = new Point(
@@ -96,7 +97,7 @@
              LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
 
             mLauncher.clickLauncherObject(mLauncher.waitForObjectInContainer(
-                    mLauncher.waitForLauncherObject("taskbar_view"), getAllAppsButtonSelector()));
+                    mLauncher.waitForLauncherObject(TASKBAR_RES_ID), getAllAppsButtonSelector()));
 
             return new AllAppsFromTaskbar(mLauncher);
         }
@@ -107,7 +108,7 @@
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to get all taskbar icons")) {
             return mLauncher.waitForObjectsInContainer(
-                    mLauncher.waitForLauncherObject("taskbar_view"),
+                    mLauncher.waitForLauncherObject(TASKBAR_RES_ID),
                     AppIcon.getAnyAppIconSelector())
                     .stream()
                     .map(UiObject2::getText)