diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index 4895b107e1..437a19b1f1 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -31,6 +31,7 @@ import androidx.test.uiautomator.Until; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.tapl.AllApps; import com.android.launcher3.tapl.Background; import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel; import com.android.launcher3.tapl.Overview; @@ -49,6 +50,9 @@ import org.junit.runner.RunWith; @LargeTest @RunWith(AndroidJUnit4.class) public class TaplTestsQuickstep extends AbstractQuickStepTest { + + private static final String APP_NAME = "LauncherTestApp"; + @Before public void setUp() throws Exception { super.setUp(); @@ -286,6 +290,30 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { getAndAssertBackground(); } + // TODO(b/204830798): test with all navigation modes(add @NavigationModeSwitch annotation) + // after the bug resolved. + @Test + @PortraitLandscape + @ScreenRecord + public void testPressBack() throws Exception { + mLauncher.getWorkspace().switchToAllApps(); + mLauncher.pressBack(); + mLauncher.getWorkspace(); + waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL); + + AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); + allApps.freeze(); + try { + allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false); + } finally { + allApps.unfreeze(); + } + mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName()); + mLauncher.pressBack(); + mLauncher.getWorkspace(); + waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL); + } + @Test @PortraitLandscape public void testOverviewForTablet() throws Exception { diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index 0ffbeeb95e..82163cbfdb 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -211,7 +211,8 @@ public abstract class AbstractLauncherUiTest { } protected TestRule getRulesInsideActivityMonitor() { - final RuleChain inner = RuleChain.outerRule(new PortraitLandscapeRunner(this)) + final RuleChain inner = RuleChain + .outerRule(new PortraitLandscapeRunner(this)) .around(new FailureWatcher(mDevice, mLauncher)); return TestHelpers.isInLauncherProcess() diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 2fa84b2430..4007c26f54 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -413,6 +413,27 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { folder.close(); } + @Test + @PortraitLandscape + public void testPressBack() throws Exception { + mLauncher.getWorkspace().switchToAllApps(); + mLauncher.pressBack(); + mLauncher.getWorkspace(); + waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL); + + AllApps allApps = mLauncher.getWorkspace().switchToAllApps(); + allApps.freeze(); + try { + allApps.getAppIcon(APP_NAME).dragToWorkspace(false, false); + } finally { + allApps.unfreeze(); + } + mLauncher.getWorkspace().getWorkspaceAppIcon(APP_NAME).launch(getAppPackageName()); + mLauncher.pressBack(); + mLauncher.getWorkspace(); + waitForState("Launcher internal state didn't switch to Home", () -> LauncherState.NORMAL); + } + public static String getAppPackageName() { return getInstrumentation().getContext().getPackageName(); } diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 3ac5fa5bbd..e2d023825c 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -76,6 +76,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Deque; @@ -110,6 +111,9 @@ public final class LauncherInstrumentation { static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN"); static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP"); + static final Pattern EVENT_KEY_BACK_DOWN = getKeyEventPattern("ACTION_DOWN", "KEYCODE_BACK"); + static final Pattern EVENT_KEY_BACK_UP = getKeyEventPattern("ACTION_UP", "KEYCODE_BACK"); + private final String mLauncherPackage; private Boolean mIsLauncher3; private long mTestStartTime = -1; @@ -125,7 +129,8 @@ public final class LauncherInstrumentation { // Where the gesture happens: outside of Launcher, inside or from inside to outside and // whether the gesture recognition triggers pilfer. public enum GestureScope { - OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE + OUTSIDE_WITHOUT_PILFER, OUTSIDE_WITH_PILFER, INSIDE, INSIDE_TO_OUTSIDE, + INSIDE_TO_OUTSIDE_WITHOUT_PILFER, } // Base class for launcher containers. @@ -195,6 +200,10 @@ public final class LauncherInstrumentation { return getTouchEventPattern("TouchInteractionService.onInputEvent", action); } + private static Pattern getKeyEventPattern(String action, String keyCode) { + return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode); + } + /** * Constructs the root of TAPL hierarchy. You get all other objects from it. */ @@ -879,6 +888,38 @@ public final class LauncherInstrumentation { } } + /** + * Press navbar back button or swipe back if in gesture navigation mode. + */ + public void pressBack() { + try (Closable e = eventsCheck(); Closable c = addContextLayer("want to press back")) { + waitForLauncherInitialized(); + final boolean launcherVisible = + isTablet() ? isLauncherContainerVisible() : isLauncherVisible(); + if (getNavigationModel() == NavigationModel.ZERO_BUTTON) { + final Point displaySize = getRealDisplaySize(); + final GestureScope gestureScope = + launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER + : GestureScope.OUTSIDE_WITHOUT_PILFER; + linearGesture(0, displaySize.y / 2, displaySize.x / 2, displaySize.y / 2, + 10, false, gestureScope); + } else { + waitForNavigationUiObject("back").click(); + if (isTablet()) { + expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN); + expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_UP); + } else if (!isLauncher3() && getNavigationModel() == NavigationModel.TWO_BUTTON) { + expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS); + expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS); + } + } + if (launcherVisible) { + expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_KEY_BACK_DOWN); + expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_KEY_BACK_UP); + } + } + } + private static BySelector getAnyObjectSelector() { return By.textStartsWith(""); } @@ -888,6 +929,11 @@ public final class LauncherInstrumentation { return hasLauncherObject(getAnyObjectSelector()); } + boolean isLauncherContainerVisible() { + final String[] containerResources = {WORKSPACE_RES_ID, OVERVIEW_RES_ID, APPS_RES_ID}; + return Arrays.stream(containerResources).anyMatch(r -> hasLauncherObject(r)); + } + /** * Gets the Workspace object if the current state is "active home", i.e. workspace. Fails if the * launcher is not in that state. @@ -1414,6 +1460,7 @@ public final class LauncherInstrumentation { break; case MotionEvent.ACTION_UP: if (notLauncher3 && gestureScope != GestureScope.INSIDE + && gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER && (gestureScope == GestureScope.OUTSIDE_WITH_PILFER || gestureScope == GestureScope.INSIDE_TO_OUTSIDE)) { expectEvent(TestProtocol.SEQUENCE_PILFER, EVENT_PILFER_POINTERS);