MotionEventInjectorTest.java revision 89e3ffc66c5a05f188ff9748b48abebc247f664b
1/* 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 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertFalse; 21import static org.junit.Assert.assertTrue; 22import static org.mockito.Matchers.anyInt; 23import static org.mockito.Matchers.argThat; 24import static org.mockito.Matchers.eq; 25import static org.mockito.Mockito.mock; 26import static org.mockito.Mockito.reset; 27import static org.mockito.Mockito.times; 28import static org.mockito.Mockito.verify; 29import static org.mockito.Mockito.verifyNoMoreInteractions; 30import static org.mockito.Mockito.verifyZeroInteractions; 31 32import android.accessibilityservice.IAccessibilityServiceClient; 33import android.os.Handler; 34import android.os.Looper; 35import android.os.Message; 36import android.os.RemoteException; 37import android.support.test.runner.AndroidJUnit4; 38import android.util.Log; 39import android.util.Pair; 40import android.view.InputDevice; 41import android.view.KeyEvent; 42import android.view.MotionEvent; 43import android.view.WindowManagerPolicy; 44import java.util.ArrayList; 45import java.util.List; 46 47import android.view.accessibility.AccessibilityEvent; 48import org.junit.Before; 49import org.junit.BeforeClass; 50import org.junit.Test; 51import org.junit.runner.RunWith; 52import org.mockito.ArgumentCaptor; 53import org.mockito.ArgumentMatcher; 54 55/** 56 * Tests for MotionEventInjector 57 */ 58@RunWith(AndroidJUnit4.class) 59public class MotionEventInjectorTest { 60 private static final String LOG_TAG = "MotionEventInjectorTest"; 61 private static final int CLICK_X = 100; 62 private static final int CLICK_Y_START = 200; 63 private static final int CLICK_Y_END = 201; 64 private static final int CLICK_DURATION = 10; 65 private static final int SEQUENCE = 50; 66 67 private static final int SECOND_CLICK_X = 1000; 68 private static final int SECOND_CLICK_Y = 2000; 69 private static final int SECOND_SEQUENCE = 51; 70 71 private static final int MOTION_EVENT_SOURCE = InputDevice.SOURCE_TOUCHSCREEN; 72 private static final int OTHER_EVENT_SOURCE = InputDevice.SOURCE_MOUSE; 73 74 MotionEventInjector mMotionEventInjector; 75 IAccessibilityServiceClient mServiceInterface; 76 List<MotionEvent> mClickList = new ArrayList<>(); 77 List<MotionEvent> mSecondClickList = new ArrayList<>(); 78 ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class); 79 ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class); 80 MessageCapturingHandler mMessageCapturingHandler; 81 MotionEventMatcher mClickEvent0Matcher; 82 MotionEventMatcher mClickEvent1Matcher; 83 MotionEventMatcher mClickEvent2Matcher; 84 MotionEventMatcher mSecondClickEvent0Matcher; 85 86 @BeforeClass 87 public static void oneTimeInitialization() { 88 if (Looper.myLooper() == null) { 89 Looper.prepare(); 90 } 91 } 92 93 @Before 94 public void setUp() { 95 mMessageCapturingHandler = new MessageCapturingHandler(new Handler.Callback() { 96 @Override 97 public boolean handleMessage(Message msg) { 98 return mMotionEventInjector.handleMessage(msg); 99 } 100 }); 101 mMotionEventInjector = new MotionEventInjector(mMessageCapturingHandler); 102 mClickList.add( 103 MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0)); 104 mClickList.add(MotionEvent.obtain( 105 0, CLICK_DURATION, MotionEvent.ACTION_MOVE, CLICK_X, CLICK_Y_END, 0)); 106 mClickList.add(MotionEvent.obtain( 107 0, CLICK_DURATION, MotionEvent.ACTION_UP, CLICK_X, CLICK_Y_END, 0)); 108 for (int i = 0; i < mClickList.size(); i++) { 109 mClickList.get(i).setSource(MOTION_EVENT_SOURCE); 110 } 111 112 mClickEvent0Matcher = new MotionEventMatcher(mClickList.get(0)); 113 mClickEvent1Matcher = new MotionEventMatcher(mClickList.get(1)); 114 mClickEvent2Matcher = new MotionEventMatcher(mClickList.get(2)); 115 116 mSecondClickList.add(MotionEvent.obtain( 117 0, 0, MotionEvent.ACTION_DOWN, SECOND_CLICK_X, SECOND_CLICK_Y, 0)); 118 mSecondClickList.add(MotionEvent.obtain( 119 0, CLICK_DURATION, MotionEvent.ACTION_MOVE, SECOND_CLICK_X, CLICK_Y_END, 0)); 120 mSecondClickList.add(MotionEvent.obtain( 121 0, CLICK_DURATION, MotionEvent.ACTION_UP, SECOND_CLICK_X, CLICK_Y_END, 0)); 122 for (int i = 0; i < mSecondClickList.size(); i++) { 123 mSecondClickList.get(i).setSource(MOTION_EVENT_SOURCE); 124 } 125 126 mSecondClickEvent0Matcher = new MotionEventMatcher(mSecondClickList.get(0)); 127 128 mServiceInterface = mock(IAccessibilityServiceClient.class); 129 } 130 131 @Test 132 public void testInjectEvents_shouldEmergeInOrderWithCorrectTiming() throws RemoteException { 133 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 134 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 135 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 136 verifyNoMoreInteractions(next); 137 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 138 139 verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), 140 eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 141 long gestureStart = mCaptor1.getValue().getDownTime(); 142 mClickEvent0Matcher.offsetTimesBy(gestureStart); 143 mClickEvent1Matcher.offsetTimesBy(gestureStart); 144 mClickEvent2Matcher.offsetTimesBy(gestureStart); 145 146 verify(next).onMotionEvent(argThat(mClickEvent0Matcher), argThat(mClickEvent0Matcher), 147 eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 148 verifyNoMoreInteractions(next); 149 reset(next); 150 151 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 152 verify(next).onMotionEvent(argThat(mClickEvent1Matcher), argThat(mClickEvent1Matcher), 153 eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 154 verifyNoMoreInteractions(next); 155 reset(next); 156 157 verifyZeroInteractions(mServiceInterface); 158 159 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 160 verify(next).onMotionEvent(argThat(mClickEvent2Matcher), argThat(mClickEvent2Matcher), 161 eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 162 verifyNoMoreInteractions(next); 163 reset(next); 164 165 verify(mServiceInterface).onPerformGestureResult(SEQUENCE, true); 166 verifyNoMoreInteractions(mServiceInterface); 167 } 168 169 @Test 170 public void testInjectEvents_eventWithManyPointers_shouldNotCrash() { 171 int manyPointersCount = 20; 172 MotionEvent.PointerCoords[] pointerCoords = 173 new MotionEvent.PointerCoords[manyPointersCount]; 174 MotionEvent.PointerProperties[] pointerProperties = 175 new MotionEvent.PointerProperties[manyPointersCount]; 176 for (int i = 0; i < manyPointersCount; i++) { 177 pointerProperties[i] = new MotionEvent.PointerProperties(); 178 pointerProperties[i].id = i; 179 pointerProperties[i].toolType = MotionEvent.TOOL_TYPE_UNKNOWN; 180 pointerCoords[i] = new MotionEvent.PointerCoords(); 181 pointerCoords[i].clear(); 182 pointerCoords[i].pressure = 1.0f; 183 pointerCoords[i].size = 1.0f; 184 pointerCoords[i].x = i; 185 pointerCoords[i].y = i; 186 } 187 List<MotionEvent> events = new ArrayList<>(); 188 events.add(MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, manyPointersCount, 189 pointerProperties, pointerCoords, 0, 0, 190 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0)); 191 events.add(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, manyPointersCount, 192 pointerProperties, pointerCoords, 0, 0, 193 1.0f, 1.0f, 0, 0, InputDevice.SOURCE_TOUCHSCREEN, 0)); 194 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 195 mMotionEventInjector.injectEvents(events, mServiceInterface, SEQUENCE); 196 mMessageCapturingHandler.sendAllMessages(); 197 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 198 assertEquals(MotionEvent.ACTION_DOWN, mCaptor1.getAllValues().get(0).getActionMasked()); 199 assertEquals(MotionEvent.ACTION_UP, mCaptor1.getAllValues().get(1).getActionMasked()); 200 } 201 202 @Test 203 public void testRegularEvent_afterGestureComplete_shouldPassToNext() { 204 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 205 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 206 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 207 mMessageCapturingHandler.sendAllMessages(); // Send all motion events 208 reset(next); 209 mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mClickList.get(0), 0); 210 verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher), 211 argThat(mClickEvent0Matcher), eq(0)); 212 } 213 214 @Test 215 public void testInjectEvents_withRealGestureUnderway_shouldCancelRealAndPassInjected() { 216 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 217 mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0); 218 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE); 219 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 220 221 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 222 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 223 assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked()); 224 reset(next); 225 226 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 227 verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), 228 eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 229 long gestureStart = mCaptor1.getValue().getDownTime(); 230 mSecondClickEvent0Matcher.offsetTimesBy(gestureStart); 231 232 verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher), 233 argThat(mSecondClickEvent0Matcher), eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 234 } 235 236 @Test 237 public void testInjectEvents_withRealMouseGestureUnderway_shouldContinueRealAndPassInjected() { 238 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 239 MotionEvent mouseEvent = MotionEvent.obtain(mClickList.get(0)); 240 mouseEvent.setSource(InputDevice.SOURCE_MOUSE); 241 MotionEventMatcher mouseEventMatcher = new MotionEventMatcher(mouseEvent); 242 mMotionEventInjector.onMotionEvent(mouseEvent, mouseEvent, 0); 243 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE); 244 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 245 246 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 247 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 248 assertTrue(mouseEventMatcher.matches(mCaptor1.getAllValues().get(0))); 249 mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(1).getDownTime()); 250 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(1))); 251 } 252 253 @Test 254 public void testInjectEvents_withRealGestureFinished_shouldJustPassInjected() { 255 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 256 mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0); 257 mMotionEventInjector.onMotionEvent(mClickList.get(1), mClickList.get(1), 0); 258 mMotionEventInjector.onMotionEvent(mClickList.get(2), mClickList.get(2), 0); 259 260 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE); 261 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 262 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 263 264 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 265 assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1))); 266 assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2))); 267 reset(next); 268 269 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 270 verify(next).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), 271 eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 272 mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getValue().getDownTime()); 273 verify(next).onMotionEvent(argThat(mSecondClickEvent0Matcher), 274 argThat(mSecondClickEvent0Matcher), eq(WindowManagerPolicy.FLAG_PASS_TO_USER)); 275 } 276 277 @Test 278 public void testOnMotionEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassReal() 279 throws RemoteException { 280 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 281 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 282 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 283 284 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 285 mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mSecondClickList.get(0), 0); 286 287 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 288 mClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(0).getDownTime()); 289 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 290 assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked()); 291 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2))); 292 verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false); 293 } 294 295 @Test 296 public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal() 297 throws RemoteException { 298 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 299 mClickList.add(MotionEvent.obtain(2 * CLICK_DURATION, 2 * CLICK_DURATION, 300 MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0)); 301 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 302 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 303 304 // Send 3 motion events, leaving the extra down in the queue 305 mMessageCapturingHandler.sendOneMessage(); 306 mMessageCapturingHandler.sendOneMessage(); 307 mMessageCapturingHandler.sendOneMessage(); 308 309 mMotionEventInjector.onMotionEvent(mSecondClickList.get(0), mClickList.get(0), 0); 310 311 verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 312 long gestureStart = mCaptor1.getAllValues().get(0).getDownTime(); 313 mClickEvent0Matcher.offsetTimesBy(gestureStart); 314 mClickEvent1Matcher.offsetTimesBy(gestureStart); 315 mClickEvent2Matcher.offsetTimesBy(gestureStart); 316 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 317 assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1))); 318 assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2))); 319 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(3))); 320 321 verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false); 322 assertFalse(mMessageCapturingHandler.hasMessages()); 323 } 324 325 @Test 326 public void testInjectEvents_openInjectedGestureInProgress_shouldCancelAndNotifyAndPassNew() 327 throws RemoteException { 328 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 329 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 330 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 331 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 332 333 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE); 334 mMessageCapturingHandler.sendLastMessage(); // Process the second event injection 335 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 336 337 verify(mServiceInterface, times(1)).onPerformGestureResult(SEQUENCE, false); 338 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 339 mClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(0).getDownTime()); 340 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 341 assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked()); 342 mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(2).getDownTime()); 343 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2))); 344 } 345 346 @Test 347 public void testInjectEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassNew() 348 throws RemoteException { 349 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 350 MotionEvent newEvent = MotionEvent.obtain(2 * CLICK_DURATION, 2 * CLICK_DURATION, 351 MotionEvent.ACTION_DOWN, CLICK_X, CLICK_Y_START, 0); 352 newEvent.setSource(mClickList.get(0).getSource()); 353 mClickList.add(newEvent); 354 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 355 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 356 357 // Send 3 motion events, leaving newEvent in the queue 358 mMessageCapturingHandler.sendOneMessage(); 359 mMessageCapturingHandler.sendOneMessage(); 360 mMessageCapturingHandler.sendOneMessage(); 361 362 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE); 363 mMessageCapturingHandler.sendLastMessage(); // Process the event injection 364 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 365 366 verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false); 367 verify(next, times(4)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 368 long gestureStart = mCaptor1.getAllValues().get(0).getDownTime(); 369 mClickEvent0Matcher.offsetTimesBy(gestureStart); 370 mClickEvent1Matcher.offsetTimesBy(gestureStart); 371 mClickEvent2Matcher.offsetTimesBy(gestureStart); 372 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 373 assertTrue(mClickEvent1Matcher.matches(mCaptor1.getAllValues().get(1))); 374 assertTrue(mClickEvent2Matcher.matches(mCaptor1.getAllValues().get(2))); 375 mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(3).getDownTime()); 376 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(3))); 377 } 378 379 @Test 380 public void testClearEvents_realGestureInProgress_shouldForgetAboutGesture() { 381 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 382 mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0); 383 mMotionEventInjector.clearEvents(MOTION_EVENT_SOURCE); 384 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SEQUENCE); 385 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 386 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 387 388 verify(next, times(2)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 389 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 390 mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(1).getDownTime()); 391 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(1))); 392 } 393 394 @Test 395 public void testClearEventsOnOtherSource_realGestureInProgress_shouldNotForgetAboutGesture() { 396 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 397 mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0); 398 mMotionEventInjector.clearEvents(OTHER_EVENT_SOURCE); 399 mMotionEventInjector.injectEvents(mSecondClickList, mServiceInterface, SECOND_SEQUENCE); 400 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 401 mMessageCapturingHandler.sendOneMessage(); // Send a motion event 402 403 verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt()); 404 assertTrue(mClickEvent0Matcher.matches(mCaptor1.getAllValues().get(0))); 405 assertEquals(MotionEvent.ACTION_CANCEL, mCaptor1.getAllValues().get(1).getActionMasked()); 406 mSecondClickEvent0Matcher.offsetTimesBy(mCaptor1.getAllValues().get(2).getDownTime()); 407 assertTrue(mSecondClickEvent0Matcher.matches(mCaptor1.getAllValues().get(2))); 408 } 409 410 @Test 411 public void testOnDestroy_shouldCancelGestures() throws RemoteException { 412 mMotionEventInjector.onDestroy(); 413 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 414 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 415 verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false); 416 } 417 418 @Test 419 public void testInjectEvents_withNoNext_shouldCancel() throws RemoteException { 420 mMotionEventInjector.injectEvents(mClickList, mServiceInterface, SEQUENCE); 421 mMessageCapturingHandler.sendOneMessage(); // Process the event injection 422 verify(mServiceInterface).onPerformGestureResult(SEQUENCE, false); 423 } 424 425 @Test 426 public void testOnMotionEvent_withNoNext_shouldNotCrash() { 427 mMotionEventInjector.onMotionEvent(mClickList.get(0), mClickList.get(0), 0); 428 } 429 430 @Test 431 public void testOnKeyEvent_shouldPassToNext() { 432 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 433 KeyEvent event = new KeyEvent(0, 0); 434 mMotionEventInjector.onKeyEvent(event, 0); 435 verify(next).onKeyEvent(event, 0); 436 } 437 438 @Test 439 public void testOnKeyEvent_withNoNext_shouldNotCrash() { 440 KeyEvent event = new KeyEvent(0, 0); 441 mMotionEventInjector.onKeyEvent(event, 0); 442 } 443 444 @Test 445 public void testOnAccessibilityEvent_shouldPassToNext() { 446 EventStreamTransformation next = attachMockNext(mMotionEventInjector); 447 AccessibilityEvent event = AccessibilityEvent.obtain(); 448 mMotionEventInjector.onAccessibilityEvent(event); 449 verify(next).onAccessibilityEvent(event); 450 } 451 452 @Test 453 public void testOnAccessibilityEvent_withNoNext_shouldNotCrash() { 454 AccessibilityEvent event = AccessibilityEvent.obtain(); 455 mMotionEventInjector.onAccessibilityEvent(event); 456 } 457 458 private EventStreamTransformation attachMockNext(MotionEventInjector motionEventInjector) { 459 EventStreamTransformation next = mock(EventStreamTransformation.class); 460 motionEventInjector.setNext(next); 461 return next; 462 } 463 464 static class MotionEventMatcher extends ArgumentMatcher<MotionEvent> { 465 long mDownTime; 466 long mEventTime; 467 long mActionMasked; 468 int mX; 469 int mY; 470 471 MotionEventMatcher(long downTime, long eventTime, int actionMasked, int x, int y) { 472 mDownTime = downTime; 473 mEventTime = eventTime; 474 mActionMasked = actionMasked; 475 mX = x; 476 mY = y; 477 } 478 479 MotionEventMatcher(MotionEvent event) { 480 this(event.getDownTime(), event.getEventTime(), event.getActionMasked(), 481 (int) event.getX(), (int) event.getY()); 482 } 483 484 void offsetTimesBy(long timeOffset) { 485 mDownTime += timeOffset; 486 mEventTime += timeOffset; 487 } 488 489 @Override 490 public boolean matches(Object o) { 491 MotionEvent event = (MotionEvent) o; 492 if ((event.getDownTime() == mDownTime) && (event.getEventTime() == mEventTime) 493 && (event.getActionMasked() == mActionMasked) && ((int) event.getX() == mX) 494 && ((int) event.getY() == mY)) { 495 return true; 496 } 497 Log.e(LOG_TAG, "MotionEvent match failed"); 498 Log.e(LOG_TAG, "event.getDownTime() = " + event.getDownTime() 499 + ", expected " + mDownTime); 500 Log.e(LOG_TAG, "event.getEventTime() = " + event.getEventTime() 501 + ", expected " + mEventTime); 502 Log.e(LOG_TAG, "event.getActionMasked() = " + event.getActionMasked() 503 + ", expected " + mActionMasked); 504 Log.e(LOG_TAG, "event.getX() = " + event.getX() + ", expected " + mX); 505 Log.e(LOG_TAG, "event.getY() = " + event.getY() + ", expected " + mY); 506 return false; 507 } 508 } 509} 510