1 /* 2 * Copyright (C) 2021 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.test.input 18 19 import android.view.InputDevice.SOURCE_MOUSE 20 import android.view.InputDevice.SOURCE_TOUCHSCREEN 21 import android.view.InputEventAssigner 22 import android.view.KeyEvent 23 import android.view.MotionEvent 24 import org.junit.Assert.assertEquals 25 import org.junit.Test 26 27 /** 28 * Create a MotionEvent with the provided action, eventTime, and source 29 */ 30 fun createMotionEvent(action: Int, eventTime: Long, source: Int): MotionEvent { 31 val downTime: Long = 10 32 val x = 1f 33 val y = 2f 34 val pressure = 3f 35 val size = 1f 36 val metaState = 0 37 val xPrecision = 0f 38 val yPrecision = 0f 39 val deviceId = 1 40 val edgeFlags = 0 41 val displayId = 0 42 return MotionEvent.obtain(downTime, eventTime, action, x, y, pressure, size, metaState, 43 xPrecision, yPrecision, deviceId, edgeFlags, source, displayId) 44 } 45 46 private fun createKeyEvent(action: Int, eventTime: Long): KeyEvent { 47 val code = KeyEvent.KEYCODE_A 48 val repeat = 0 49 return KeyEvent(eventTime, eventTime, action, code, repeat) 50 } 51 52 class InputEventAssignerTest { 53 companion object { 54 private const val TAG = "InputEventAssignerTest" 55 } 56 57 /** 58 * A single MOVE event should be assigned to the next available frame. 59 */ 60 @Test 61 fun testTouchGesture() { 62 val assigner = InputEventAssigner() 63 val event = createMotionEvent(MotionEvent.ACTION_MOVE, 10, SOURCE_TOUCHSCREEN) 64 val eventId = assigner.processEvent(event) 65 assertEquals(event.id, eventId) 66 } 67 68 /** 69 * DOWN event should be used until a vsync comes in. After vsync, the latest event should be 70 * produced. 71 */ 72 @Test 73 fun testTouchDownWithMove() { 74 val assigner = InputEventAssigner() 75 val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_TOUCHSCREEN) 76 val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_TOUCHSCREEN) 77 val move2 = createMotionEvent(MotionEvent.ACTION_MOVE, 13, SOURCE_TOUCHSCREEN) 78 val move3 = createMotionEvent(MotionEvent.ACTION_MOVE, 14, SOURCE_TOUCHSCREEN) 79 val move4 = createMotionEvent(MotionEvent.ACTION_MOVE, 15, SOURCE_TOUCHSCREEN) 80 var eventId = assigner.processEvent(down) 81 assertEquals(down.id, eventId) 82 eventId = assigner.processEvent(move1) 83 assertEquals(down.id, eventId) 84 eventId = assigner.processEvent(move2) 85 // Even though we already had 2 move events, there was no choreographer callback yet. 86 // Therefore, we should still get the id of the down event 87 assertEquals(down.id, eventId) 88 89 // Now send CALLBACK_INPUT to the assigner. It should provide the latest motion event 90 assigner.notifyFrameProcessed() 91 eventId = assigner.processEvent(move3) 92 assertEquals(move3.id, eventId) 93 eventId = assigner.processEvent(move4) 94 assertEquals(move4.id, eventId) 95 } 96 97 /** 98 * Similar to the above test, but with SOURCE_MOUSE. Since we don't have down latency 99 * concept for non-touchscreens, the latest input event will be used. 100 */ 101 @Test 102 fun testMouseDownWithMove() { 103 val assigner = InputEventAssigner() 104 val down = createMotionEvent(MotionEvent.ACTION_DOWN, 10, SOURCE_MOUSE) 105 val move1 = createMotionEvent(MotionEvent.ACTION_MOVE, 12, SOURCE_MOUSE) 106 var eventId = assigner.processEvent(down) 107 assertEquals(down.id, eventId) 108 eventId = assigner.processEvent(move1) 109 assertEquals(move1.id, eventId) 110 } 111 112 /** 113 * KeyEvents are processed immediately, so the latest event should be returned. 114 */ 115 @Test 116 fun testKeyEvent() { 117 val assigner = InputEventAssigner() 118 val down = createKeyEvent(KeyEvent.ACTION_DOWN, 20) 119 var eventId = assigner.processEvent(down) 120 assertEquals(down.id, eventId) 121 val up = createKeyEvent(KeyEvent.ACTION_UP, 21) 122 eventId = assigner.processEvent(up) 123 // DOWN is only sticky for Motions, not for keys 124 assertEquals(up.id, eventId) 125 assigner.notifyFrameProcessed() 126 val down2 = createKeyEvent(KeyEvent.ACTION_DOWN, 22) 127 eventId = assigner.processEvent(down2) 128 assertEquals(down2.id, eventId) 129 } 130 } 131