Loading services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +9 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.accessibility; import static android.view.InputDevice.SOURCE_CLASS_POINTER; import static android.view.MotionEvent.ACTION_SCROLL; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; Loading Loading @@ -425,6 +427,12 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo boolean shouldProcessMultiDeviceEvent(InputEvent event, int policyFlags) { if (event instanceof MotionEvent motion) { if (!motion.isFromSource(SOURCE_CLASS_POINTER) || motion.getAction() == ACTION_SCROLL) { // Non-pointer events are focus-dispatched and don't require special logic. // Scroll events are stand-alone and therefore can be considered to not be part of // a stream. return true; } // Only allow 1 device to be sending motion events at a time // If the event is from an active device, let it through. // If the event is not from an active device, only let it through if it starts a new Loading Loading @@ -481,7 +489,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } private void processMotionEvent(EventStreamState state, MotionEvent event, int policyFlags) { if (!state.shouldProcessScroll() && event.getActionMasked() == MotionEvent.ACTION_SCROLL) { if (!state.shouldProcessScroll() && event.getActionMasked() == ACTION_SCROLL) { super.onInputEvent(event, policyFlags); return; } Loading services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt +25 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DisplayAdjustments import android.view.DisplayInfo import android.view.IInputFilterHost import android.view.InputDevice.SOURCE_JOYSTICK import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputEvent Loading Loading @@ -130,6 +131,8 @@ class AccessibilityInputFilterInputTest { private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) private val stylusDeviceId = 2 private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) private val joystickDeviceId = 3 private val fromJoystick = allOf(withDeviceId(joystickDeviceId), withSource(SOURCE_JOYSTICK)) @Before fun setUp() { Loading Loading @@ -457,6 +460,23 @@ class AccessibilityInputFilterInputTest { verifier.assertNoEvents() } /** * Send some joystick events and ensure they pass through normally. */ @Test fun testJoystickEvents() { enableFeatures(ALL_A11Y_FEATURES) sendJoystickEvent() verifier.assertReceivedMotion(fromJoystick) sendJoystickEvent() verifier.assertReceivedMotion(fromJoystick) sendJoystickEvent() verifier.assertReceivedMotion(fromJoystick) } private fun createStubDisplay(displayId: Int, displayInfo: DisplayInfo): Display { val display = Display(DisplayManagerGlobal.getInstance(), displayId, displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) Loading @@ -477,6 +497,11 @@ class AccessibilityInputFilterInputTest { send(createMotionEvent(action, downTime, eventTime, STYLUS_SOURCE, stylusDeviceId)) } private fun sendJoystickEvent() { val time = SystemClock.uptimeMillis() send(createMotionEvent(ACTION_MOVE, time, time, SOURCE_JOYSTICK, joystickDeviceId)) } private fun send(event: InputEvent) { // We need to make a copy of the event before sending it to the filter, because the filter // will recycle it, but the caller of this function might want to still be able to use Loading Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +9 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.accessibility; import static android.view.InputDevice.SOURCE_CLASS_POINTER; import static android.view.MotionEvent.ACTION_SCROLL; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; Loading Loading @@ -425,6 +427,12 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo boolean shouldProcessMultiDeviceEvent(InputEvent event, int policyFlags) { if (event instanceof MotionEvent motion) { if (!motion.isFromSource(SOURCE_CLASS_POINTER) || motion.getAction() == ACTION_SCROLL) { // Non-pointer events are focus-dispatched and don't require special logic. // Scroll events are stand-alone and therefore can be considered to not be part of // a stream. return true; } // Only allow 1 device to be sending motion events at a time // If the event is from an active device, let it through. // If the event is not from an active device, only let it through if it starts a new Loading Loading @@ -481,7 +489,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo } private void processMotionEvent(EventStreamState state, MotionEvent event, int policyFlags) { if (!state.shouldProcessScroll() && event.getActionMasked() == MotionEvent.ACTION_SCROLL) { if (!state.shouldProcessScroll() && event.getActionMasked() == ACTION_SCROLL) { super.onInputEvent(event, policyFlags); return; } Loading
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt +25 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DisplayAdjustments import android.view.DisplayInfo import android.view.IInputFilterHost import android.view.InputDevice.SOURCE_JOYSTICK import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputEvent Loading Loading @@ -130,6 +131,8 @@ class AccessibilityInputFilterInputTest { private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) private val stylusDeviceId = 2 private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) private val joystickDeviceId = 3 private val fromJoystick = allOf(withDeviceId(joystickDeviceId), withSource(SOURCE_JOYSTICK)) @Before fun setUp() { Loading Loading @@ -457,6 +460,23 @@ class AccessibilityInputFilterInputTest { verifier.assertNoEvents() } /** * Send some joystick events and ensure they pass through normally. */ @Test fun testJoystickEvents() { enableFeatures(ALL_A11Y_FEATURES) sendJoystickEvent() verifier.assertReceivedMotion(fromJoystick) sendJoystickEvent() verifier.assertReceivedMotion(fromJoystick) sendJoystickEvent() verifier.assertReceivedMotion(fromJoystick) } private fun createStubDisplay(displayId: Int, displayInfo: DisplayInfo): Display { val display = Display(DisplayManagerGlobal.getInstance(), displayId, displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) Loading @@ -477,6 +497,11 @@ class AccessibilityInputFilterInputTest { send(createMotionEvent(action, downTime, eventTime, STYLUS_SOURCE, stylusDeviceId)) } private fun sendJoystickEvent() { val time = SystemClock.uptimeMillis() send(createMotionEvent(ACTION_MOVE, time, time, SOURCE_JOYSTICK, joystickDeviceId)) } private fun send(event: InputEvent) { // We need to make a copy of the event before sending it to the filter, because the filter // will recycle it, but the caller of this function might want to still be able to use Loading