Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a5dd6e8 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

A11yInputFilter: only multiplex pointer events

For events that are focus-dispatched, like joystick events, and also for
ACTION_SCROLL events (since they are always treated independently), we
don't need to turn on the multiplexer. The multiplexer should only be
used on pointer events.

The AccessibilityDisplayProxyTest was tested on tangor by first removing
all of the test assumptions locally (otherwise, the tests were skipped
due to assumption failure).

Bug: 326686780
Test: atest AccessibilityInputFilterInputTest
Test: atest android.accessibilityservice.cts.AccessibilityEndToEndTest#testOnMotionEvent_interceptsEventFromRequestedSource_SetAndUnset
Test: atest AccessibilityDisplayProxyTest
Change-Id: I40a1b42aa8a169138c96972a39ebed5d16483d11
parent 05a19f50
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -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;

@@ -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
@@ -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;
        }
+25 −0
Original line number Diff line number Diff line
@@ -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
@@ -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() {
@@ -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)
@@ -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