• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2024 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 android.hardware.input
18 
19 import android.content.Context
20 import android.content.ContextWrapper
21 import android.platform.test.annotations.Presubmit
22 import android.platform.test.flag.junit.SetFlagsRule
23 import android.view.KeyEvent
24 import androidx.test.core.app.ApplicationProvider
25 import com.android.test.input.MockInputManagerRule
26 import kotlin.test.assertEquals
27 import kotlin.test.assertNotNull
28 import kotlin.test.assertNull
29 import kotlin.test.fail
30 import org.junit.Assert.assertThrows
31 import org.junit.Before
32 import org.junit.Rule
33 import org.junit.Test
34 import org.junit.runner.RunWith
35 import org.mockito.Mockito
36 import org.mockito.Mockito.doAnswer
37 import org.mockito.Mockito.`when`
38 import org.mockito.junit.MockitoJUnitRunner
39 
40 /**
41  * Tests for [InputManager.KeyGestureEventHandler].
42  *
43  * Build/Install/Run: atest InputTests:KeyGestureEventHandlerTest
44  */
45 @Presubmit
46 @RunWith(MockitoJUnitRunner::class)
47 class KeyGestureEventHandlerTest {
48 
49     companion object {
50         const val DEVICE_ID = 1
51         val HOME_GESTURE_EVENT =
52             KeyGestureEvent.Builder()
53                 .setDeviceId(DEVICE_ID)
54                 .setKeycodes(intArrayOf(KeyEvent.KEYCODE_H))
55                 .setModifierState(KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON)
56                 .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_HOME)
57                 .build()
58         val BACK_GESTURE_EVENT =
59             KeyGestureEvent.Builder()
60                 .setDeviceId(DEVICE_ID)
61                 .setKeycodes(intArrayOf(KeyEvent.KEYCODE_DEL))
62                 .setModifierState(KeyEvent.META_META_ON or KeyEvent.META_META_LEFT_ON)
63                 .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_BACK)
64                 .build()
65     }
66 
67     @get:Rule val rule = SetFlagsRule()
68     @get:Rule val inputManagerRule = MockInputManagerRule()
69 
70     private var registeredListener: IKeyGestureHandler? = null
71     private lateinit var context: Context
72     private lateinit var inputManager: InputManager
73 
74     @Before
75     fun setUp() {
76         context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
77         inputManager = InputManager(context)
78         `when`(context.getSystemService(Mockito.eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
79 
80         // Handle key gesture handler registration.
81         doAnswer {
82                 val listener = it.getArgument(1) as IKeyGestureHandler
83                 if (
84                     registeredListener != null &&
85                         registeredListener!!.asBinder() != listener.asBinder()
86                 ) {
87                     // There can only be one registered key gesture handler per process.
88                     fail("Trying to register a new listener when one already exists")
89                 }
90                 registeredListener = listener
91                 null
92             }
93             .`when`(inputManagerRule.mock)
94             .registerKeyGestureHandler(Mockito.any(), Mockito.any())
95 
96         // Handle key gesture handler being unregistered.
97         doAnswer {
98                 val listener = it.getArgument(0) as IKeyGestureHandler
99                 if (
100                     registeredListener == null ||
101                         registeredListener!!.asBinder() != listener.asBinder()
102                 ) {
103                     fail("Trying to unregister a listener that is not registered")
104                 }
105                 registeredListener = null
106                 null
107             }
108             .`when`(inputManagerRule.mock)
109             .unregisterKeyGestureHandler(Mockito.any())
110     }
111 
112     private fun handleKeyGestureEvent(event: KeyGestureEvent) {
113         val eventToSend = AidlKeyGestureEvent()
114         eventToSend.deviceId = event.deviceId
115         eventToSend.keycodes = event.keycodes
116         eventToSend.modifierState = event.modifierState
117         eventToSend.gestureType = event.keyGestureType
118         eventToSend.action = event.action
119         eventToSend.displayId = event.displayId
120         eventToSend.flags = event.flags
121         registeredListener!!.handleKeyGesture(eventToSend, null)
122     }
123 
124     @Test
125     fun testHandlerHasCorrectGestureNotified() {
126         var callbackCount = 0
127 
128         // Add a key gesture event listener
129         inputManager.registerKeyGestureEventHandler(
130             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME)
131         ) { event, _ ->
132             assertEquals(HOME_GESTURE_EVENT, event)
133             callbackCount++
134         }
135 
136         // Request handling for key gesture event will notify the handler.
137         handleKeyGestureEvent(HOME_GESTURE_EVENT)
138         assertEquals(1, callbackCount)
139     }
140 
141     @Test
142     fun testAddingHandlersRegistersInternalCallbackHandler() {
143         // Set up two callbacks.
144         val callback1 = InputManager.KeyGestureEventHandler { _, _ -> }
145         val callback2 = InputManager.KeyGestureEventHandler { _, _ -> }
146 
147         assertNull(registeredListener)
148 
149         // Adding the handler should register the callback with InputManagerService.
150         inputManager.registerKeyGestureEventHandler(
151             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
152             callback1,
153         )
154         assertNotNull(registeredListener)
155 
156         // Adding another handler should not register new internal listener.
157         val currListener = registeredListener
158         inputManager.registerKeyGestureEventHandler(
159             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_BACK),
160             callback2,
161         )
162         assertEquals(currListener, registeredListener)
163     }
164 
165     @Test
166     fun testRemovingHandlersUnregistersInternalCallbackHandler() {
167         // Set up two callbacks.
168         val callback1 = InputManager.KeyGestureEventHandler { _, _ -> }
169         val callback2 = InputManager.KeyGestureEventHandler { _, _ -> }
170 
171         inputManager.registerKeyGestureEventHandler(
172             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
173             callback1,
174         )
175         inputManager.registerKeyGestureEventHandler(
176             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_BACK),
177             callback2,
178         )
179 
180         // Only removing all handlers should remove the internal callback
181         inputManager.unregisterKeyGestureEventHandler(callback1)
182         assertNotNull(registeredListener)
183         inputManager.unregisterKeyGestureEventHandler(callback2)
184         assertNull(registeredListener)
185     }
186 
187     @Test
188     fun testMultipleHandlers() {
189         // Set up two callbacks.
190         var callbackCount1 = 0
191         var callbackCount2 = 0
192         // Handler 1 captures all home gestures
193         val callback1 =
194             InputManager.KeyGestureEventHandler { event, _ ->
195                 callbackCount1++
196                 assertEquals(KeyGestureEvent.KEY_GESTURE_TYPE_HOME, event.keyGestureType)
197             }
198         // Handler 2 captures all back gestures
199         val callback2 =
200             InputManager.KeyGestureEventHandler { event, _ ->
201                 callbackCount2++
202                 assertEquals(KeyGestureEvent.KEY_GESTURE_TYPE_BACK, event.keyGestureType)
203             }
204 
205         // Add both key gesture event handlers
206         inputManager.registerKeyGestureEventHandler(
207             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
208             callback1,
209         )
210         inputManager.registerKeyGestureEventHandler(
211             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_BACK),
212             callback2,
213         )
214 
215         // Request handling for home key gesture event, should notify only callback1
216         handleKeyGestureEvent(HOME_GESTURE_EVENT)
217         assertEquals(1, callbackCount1)
218         assertEquals(0, callbackCount2)
219 
220         // Request handling for back key gesture event, should notify only callback2
221         handleKeyGestureEvent(BACK_GESTURE_EVENT)
222         assertEquals(1, callbackCount1)
223         assertEquals(1, callbackCount2)
224 
225         inputManager.unregisterKeyGestureEventHandler(callback1)
226 
227         // Request handling for home key gesture event, should not trigger callback2
228         handleKeyGestureEvent(HOME_GESTURE_EVENT)
229         assertEquals(1, callbackCount1)
230         assertEquals(1, callbackCount2)
231     }
232 
233     @Test
234     fun testUnableToRegisterSameHandlerTwice() {
235         val handler = InputManager.KeyGestureEventHandler { _, _ -> }
236 
237         inputManager.registerKeyGestureEventHandler(
238             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
239             handler,
240         )
241 
242         assertThrows(IllegalArgumentException::class.java) {
243             inputManager.registerKeyGestureEventHandler(
244                 listOf(KeyGestureEvent.KEY_GESTURE_TYPE_BACK),
245                 handler,
246             )
247         }
248     }
249 
250     @Test
251     fun testUnableToRegisterSameGestureTwice() {
252         val handler1 = InputManager.KeyGestureEventHandler { _, _ -> }
253         val handler2 = InputManager.KeyGestureEventHandler { _, _ -> }
254 
255         inputManager.registerKeyGestureEventHandler(
256             listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
257             handler1,
258         )
259 
260         assertThrows(IllegalArgumentException::class.java) {
261             inputManager.registerKeyGestureEventHandler(
262                 listOf(KeyGestureEvent.KEY_GESTURE_TYPE_HOME),
263                 handler2,
264             )
265         }
266     }
267 }
268