Loading services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java +9 −1 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.accessibility; 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_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_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) { boolean shouldProcessMultiDeviceEvent(InputEvent event, int policyFlags) { if (event instanceof MotionEvent motion) { 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 // 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 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 // 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) { 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); super.onInputEvent(event, policyFlags); return; return; } } Loading services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt +25 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DisplayAdjustments import android.view.DisplayAdjustments import android.view.DisplayInfo import android.view.DisplayInfo import android.view.IInputFilterHost import android.view.IInputFilterHost import android.view.InputDevice.SOURCE_JOYSTICK import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputEvent import android.view.InputEvent Loading Loading @@ -130,6 +131,8 @@ class AccessibilityInputFilterInputTest { private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) private val stylusDeviceId = 2 private val stylusDeviceId = 2 private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) private val joystickDeviceId = 3 private val fromJoystick = allOf(withDeviceId(joystickDeviceId), withSource(SOURCE_JOYSTICK)) @Before @Before fun setUp() { fun setUp() { Loading Loading @@ -457,6 +460,23 @@ class AccessibilityInputFilterInputTest { verifier.assertNoEvents() 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 { private fun createStubDisplay(displayId: Int, displayInfo: DisplayInfo): Display { val display = Display(DisplayManagerGlobal.getInstance(), displayId, val display = Display(DisplayManagerGlobal.getInstance(), displayId, displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) Loading @@ -477,6 +497,11 @@ class AccessibilityInputFilterInputTest { send(createMotionEvent(action, downTime, eventTime, STYLUS_SOURCE, stylusDeviceId)) 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) { private fun send(event: InputEvent) { // We need to make a copy of the event before sending it to the filter, because the filter // 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 // 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 Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.server.accessibility; 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_ACCESSIBILITY_MAGNIFICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_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) { boolean shouldProcessMultiDeviceEvent(InputEvent event, int policyFlags) { if (event instanceof MotionEvent motion) { 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 // 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 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 // 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) { 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); super.onInputEvent(event, policyFlags); return; return; } } Loading
services/tests/servicestests/src/com/android/server/accessibility/AccessibilityInputFilterInputTest.kt +25 −0 Original line number Original line Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.Display.DEFAULT_DISPLAY import android.view.DisplayAdjustments import android.view.DisplayAdjustments import android.view.DisplayInfo import android.view.DisplayInfo import android.view.IInputFilterHost import android.view.IInputFilterHost import android.view.InputDevice.SOURCE_JOYSTICK import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_STYLUS import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputDevice.SOURCE_TOUCHSCREEN import android.view.InputEvent import android.view.InputEvent Loading Loading @@ -130,6 +131,8 @@ class AccessibilityInputFilterInputTest { private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) private val fromTouchScreen = allOf(withDeviceId(touchDeviceId), withSource(SOURCE_TOUCHSCREEN)) private val stylusDeviceId = 2 private val stylusDeviceId = 2 private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) private val fromStylus = allOf(withDeviceId(stylusDeviceId), withSource(STYLUS_SOURCE)) private val joystickDeviceId = 3 private val fromJoystick = allOf(withDeviceId(joystickDeviceId), withSource(SOURCE_JOYSTICK)) @Before @Before fun setUp() { fun setUp() { Loading Loading @@ -457,6 +460,23 @@ class AccessibilityInputFilterInputTest { verifier.assertNoEvents() 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 { private fun createStubDisplay(displayId: Int, displayInfo: DisplayInfo): Display { val display = Display(DisplayManagerGlobal.getInstance(), displayId, val display = Display(DisplayManagerGlobal.getInstance(), displayId, displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) displayInfo, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS) Loading @@ -477,6 +497,11 @@ class AccessibilityInputFilterInputTest { send(createMotionEvent(action, downTime, eventTime, STYLUS_SOURCE, stylusDeviceId)) 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) { private fun send(event: InputEvent) { // We need to make a copy of the event before sending it to the filter, because the filter // 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 // will recycle it, but the caller of this function might want to still be able to use Loading