diff --git a/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java b/quickstep/ext_tests/src/com/android/quickstep/DebugQuickstepTestInformationHandler.java index 2ffb28e8fb..0c1f05f923 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 androidx.annotation.Nullable; 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 @@ public abstract class DebugQuickstepTestInformationHandler extends QuickstepTest 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 @@ public abstract class DebugQuickstepTestInformationHandler extends QuickstepTest 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 @@ public abstract class DebugQuickstepTestInformationHandler extends QuickstepTest } } - 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 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 d69b8d291c..9393b0f7ab 100644 --- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java @@ -43,8 +43,8 @@ public class DesktopTaskbarUIController extends TaskbarUIController { 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 6c740bac50..6e0b71dca0 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -30,7 +30,6 @@ import android.view.WindowManagerGlobal; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import com.android.launcher3.DeviceProfile; import com.android.launcher3.LauncherState; @@ -123,24 +122,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { shouldDelayLauncherStateAnim); } - /** - * 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. * diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index e1bcbe23bf..3b1e6774b4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -773,6 +773,24 @@ public class TaskbarActivityContext extends BaseTaskbarContext { 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 35c5b96b9a..80b3c1d095 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -36,6 +36,7 @@ import android.view.Display; 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 @@ public class TaskbarManager { * 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 3ea917334c..d9d55e765f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -210,7 +210,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba 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 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba 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 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba * 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 fcc34c6d99..114bfecb6e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -49,9 +49,13 @@ public class TaskbarUIController { 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 1df9c02ee8..9337cb55bc 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTaskbar.java @@ -67,6 +67,13 @@ public class TaplTestsTaskbar extends AbstractQuickStepTest { mLauncher.getLaunchedAppState().showTaskbar(); } + @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 67efb58848..5116b01ba5 100644 --- a/src/com/android/launcher3/testing/shared/TestProtocol.java +++ b/src/com/android/launcher3/testing/shared/TestProtocol.java @@ -86,6 +86,7 @@ public final class TestProtocol { 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 0416783998..a17651b640 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,12 +55,22 @@ public final class LaunchedAppState extends Background { 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. * @@ -71,7 +82,7 @@ public final class LaunchedAppState extends Background { 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 @@ public final class LaunchedAppState extends Background { 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 fa7e8e93bb..1fb8cc7df8 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -168,7 +168,7 @@ public final class LauncherInstrumentation { 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 @@ public final class LauncherInstrumentation { 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 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 5d9be3604d..0f9d5f52c7 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 @@ public final class Taskbar { 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 @@ public final class Taskbar { 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 @@ public final class Taskbar { 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 @@ public final class Taskbar { 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)