Introduce multi finger trackpad gestures to tapl tests
- Add tests to go to overview from home and all apps
Bug: 281732733
Test: presubmit
Change-Id: Ief6d72d7293ca7dff935e764362aa5ab271fd36b
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
index e92dc8f..4c6874e 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsTrackpad.java
@@ -16,11 +16,13 @@
package com.android.quickstep;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assume.assumeTrue;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
@@ -38,12 +40,11 @@
public void setUp() throws Exception {
super.setUp();
TaplTestsLauncher3.initialize(this);
- mLauncher.setSwipeFromTrackpad(true);
}
@After
public void tearDown() {
- mLauncher.setSwipeFromTrackpad(false);
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.NONE);
}
@Test
@@ -52,7 +53,30 @@
public void goHome() throws Exception {
assumeTrue(mLauncher.isTablet());
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
startTestActivity(2);
mLauncher.goHome();
}
+
+ @Test
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void switchToOverview() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.THREE_FINGER);
+ startTestActivity(2);
+ mLauncher.goHome().switchToOverview();
+ }
+
+ @Test
+ @PortraitLandscape
+ @NavigationModeSwitch
+ public void testAllAppsFromHome() throws Exception {
+ assumeTrue(mLauncher.isTablet());
+
+ mLauncher.setTrackpadGestureType(TrackpadGestureType.TWO_FINGER);
+ assertNotNull("switchToAllApps() returned null",
+ mLauncher.getWorkspace().switchToAllApps());
+ }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index 31e9aa2..3dab9a8 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -30,6 +30,8 @@
import androidx.annotation.NonNull;
import androidx.test.uiautomator.UiObject2;
+import com.android.launcher3.tapl.LauncherInstrumentation.NavigationModel;
+import com.android.launcher3.tapl.LauncherInstrumentation.TrackpadGestureType;
import com.android.launcher3.testing.shared.TestProtocol;
import java.util.List;
@@ -75,80 +77,76 @@
}
protected void goToOverviewUnchecked() {
- switch (mLauncher.getNavigationModel()) {
- case ZERO_BUTTON: {
- final long downTime = SystemClock.uptimeMillis();
- sendDownPointerToEnterOverviewToLauncher(downTime);
- String swipeAndHoldToEnterOverviewActionName =
- "swiping and holding to enter overview";
- // If swiping from an app (e.g. Overview is in Background), we pause and hold on
- // swipe up to make overview appear, or else swiping without holding would take
- // us to the Home state. If swiping up from Home (e.g. Overview in Home or
- // Workspace state where the below condition is true), there is no need to pause,
- // and we will not test for an intermediate carousel as one will not exist.
- if (zeroButtonToOverviewGestureStateTransitionWhileHolding()) {
- mLauncher.runToState(
- () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
- OVERVIEW_STATE_ORDINAL, swipeAndHoldToEnterOverviewActionName);
- sendUpPointerToEnterOverviewToLauncher(downTime);
- } else {
- // If swiping up from an app to overview, pause on intermediate carousel
- // until snapshots are visible. No intermediate carousel when swiping from
- // Home. The task swiped up is not a snapshot but the TaskViewSimulator. If
- // only a single task exists, no snapshots will be available during swipe up.
- mLauncher.executeAndWaitForLauncherEvent(
- () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
- event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(
- event.getClassName().toString()),
- () -> "Pause wasn't detected",
- swipeAndHoldToEnterOverviewActionName);
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
- "paused on swipe up to overview")) {
- if (mLauncher.getRecentTasks().size() > 1) {
- // When swiping up to grid-overview for tablets, the swiped tab will be
- // in the middle of the screen (TaskViewSimulator, not a snapshot), and
- // all remaining snapshots will be to the left of that task. In
- // non-tablet overview, snapshots can be on either side of the swiped
- // task, but we still check that they become visible after swiping and
- // pausing.
- mLauncher.waitForOverviewObject("snapshot");
- if (mLauncher.isTablet()) {
- List<UiObject2> tasks = mLauncher.getDevice().findObjects(
- mLauncher.getOverviewObjectSelector("snapshot"));
- final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
- mLauncher.assertTrue(
- "All tasks not to the left of the swiped task",
- tasks.stream()
- .allMatch(
- t -> t.getVisibleBounds().right < centerX));
- }
-
- }
- String upPointerToEnterOverviewActionName =
- "sending UP pointer to enter overview";
- mLauncher.runToState(() -> sendUpPointerToEnterOverviewToLauncher(downTime),
- OVERVIEW_STATE_ORDINAL, upPointerToEnterOverviewActionName);
- }
- }
- break;
- }
-
- case THREE_BUTTON:
- if (mLauncher.isTablet()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_DOWN);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
- LauncherInstrumentation.EVENT_TOUCH_UP);
- }
- if (mLauncher.isTrackpadGestureEnabled()) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
- }
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ if (mLauncher.getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || mLauncher.getTrackpadGestureType() == TrackpadGestureType.THREE_FINGER) {
+ final long downTime = SystemClock.uptimeMillis();
+ sendDownPointerToEnterOverviewToLauncher(downTime);
+ String swipeAndHoldToEnterOverviewActionName =
+ "swiping and holding to enter overview";
+ // If swiping from an app (e.g. Overview is in Background), we pause and hold on
+ // swipe up to make overview appear, or else swiping without holding would take
+ // us to the Home state. If swiping up from Home (e.g. Overview in Home or
+ // Workspace state where the below condition is true), there is no need to pause,
+ // and we will not test for an intermediate carousel as one will not exist.
+ if (zeroButtonToOverviewGestureStateTransitionWhileHolding()) {
mLauncher.runToState(
- () -> mLauncher.waitForNavigationUiObject("recent_apps").click(),
- OVERVIEW_STATE_ORDINAL, "clicking Recents button");
- break;
+ () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
+ OVERVIEW_STATE_ORDINAL, swipeAndHoldToEnterOverviewActionName);
+ sendUpPointerToEnterOverviewToLauncher(downTime);
+ } else {
+ // If swiping up from an app to overview, pause on intermediate carousel
+ // until snapshots are visible. No intermediate carousel when swiping from
+ // Home. The task swiped up is not a snapshot but the TaskViewSimulator. If
+ // only a single task exists, no snapshots will be available during swipe up.
+ mLauncher.executeAndWaitForLauncherEvent(
+ () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
+ event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(
+ event.getClassName().toString()),
+ () -> "Pause wasn't detected",
+ swipeAndHoldToEnterOverviewActionName);
+ try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ "paused on swipe up to overview")) {
+ if (mLauncher.getRecentTasks().size() > 1) {
+ // When swiping up to grid-overview for tablets, the swiped tab will be
+ // in the middle of the screen (TaskViewSimulator, not a snapshot), and
+ // all remaining snapshots will be to the left of that task. In
+ // non-tablet overview, snapshots can be on either side of the swiped
+ // task, but we still check that they become visible after swiping and
+ // pausing.
+ mLauncher.waitForOverviewObject("snapshot");
+ if (mLauncher.isTablet()) {
+ List<UiObject2> tasks = mLauncher.getDevice().findObjects(
+ mLauncher.getOverviewObjectSelector("snapshot"));
+ final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
+ mLauncher.assertTrue(
+ "All tasks not to the left of the swiped task",
+ tasks.stream()
+ .allMatch(
+ t -> t.getVisibleBounds().right < centerX));
+ }
+
+ }
+ String upPointerToEnterOverviewActionName =
+ "sending UP pointer to enter overview";
+ mLauncher.runToState(() -> sendUpPointerToEnterOverviewToLauncher(downTime),
+ OVERVIEW_STATE_ORDINAL, upPointerToEnterOverviewActionName);
+ }
+ }
+ } else {
+ if (mLauncher.isTablet()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+ LauncherInstrumentation.EVENT_TOUCH_DOWN);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN,
+ LauncherInstrumentation.EVENT_TOUCH_UP);
+ }
+ if (mLauncher.isTrackpadGestureEnabled()) {
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_UP_TIS);
+ }
+ mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, SQUARE_BUTTON_EVENT);
+ mLauncher.runToState(
+ () -> mLauncher.waitForNavigationUiObject("recent_apps").click(),
+ OVERVIEW_STATE_ORDINAL, "clicking Recents button");
}
expectSwitchToOverviewEvents();
}
@@ -263,10 +261,8 @@
endY = startY;
}
- final boolean isZeroButton = mLauncher.getNavigationModel()
- == LauncherInstrumentation.NavigationModel.ZERO_BUTTON;
LauncherInstrumentation.GestureScope gestureScope =
- launcherWasVisible && isZeroButton
+ launcherWasVisible
? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
: LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
mLauncher.executeAndWaitForEvent(
@@ -326,6 +322,8 @@
}
protected int getSwipeStartY() {
- return mLauncher.getRealDisplaySize().y - 1;
+ return mLauncher.getTrackpadGestureType() == TrackpadGestureType.THREE_FINGER
+ ? mLauncher.getDevice().getDisplayHeight() * 3 / 4
+ : mLauncher.getRealDisplaySize().y - 1;
}
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index ce50e22..5b67d73 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -139,6 +139,13 @@
OUTSIDE_WITH_KEYCODE,
}
+ public enum TrackpadGestureType {
+ NONE,
+ TWO_FINGER,
+ THREE_FINGER,
+ FOUR_FINGER
+ }
+
// Base class for launcher containers.
abstract static class VisibleContainer {
protected final LauncherInstrumentation mLauncher;
@@ -198,7 +205,7 @@
private boolean mCheckEventsForSuccessfulGestures = false;
private Runnable mOnLauncherCrashed;
- private boolean mSwipeFromTrackpad = false;
+ private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE;
private int mPointerCount = 0;
private static Pattern getTouchEventPattern(String prefix, String action) {
@@ -715,8 +722,17 @@
mIgnoreTaskbarVisibility = ignoreTaskbarVisibility;
}
- public void setSwipeFromTrackpad(boolean swipeFromTrackpad) {
- mSwipeFromTrackpad = swipeFromTrackpad;
+ /**
+ * Set the trackpad gesture type of the interaction.
+ * @param trackpadGestureType whether it's not from trackpad, two-finger, three-finger, or
+ * four-finger gesture.
+ */
+ public void setTrackpadGestureType(TrackpadGestureType trackpadGestureType) {
+ mTrackpadGestureType = trackpadGestureType;
+ }
+
+ TrackpadGestureType getTrackpadGestureType() {
+ return mTrackpadGestureType;
}
/**
@@ -1008,8 +1024,11 @@
// We need waiting for any accessibility event generated after pressing Home because
// otherwise waitForIdle may return immediately in case when there was a big enough
// pause in accessibility events prior to pressing Home.
+ boolean isThreeFingerTrackpadGesture =
+ mTrackpadGestureType == TrackpadGestureType.THREE_FINGER;
final String action;
- if (getNavigationModel() == NavigationModel.ZERO_BUTTON || mSwipeFromTrackpad) {
+ if (getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || isThreeFingerTrackpadGesture) {
checkForAnomaly(false, true);
final Point displaySize = getRealDisplaySize();
@@ -1025,8 +1044,9 @@
} else {
action = "swiping up to home";
- int startY = mSwipeFromTrackpad ? displaySize.y * 3 / 4 : displaySize.y - 1;
- int endY = mSwipeFromTrackpad ? displaySize.y / 4 : displaySize.y / 2;
+ int startY = isThreeFingerTrackpadGesture ? displaySize.y * 3 / 4
+ : displaySize.y - 1;
+ int endY = isThreeFingerTrackpadGesture ? displaySize.y / 4 : displaySize.y / 2;
swipeToState(
displaySize.x / 2, startY,
displaySize.x / 2, endY,
@@ -1070,15 +1090,18 @@
waitForLauncherInitialized();
final boolean launcherVisible =
isTablet() ? isLauncherContainerVisible() : isLauncherVisible();
- if (getNavigationModel() == NavigationModel.ZERO_BUTTON || mSwipeFromTrackpad) {
+ boolean isThreeFingerTrackpadGesture =
+ mTrackpadGestureType == TrackpadGestureType.THREE_FINGER;
+ if (getNavigationModel() == NavigationModel.ZERO_BUTTON
+ || isThreeFingerTrackpadGesture) {
final Point displaySize = getRealDisplaySize();
final GestureScope gestureScope =
launcherVisible ? GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
: GestureScope.OUTSIDE_WITH_KEYCODE;
// TODO(b/225505986): change startY and endY back to displaySize.y / 2 once the
// issue is solved.
- int startX = mSwipeFromTrackpad ? displaySize.x / 4 : 0;
- int endX = mSwipeFromTrackpad ? displaySize.x * 3 / 4 : displaySize.x / 2;
+ int startX = isThreeFingerTrackpadGesture ? displaySize.x / 4 : 0;
+ int endX = isThreeFingerTrackpadGesture ? displaySize.x * 3 / 4 : displaySize.x / 2;
linearGesture(startX, displaySize.y / 4, endX, displaySize.y / 4,
10, false, gestureScope);
} else {
@@ -1615,19 +1638,29 @@
final Point start = new Point(startX, startY);
final Point end = new Point(endX, endY);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
- if (mSwipeFromTrackpad) {
+ if (mTrackpadGestureType != TrackpadGestureType.NONE) {
sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 1),
start, gestureScope);
- sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 2),
- start, gestureScope);
+ if (mTrackpadGestureType == TrackpadGestureType.THREE_FINGER
+ || mTrackpadGestureType == TrackpadGestureType.FOUR_FINGER) {
+ sendPointer(downTime, downTime,
+ getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 2),
+ start, gestureScope);
+ if (mTrackpadGestureType == TrackpadGestureType.FOUR_FINGER) {
+ sendPointer(downTime, downTime,
+ getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 3),
+ start, gestureScope);
+ }
+ }
}
final long endTime = movePointer(
start, end, steps, false, downTime, downTime, slowDown, gestureScope);
- if (mSwipeFromTrackpad) {
- sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_UP, 2),
- start, gestureScope);
- sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_UP, 1),
- start, gestureScope);
+ if (mTrackpadGestureType != TrackpadGestureType.NONE) {
+ for (int i = mPointerCount; i >= 2; i--) {
+ sendPointer(downTime, downTime,
+ getPointerAction(MotionEvent.ACTION_POINTER_UP, i - 1),
+ start, gestureScope);
+ }
}
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end, gestureScope);
}
@@ -1659,20 +1692,25 @@
return getContext().getResources();
}
- private static MotionEvent getTrackpadThreeFingerMotionEvent(long downTime, long eventTime,
- int action, float x, float y, int pointerCount) {
+ private static MotionEvent getTrackpadMotionEvent(long downTime, long eventTime,
+ int action, float x, float y, int pointerCount, TrackpadGestureType gestureType) {
MotionEvent.PointerProperties[] pointerProperties =
new MotionEvent.PointerProperties[pointerCount];
MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount];
+ boolean isMultiFingerGesture = gestureType != TrackpadGestureType.TWO_FINGER;
for (int i = 0; i < pointerCount; i++) {
pointerProperties[i] = getPointerProperties(i);
pointerCoords[i] = getPointerCoords(x, y);
- pointerCoords[i].setAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT, 3);
+ if (isMultiFingerGesture) {
+ pointerCoords[i].setAxisValue(AXIS_GESTURE_SWIPE_FINGER_COUNT,
+ gestureType == TrackpadGestureType.THREE_FINGER ? 3 : 4);
+ }
}
return MotionEvent.obtain(downTime, eventTime, action, pointerCount, pointerProperties,
pointerCoords, 0, 0, 1.0f, 1.0f, 0, 0,
InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_CLASS_POINTER, 0, 0,
- MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE);
+ isMultiFingerGesture ? MotionEvent.CLASSIFICATION_MULTI_FINGER_SWIPE
+ : MotionEvent.CLASSIFICATION_TWO_FINGER_SWIPE);
}
private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
@@ -1712,22 +1750,25 @@
public void sendPointer(long downTime, long currentTime, int action, Point point,
GestureScope gestureScope) {
final boolean hasTIS = hasTIS();
- int pointerCount = 1;
+ int pointerCount = mPointerCount;
+ boolean isTrackpadGesture = mTrackpadGestureType != TrackpadGestureType.NONE;
+ boolean isTwoFingerTrackpadGesture = mTrackpadGestureType == TrackpadGestureType.TWO_FINGER;
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
- && !mSwipeFromTrackpad) {
+ && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
}
if (hasTIS && (isTrackpadGestureEnabled()
|| getNavigationModel() != NavigationModel.THREE_BUTTON)) {
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
}
- if (mSwipeFromTrackpad) {
+ if (isTrackpadGesture) {
mPointerCount = 1;
+ pointerCount = mPointerCount;
}
break;
case MotionEvent.ACTION_UP:
@@ -1740,7 +1781,7 @@
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
- && !mSwipeFromTrackpad) {
+ && (!isTrackpadGesture || isTwoFingerTrackpadGesture)) {
expectEvent(TestProtocol.SEQUENCE_MAIN,
gestureScope == GestureScope.INSIDE
|| gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
@@ -1767,8 +1808,6 @@
pointerCount = mPointerCount;
break;
case MotionEvent.ACTION_POINTER_UP:
- pointerCount = mPointerCount;
-
// When the gesture is handled outside, it's cancelled within launcher.
if (gestureScope != GestureScope.INSIDE_TO_OUTSIDE_WITH_KEYCODE
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
@@ -1779,9 +1818,10 @@
break;
}
- final MotionEvent event = mSwipeFromTrackpad
- ? getTrackpadThreeFingerMotionEvent(
- downTime, currentTime, action, point.x, point.y, pointerCount)
+ final MotionEvent event = isTrackpadGesture
+ ? getTrackpadMotionEvent(
+ downTime, currentTime, action, point.x, point.y, pointerCount,
+ mTrackpadGestureType)
: getMotionEvent(downTime, currentTime, action, point.x, point.y);
assertTrue("injectInputEvent failed",
mInstrumentation.getUiAutomation().injectInputEvent(event, true, false));