Add initial trackpad tapl tests

- go home

Bug: 281732733
Test: presubmit
Change-Id: I538d63bde2bf427a02c2bc355eab71546d667bf9
This commit is contained in:
Tracy Zhou
2023-05-26 01:05:30 -07:00
parent 491b0f9028
commit 323958007d
2 changed files with 164 additions and 23 deletions
@@ -0,0 +1,58 @@
/*
* Copyright (C) 2023 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.quickstep;
import static org.junit.Assume.assumeTrue;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.launcher3.ui.PortraitLandscapeRunner.PortraitLandscape;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.quickstep.NavigationModeSwitchRule.NavigationModeSwitch;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class TaplTestsTrackpad extends AbstractQuickStepTest {
@Before
public void setUp() throws Exception {
super.setUp();
TaplTestsLauncher3.initialize(this);
mLauncher.setSwipeFromTrackpad(true);
}
@After
public void tearDown() {
mLauncher.setSwipeFromTrackpad(false);
}
@Test
@PortraitLandscape
@NavigationModeSwitch
public void goHome() throws Exception {
assumeTrue(mLauncher.isTablet());
startTestActivity(2);
mLauncher.goHome();
}
}
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.DONT_KILL_APP;
import static android.content.pm.PackageManager.MATCH_ALL;
import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
import static android.view.MotionEvent.AXIS_GESTURE_SWIPE_FINGER_COUNT;
import static com.android.launcher3.tapl.Folder.FOLDER_CONTENT_RES_ID;
import static com.android.launcher3.tapl.TestHelpers.getOverviewPackageName;
@@ -197,11 +198,18 @@ public final class LauncherInstrumentation {
private boolean mCheckEventsForSuccessfulGestures = false;
private Runnable mOnLauncherCrashed;
private boolean mSwipeFromTrackpad = false;
private int mPointerCount = 0;
private static Pattern getTouchEventPattern(String prefix, String action) {
// The pattern includes checks that we don't get a multi-touch events or other surprises.
return getTouchEventPattern(prefix, action, 1);
}
private static Pattern getTouchEventPattern(String prefix, String action, int pointerCount) {
return Pattern.compile(
prefix + ": MotionEvent.*?action=" + action + ".*?id\\[0\\]=0"
+ ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount=1");
+ ".*?toolType\\[0\\]=TOOL_TYPE_FINGER.*?buttonState=0.*?pointerCount="
+ pointerCount);
}
private static Pattern getTouchEventPattern(String action) {
@@ -212,6 +220,10 @@ public final class LauncherInstrumentation {
return getTouchEventPattern("TouchInteractionService.onInputEvent", action);
}
private static Pattern getTouchEventPatternTIS(String action, int pointerCount) {
return getTouchEventPattern("TouchInteractionService.onInputEvent", action, pointerCount);
}
private static Pattern getKeyEventPattern(String action, String keyCode) {
return Pattern.compile("Key event: KeyEvent.*action=" + action + ".*keyCode=" + keyCode);
}
@@ -703,6 +715,10 @@ public final class LauncherInstrumentation {
mIgnoreTaskbarVisibility = ignoreTaskbarVisibility;
}
public void setSwipeFromTrackpad(boolean swipeFromTrackpad) {
mSwipeFromTrackpad = swipeFromTrackpad;
}
/**
* Sets expected rotation.
* TAPL periodically checks that Launcher didn't suddenly change the rotation to unexpected one.
@@ -993,7 +1009,7 @@ public final class LauncherInstrumentation {
// otherwise waitForIdle may return immediately in case when there was a big enough
// pause in accessibility events prior to pressing Home.
final String action;
if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
if (getNavigationModel() == NavigationModel.ZERO_BUTTON || mSwipeFromTrackpad) {
checkForAnomaly(false, true);
final Point displaySize = getRealDisplaySize();
@@ -1009,9 +1025,11 @@ public final class LauncherInstrumentation {
} 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;
swipeToState(
displaySize.x / 2, displaySize.y - 1,
displaySize.x / 2, displaySize.y / 2,
displaySize.x / 2, startY,
displaySize.x / 2, endY,
ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME, NORMAL_STATE_ORDINAL,
gestureStartFromLauncher ? GestureScope.INSIDE_TO_OUTSIDE
: GestureScope.OUTSIDE_WITH_PILFER);
@@ -1052,14 +1070,16 @@ public final class LauncherInstrumentation {
waitForLauncherInitialized();
final boolean launcherVisible =
isTablet() ? isLauncherContainerVisible() : isLauncherVisible();
if (getNavigationModel() == NavigationModel.ZERO_BUTTON) {
if (getNavigationModel() == NavigationModel.ZERO_BUTTON || mSwipeFromTrackpad) {
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.
linearGesture(0, displaySize.y / 4, displaySize.x / 2, displaySize.y / 4,
int startX = mSwipeFromTrackpad ? displaySize.x / 4 : 0;
int endX = mSwipeFromTrackpad ? displaySize.x * 3 / 4 : displaySize.x / 2;
linearGesture(startX, displaySize.y / 4, endX, displaySize.y / 4,
10, false, gestureScope);
} else {
waitForNavigationUiObject("back").click();
@@ -1589,18 +1609,33 @@ public final class LauncherInstrumentation {
// Inject a swipe gesture. Inject exactly 'steps' motion points, incrementing event time by a
// fixed interval each time.
public void linearGesture(int startX, int startY, int endX, int endY, int steps,
boolean slowDown,
GestureScope gestureScope) {
boolean slowDown, GestureScope gestureScope) {
log("linearGesture: " + startX + ", " + startY + " -> " + endX + ", " + endY);
final long downTime = SystemClock.uptimeMillis();
final Point start = new Point(startX, startY);
final Point end = new Point(endX, endY);
sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
if (mSwipeFromTrackpad) {
sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 1),
start, gestureScope);
sendPointer(downTime, downTime, getPointerAction(MotionEvent.ACTION_POINTER_DOWN, 2),
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);
}
sendPointer(downTime, endTime, MotionEvent.ACTION_UP, end, gestureScope);
}
private static int getPointerAction(int action, int index) {
return action + (index << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
}
long movePointer(Point start, Point end, int steps, boolean isDecelerating, long downTime,
long startTime, boolean slowDown, GestureScope gestureScope) {
long endTime = movePointer(downTime, startTime, steps * GESTURE_STEP_MS,
@@ -1624,22 +1659,44 @@ public final class LauncherInstrumentation {
return getContext().getResources();
}
private static MotionEvent getTrackpadThreeFingerMotionEvent(long downTime, long eventTime,
int action, float x, float y, int pointerCount) {
MotionEvent.PointerProperties[] pointerProperties =
new MotionEvent.PointerProperties[pointerCount];
MotionEvent.PointerCoords[] pointerCoords = new MotionEvent.PointerCoords[pointerCount];
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);
}
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);
}
private static MotionEvent getMotionEvent(long downTime, long eventTime, int action,
float x, float y) {
MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
properties.id = 0;
properties.toolType = Configurator.getInstance().getToolType();
return MotionEvent.obtain(downTime, eventTime, action, 1,
new MotionEvent.PointerProperties[] {getPointerProperties(0)},
new MotionEvent.PointerCoords[] {getPointerCoords(x, y)},
0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
}
private static MotionEvent.PointerProperties getPointerProperties(int pointerId) {
MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties();
properties.id = pointerId;
properties.toolType = Configurator.getInstance().getToolType();
return properties;
}
private static MotionEvent.PointerCoords getPointerCoords(float x, float y) {
MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
coords.pressure = 1;
coords.size = 1;
coords.x = x;
coords.y = y;
return MotionEvent.obtain(downTime, eventTime, action, 1,
new MotionEvent.PointerProperties[]{properties},
new MotionEvent.PointerCoords[]{coords},
0, 0, 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);
return coords;
}
private boolean hasTIS() {
@@ -1655,17 +1712,23 @@ public final class LauncherInstrumentation {
public void sendPointer(long downTime, long currentTime, int action, Point point,
GestureScope gestureScope) {
final boolean hasTIS = hasTIS();
switch (action) {
int pointerCount = 1;
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) {
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
&& !mSwipeFromTrackpad) {
expectEvent(TestProtocol.SEQUENCE_MAIN, EVENT_TOUCH_DOWN);
}
if (hasTIS && (isTrackpadGestureEnabled()
|| getNavigationModel() != NavigationModel.THREE_BUTTON)) {
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_TOUCH_DOWN_TIS);
}
if (mSwipeFromTrackpad) {
mPointerCount = 1;
}
break;
case MotionEvent.ACTION_UP:
if (hasTIS && gestureScope != GestureScope.INSIDE
@@ -1676,7 +1739,8 @@ public final class LauncherInstrumentation {
}
if (gestureScope != GestureScope.OUTSIDE_WITH_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITHOUT_PILFER
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE) {
&& gestureScope != GestureScope.OUTSIDE_WITH_KEYCODE
&& !mSwipeFromTrackpad) {
expectEvent(TestProtocol.SEQUENCE_MAIN,
gestureScope == GestureScope.INSIDE
|| gestureScope == GestureScope.OUTSIDE_WITHOUT_PILFER
@@ -1696,9 +1760,29 @@ public final class LauncherInstrumentation {
case MotionEvent.ACTION_HOVER_EXIT:
expectEvent(TestProtocol.SEQUENCE_TIS, EVENT_HOVER_EXIT_TIS);
break;
case MotionEvent.ACTION_POINTER_DOWN:
mPointerCount++;
expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
"ACTION_POINTER_DOWN", mPointerCount));
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) {
expectEvent(TestProtocol.SEQUENCE_TIS, getTouchEventPatternTIS(
"ACTION_POINTER_UP", mPointerCount));
}
mPointerCount--;
break;
}
final MotionEvent event = getMotionEvent(downTime, currentTime, action, point.x, point.y);
final MotionEvent event = mSwipeFromTrackpad
? getTrackpadThreeFingerMotionEvent(
downTime, currentTime, action, point.x, point.y, pointerCount)
: getMotionEvent(downTime, currentTime, action, point.x, point.y);
assertTrue("injectInputEvent failed",
mInstrumentation.getUiAutomation().injectInputEvent(event, true, false));
event.recycle();
@@ -1706,8 +1790,7 @@ public final class LauncherInstrumentation {
public long movePointer(long downTime, long startTime, long duration, Point from, Point to,
GestureScope gestureScope) {
return movePointer(
downTime, startTime, duration, false, from, to, gestureScope);
return movePointer(downTime, startTime, duration, false, from, to, gestureScope);
}
public long movePointer(long downTime, long startTime, long duration, boolean isDecelerating,