Loading services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java +24 −9 Original line number Diff line number Diff line Loading @@ -648,11 +648,17 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) private void onKeyEventInternal(KeyEvent event, int policyFlags) { boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; int keyCode = event.getKeyCode(); mActiveInputDeviceId = event.getDeviceId(); InputDevice inputDevice = mInputManager.getInputDevice(mActiveInputDeviceId); final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; final int keyCode = event.getKeyCode(); final int deviceId = event.getDeviceId(); InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (!isDeviceEligible(inputDevice)) { // Pass non-mouse key events to the next handler super.onKeyEvent(event, policyFlags); return; } mActiveInputDeviceId = deviceId; boolean usePrimaryKeys = shouldUsePrimaryKeysForDevice(inputDevice); if (!mDeviceKeyCodeMap.contains(mActiveInputDeviceId)) { Loading Loading @@ -874,10 +880,11 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation */ @Override public void onInputDeviceAdded(int deviceId) { final InputDevice device = mInputManager.getInputDevice(deviceId); if (device != null && device.isFullKeyboard()) { deviceHasNumpad(device); final InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (isDeviceEligible(inputDevice)) { deviceHasNumpad(inputDevice); } onInputDeviceChangedInternal(inputDevice); } @Override Loading @@ -896,13 +903,21 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation @Override public void onInputDeviceChanged(int deviceId) { InputDevice inputDevice = mInputManager.getInputDevice(deviceId); onInputDeviceChangedInternal(inputDevice); } private void onInputDeviceChangedInternal(@NonNull InputDevice inputDevice) { // Update the enum mapping only if input device that changed is a keyboard if (inputDevice.isFullKeyboard()) { if (isDeviceEligible(inputDevice)) { initializeDeviceToEnumMap(inputDevice, shouldUsePrimaryKeysForDevice(inputDevice)); Slog.i(LOG_TAG, "Updating key code enum map for device ID: " + deviceId); Slog.i(LOG_TAG, "Updating key code enum map for device ID: " + inputDevice.getId()); } } private boolean isDeviceEligible(@Nullable InputDevice device) { return device != null && device.isFullKeyboard() && device.isPhysicalDevice(); } /** * Observes and updates various mouse keys setting values. */ Loading services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt +37 −10 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ class MouseKeysInterceptorTest { companion object { const val DISPLAY_ID = 1 const val DEVICE_ID = 123 const val VIRTUAL_DEVICE_ID = 456 // This delay is required for key events to be sent and handled correctly. // The handler only performs a move/scroll event if it receives the key event // at INTERVAL_MILLIS (which happens in practice). Hence, we need this delay in the tests. Loading @@ -92,6 +93,7 @@ class MouseKeysInterceptorTest { private lateinit var mouseKeysInterceptor: MouseKeysInterceptor private lateinit var inputDevice: InputDevice private lateinit var virtualInputDevice: InputDevice private val clock = OffsettableClock() private val testLooper = TestLooper { clock.now() } Loading Loading @@ -135,9 +137,12 @@ class MouseKeysInterceptorTest { testSession = InputManagerGlobal.createTestSession(iInputManager) mockInputManager = InputManager(testableContext) inputDevice = createInputDevice(DEVICE_ID) inputDevice = createInputDevice(DEVICE_ID, /* isVirtual= */ false) virtualInputDevice = createInputDevice(VIRTUAL_DEVICE_ID, /* isVirtual */ true) Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID)) .thenReturn(inputDevice) Mockito.`when`(iInputManager.getInputDevice(VIRTUAL_DEVICE_ID)) .thenReturn(virtualInputDevice) Mockito.`when`(mockVirtualDeviceManagerInternal.getDeviceIdsForUid(Mockito.anyInt())) .thenReturn(ArraySet(setOf(DEVICE_ID))) Loading @@ -153,7 +158,8 @@ class MouseKeysInterceptorTest { Mockito.any(VirtualMouseConfig::class.java) )).thenReturn(mockVirtualMouse) Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID)) Mockito.`when`(iInputManager.inputDeviceIds) .thenReturn(intArrayOf(DEVICE_ID, VIRTUAL_DEVICE_ID)) Mockito.`when`(mockAms.traceManager).thenReturn(mockTraceManager) } Loading Loading @@ -605,6 +611,23 @@ class MouseKeysInterceptorTest { verifyKeyEventsEqual(primaryKeyDownEvent, nextInterceptor.events.poll()!!) } @Test fun whenMouseKeyEventArrives_fromVirtualKeyboard_eventIsPassedToNextInterceptor() { setupMouseKeysInterceptor(usePrimaryKeys = true) for (ev in MouseKeysInterceptor.MouseKeyEvent.entries) { val downTime = clock.now() val keyCode = ev.getKeyCodeValue(USE_PRIMARY_KEYS) val downEvent = KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, VIRTUAL_DEVICE_ID, 0 ) mouseKeysInterceptor.onKeyEvent(downEvent, 0) testLooper.dispatchAll() assertThat(nextInterceptor.events).hasSize(1) verifyKeyEventsEqual(downEvent, nextInterceptor.events.poll()!!) } } private fun verifyRelativeEvents(expectedX: FloatArray, expectedY: FloatArray) { assertThat(expectedX.size).isEqualTo(expectedY.size) val expectedSize = expectedX.size Loading Loading @@ -668,6 +691,7 @@ class MouseKeysInterceptorTest { private fun createInputDevice( deviceId: Int, isVirtual: Boolean, generation: Int = -1 ): InputDevice = InputDevice.Builder() Loading @@ -675,6 +699,9 @@ class MouseKeysInterceptorTest { .setName("Device $deviceId") .setDescriptor("descriptor $deviceId") .setGeneration(generation) .setIsVirtualDevice(isVirtual) .setSources(InputDevice.SOURCE_KEYBOARD) .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC) .build() private class TrackingInterceptor : BaseEventStreamTransformation() { Loading Loading
services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java +24 −9 Original line number Diff line number Diff line Loading @@ -648,11 +648,17 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) private void onKeyEventInternal(KeyEvent event, int policyFlags) { boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; int keyCode = event.getKeyCode(); mActiveInputDeviceId = event.getDeviceId(); InputDevice inputDevice = mInputManager.getInputDevice(mActiveInputDeviceId); final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN; final int keyCode = event.getKeyCode(); final int deviceId = event.getDeviceId(); InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (!isDeviceEligible(inputDevice)) { // Pass non-mouse key events to the next handler super.onKeyEvent(event, policyFlags); return; } mActiveInputDeviceId = deviceId; boolean usePrimaryKeys = shouldUsePrimaryKeysForDevice(inputDevice); if (!mDeviceKeyCodeMap.contains(mActiveInputDeviceId)) { Loading Loading @@ -874,10 +880,11 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation */ @Override public void onInputDeviceAdded(int deviceId) { final InputDevice device = mInputManager.getInputDevice(deviceId); if (device != null && device.isFullKeyboard()) { deviceHasNumpad(device); final InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (isDeviceEligible(inputDevice)) { deviceHasNumpad(inputDevice); } onInputDeviceChangedInternal(inputDevice); } @Override Loading @@ -896,13 +903,21 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation @Override public void onInputDeviceChanged(int deviceId) { InputDevice inputDevice = mInputManager.getInputDevice(deviceId); onInputDeviceChangedInternal(inputDevice); } private void onInputDeviceChangedInternal(@NonNull InputDevice inputDevice) { // Update the enum mapping only if input device that changed is a keyboard if (inputDevice.isFullKeyboard()) { if (isDeviceEligible(inputDevice)) { initializeDeviceToEnumMap(inputDevice, shouldUsePrimaryKeysForDevice(inputDevice)); Slog.i(LOG_TAG, "Updating key code enum map for device ID: " + deviceId); Slog.i(LOG_TAG, "Updating key code enum map for device ID: " + inputDevice.getId()); } } private boolean isDeviceEligible(@Nullable InputDevice device) { return device != null && device.isFullKeyboard() && device.isPhysicalDevice(); } /** * Observes and updates various mouse keys setting values. */ Loading
services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt +37 −10 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ class MouseKeysInterceptorTest { companion object { const val DISPLAY_ID = 1 const val DEVICE_ID = 123 const val VIRTUAL_DEVICE_ID = 456 // This delay is required for key events to be sent and handled correctly. // The handler only performs a move/scroll event if it receives the key event // at INTERVAL_MILLIS (which happens in practice). Hence, we need this delay in the tests. Loading @@ -92,6 +93,7 @@ class MouseKeysInterceptorTest { private lateinit var mouseKeysInterceptor: MouseKeysInterceptor private lateinit var inputDevice: InputDevice private lateinit var virtualInputDevice: InputDevice private val clock = OffsettableClock() private val testLooper = TestLooper { clock.now() } Loading Loading @@ -135,9 +137,12 @@ class MouseKeysInterceptorTest { testSession = InputManagerGlobal.createTestSession(iInputManager) mockInputManager = InputManager(testableContext) inputDevice = createInputDevice(DEVICE_ID) inputDevice = createInputDevice(DEVICE_ID, /* isVirtual= */ false) virtualInputDevice = createInputDevice(VIRTUAL_DEVICE_ID, /* isVirtual */ true) Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID)) .thenReturn(inputDevice) Mockito.`when`(iInputManager.getInputDevice(VIRTUAL_DEVICE_ID)) .thenReturn(virtualInputDevice) Mockito.`when`(mockVirtualDeviceManagerInternal.getDeviceIdsForUid(Mockito.anyInt())) .thenReturn(ArraySet(setOf(DEVICE_ID))) Loading @@ -153,7 +158,8 @@ class MouseKeysInterceptorTest { Mockito.any(VirtualMouseConfig::class.java) )).thenReturn(mockVirtualMouse) Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID)) Mockito.`when`(iInputManager.inputDeviceIds) .thenReturn(intArrayOf(DEVICE_ID, VIRTUAL_DEVICE_ID)) Mockito.`when`(mockAms.traceManager).thenReturn(mockTraceManager) } Loading Loading @@ -605,6 +611,23 @@ class MouseKeysInterceptorTest { verifyKeyEventsEqual(primaryKeyDownEvent, nextInterceptor.events.poll()!!) } @Test fun whenMouseKeyEventArrives_fromVirtualKeyboard_eventIsPassedToNextInterceptor() { setupMouseKeysInterceptor(usePrimaryKeys = true) for (ev in MouseKeysInterceptor.MouseKeyEvent.entries) { val downTime = clock.now() val keyCode = ev.getKeyCodeValue(USE_PRIMARY_KEYS) val downEvent = KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode, 0, 0, VIRTUAL_DEVICE_ID, 0 ) mouseKeysInterceptor.onKeyEvent(downEvent, 0) testLooper.dispatchAll() assertThat(nextInterceptor.events).hasSize(1) verifyKeyEventsEqual(downEvent, nextInterceptor.events.poll()!!) } } private fun verifyRelativeEvents(expectedX: FloatArray, expectedY: FloatArray) { assertThat(expectedX.size).isEqualTo(expectedY.size) val expectedSize = expectedX.size Loading Loading @@ -668,6 +691,7 @@ class MouseKeysInterceptorTest { private fun createInputDevice( deviceId: Int, isVirtual: Boolean, generation: Int = -1 ): InputDevice = InputDevice.Builder() Loading @@ -675,6 +699,9 @@ class MouseKeysInterceptorTest { .setName("Device $deviceId") .setDescriptor("descriptor $deviceId") .setGeneration(generation) .setIsVirtualDevice(isVirtual) .setSources(InputDevice.SOURCE_KEYBOARD) .setKeyboardType(InputDevice.KEYBOARD_TYPE_ALPHABETIC) .build() private class TrackingInterceptor : BaseEventStreamTransformation() { Loading