blob: 5f0fa874b7dac8658c6e404a77f3123a7e175f35 [file] [log] [blame]
Phil Weavera7dcedc2016-07-15 08:40:37 -07001/*
2 * Copyright (C) 2016 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
17package com.android.server.accessibility;
18
Phil Weaver2f165942016-09-21 11:18:05 -070019import static android.view.MotionEvent.ACTION_DOWN;
20import static android.view.MotionEvent.ACTION_UP;
Adrian Roose99bc052017-11-20 17:55:31 +010021import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER;
Bill Peckhama74879d2018-09-08 10:06:40 -070022
Phil Weaver2f165942016-09-21 11:18:05 -070023import static org.hamcrest.CoreMatchers.allOf;
24import static org.hamcrest.CoreMatchers.anyOf;
25import static org.hamcrest.CoreMatchers.everyItem;
26import static org.hamcrest.MatcherAssert.assertThat;
Phil Weavera7dcedc2016-07-15 08:40:37 -070027import static org.junit.Assert.assertEquals;
28import static org.junit.Assert.assertFalse;
29import static org.junit.Assert.assertTrue;
Phil Weaver2f165942016-09-21 11:18:05 -070030import static org.mockito.Matchers.anyBoolean;
Phil Weavera7dcedc2016-07-15 08:40:37 -070031import static org.mockito.Matchers.anyInt;
Phil Weavera7dcedc2016-07-15 08:40:37 -070032import static org.mockito.Matchers.eq;
33import static org.mockito.Mockito.mock;
34import static org.mockito.Mockito.reset;
35import static org.mockito.Mockito.times;
36import static org.mockito.Mockito.verify;
37import static org.mockito.Mockito.verifyNoMoreInteractions;
38import static org.mockito.Mockito.verifyZeroInteractions;
Paul Duffin192bb0b2017-03-09 18:49:41 +000039import static org.mockito.hamcrest.MockitoHamcrest.argThat;
Phil Weavera7dcedc2016-07-15 08:40:37 -070040
Phil Weaver2f165942016-09-21 11:18:05 -070041import android.accessibilityservice.GestureDescription.GestureStep;
42import android.accessibilityservice.GestureDescription.TouchPoint;
Phil Weavera7dcedc2016-07-15 08:40:37 -070043import android.accessibilityservice.IAccessibilityServiceClient;
Phil Weaver2f165942016-09-21 11:18:05 -070044import android.graphics.Point;
Phil Weavera7dcedc2016-07-15 08:40:37 -070045import android.os.Handler;
46import android.os.Looper;
47import android.os.Message;
48import android.os.RemoteException;
Phil Weavera7dcedc2016-07-15 08:40:37 -070049import android.util.Log;
Phil Weavera7dcedc2016-07-15 08:40:37 -070050import android.view.InputDevice;
51import android.view.KeyEvent;
52import android.view.MotionEvent;
Phil Weavera7dcedc2016-07-15 08:40:37 -070053import android.view.accessibility.AccessibilityEvent;
Bill Peckhama74879d2018-09-08 10:06:40 -070054
55import androidx.test.runner.AndroidJUnit4;
56
Phil Weaver2f165942016-09-21 11:18:05 -070057import org.hamcrest.Description;
58import org.hamcrest.Matcher;
59import org.hamcrest.TypeSafeMatcher;
Phil Weavera7dcedc2016-07-15 08:40:37 -070060import org.junit.Before;
61import org.junit.BeforeClass;
62import org.junit.Test;
63import org.junit.runner.RunWith;
64import org.mockito.ArgumentCaptor;
Phil Weavera7dcedc2016-07-15 08:40:37 -070065
Bill Peckhama74879d2018-09-08 10:06:40 -070066import java.util.ArrayList;
67import java.util.Arrays;
68import java.util.List;
69
Phil Weavera7dcedc2016-07-15 08:40:37 -070070/**
71 * Tests for MotionEventInjector
72 */
73@RunWith(AndroidJUnit4.class)
74public class MotionEventInjectorTest {
75 private static final String LOG_TAG = "MotionEventInjectorTest";
Phil Weaver2f165942016-09-21 11:18:05 -070076 private static final Matcher<MotionEvent> IS_ACTION_DOWN =
77 new MotionEventActionMatcher(ACTION_DOWN);
78 private static final Matcher<MotionEvent> IS_ACTION_POINTER_DOWN =
79 new MotionEventActionMatcher(MotionEvent.ACTION_POINTER_DOWN);
80 private static final Matcher<MotionEvent> IS_ACTION_UP =
81 new MotionEventActionMatcher(ACTION_UP);
82 private static final Matcher<MotionEvent> IS_ACTION_POINTER_UP =
83 new MotionEventActionMatcher(MotionEvent.ACTION_POINTER_UP);
84 private static final Matcher<MotionEvent> IS_ACTION_CANCEL =
85 new MotionEventActionMatcher(MotionEvent.ACTION_CANCEL);
86 private static final Matcher<MotionEvent> IS_ACTION_MOVE =
87 new MotionEventActionMatcher(MotionEvent.ACTION_MOVE);
Phil Weavera7dcedc2016-07-15 08:40:37 -070088
Phil Weaver2f165942016-09-21 11:18:05 -070089 private static final Point LINE_START = new Point(100, 200);
90 private static final Point LINE_END = new Point(100, 300);
91 private static final int LINE_DURATION = 100;
92 private static final int LINE_SEQUENCE = 50;
93
94 private static final Point CLICK_POINT = new Point(1000, 2000);
95 private static final int CLICK_DURATION = 10;
96 private static final int CLICK_SEQUENCE = 51;
Phil Weavera7dcedc2016-07-15 08:40:37 -070097
98 private static final int MOTION_EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN;
99 private static final int OTHER_EVENT_SOURCE = InputDevice.SOURCE_MOUSE;
100
Phil Weaver2f165942016-09-21 11:18:05 -0700101 private static final Point CONTINUED_LINE_START = new Point(500, 300);
102 private static final Point CONTINUED_LINE_MID1 = new Point(500, 400);
103 private static final Point CONTINUED_LINE_MID2 = new Point(600, 300);
104 private static final Point CONTINUED_LINE_END = new Point(600, 400);
105 private static final int CONTINUED_LINE_STROKE_ID_1 = 100;
106 private static final int CONTINUED_LINE_STROKE_ID_2 = 101;
107 private static final int CONTINUED_LINE_INTERVAL = 100;
108 private static final int CONTINUED_LINE_SEQUENCE_1 = 52;
109 private static final int CONTINUED_LINE_SEQUENCE_2 = 53;
110
Phil Weavera7dcedc2016-07-15 08:40:37 -0700111 MotionEventInjector mMotionEventInjector;
112 IAccessibilityServiceClient mServiceInterface;
Phil Weaver2f165942016-09-21 11:18:05 -0700113 List<GestureStep> mLineList = new ArrayList<>();
114 List<GestureStep> mClickList = new ArrayList<>();
115 List<GestureStep> mContinuedLineList1 = new ArrayList<>();
116 List<GestureStep> mContinuedLineList2 = new ArrayList<>();
117
118 MotionEvent mClickDownEvent;
119 MotionEvent mClickUpEvent;
120
Phil Weavera7dcedc2016-07-15 08:40:37 -0700121 ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
122 ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
123 MessageCapturingHandler mMessageCapturingHandler;
Phil Weaver2f165942016-09-21 11:18:05 -0700124 Matcher<MotionEvent> mIsLineStart;
125 Matcher<MotionEvent> mIsLineMiddle;
126 Matcher<MotionEvent> mIsLineEnd;
127 Matcher<MotionEvent> mIsClickDown;
128 Matcher<MotionEvent> mIsClickUp;
Phil Weavera7dcedc2016-07-15 08:40:37 -0700129
130 @BeforeClass
131 public static void oneTimeInitialization() {
132 if (Looper.myLooper() == null) {
133 Looper.prepare();
134 }
135 }
136
137 @Before
138 public void setUp() {
Phil Weaver89e3ffc2016-09-19 13:51:10 -0700139 mMessageCapturingHandler = new MessageCapturingHandler(new Handler.Callback() {
140 @Override
141 public boolean handleMessage(Message msg) {
142 return mMotionEventInjector.handleMessage(msg);
143 }
144 });
Phil Weavera7dcedc2016-07-15 08:40:37 -0700145 mMotionEventInjector = new MotionEventInjector(mMessageCapturingHandler);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700146 mServiceInterface = mock(IAccessibilityServiceClient.class);
Phil Weaver2f165942016-09-21 11:18:05 -0700147
148 mLineList = createSimpleGestureFromPoints(0, 0, false, LINE_DURATION, LINE_START, LINE_END);
149 mClickList = createSimpleGestureFromPoints(
150 0, 0, false, CLICK_DURATION, CLICK_POINT, CLICK_POINT);
151 mContinuedLineList1 = createSimpleGestureFromPoints(CONTINUED_LINE_STROKE_ID_1, 0, true,
152 CONTINUED_LINE_INTERVAL, CONTINUED_LINE_START, CONTINUED_LINE_MID1);
153 mContinuedLineList2 = createSimpleGestureFromPoints(CONTINUED_LINE_STROKE_ID_2,
154 CONTINUED_LINE_STROKE_ID_1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1,
155 CONTINUED_LINE_MID2, CONTINUED_LINE_END);
156
157 mClickDownEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, CLICK_POINT.x, CLICK_POINT.y, 0);
158 mClickDownEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
159 mClickUpEvent = MotionEvent.obtain(0, CLICK_DURATION, ACTION_UP, CLICK_POINT.x,
160 CLICK_POINT.y, 0);
161 mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
162
163 mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
164 hasTimeFromDown(0));
165 mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
166 hasTimeFromDown(LINE_DURATION));
167 mIsLineEnd = allOf(IS_ACTION_UP, isAtPoint(LINE_END), hasStandardInitialization(),
168 hasTimeFromDown(LINE_DURATION));
169 mIsClickDown = allOf(IS_ACTION_DOWN, isAtPoint(CLICK_POINT), hasStandardInitialization(),
170 hasTimeFromDown(0));
171 mIsClickUp = allOf(IS_ACTION_UP, isAtPoint(CLICK_POINT), hasStandardInitialization(),
172 hasTimeFromDown(CLICK_DURATION));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700173 }
174
175 @Test
176 public void testInjectEvents_shouldEmergeInOrderWithCorrectTiming() throws RemoteException {
177 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700178 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700179 verifyNoMoreInteractions(next);
180 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
181
Phil Weaver2f165942016-09-21 11:18:05 -0700182 verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER));
183 verify(next).onMotionEvent(argThat(mIsLineStart), argThat(mIsLineStart),
184 eq(FLAG_PASS_TO_USER));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700185 verifyNoMoreInteractions(next);
186 reset(next);
187
Phil Weaver2f165942016-09-21 11:18:05 -0700188 Matcher<MotionEvent> hasRightDownTime = hasDownTime(mCaptor1.getValue().getDownTime());
189
Phil Weavera7dcedc2016-07-15 08:40:37 -0700190 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
Phil Weaver2f165942016-09-21 11:18:05 -0700191 verify(next).onMotionEvent(argThat(allOf(mIsLineMiddle, hasRightDownTime)),
192 argThat(allOf(mIsLineMiddle, hasRightDownTime)), eq(FLAG_PASS_TO_USER));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700193 verifyNoMoreInteractions(next);
194 reset(next);
195
196 verifyZeroInteractions(mServiceInterface);
197
198 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
Phil Weaver2f165942016-09-21 11:18:05 -0700199 verify(next).onMotionEvent(argThat(allOf(mIsLineEnd, hasRightDownTime)),
200 argThat(allOf(mIsLineEnd, hasRightDownTime)), eq(FLAG_PASS_TO_USER));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700201 verifyNoMoreInteractions(next);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700202
Phil Weaver2f165942016-09-21 11:18:05 -0700203 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700204 verifyNoMoreInteractions(mServiceInterface);
205 }
206
207 @Test
Phil Weaver2f165942016-09-21 11:18:05 -0700208 public void testInjectEvents_gestureWithTooManyPoints_shouldNotCrash() throws Exception {
209 int tooManyPointsCount = 20;
210 TouchPoint[] startTouchPoints = new TouchPoint[tooManyPointsCount];
211 TouchPoint[] endTouchPoints = new TouchPoint[tooManyPointsCount];
212 for (int i = 0; i < tooManyPointsCount; i++) {
213 startTouchPoints[i] = new TouchPoint();
214 startTouchPoints[i].mIsStartOfPath = true;
215 startTouchPoints[i].mX = i;
216 startTouchPoints[i].mY = i;
217 endTouchPoints[i] = new TouchPoint();
218 endTouchPoints[i].mIsEndOfPath = true;
219 endTouchPoints[i].mX = i;
220 endTouchPoints[i].mY = i;
Phil Weavera7dcedc2016-07-15 08:40:37 -0700221 }
Phil Weaver2f165942016-09-21 11:18:05 -0700222 List<GestureStep> events = Arrays.asList(
223 new GestureStep(0, tooManyPointsCount, startTouchPoints),
224 new GestureStep(CLICK_DURATION, tooManyPointsCount, endTouchPoints));
225 attachMockNext(mMotionEventInjector);
226 injectEventsSync(events, mServiceInterface, CLICK_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700227 mMessageCapturingHandler.sendAllMessages();
Phil Weaver2f165942016-09-21 11:18:05 -0700228 verify(mServiceInterface).onPerformGestureResult(eq(CLICK_SEQUENCE), anyBoolean());
Phil Weavera7dcedc2016-07-15 08:40:37 -0700229 }
230
231 @Test
232 public void testRegularEvent_afterGestureComplete_shouldPassToNext() {
233 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700234 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700235 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
236 reset(next);
Phil Weaver2f165942016-09-21 11:18:05 -0700237 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
238 verify(next).onMotionEvent(argThat(mIsClickDown), argThat(mIsClickDown), eq(0));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700239 }
240
241 @Test
242 public void testInjectEvents_withRealGestureUnderway_shouldCancelRealAndPassInjected() {
243 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700244 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
245 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700246
247 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700248 assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
249 assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700250 reset(next);
251
252 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
Phil Weaver2f165942016-09-21 11:18:05 -0700253 verify(next).onMotionEvent(
254 argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700255 }
256
257 @Test
258 public void testInjectEvents_withRealMouseGestureUnderway_shouldContinueRealAndPassInjected() {
259 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700260 MotionEvent mouseEvent = MotionEvent.obtain(mClickDownEvent);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700261 mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
Phil Weaver2f165942016-09-21 11:18:05 -0700262 MotionEventMatcher isMouseEvent = new MotionEventMatcher(mouseEvent);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700263 mMotionEventInjector.onMotionEvent(mouseEvent, mouseEvent, 0);
Phil Weaver2f165942016-09-21 11:18:05 -0700264 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700265
266 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
267 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700268 assertThat(mCaptor1.getAllValues().get(0), isMouseEvent);
269 assertThat(mCaptor1.getAllValues().get(1), mIsLineStart);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700270 }
271
272 @Test
273 public void testInjectEvents_withRealGestureFinished_shouldJustPassInjected() {
274 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700275 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
276 mMotionEventInjector.onMotionEvent(mClickUpEvent, mClickUpEvent, 0);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700277
Phil Weaver2f165942016-09-21 11:18:05 -0700278 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
279 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
280 assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
281 assertThat(mCaptor1.getAllValues().get(1), mIsClickUp);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700282 reset(next);
283
284 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
Phil Weaver2f165942016-09-21 11:18:05 -0700285 verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), eq(FLAG_PASS_TO_USER));
286 verify(next).onMotionEvent(
287 argThat(mIsLineStart), argThat(mIsLineStart), eq(FLAG_PASS_TO_USER));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700288 }
289
290 @Test
291 public void testOnMotionEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassReal()
292 throws RemoteException {
293 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700294 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700295 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
Phil Weaver2f165942016-09-21 11:18:05 -0700296 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700297
298 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700299 assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
300 assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
301 assertThat(mCaptor1.getAllValues().get(2), mIsClickDown);
302 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700303 }
304
305 @Test
306 public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
307 throws RemoteException {
308 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700309 // Tack a click down to the end of the line
310 TouchPoint clickTouchPoint = new TouchPoint();
311 clickTouchPoint.mIsStartOfPath = true;
312 clickTouchPoint.mX = CLICK_POINT.x;
313 clickTouchPoint.mY = CLICK_POINT.y;
314 mLineList.add(new GestureStep(0, 1, new TouchPoint[] {clickTouchPoint}));
315
316 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700317
318 // Send 3 motion events, leaving the extra down in the queue
319 mMessageCapturingHandler.sendOneMessage();
320 mMessageCapturingHandler.sendOneMessage();
321 mMessageCapturingHandler.sendOneMessage();
322
Phil Weaver2f165942016-09-21 11:18:05 -0700323 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700324
325 verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700326 assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
327 assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
328 assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
329 assertThat(mCaptor1.getAllValues().get(3), mIsClickDown);
330 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700331 assertFalse(mMessageCapturingHandler.hasMessages());
332 }
333
334 @Test
335 public void testInjectEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassNew()
336 throws RemoteException {
337 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700338 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700339 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
340
Phil Weaver2f165942016-09-21 11:18:05 -0700341 injectEventsSync(mClickList, mServiceInterface, CLICK_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700342 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
343
Phil Weaver2f165942016-09-21 11:18:05 -0700344 verify(mServiceInterface, times(1)).onPerformGestureResult(LINE_SEQUENCE, false);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700345 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700346 assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
347 assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
348 assertThat(mCaptor1.getAllValues().get(2), mIsClickDown);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700349 }
350
351 @Test
352 public void testInjectEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassNew()
353 throws RemoteException {
354 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700355 // Tack a click down to the end of the line
356 TouchPoint clickTouchPoint = new TouchPoint();
357 clickTouchPoint.mIsStartOfPath = true;
358 clickTouchPoint.mX = CLICK_POINT.x;
359 clickTouchPoint.mY = CLICK_POINT.y;
360 mLineList.add(new GestureStep(0, 1, new TouchPoint[] {clickTouchPoint}));
361 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700362
363 // Send 3 motion events, leaving newEvent in the queue
364 mMessageCapturingHandler.sendOneMessage();
365 mMessageCapturingHandler.sendOneMessage();
366 mMessageCapturingHandler.sendOneMessage();
367
Phil Weaver2f165942016-09-21 11:18:05 -0700368 injectEventsSync(mClickList, mServiceInterface, CLICK_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700369 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
370
Phil Weaver2f165942016-09-21 11:18:05 -0700371 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700372 verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700373 assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
374 assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
375 assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
376 assertThat(mCaptor1.getAllValues().get(3), mIsClickDown);
377 }
378
379 @Test
380 public void testContinuedGesture_continuationArrivesAfterDispatched_gestureCompletes()
381 throws Exception {
382 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
383 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
384 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
385 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
386 injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
387 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
388 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
389 verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
390 List<MotionEvent> events = mCaptor1.getAllValues();
391 long downTime = events.get(0).getDownTime();
392 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
393 hasEventTime(downTime)));
394 assertThat(events, everyItem(hasDownTime(downTime)));
395 assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
396 hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
397 // Timing will restart when the gesture continues
398 long secondSequenceStart = events.get(2).getEventTime();
Phil Weaverf00cd142017-03-03 13:44:00 -0800399 assertTrue(secondSequenceStart >= events.get(1).getEventTime());
Phil Weaver2f165942016-09-21 11:18:05 -0700400 assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE));
401 assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
402 hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
403 assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_UP,
404 hasEventTime(secondSequenceStart + CONTINUED_LINE_INTERVAL)));
405 }
406
407 @Test
408 public void testContinuedGesture_withTwoTouchPoints_gestureCompletes()
409 throws Exception {
410 // Run one point through the continued line backwards
411 int backLineId1 = 30;
412 int backLineId2 = 30;
413 List<GestureStep> continuedBackLineList1 = createSimpleGestureFromPoints(backLineId1, 0,
414 true, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_END, CONTINUED_LINE_MID2);
415 List<GestureStep> continuedBackLineList2 = createSimpleGestureFromPoints(backLineId2,
416 backLineId1, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID2,
417 CONTINUED_LINE_MID1, CONTINUED_LINE_START);
418 List<GestureStep> combinedLines1 = combineGestureSteps(
419 mContinuedLineList1, continuedBackLineList1);
420 List<GestureStep> combinedLines2 = combineGestureSteps(
421 mContinuedLineList2, continuedBackLineList2);
422
423 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
424 injectEventsSync(combinedLines1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
425 injectEventsSync(combinedLines2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
426 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
427 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
428 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
429 verify(next, times(7)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
430 List<MotionEvent> events = mCaptor1.getAllValues();
431 long downTime = events.get(0).getDownTime();
432 assertThat(events.get(0), allOf(
433 anyOf(isAtPoint(CONTINUED_LINE_END), isAtPoint(CONTINUED_LINE_START)),
434 IS_ACTION_DOWN, hasEventTime(downTime)));
435 assertThat(events, everyItem(hasDownTime(downTime)));
436 assertThat(events.get(1), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
437 IS_ACTION_POINTER_DOWN, hasEventTime(downTime)));
438 assertThat(events.get(2), allOf(containsPoints(CONTINUED_LINE_MID1, CONTINUED_LINE_MID2),
439 IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
440 assertThat(events.get(3), allOf(containsPoints(CONTINUED_LINE_MID1, CONTINUED_LINE_MID2),
441 IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
442 assertThat(events.get(4), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
443 IS_ACTION_MOVE, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
444 assertThat(events.get(5), allOf(containsPoints(CONTINUED_LINE_START, CONTINUED_LINE_END),
445 IS_ACTION_POINTER_UP, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
446 assertThat(events.get(6), allOf(
447 anyOf(isAtPoint(CONTINUED_LINE_END), isAtPoint(CONTINUED_LINE_START)),
448 IS_ACTION_UP, hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
449 }
450
451
452 @Test
453 public void testContinuedGesture_continuationArrivesWhileDispatching_gestureCompletes()
454 throws Exception {
455 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
456 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
457 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
458 injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
459 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
460 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
461 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
462 verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
463 List<MotionEvent> events = mCaptor1.getAllValues();
464 long downTime = events.get(0).getDownTime();
465 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
466 hasEventTime(downTime)));
467 assertThat(events, everyItem(hasDownTime(downTime)));
468 assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
469 hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
470 assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
471 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
472 assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
473 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
474 assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_UP,
475 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
476 }
477
478 @Test
479 public void testContinuedGesture_twoContinuationsArriveWhileDispatching_gestureCompletes()
480 throws Exception {
481 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
482 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
483 // Continue line again
484 List<GestureStep> continuedLineList2 = createSimpleGestureFromPoints(
485 CONTINUED_LINE_STROKE_ID_2, CONTINUED_LINE_STROKE_ID_1, true,
486 CONTINUED_LINE_INTERVAL, CONTINUED_LINE_MID1,
487 CONTINUED_LINE_MID2, CONTINUED_LINE_END);
488 // Finish line by backtracking
489 int strokeId3 = CONTINUED_LINE_STROKE_ID_2 + 1;
490 int sequence3 = CONTINUED_LINE_SEQUENCE_2 + 1;
491 List<GestureStep> continuedLineList3 = createSimpleGestureFromPoints(strokeId3,
492 CONTINUED_LINE_STROKE_ID_2, false, CONTINUED_LINE_INTERVAL, CONTINUED_LINE_END,
493 CONTINUED_LINE_MID2);
494
495 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
496 injectEventsSync(continuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
497 injectEventsSync(continuedLineList3, mServiceInterface, sequence3);
498 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
499 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
500 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, true);
501 verify(mServiceInterface).onPerformGestureResult(sequence3, true);
502 verify(next, times(6)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
503 List<MotionEvent> events = mCaptor1.getAllValues();
504 long downTime = events.get(0).getDownTime();
505 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN,
506 hasEventTime(downTime)));
507 assertThat(events, everyItem(hasDownTime(downTime)));
508 assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE,
509 hasEventTime(downTime + CONTINUED_LINE_INTERVAL)));
510 assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
511 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 2)));
512 assertThat(events.get(3), allOf(isAtPoint(CONTINUED_LINE_END), IS_ACTION_MOVE,
513 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 3)));
514 assertThat(events.get(4), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_MOVE,
515 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 4)));
516 assertThat(events.get(5), allOf(isAtPoint(CONTINUED_LINE_MID2), IS_ACTION_UP,
517 hasEventTime(downTime + CONTINUED_LINE_INTERVAL * 4)));
518 }
519
520 @Test
521 public void testContinuedGesture_nonContinuingGestureArrivesDuringDispatch_gestureCanceled()
522 throws Exception {
523 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
524 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
525 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
526 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
527 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
528 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, false);
529 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
530 verify(next, times(5)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
531 List<MotionEvent> events = mCaptor1.getAllValues();
532 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
533 assertThat(events.get(1), IS_ACTION_CANCEL);
534 assertThat(events.get(2), allOf(isAtPoint(LINE_START), IS_ACTION_DOWN));
535 assertThat(events.get(3), allOf(isAtPoint(LINE_END), IS_ACTION_MOVE));
536 assertThat(events.get(4), allOf(isAtPoint(LINE_END), IS_ACTION_UP));
537 }
538
539 @Test
540 public void testContinuedGesture_nonContinuingGestureArrivesAfterDispatch_gestureCanceled()
541 throws Exception {
542 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
543 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
544 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
545 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
546 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
547 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
548 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
549 verify(next, times(6)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
550 List<MotionEvent> events = mCaptor1.getAllValues();
551 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
552 assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
553 assertThat(events.get(2), IS_ACTION_CANCEL);
554 assertThat(events.get(3), allOf(isAtPoint(LINE_START), IS_ACTION_DOWN));
555 assertThat(events.get(4), allOf(isAtPoint(LINE_END), IS_ACTION_MOVE));
556 assertThat(events.get(5), allOf(isAtPoint(LINE_END), IS_ACTION_UP));
557 }
558
559 @Test
560 public void testContinuedGesture_misMatchedContinuationArrives_bothGesturesCanceled()
561 throws Exception {
562 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
563 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
564 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
565 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
566 List<GestureStep> discontinuousGesture = mContinuedLineList2
567 .subList(1, mContinuedLineList2.size());
568 injectEventsSync(discontinuousGesture, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
569 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
570 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
571 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
572 List<MotionEvent> events = mCaptor1.getAllValues();
573 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
574 assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
575 assertThat(events.get(2), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_CANCEL));
576 }
577
578 @Test
579 public void testContinuedGesture_continuationArrivesFromOtherService_bothGesturesCanceled()
580 throws Exception {
581 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
582 IAccessibilityServiceClient otherService = mock(IAccessibilityServiceClient.class);
583 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
584 mMessageCapturingHandler.sendOneMessage(); // Send a motion events
585 injectEventsSync(mContinuedLineList2, otherService, CONTINUED_LINE_SEQUENCE_2);
586 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
587 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, false);
588 verify(otherService).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
589 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
590 List<MotionEvent> events = mCaptor1.getAllValues();
591 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
592 assertThat(events.get(1), IS_ACTION_CANCEL);
593 }
594
595 @Test
596 public void testContinuedGesture_realGestureArrivesInBetween_getsCanceled()
597 throws Exception {
598 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
599 injectEventsSync(mContinuedLineList1, mServiceInterface, CONTINUED_LINE_SEQUENCE_1);
600 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
601 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_1, true);
602
603 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
604
605 injectEventsSync(mContinuedLineList2, mServiceInterface, CONTINUED_LINE_SEQUENCE_2);
606 mMessageCapturingHandler.sendAllMessages(); // Send all motion events
607 verify(mServiceInterface).onPerformGestureResult(CONTINUED_LINE_SEQUENCE_2, false);
608 verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
609 List<MotionEvent> events = mCaptor1.getAllValues();
610 assertThat(events.get(0), allOf(isAtPoint(CONTINUED_LINE_START), IS_ACTION_DOWN));
611 assertThat(events.get(1), allOf(isAtPoint(CONTINUED_LINE_MID1), IS_ACTION_MOVE));
612 assertThat(events.get(2), IS_ACTION_CANCEL);
613 assertThat(events.get(3), allOf(isAtPoint(CLICK_POINT), IS_ACTION_DOWN));
Phil Weavera7dcedc2016-07-15 08:40:37 -0700614 }
615
616 @Test
617 public void testClearEvents_realGestureInProgress_shouldForgetAboutGesture() {
618 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700619 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700620 mMotionEventInjector.clearEvents(MOTION_EVENT_SOURCE);
Phil Weaver2f165942016-09-21 11:18:05 -0700621 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700622 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
623
624 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700625 assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
626 assertThat(mCaptor1.getAllValues().get(1), mIsLineStart);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700627 }
628
629 @Test
630 public void testClearEventsOnOtherSource_realGestureInProgress_shouldNotForgetAboutGesture() {
631 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
Phil Weaver2f165942016-09-21 11:18:05 -0700632 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700633 mMotionEventInjector.clearEvents(OTHER_EVENT_SOURCE);
Phil Weaver2f165942016-09-21 11:18:05 -0700634 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700635 mMessageCapturingHandler.sendOneMessage(); // Send a motion event
636
637 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
Phil Weaver2f165942016-09-21 11:18:05 -0700638 assertThat(mCaptor1.getAllValues().get(0), mIsClickDown);
639 assertThat(mCaptor1.getAllValues().get(1), IS_ACTION_CANCEL);
640 assertThat(mCaptor1.getAllValues().get(2), mIsLineStart);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700641 }
642
643 @Test
644 public void testOnDestroy_shouldCancelGestures() throws RemoteException {
645 mMotionEventInjector.onDestroy();
Phil Weaver2f165942016-09-21 11:18:05 -0700646 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
647 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700648 }
649
650 @Test
651 public void testInjectEvents_withNoNext_shouldCancel() throws RemoteException {
Phil Weaver2f165942016-09-21 11:18:05 -0700652 injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
653 verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700654 }
655
656 @Test
657 public void testOnMotionEvent_withNoNext_shouldNotCrash() {
Phil Weaver2f165942016-09-21 11:18:05 -0700658 mMotionEventInjector.onMotionEvent(mClickDownEvent, mClickDownEvent, 0);
Phil Weavera7dcedc2016-07-15 08:40:37 -0700659 }
660
661 @Test
662 public void testOnKeyEvent_shouldPassToNext() {
663 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
664 KeyEvent event = new KeyEvent(0, 0);
665 mMotionEventInjector.onKeyEvent(event, 0);
666 verify(next).onKeyEvent(event, 0);
667 }
668
669 @Test
670 public void testOnKeyEvent_withNoNext_shouldNotCrash() {
671 KeyEvent event = new KeyEvent(0, 0);
672 mMotionEventInjector.onKeyEvent(event, 0);
673 }
674
675 @Test
676 public void testOnAccessibilityEvent_shouldPassToNext() {
677 EventStreamTransformation next = attachMockNext(mMotionEventInjector);
678 AccessibilityEvent event = AccessibilityEvent.obtain();
679 mMotionEventInjector.onAccessibilityEvent(event);
680 verify(next).onAccessibilityEvent(event);
681 }
682
683 @Test
684 public void testOnAccessibilityEvent_withNoNext_shouldNotCrash() {
685 AccessibilityEvent event = AccessibilityEvent.obtain();
686 mMotionEventInjector.onAccessibilityEvent(event);
687 }
688
Phil Weaver2f165942016-09-21 11:18:05 -0700689 private void injectEventsSync(List<GestureStep> gestureSteps,
690 IAccessibilityServiceClient serviceInterface, int sequence) {
691 mMotionEventInjector.injectEvents(gestureSteps, serviceInterface, sequence);
692 // Dispatch the message sent by the injector. Our simple handler doesn't guarantee stuff
693 // happens in order.
694 mMessageCapturingHandler.sendLastMessage();
695 }
696
697 private List<GestureStep> createSimpleGestureFromPoints(int strokeId, int continuedStrokeId,
698 boolean continued, long interval, Point... points) {
699 List<GestureStep> gesture = new ArrayList<>(points.length);
700 TouchPoint[] touchPoints = new TouchPoint[1];
701 touchPoints[0] = new TouchPoint();
702 for (int i = 0; i < points.length; i++) {
703 touchPoints[0].mX = points[i].x;
704 touchPoints[0].mY = points[i].y;
705 touchPoints[0].mIsStartOfPath = ((i == 0) && (continuedStrokeId <= 0));
706 touchPoints[0].mContinuedStrokeId = continuedStrokeId;
707 touchPoints[0].mStrokeId = strokeId;
708 touchPoints[0].mIsEndOfPath = ((i == points.length - 1) && !continued);
709 gesture.add(new GestureStep(interval * i, 1, touchPoints));
710 }
711 return gesture;
712 }
713
714 List<GestureStep> combineGestureSteps(List<GestureStep> list1, List<GestureStep> list2) {
715 assertEquals(list1.size(), list2.size());
716 List<GestureStep> gesture = new ArrayList<>(list1.size());
717 for (int i = 0; i < list1.size(); i++) {
718 int numPoints1 = list1.get(i).numTouchPoints;
719 int numPoints2 = list2.get(i).numTouchPoints;
720 TouchPoint[] touchPoints = new TouchPoint[numPoints1 + numPoints2];
721 for (int j = 0; j < numPoints1; j++) {
722 touchPoints[j] = new TouchPoint();
723 touchPoints[j].copyFrom(list1.get(i).touchPoints[j]);
724 }
725 for (int j = 0; j < numPoints2; j++) {
726 touchPoints[numPoints1 + j] = new TouchPoint();
727 touchPoints[numPoints1 + j].copyFrom(list2.get(i).touchPoints[j]);
728 }
729 gesture.add(new GestureStep(list1.get(i).timeSinceGestureStart,
730 numPoints1 + numPoints2, touchPoints));
731 }
732 return gesture;
733 }
734
Phil Weavera7dcedc2016-07-15 08:40:37 -0700735 private EventStreamTransformation attachMockNext(MotionEventInjector motionEventInjector) {
736 EventStreamTransformation next = mock(EventStreamTransformation.class);
737 motionEventInjector.setNext(next);
738 return next;
739 }
740
Paul Duffin192bb0b2017-03-09 18:49:41 +0000741 static class MotionEventMatcher extends TypeSafeMatcher<MotionEvent> {
Phil Weavera7dcedc2016-07-15 08:40:37 -0700742 long mDownTime;
743 long mEventTime;
744 long mActionMasked;
745 int mX;
746 int mY;
747
748 MotionEventMatcher(long downTime, long eventTime, int actionMasked, int x, int y) {
749 mDownTime = downTime;
750 mEventTime = eventTime;
751 mActionMasked = actionMasked;
752 mX = x;
753 mY = y;
754 }
755
756 MotionEventMatcher(MotionEvent event) {
757 this(event.getDownTime(), event.getEventTime(), event.getActionMasked(),
758 (int) event.getX(), (int) event.getY());
759 }
760
761 void offsetTimesBy(long timeOffset) {
762 mDownTime += timeOffset;
763 mEventTime += timeOffset;
764 }
765
766 @Override
Paul Duffin192bb0b2017-03-09 18:49:41 +0000767 public boolean matchesSafely(MotionEvent event) {
Phil Weavera7dcedc2016-07-15 08:40:37 -0700768 if ((event.getDownTime() == mDownTime) && (event.getEventTime() == mEventTime)
769 && (event.getActionMasked() == mActionMasked) && ((int) event.getX() == mX)
770 && ((int) event.getY() == mY)) {
771 return true;
772 }
773 Log.e(LOG_TAG, "MotionEvent match failed");
774 Log.e(LOG_TAG, "event.getDownTime() = " + event.getDownTime()
775 + ", expected " + mDownTime);
776 Log.e(LOG_TAG, "event.getEventTime() = " + event.getEventTime()
777 + ", expected " + mEventTime);
778 Log.e(LOG_TAG, "event.getActionMasked() = " + event.getActionMasked()
779 + ", expected " + mActionMasked);
780 Log.e(LOG_TAG, "event.getX() = " + event.getX() + ", expected " + mX);
781 Log.e(LOG_TAG, "event.getY() = " + event.getY() + ", expected " + mY);
782 return false;
783 }
Paul Duffin192bb0b2017-03-09 18:49:41 +0000784
785 @Override
786 public void describeTo(Description description) {
787 description.appendText("Motion event matcher");
788 }
Phil Weavera7dcedc2016-07-15 08:40:37 -0700789 }
Phil Weaver2f165942016-09-21 11:18:05 -0700790
791 private static class MotionEventActionMatcher extends TypeSafeMatcher<MotionEvent> {
792 int mAction;
793
794 MotionEventActionMatcher(int action) {
795 super();
796 mAction = action;
797 }
798
799 @Override
800 protected boolean matchesSafely(MotionEvent motionEvent) {
801 return motionEvent.getActionMasked() == mAction;
802 }
803
804 @Override
805 public void describeTo(Description description) {
806 description.appendText("Matching to action " + mAction);
807 }
808 }
809
810 private static TypeSafeMatcher<MotionEvent> isAtPoint(final Point point) {
811 return new TypeSafeMatcher<MotionEvent>() {
812 @Override
813 protected boolean matchesSafely(MotionEvent event) {
814 return ((event.getX() == point.x) && (event.getY() == point.y));
815 }
816
817 @Override
818 public void describeTo(Description description) {
819 description.appendText("Is at point " + point);
820 }
821 };
822 }
823
824 private static TypeSafeMatcher<MotionEvent> containsPoints(final Point... points) {
825 return new TypeSafeMatcher<MotionEvent>() {
826 @Override
827 protected boolean matchesSafely(MotionEvent event) {
828 MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
829 for (int i = 0; i < points.length; i++) {
830 boolean havePoint = false;
831 for (int j = 0; j < points.length; j++) {
832 event.getPointerCoords(j, coords);
833 if ((points[i].x == coords.x) && (points[i].y == coords.y)) {
834 havePoint = true;
835 }
836 }
837 if (!havePoint) {
838 return false;
839 }
840 }
841 return true;
842 }
843
844 @Override
845 public void describeTo(Description description) {
846 description.appendText("Contains points " + points);
847 }
848 };
849 }
850
851 private static TypeSafeMatcher<MotionEvent> hasDownTime(final long downTime) {
852 return new TypeSafeMatcher<MotionEvent>() {
853 @Override
854 protected boolean matchesSafely(MotionEvent event) {
855 return event.getDownTime() == downTime;
856 }
857
858 @Override
859 public void describeTo(Description description) {
860 description.appendText("Down time = " + downTime);
861 }
862 };
863 }
864
865 private static TypeSafeMatcher<MotionEvent> hasEventTime(final long eventTime) {
866 return new TypeSafeMatcher<MotionEvent>() {
867 @Override
868 protected boolean matchesSafely(MotionEvent event) {
869 return event.getEventTime() == eventTime;
870 }
871
872 @Override
873 public void describeTo(Description description) {
874 description.appendText("Event time = " + eventTime);
875 }
876 };
877 }
878
879 private static TypeSafeMatcher<MotionEvent> hasTimeFromDown(final long timeFromDown) {
880 return new TypeSafeMatcher<MotionEvent>() {
881 @Override
882 protected boolean matchesSafely(MotionEvent event) {
883 return (event.getEventTime() - event.getDownTime()) == timeFromDown;
884 }
885
886 @Override
887 public void describeTo(Description description) {
888 description.appendText("Time from down to event times = " + timeFromDown);
889 }
890 };
891 }
892
893 private static TypeSafeMatcher<MotionEvent> hasStandardInitialization() {
894 return new TypeSafeMatcher<MotionEvent>() {
895 @Override
896 protected boolean matchesSafely(MotionEvent event) {
897 return (0 == event.getActionIndex()) && (0 == event.getDeviceId())
898 && (0 == event.getEdgeFlags()) && (0 == event.getFlags())
899 && (0 == event.getMetaState()) && (0F == event.getOrientation())
900 && (0F == event.getTouchMajor()) && (0F == event.getTouchMinor())
901 && (1F == event.getXPrecision()) && (1F == event.getYPrecision())
902 && (1 == event.getPointerCount()) && (1F == event.getPressure())
903 && (InputDevice.SOURCE_TOUCHSCREEN == event.getSource());
904 }
905
906 @Override
907 public void describeTo(Description description) {
908 description.appendText("Has standard values for all parameters");
909 }
910 };
911 }
Phil Weavera7dcedc2016-07-15 08:40:37 -0700912}