1 /*
2 * Copyright (C) 2023 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 package android.hardware.input
17
18 import android.content.Context
19 import android.content.ContextWrapper
20 import android.content.res.Resources
21 import android.platform.test.annotations.Presubmit
22 import android.view.Display
23 import android.view.DisplayInfo
24 import android.view.InputDevice
25 import androidx.test.core.app.ApplicationProvider
26 import com.android.test.input.MockInputManagerRule
27 import org.junit.Assert.assertEquals
28 import org.junit.Assert.assertNotNull
29 import org.junit.Before
30 import org.junit.Rule
31 import org.junit.Test
32 import org.junit.runner.RunWith
33 import org.mockito.Mockito
34 import org.mockito.Mockito.eq
35 import org.mockito.Mockito.`when`
36 import org.mockito.junit.MockitoJUnitRunner
37
38 /**
39 * Tests for [InputManager].
40 *
41 * Build/Install/Run: atest InputTests:InputManagerTest
42 */
43 @Presubmit
44 @RunWith(MockitoJUnitRunner::class)
45 class InputManagerTest {
46
47 companion object {
48 const val DEVICE_ID = 42
49 const val SECOND_DEVICE_ID = 96
50 const val THIRD_DEVICE_ID = 99
51 }
52
53 @get:Rule val inputManagerRule = MockInputManagerRule()
54
55 private lateinit var devicesChangedListener: IInputDevicesChangedListener
56 private val deviceGenerationMap = mutableMapOf<Int /*deviceId*/, Int /*generation*/>()
57 private lateinit var context: Context
58 private lateinit var inputManager: InputManager
59
60 @Before
setUpnull61 fun setUp() {
62 context = Mockito.spy(ContextWrapper(ApplicationProvider.getApplicationContext()))
63 inputManager = InputManager(context)
64 `when`(context.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager)
65 `when`(inputManagerRule.mock.inputDeviceIds).then { deviceGenerationMap.keys.toIntArray() }
66 }
67
notifyDeviceChangednull68 private fun notifyDeviceChanged(
69 deviceId: Int,
70 associatedDisplayId: Int,
71 usiVersion: HostUsiVersion?,
72 ) {
73 val generation =
74 deviceGenerationMap[deviceId]?.plus(1)
75 ?: throw IllegalArgumentException("Device $deviceId was never added!")
76 deviceGenerationMap[deviceId] = generation
77
78 `when`(inputManagerRule.mock.getInputDevice(deviceId))
79 .thenReturn(createInputDevice(deviceId, associatedDisplayId, usiVersion, generation))
80 val list = deviceGenerationMap.flatMap { listOf(it.key, it.value) }
81 if (::devicesChangedListener.isInitialized) {
82 devicesChangedListener.onInputDevicesChanged(list.toIntArray())
83 }
84 }
85
addInputDevicenull86 private fun addInputDevice(
87 deviceId: Int,
88 associatedDisplayId: Int,
89 usiVersion: HostUsiVersion?,
90 ) {
91 deviceGenerationMap[deviceId] = 0
92 notifyDeviceChanged(deviceId, associatedDisplayId, usiVersion)
93 }
94
95 @Test
testUsiVersionDisplayAssociationnull96 fun testUsiVersionDisplayAssociation() {
97 addInputDevice(DEVICE_ID, Display.DEFAULT_DISPLAY, null)
98 addInputDevice(SECOND_DEVICE_ID, Display.INVALID_DISPLAY, HostUsiVersion(9, 8))
99 addInputDevice(THIRD_DEVICE_ID, 42, HostUsiVersion(3, 1))
100
101 val usiVersion = inputManager.getHostUsiVersion(createDisplay(42))
102 assertNotNull(usiVersion)
103 assertEquals(3, usiVersion!!.majorVersion)
104 assertEquals(1, usiVersion.minorVersion)
105 }
106
107 @Test
testUsiVersionFallBackToDisplayConfignull108 fun testUsiVersionFallBackToDisplayConfig() {
109 addInputDevice(DEVICE_ID, Display.DEFAULT_DISPLAY, null)
110
111 `when`(inputManagerRule.mock.getHostUsiVersionFromDisplayConfig(eq(42)))
112 .thenReturn(HostUsiVersion(9, 8))
113 val usiVersion = inputManager.getHostUsiVersion(createDisplay(42))
114 assertEquals(HostUsiVersion(9, 8), usiVersion)
115 }
116 }
117
createInputDevicenull118 private fun createInputDevice(
119 deviceId: Int,
120 associatedDisplayId: Int,
121 usiVersion: HostUsiVersion? = null,
122 generation: Int = -1,
123 ): InputDevice =
124 InputDevice.Builder()
125 .setId(deviceId)
126 .setName("Device $deviceId")
127 .setDescriptor("descriptor $deviceId")
128 .setAssociatedDisplayId(associatedDisplayId)
129 .setUsiVersion(usiVersion)
130 .setGeneration(generation)
131 .build()
132
133 private fun createDisplay(displayId: Int): Display {
134 val res: Resources? = null
135 return Display(null /* global */, displayId, DisplayInfo(), res)
136 }
137