diff --git a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java index 44c23ba9a2..6a7b6f8780 100644 --- a/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java +++ b/quickstep/tests/src/com/android/quickstep/AbstractQuickStepTest.java @@ -26,6 +26,7 @@ import androidx.test.uiautomator.Until; import com.android.launcher3.tapl.LaunchedAppState; import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.uioverrides.QuickstepLauncher; +import com.android.launcher3.util.TestUtil; import com.android.quickstep.views.RecentsView; import org.junit.rules.RuleChain; @@ -56,7 +57,7 @@ public abstract class AbstractQuickStepTest extends AbstractLauncherUiTest getFromRecents(recents -> !recents.isStarted()), - DEFAULT_UI_TIMEOUT, mLauncher); + mLauncher); } @Test @@ -254,7 +253,8 @@ public class FallbackRecentsTest { startTestActivity(2); waitForRecentsActivityStop(); Wait.atMost("Expected three apps in the task list", - () -> mLauncher.getRecentTasks().size() >= 3, DEFAULT_ACTIVITY_TIMEOUT, mLauncher); + () -> mLauncher.getRecentTasks().size() >= 3, + mLauncher); checkTestLauncher(); BaseOverview overview = mLauncher.getLaunchedAppState().switchToOverview(); @@ -282,7 +282,7 @@ public class FallbackRecentsTest { assertNotNull("OverviewTask.open returned null", task.open()); assertTrue("Test activity didn't open from Overview", TestHelpers.wait(Until.hasObject( By.pkg(getAppPackageName()).text("TestActivity2")), - DEFAULT_UI_TIMEOUT)); + TestUtil.DEFAULT_UI_TIMEOUT)); // Test dismissing a task. diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index 4459ed6944..77f4c05f53 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -57,8 +57,6 @@ public class NavigationModeSwitchRule implements TestRule { static final String TAG = "QuickStepOnOffRule"; - public static final int WAIT_TIME_MS = 10000; - public enum Mode { THREE_BUTTON, ZERO_BUTTON, ALL } @@ -179,12 +177,13 @@ public class NavigationModeSwitchRule implements TestRule { } Wait.atMost("Couldn't switch to " + overlayPackage, - () -> launcher.getNavigationModel() == expectedMode, WAIT_TIME_MS, launcher); + () -> launcher.getNavigationModel() == expectedMode, + launcher); Wait.atMost(() -> "Switching nav mode: " + launcher.getNavigationModeMismatchError(false), () -> launcher.getNavigationModeMismatchError(false) == null, - WAIT_TIME_MS, launcher); + launcher); AbstractLauncherUiTest.checkDetectedLeaks(launcher, false); return true; } diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt b/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt index 120a89b0f8..f58c84e2a2 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsOverviewDesktop.kt @@ -26,6 +26,7 @@ import com.android.launcher3.tapl.OverviewTask import com.android.launcher3.ui.AbstractLauncherUiTest import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape import com.android.launcher3.uioverrides.QuickstepLauncher +import com.android.launcher3.util.TestUtil import com.google.common.truth.Truth.assertWithMessage import org.junit.Before import org.junit.Test @@ -172,7 +173,7 @@ class TaplTestsOverviewDesktop : AbstractLauncherUiTest() { .that( mDevice.wait( Until.hasObject(By.pkg(getAppPackageName()).text("TestActivity$index")), - DEFAULT_UI_TIMEOUT, + TestUtil.DEFAULT_UI_TIMEOUT, ) ) .isTrue() diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index 5ff2af705b..f1fe2d2d7e 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -47,6 +47,7 @@ import com.android.launcher3.tapl.OverviewTask; import com.android.launcher3.tapl.SelectModeButtons; import com.android.launcher3.tapl.Workspace; import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape; +import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.Wait; import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord; import com.android.launcher3.util.rule.TestStabilityRule; @@ -145,7 +146,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { assertNotNull("OverviewTask.open returned null", task.open()); assertTrue("Test activity didn't open from Overview", mDevice.wait(Until.hasObject( By.pkg(getAppPackageName()).text("TestActivity2")), - DEFAULT_UI_TIMEOUT)); + TestUtil.DEFAULT_UI_TIMEOUT)); executeOnLauncher(launcher -> assertTrue( "Launcher activity is the top activity; expecting another activity to be the top " + "one", @@ -448,7 +449,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { mDevice.wait(Until.hasObject(By.pkg(getAppPackageName()).text( mLauncher.isGridOnlyOverviewEnabled() ? "TestActivity12" : "TestActivity13")), - DEFAULT_UI_TIMEOUT)); + TestUtil.DEFAULT_UI_TIMEOUT)); // Scroll the task offscreen as it is now first overview = mLauncher.goHome().switchToOverview(); @@ -563,7 +564,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { mLauncher.getDevice().setOrientationLeft(); startTestActivity(7); Wait.atMost("Device should not be in natural orientation", - () -> !mDevice.isNaturalOrientation(), DEFAULT_UI_TIMEOUT, mLauncher); + () -> !mDevice.isNaturalOrientation(), mLauncher); mLauncher.goHome(); } finally { mLauncher.setExpectedRotationCheckEnabled(true); diff --git a/tests/src/com/android/launcher3/LauncherIntentTest.java b/tests/src/com/android/launcher3/LauncherIntentTest.java index aeeb42a363..3e16713a2d 100644 --- a/tests/src/com/android/launcher3/LauncherIntentTest.java +++ b/tests/src/com/android/launcher3/LauncherIntentTest.java @@ -23,7 +23,7 @@ import android.content.Intent; import android.platform.test.annotations.LargeTest; import android.view.KeyEvent; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.launcher3.allapps.ActivityAllAppsContainerView; import com.android.launcher3.allapps.SearchRecyclerView; diff --git a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java index 44b8ff86f9..1816030b45 100644 --- a/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java +++ b/tests/src/com/android/launcher3/dragging/TaplUninstallRemoveTest.java @@ -69,8 +69,7 @@ public class TaplUninstallRemoveTest extends AbstractLauncherUiTest { private void verifyAppUninstalledFromAllApps(Workspace workspace, String appName) { final HomeAllApps allApps = workspace.switchToAllApps(); Wait.atMost(appName + " app was found on all apps after being uninstalled", - () -> allApps.tryGetAppIcon(appName) == null, - DEFAULT_UI_TIMEOUT, mLauncher); + () -> allApps.tryGetAppIcon(appName) == null, mLauncher); } private void installDummyAppAndWaitForUIUpdate() throws IOException { diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 206647a19c..1fbdcebb51 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -32,8 +32,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; -import android.content.pm.LauncherActivityInfo; -import android.content.pm.LauncherApps; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.graphics.Point; @@ -97,10 +95,8 @@ import java.util.function.Supplier; */ public abstract class AbstractLauncherUiTest { - public static final long DEFAULT_ACTIVITY_TIMEOUT = TimeUnit.SECONDS.toMillis(10); public static final long DEFAULT_BROADCAST_TIMEOUT_SECS = 10; - public static final long DEFAULT_UI_TIMEOUT = TestUtil.DEFAULT_UI_TIMEOUT; private static final String TAG = "AbstractLauncherUiTest"; private static final long BYTES_PER_MEGABYTE = 1 << 20; @@ -151,7 +147,7 @@ public abstract class AbstractLauncherUiTest { launcher.forceGc(); return MAIN_EXECUTOR.submit( () -> launcher.noLeakedActivities(requireOneActiveActivity)).get(); - }, DEFAULT_UI_TIMEOUT, launcher); + }, launcher); } public static String getAppPackageName() { @@ -443,7 +439,7 @@ public abstract class AbstractLauncherUiTest { */ protected T getOnUiThread(final Callable callback) { try { - return mMainThreadExecutor.submit(callback).get(DEFAULT_UI_TIMEOUT, + return mMainThreadExecutor.submit(callback).get(TestUtil.DEFAULT_UI_TIMEOUT, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { Log.e(TAG, "Timeout in getOnUiThread, sending SIGABRT", e); @@ -498,13 +494,7 @@ public abstract class AbstractLauncherUiTest { // flakiness. protected void waitForLauncherCondition(String message, Function condition) { - waitForLauncherCondition(message, condition, DEFAULT_ACTIVITY_TIMEOUT); - } - - // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide - // flakiness. - protected O getOnceNotNull(String message, Function f) { - return getOnceNotNull(message, f, DEFAULT_ACTIVITY_TIMEOUT); + waitForLauncherCondition(message, condition, TestUtil.DEFAULT_UI_TIMEOUT); } // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide @@ -513,12 +503,12 @@ public abstract class AbstractLauncherUiTest { String message, Function condition, long timeout) { verifyKeyguardInvisible(); if (!TestHelpers.isInLauncherProcess()) return; - Wait.atMost(message, () -> getFromLauncher(condition), timeout, mLauncher); + Wait.atMost(message, () -> getFromLauncher(condition), mLauncher, timeout); } // Cannot be used in TaplTests after injecting any gesture using Tapl because this can hide // flakiness. - protected T getOnceNotNull(String message, Function f, long timeout) { + protected T getOnceNotNull(String message, Function f) { if (!TestHelpers.isInLauncherProcess()) return null; final Object[] output = new Object[1]; @@ -526,7 +516,7 @@ public abstract class AbstractLauncherUiTest { final Object fromLauncher = getFromLauncher(f); output[0] = fromLauncher; return fromLauncher != null; - }, timeout, mLauncher); + }, mLauncher); return (T) output[0]; } @@ -540,12 +530,7 @@ public abstract class AbstractLauncherUiTest { Wait.atMost(message, () -> { testThreadAction.run(); return getFromLauncher(condition); - }, timeout, mLauncher); - } - - protected LauncherActivityInfo getSettingsApp() { - return mTargetContext.getSystemService(LauncherApps.class) - .getActivityList("com.android.settings", Process.myUserHandle()).get(0); + }, mLauncher, timeout); } /** @@ -633,13 +618,13 @@ public abstract class AbstractLauncherUiTest { } getInstrumentation().getTargetContext().startActivity(intent); assertTrue("App didn't start: " + selector, - TestHelpers.wait(Until.hasObject(selector), DEFAULT_UI_TIMEOUT)); + TestHelpers.wait(Until.hasObject(selector), TestUtil.DEFAULT_UI_TIMEOUT)); // Wait for the Launcher to stop. final LauncherInstrumentation launcherInstrumentation = new LauncherInstrumentation(); Wait.atMost("Launcher activity didn't stop", () -> !launcherInstrumentation.isLauncherActivityStarted(), - DEFAULT_ACTIVITY_TIMEOUT, launcherInstrumentation); + launcherInstrumentation); } public static ActivityInfo resolveSystemAppInfo(String category) { @@ -662,8 +647,7 @@ public abstract class AbstractLauncherUiTest { launcher.finish(); } }); - waitForLauncherCondition( - "Launcher still active", launcher -> launcher == null, DEFAULT_UI_TIMEOUT); + waitForLauncherCondition("Launcher still active", launcher -> launcher == null); } protected boolean isInLaunchedApp(LAUNCHER_TYPE launcher) { diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java index 7ff4f22e3d..7845222b6e 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplAddConfigWidgetTest.java @@ -103,12 +103,12 @@ public class TaplAddConfigWidgetTest extends AbstractLauncherUiTest { setResultAndWaitForAnimation(acceptConfig); if (acceptConfig) { - Wait.atMost("", new WidgetSearchCondition(), DEFAULT_ACTIVITY_TIMEOUT, mLauncher); + Wait.atMost("", new WidgetSearchCondition(), mLauncher); assertNotNull(mAppWidgetManager.getAppWidgetInfo(mWidgetId)); } else { // Verify that the widget id is deleted. Wait.atMost("", () -> mAppWidgetManager.getAppWidgetInfo(mWidgetId) == null, - DEFAULT_ACTIVITY_TIMEOUT, mLauncher); + mLauncher); } } diff --git a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java index 9a2147af4b..460ffc4b59 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplAddWidgetTest.java @@ -29,6 +29,7 @@ import com.android.launcher3.tapl.WidgetResizeFrame; import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape; import com.android.launcher3.ui.TestViewHelpers; +import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; @@ -68,7 +69,7 @@ public class TaplAddWidgetTest extends AbstractLauncherUiTest { resizeFrame.dismiss(); final Widget widget = mLauncher.getWorkspace().tryGetWidget(widgetInfo.label, - DEFAULT_UI_TIMEOUT); + TestUtil.DEFAULT_UI_TIMEOUT); assertNotNull("Widget not found on the workspace", widget); widget.launch(getAppPackageName()); mLauncher.disableDebugTracing(); // b/289161193 diff --git a/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java index d40d3bc8e0..4cdbd96641 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplBindWidgetTest.java @@ -53,6 +53,7 @@ import com.android.launcher3.tapl.Widget; import com.android.launcher3.tapl.Workspace; import com.android.launcher3.ui.AbstractLauncherUiTest; import com.android.launcher3.ui.TestViewHelpers; +import com.android.launcher3.util.TestUtil; import com.android.launcher3.util.rule.ShellCommandRule; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.WidgetManagerHelper; @@ -233,13 +234,15 @@ public class TaplBindWidgetTest extends AbstractLauncherUiTest { } private void verifyWidgetPresent(LauncherAppWidgetProviderInfo info) { - final Widget widget = mLauncher.getWorkspace().tryGetWidget(info.label, DEFAULT_UI_TIMEOUT); + final Widget widget = mLauncher.getWorkspace().tryGetWidget(info.label, + TestUtil.DEFAULT_UI_TIMEOUT); assertTrue("Widget is not present", widget != null); } private void verifyPendingWidgetPresent() { - final Widget widget = mLauncher.getWorkspace().tryGetPendingWidget(DEFAULT_UI_TIMEOUT); + final Widget widget = mLauncher.getWorkspace().tryGetPendingWidget( + TestUtil.DEFAULT_UI_TIMEOUT); assertTrue("Pending widget is not present", widget != null); } diff --git a/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java index 35c7cabb61..fe3b2eea6c 100644 --- a/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java +++ b/tests/src/com/android/launcher3/ui/widget/TaplRequestPinItemTest.java @@ -169,8 +169,7 @@ public class TaplRequestPinItemTest extends AbstractLauncherUiTest { // Go back to home mLauncher.goHome(); - Wait.atMost("", new ItemSearchCondition(itemMatcher), DEFAULT_ACTIVITY_TIMEOUT, - mLauncher); + Wait.atMost("", new ItemSearchCondition(itemMatcher), mLauncher); } /** diff --git a/tests/src/com/android/launcher3/util/Wait.java b/tests/src/com/android/launcher3/util/Wait.java deleted file mode 100644 index 50bc32e509..0000000000 --- a/tests/src/com/android/launcher3/util/Wait.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.android.launcher3.util; - -import android.os.SystemClock; -import android.util.Log; - -import com.android.launcher3.tapl.LauncherInstrumentation; - -import org.junit.Assert; - -import java.util.function.Supplier; - -/** - * A utility class for waiting for a condition to be true. - */ -public class Wait { - - private static final long DEFAULT_SLEEP_MS = 200; - - public static void atMost(String message, Condition condition, long timeout, - LauncherInstrumentation launcher) { - atMost(() -> message, condition, timeout, DEFAULT_SLEEP_MS, launcher); - } - - public static void atMost(Supplier message, Condition condition, long timeout, - LauncherInstrumentation launcher) { - atMost(message, condition, timeout, DEFAULT_SLEEP_MS, launcher); - } - - public static void atMost(Supplier message, Condition condition, long timeout, - long sleepMillis, - LauncherInstrumentation launcher) { - final long startTime = SystemClock.uptimeMillis(); - long endTime = startTime + timeout; - Log.d("Wait", "atMost: " + startTime + " - " + endTime); - while (SystemClock.uptimeMillis() < endTime) { - try { - if (condition.isTrue()) { - return; - } - } catch (Throwable t) { - throw new RuntimeException(t); - } - SystemClock.sleep(sleepMillis); - } - - // Check once more before returning false. - try { - if (condition.isTrue()) { - return; - } - } catch (Throwable t) { - throw new RuntimeException(t); - } - Log.d("Wait", "atMost: timed out: " + SystemClock.uptimeMillis()); - launcher.checkForAnomaly(false, false); - Assert.fail(message.get()); - } - - /** - * Interface representing a generic condition - */ - public interface Condition { - - boolean isTrue() throws Throwable; - } -} diff --git a/tests/src/com/android/launcher3/util/Wait.kt b/tests/src/com/android/launcher3/util/Wait.kt new file mode 100644 index 0000000000..1e5af54d86 --- /dev/null +++ b/tests/src/com/android/launcher3/util/Wait.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.util + +import android.os.SystemClock +import android.util.Log +import com.android.launcher3.tapl.LauncherInstrumentation +import java.util.function.Supplier +import org.junit.Assert + +/** A utility class for waiting for a condition to be true. */ +object Wait { + private const val DEFAULT_SLEEP_MS: Long = 200 + + @JvmStatic + @JvmOverloads + fun atMost( + message: String, + condition: Condition, + launcherInstrumentation: LauncherInstrumentation? = null, + timeout: Long = TestUtil.DEFAULT_UI_TIMEOUT, + ) { + atMost({ message }, condition, launcherInstrumentation, timeout) + } + + @JvmStatic + @JvmOverloads + fun atMost( + message: Supplier, + condition: Condition, + launcherInstrumentation: LauncherInstrumentation? = null, + timeout: Long = TestUtil.DEFAULT_UI_TIMEOUT, + ) { + val startTime = SystemClock.uptimeMillis() + val endTime = startTime + timeout + Log.d("Wait", "atMost: $startTime - $endTime") + while (SystemClock.uptimeMillis() < endTime) { + try { + if (condition.isTrue()) { + return + } + } catch (t: Throwable) { + throw RuntimeException(t) + } + SystemClock.sleep(DEFAULT_SLEEP_MS) + } + + // Check once more before returning false. + try { + if (condition.isTrue()) { + return + } + } catch (t: Throwable) { + throw RuntimeException(t) + } + Log.d("Wait", "atMost: timed out: " + SystemClock.uptimeMillis()) + launcherInstrumentation?.checkForAnomaly(false, false) + Assert.fail(message.get()) + } + + /** Interface representing a generic condition */ + fun interface Condition { + + @Throws(Throwable::class) fun isTrue(): Boolean + } +}