• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.accessibility;
18 
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.reset;
21 import static org.mockito.Mockito.verify;
22 import static org.mockito.Mockito.when;
23 
24 import android.accessibilityservice.AccessibilityService;
25 import android.content.Context;
26 import android.content.res.Resources;
27 import android.graphics.Point;
28 import android.graphics.PointF;
29 import android.util.DisplayMetrics;
30 import android.view.GestureDetector;
31 import android.view.MotionEvent;
32 
33 import org.junit.Before;
34 import org.junit.Test;
35 
36 import java.util.ArrayList;
37 
38 /**
39  * Tests for AccessibilityGestureDetector
40  */
41 public class AccessibilityGestureDetectorTest {
42 
43     // Constants for testRecognizeGesturePath()
44     private static final PointF PATH_START = new PointF(300f, 300f);
45     private static final int PATH_STEP_PIXELS = 200;
46     private static final long PATH_STEP_MILLISEC = 100;
47 
48     // Data used by all tests
49     private AccessibilityGestureDetector mDetector;
50     private AccessibilityGestureDetector.Listener mResultListener;
51 
52     @Before
setUp()53     public void setUp() {
54         // Construct a mock Context.
55         DisplayMetrics displayMetricsMock = mock(DisplayMetrics.class);
56         displayMetricsMock.xdpi = 500;
57         displayMetricsMock.ydpi = 500;
58         Resources mockResources = mock(Resources.class);
59         when(mockResources.getDisplayMetrics()).thenReturn(displayMetricsMock);
60         Context contextMock = mock(Context.class);
61         when(contextMock.getResources()).thenReturn(mockResources);
62 
63         // Construct a testable AccessibilityGestureDetector.
64         mResultListener = mock(AccessibilityGestureDetector.Listener.class);
65         GestureDetector doubleTapDetectorMock = mock(GestureDetector.class);
66         mDetector = new AccessibilityGestureDetector(contextMock, mResultListener, doubleTapDetectorMock);
67     }
68 
69 
70     @Test
testRecognizeGesturePath()71     public void testRecognizeGesturePath() {
72         final int d = 1000;  // Length of each segment in the test gesture, in pixels.
73 
74         testPath(p(-d, +0), AccessibilityService.GESTURE_SWIPE_LEFT);
75         testPath(p(+d, +0), AccessibilityService.GESTURE_SWIPE_RIGHT);
76         testPath(p(+0, -d), AccessibilityService.GESTURE_SWIPE_UP);
77         testPath(p(+0, +d), AccessibilityService.GESTURE_SWIPE_DOWN);
78 
79         testPath(p(-d, +0), p((-d - d), +0), AccessibilityService.GESTURE_SWIPE_LEFT);
80         testPath(p(-d, +0), p(+0, +0), AccessibilityService.GESTURE_SWIPE_LEFT_AND_RIGHT);
81         testPath(p(-d, +0), p(-d, -d), AccessibilityService.GESTURE_SWIPE_LEFT_AND_UP);
82         testPath(p(-d, +0), p(-d, +d), AccessibilityService.GESTURE_SWIPE_LEFT_AND_DOWN);
83 
84         testPath(p(+d, +0), p(+0, +0), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_LEFT);
85         testPath(p(+d, +0), p((+d + d), +0), AccessibilityService.GESTURE_SWIPE_RIGHT);
86         testPath(p(+d, +0), p(+d, -d), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_UP);
87         testPath(p(+d, +0), p(+d, +d), AccessibilityService.GESTURE_SWIPE_RIGHT_AND_DOWN);
88 
89         testPath(p(+0, -d), p(-d, -d), AccessibilityService.GESTURE_SWIPE_UP_AND_LEFT);
90         testPath(p(+0, -d), p(+d, -d), AccessibilityService.GESTURE_SWIPE_UP_AND_RIGHT);
91         testPath(p(+0, -d), p(+0, (-d - d)), AccessibilityService.GESTURE_SWIPE_UP);
92         testPath(p(+0, -d), p(+0, +0), AccessibilityService.GESTURE_SWIPE_UP_AND_DOWN);
93 
94         testPath(p(+0, +d), p(-d, +d), AccessibilityService.GESTURE_SWIPE_DOWN_AND_LEFT);
95         testPath(p(+0, +d), p(+d, +d), AccessibilityService.GESTURE_SWIPE_DOWN_AND_RIGHT);
96         testPath(p(+0, +d), p(+0, +0), AccessibilityService.GESTURE_SWIPE_DOWN_AND_UP);
97         testPath(p(+0, +d), p(+0, (+d + d)), AccessibilityService.GESTURE_SWIPE_DOWN);
98     }
99 
100     /** Convenient short alias to make a Point. */
p(int x, int y)101     private static Point p(int x, int y) {
102         return new Point(x, y);
103     }
104 
105     /** Test recognizing path from PATH_START to PATH_START+delta. */
testPath(Point delta, int gestureId)106     private void testPath(Point delta, int gestureId) {
107         ArrayList<PointF> path = new ArrayList<>();
108         path.add(PATH_START);
109 
110         PointF segmentEnd = new PointF(PATH_START.x + delta.x, PATH_START.y + delta.y);
111         fillPath(PATH_START, segmentEnd, path);
112 
113         testPath(path, gestureId);
114     }
115 
116     /** Test recognizing path from PATH_START to PATH_START+delta1 to PATH_START+delta2. */
testPath(Point delta1, Point delta2, int gestureId)117     private void testPath(Point delta1, Point delta2, int gestureId) {
118         ArrayList<PointF> path = new ArrayList<>();
119         path.add(PATH_START);
120 
121         PointF startPlusDelta1 = new PointF(PATH_START.x + delta1.x, PATH_START.y + delta1.y);
122         fillPath(PATH_START, startPlusDelta1, path);
123 
124         PointF startPlusDelta2 = new PointF(PATH_START.x + delta2.x, PATH_START.y + delta2.y);
125         fillPath(startPlusDelta1, startPlusDelta2, path);
126 
127         testPath(path, gestureId);
128     }
129 
130     /** Fill in movement points from start to end, appending points to path. */
fillPath(PointF start, PointF end, ArrayList<PointF> path)131     private void fillPath(PointF start, PointF end, ArrayList<PointF> path) {
132         // Calculate number of path steps needed.
133         float deltaX = end.x - start.x;
134         float deltaY = end.y - start.y;
135         float distance = (float) Math.hypot(deltaX, deltaY);
136         float numSteps = distance / (float) PATH_STEP_PIXELS;
137         float stepX = (float) deltaX / numSteps;
138         float stepY = (float) deltaY / numSteps;
139 
140         // For each path step from start (non-inclusive) to end ... add a motion point.
141         for (int step = 1; step < numSteps; ++step) {
142             path.add(new PointF(
143                 (start.x + (stepX * (float) step)),
144                 (start.y + (stepY * (float) step))));
145         }
146     }
147 
148     /** Test recognizing a path made of motion event points. */
testPath(ArrayList<PointF> path, int gestureId)149     private void testPath(ArrayList<PointF> path, int gestureId) {
150         // Clear last recognition result.
151         reset(mResultListener);
152 
153         int policyFlags = 0;
154         long eventDownTimeMs = 0;
155         long eventTimeMs = eventDownTimeMs;
156 
157         // For each path point...
158         for (int pointIndex = 0; pointIndex < path.size(); ++pointIndex) {
159 
160             // Create motion event.
161             PointF point = path.get(pointIndex);
162             int action = MotionEvent.ACTION_MOVE;
163             if (pointIndex == 0) {
164                 action = MotionEvent.ACTION_DOWN;
165             } else if (pointIndex == path.size() - 1) {
166                 action = MotionEvent.ACTION_UP;
167             }
168             MotionEvent event = MotionEvent.obtain(eventDownTimeMs, eventTimeMs, action,
169                     point.x, point.y, 0);
170 
171             // Send event.
172             mDetector.onMotionEvent(event, event, policyFlags);
173             eventTimeMs += PATH_STEP_MILLISEC;
174         }
175 
176         // Check that correct gesture was recognized.
177         verify(mResultListener).onGestureCompleted(gestureId);
178     }
179 }
180