blob: b7079124fb7963506db3339e03234672c3018c70 [file] [log] [blame]
Chad Brower6029cae2017-01-18 15:29:33 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Ameer Armaly9339c592019-07-23 13:43:09 -070017package com.android.server.accessibility.gestures;
Chad Brower6029cae2017-01-18 15:29:33 -080018
RyanlwLina0daddd2019-06-19 11:39:01 +080019import static org.mockito.ArgumentMatchers.argThat;
Chad Brower6029cae2017-01-18 15:29:33 -080020import static org.mockito.Mockito.mock;
21import static org.mockito.Mockito.reset;
Chad Brower6029cae2017-01-18 15:29:33 -080022import static org.mockito.Mockito.verify;
Dieter Hsua7fa8142018-08-29 19:48:42 +080023import static org.mockito.Mockito.when;
Chad Brower6029cae2017-01-18 15:29:33 -080024
25import android.accessibilityservice.AccessibilityService;
26import android.content.Context;
27import android.content.res.Resources;
28import android.graphics.Point;
29import android.graphics.PointF;
Chad Brower6029cae2017-01-18 15:29:33 -080030import android.util.DisplayMetrics;
31import android.view.GestureDetector;
32import android.view.MotionEvent;
Dieter Hsua7fa8142018-08-29 19:48:42 +080033
Chad Brower6029cae2017-01-18 15:29:33 -080034import org.junit.Before;
Chad Brower6029cae2017-01-18 15:29:33 -080035import org.junit.Test;
36
Dieter Hsua7fa8142018-08-29 19:48:42 +080037import java.util.ArrayList;
Chad Brower6029cae2017-01-18 15:29:33 -080038
39/**
40 * Tests for AccessibilityGestureDetector
41 */
42public class AccessibilityGestureDetectorTest {
43
44 // Constants for testRecognizeGesturePath()
45 private static final PointF PATH_START = new PointF(300f, 300f);
46 private static final int PATH_STEP_PIXELS = 200;
47 private static final long PATH_STEP_MILLISEC = 100;
48
Chad Brower6029cae2017-01-18 15:29:33 -080049 // Data used by all tests
Dieter Hsu01f426f2018-08-09 01:45:39 +080050 private AccessibilityGestureDetector mDetector;
Chad Brower6029cae2017-01-18 15:29:33 -080051 private AccessibilityGestureDetector.Listener mResultListener;
52
Chad Brower6029cae2017-01-18 15:29:33 -080053 @Before
54 public void setUp() {
55 // Construct a mock Context.
56 DisplayMetrics displayMetricsMock = mock(DisplayMetrics.class);
57 displayMetricsMock.xdpi = 500;
58 displayMetricsMock.ydpi = 500;
59 Resources mockResources = mock(Resources.class);
60 when(mockResources.getDisplayMetrics()).thenReturn(displayMetricsMock);
61 Context contextMock = mock(Context.class);
Chad Brower6029cae2017-01-18 15:29:33 -080062 when(contextMock.getResources()).thenReturn(mockResources);
63
64 // Construct a testable AccessibilityGestureDetector.
65 mResultListener = mock(AccessibilityGestureDetector.Listener.class);
Chad Brower6029cae2017-01-18 15:29:33 -080066 GestureDetector doubleTapDetectorMock = mock(GestureDetector.class);
Dieter Hsu01f426f2018-08-09 01:45:39 +080067 mDetector = new AccessibilityGestureDetector(contextMock, mResultListener, doubleTapDetectorMock);
Chad Brower6029cae2017-01-18 15:29:33 -080068 }
69
70
71 @Test
72 public void testRecognizeGesturePath() {
73 final int d = 1000; // Length of each segment in the test gesture, in pixels.
74
75 testPath(p(-d, +0), AccessibilityService.GESTURE_SWIPE_LEFT);
76 testPath(p(+d, +0), AccessibilityService.GESTURE_SWIPE_RIGHT);
77 testPath(p(+0, -d), AccessibilityService.GESTURE_SWIPE_UP);
78 testPath(p(+0, +d), AccessibilityService.GESTURE_SWIPE_DOWN);
79
80 testPath(p(-d, +0), p((-d - d), +0), AccessibilityService.GESTURE_SWIPE_LEFT);
81 testPath(p(-d, +0), p(+0, +0), AccessibilityService.GESTURE_SWIPE_LEFT_AND_RIGHT);
82 testPath(p(-d, +0), p(-d, -d), AccessibilityService.GESTURE_SWIPE_LEFT_AND_UP);
83 testPath(p(-d, +0), p(-d, +d), AccessibilityService.GESTURE_SWIPE_LEFT_AND_DOWN);
84
85 testPath(p(+d, +0), p(+0, +0), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_LEFT);
86 testPath(p(+d, +0), p((+d + d), +0), AccessibilityService.GESTURE_SWIPE_RIGHT);
87 testPath(p(+d, +0), p(+d, -d), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP);
88 testPath(p(+d, +0), p(+d, +d), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_DOWN);
89
90 testPath(p(+0, -d), p(-d, -d), AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT);
91 testPath(p(+0, -d), p(+d, -d), AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT);
92 testPath(p(+0, -d), p(+0, (-d - d)), AccessibilityService.GESTURE_SWIPE_UP);
93 testPath(p(+0, -d), p(+0, +0), AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN);
94
95 testPath(p(+0, +d), p(-d, +d), AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT);
96 testPath(p(+0, +d), p(+d, +d), AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT);
97 testPath(p(+0, +d), p(+0, +0), AccessibilityService.GESTURE_SWIPE_DOWN_AND_UP);
98 testPath(p(+0, +d), p(+0, (+d + d)), AccessibilityService.GESTURE_SWIPE_DOWN);
99 }
100
101 /** Convenient short alias to make a Point. */
102 private static Point p(int x, int y) {
103 return new Point(x, y);
104 }
105
106 /** Test recognizing path from PATH_START to PATH_START+delta. */
107 private void testPath(Point delta, int gestureId) {
108 ArrayList<PointF> path = new ArrayList<>();
109 path.add(PATH_START);
110
111 PointF segmentEnd = new PointF(PATH_START.x + delta.x, PATH_START.y + delta.y);
112 fillPath(PATH_START, segmentEnd, path);
113
114 testPath(path, gestureId);
115 }
116
117 /** Test recognizing path from PATH_START to PATH_START+delta1 to PATH_START+delta2. */
118 private void testPath(Point delta1, Point delta2, int gestureId) {
119 ArrayList<PointF> path = new ArrayList<>();
120 path.add(PATH_START);
121
122 PointF startPlusDelta1 = new PointF(PATH_START.x + delta1.x, PATH_START.y + delta1.y);
123 fillPath(PATH_START, startPlusDelta1, path);
124
125 PointF startPlusDelta2 = new PointF(PATH_START.x + delta2.x, PATH_START.y + delta2.y);
126 fillPath(startPlusDelta1, startPlusDelta2, path);
127
128 testPath(path, gestureId);
129 }
130
131 /** Fill in movement points from start to end, appending points to path. */
132 private void fillPath(PointF start, PointF end, ArrayList<PointF> path) {
133 // Calculate number of path steps needed.
134 float deltaX = end.x - start.x;
135 float deltaY = end.y - start.y;
136 float distance = (float) Math.hypot(deltaX, deltaY);
137 float numSteps = distance / (float) PATH_STEP_PIXELS;
138 float stepX = (float) deltaX / numSteps;
139 float stepY = (float) deltaY / numSteps;
140
141 // For each path step from start (non-inclusive) to end ... add a motion point.
142 for (int step = 1; step < numSteps; ++step) {
143 path.add(new PointF(
144 (start.x + (stepX * (float) step)),
145 (start.y + (stepY * (float) step))));
146 }
147 }
148
149 /** Test recognizing a path made of motion event points. */
150 private void testPath(ArrayList<PointF> path, int gestureId) {
151 // Clear last recognition result.
152 reset(mResultListener);
153
154 int policyFlags = 0;
155 long eventDownTimeMs = 0;
156 long eventTimeMs = eventDownTimeMs;
157
158 // For each path point...
159 for (int pointIndex = 0; pointIndex < path.size(); ++pointIndex) {
160
161 // Create motion event.
162 PointF point = path.get(pointIndex);
163 int action = MotionEvent.ACTION_MOVE;
164 if (pointIndex == 0) {
165 action = MotionEvent.ACTION_DOWN;
166 } else if (pointIndex == path.size() - 1) {
167 action = MotionEvent.ACTION_UP;
168 }
169 MotionEvent event = MotionEvent.obtain(eventDownTimeMs, eventTimeMs, action,
170 point.x, point.y, 0);
171
172 // Send event.
Jackal Guo79ea4822018-07-13 16:09:09 +0800173 mDetector.onMotionEvent(event, event, policyFlags);
Chad Brower6029cae2017-01-18 15:29:33 -0800174 eventTimeMs += PATH_STEP_MILLISEC;
175 }
176
177 // Check that correct gesture was recognized.
RyanlwLina0daddd2019-06-19 11:39:01 +0800178 verify(mResultListener).onGestureCompleted(
RyanlwLin0d17f042019-09-02 21:22:09 +0800179 argThat(gestureEvent -> gestureEvent.getGestureId() == gestureId));
Chad Brower6029cae2017-01-18 15:29:33 -0800180 }
181}