Loading services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java +6 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.accessibility.magnification; import static android.view.InputDevice.SOURCE_MOUSE; import static android.view.InputDevice.SOURCE_STYLUS; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; Loading Loading @@ -342,8 +340,12 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH cancelFling(); } handleTouchEventWith(mCurrentState, event, rawEvent, policyFlags); } else if (Flags.enableMagnificationFollowsMouse() && (event.getSource() == SOURCE_MOUSE || event.getSource() == SOURCE_STYLUS)) { } } @Override void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { if (Flags.enableMagnificationFollowsMouse()) { if (mFullScreenMagnificationController.isActivated(mDisplayId)) { // TODO(b/354696546): Allow mouse/stylus to activate whichever display they are // over, rather than only interacting with the current display. Loading @@ -351,8 +353,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH // Send through the mouse/stylus event handler. mMouseEventHandler.onEvent(event, mDisplayId); } // Dispatch to normal event handling flow. dispatchTransformedEvent(event, rawEvent, policyFlags); } } Loading services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java +38 −39 Original line number Diff line number Diff line Loading @@ -127,9 +127,10 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo if (DEBUG_EVENT_STREAM) { storeEventInto(mDebugInputEventHistory, event); } if (shouldDispatchTransformedEvent(event)) { dispatchTransformedEvent(event, rawEvent, policyFlags); } else { switch (event.getSource()) { case SOURCE_TOUCHSCREEN: { if (magnificationShortcutExists()) { // Observe touchscreen events while magnification activation is detected. onMotionEventInternal(event, rawEvent, policyFlags); final int action = event.getAction(); Loading @@ -138,38 +139,29 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo } else if (action == ACTION_UP || action == ACTION_CANCEL) { mCallback.onTouchInteractionEnd(mDisplayId, getMode()); } // Return early: Do not dispatch event through normal eventing // flow, it has been fully consumed by the magnifier. return; } } /** * Some touchscreen, mouse and stylus events may modify magnifier state. Checks for whether the * event should not be dispatched to the magnifier. * * @param event The event to check. * @return `true` if the event should be sent through the normal event flow or `false` if it * should be observed by magnifier. */ private boolean shouldDispatchTransformedEvent(MotionEvent event) { if (event.getSource() == SOURCE_TOUCHSCREEN) { if (mDetectSingleFingerTripleTap || mDetectTwoFingerTripleTap || mDetectShortcutTrigger) { // Observe touchscreen events while magnification activation is detected. return false; } break; case SOURCE_MOUSE: case SOURCE_STYLUS: { if (magnificationShortcutExists() && Flags.enableMagnificationFollowsMouse()) { handleMouseOrStylusEvent(event, rawEvent, policyFlags); } } if (Flags.enableMagnificationFollowsMouse()) { if (event.isFromSource(SOURCE_MOUSE) || event.isFromSource(SOURCE_STYLUS)) { // Note that mouse events include other mouse-like pointing devices // such as touchpads and pointing sticks. // Observe any mouse or stylus movement. // We observe all movement to ensure that events continue to come in order, // even though only some movement types actually move the viewport. return false; break; default: break; } // Dispatch event through normal eventing flow. dispatchTransformedEvent(event, rawEvent, policyFlags); } // Magnification dispatches (ignores) all other events return true; private boolean magnificationShortcutExists() { return (mDetectSingleFingerTripleTap || mDetectTwoFingerTripleTap || mDetectShortcutTrigger); } final void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { Loading Loading @@ -201,6 +193,13 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo */ abstract void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags); /** * Called when this MagnificationGestureHandler should handle a mouse or stylus motion event, * but not re-dispatch it when completed. */ abstract void handleMouseOrStylusEvent( MotionEvent event, MotionEvent rawEvent, int policyFlags); /** * Called when the shortcut target is magnification. */ Loading services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java +5 −1 Original line number Diff line number Diff line Loading @@ -146,10 +146,14 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl transitionTo(mDetectingState); } @Override void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { // Window Magnification viewport doesn't move with mouse events (yet). } @Override void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) { if (event.getSource() != SOURCE_TOUCHSCREEN) { // Window Magnification viewport doesn't move with mouse events (yet). return; } // To keep InputEventConsistencyVerifiers within GestureDetectors happy. Loading services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java +78 −0 Original line number Diff line number Diff line Loading @@ -18,13 +18,20 @@ package com.android.server.accessibility.magnification; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_HOVER_MOVE; import static android.view.MotionEvent.ACTION_UP; import static junit.framework.Assert.assertFalse; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.testng.AssertJUnit.assertTrue; import android.annotation.NonNull; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.view.InputDevice; import android.view.MotionEvent; Loading @@ -32,8 +39,10 @@ import android.view.MotionEvent; import androidx.test.runner.AndroidJUnit4; import com.android.server.accessibility.AccessibilityTraceManager; import com.android.server.accessibility.Flags; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -45,6 +54,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class MagnificationGestureHandlerTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private TestMagnificationGestureHandler mMgh; private static final int DISPLAY_0 = 0; private static final int FULLSCREEN_MODE = Loading Loading @@ -80,6 +92,66 @@ public class MagnificationGestureHandlerTest { } } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromMouse_handleMouseOrStylusEvent() { final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); mouseEvent.setSource(InputDevice.SOURCE_MOUSE); mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0); try { assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { mouseEvent.recycle(); } } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromStylus_handleMouseOrStylusEvent() { final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); stylusEvent.setSource(InputDevice.SOURCE_STYLUS); mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0); try { assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { stylusEvent.recycle(); } } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromMouse_handleMouseOrStylusEventNotCalled() { final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); mouseEvent.setSource(InputDevice.SOURCE_MOUSE); mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0); try { assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { mouseEvent.recycle(); } } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromStylus_handleMouseOrStylusEventNotCalled() { final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); stylusEvent.setSource(InputDevice.SOURCE_STYLUS); mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0); try { assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { stylusEvent.recycle(); } } @Test public void onMotionEvent_downEvent_handleInteractionStart() { final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); Loading Loading @@ -125,6 +197,7 @@ public class MagnificationGestureHandlerTest { private static class TestMagnificationGestureHandler extends MagnificationGestureHandler { boolean mIsInternalMethodCalled = false; boolean mIsHandleMouseOrStylusEventCalled = false; TestMagnificationGestureHandler(int displayId, boolean detectSingleFingerTripleTap, boolean detectTwoFingerTripleTap, Loading @@ -134,6 +207,11 @@ public class MagnificationGestureHandlerTest { detectShortcutTrigger, trace, callback); } @Override void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mIsHandleMouseOrStylusEventCalled = true; } @Override void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mIsInternalMethodCalled = true; Loading Loading
services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java +6 −6 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.server.accessibility.magnification; import static android.view.InputDevice.SOURCE_MOUSE; import static android.view.InputDevice.SOURCE_STYLUS; import static android.view.InputDevice.SOURCE_TOUCHSCREEN; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; Loading Loading @@ -342,8 +340,12 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH cancelFling(); } handleTouchEventWith(mCurrentState, event, rawEvent, policyFlags); } else if (Flags.enableMagnificationFollowsMouse() && (event.getSource() == SOURCE_MOUSE || event.getSource() == SOURCE_STYLUS)) { } } @Override void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { if (Flags.enableMagnificationFollowsMouse()) { if (mFullScreenMagnificationController.isActivated(mDisplayId)) { // TODO(b/354696546): Allow mouse/stylus to activate whichever display they are // over, rather than only interacting with the current display. Loading @@ -351,8 +353,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH // Send through the mouse/stylus event handler. mMouseEventHandler.onEvent(event, mDisplayId); } // Dispatch to normal event handling flow. dispatchTransformedEvent(event, rawEvent, policyFlags); } } Loading
services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java +38 −39 Original line number Diff line number Diff line Loading @@ -127,9 +127,10 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo if (DEBUG_EVENT_STREAM) { storeEventInto(mDebugInputEventHistory, event); } if (shouldDispatchTransformedEvent(event)) { dispatchTransformedEvent(event, rawEvent, policyFlags); } else { switch (event.getSource()) { case SOURCE_TOUCHSCREEN: { if (magnificationShortcutExists()) { // Observe touchscreen events while magnification activation is detected. onMotionEventInternal(event, rawEvent, policyFlags); final int action = event.getAction(); Loading @@ -138,38 +139,29 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo } else if (action == ACTION_UP || action == ACTION_CANCEL) { mCallback.onTouchInteractionEnd(mDisplayId, getMode()); } // Return early: Do not dispatch event through normal eventing // flow, it has been fully consumed by the magnifier. return; } } /** * Some touchscreen, mouse and stylus events may modify magnifier state. Checks for whether the * event should not be dispatched to the magnifier. * * @param event The event to check. * @return `true` if the event should be sent through the normal event flow or `false` if it * should be observed by magnifier. */ private boolean shouldDispatchTransformedEvent(MotionEvent event) { if (event.getSource() == SOURCE_TOUCHSCREEN) { if (mDetectSingleFingerTripleTap || mDetectTwoFingerTripleTap || mDetectShortcutTrigger) { // Observe touchscreen events while magnification activation is detected. return false; } break; case SOURCE_MOUSE: case SOURCE_STYLUS: { if (magnificationShortcutExists() && Flags.enableMagnificationFollowsMouse()) { handleMouseOrStylusEvent(event, rawEvent, policyFlags); } } if (Flags.enableMagnificationFollowsMouse()) { if (event.isFromSource(SOURCE_MOUSE) || event.isFromSource(SOURCE_STYLUS)) { // Note that mouse events include other mouse-like pointing devices // such as touchpads and pointing sticks. // Observe any mouse or stylus movement. // We observe all movement to ensure that events continue to come in order, // even though only some movement types actually move the viewport. return false; break; default: break; } // Dispatch event through normal eventing flow. dispatchTransformedEvent(event, rawEvent, policyFlags); } // Magnification dispatches (ignores) all other events return true; private boolean magnificationShortcutExists() { return (mDetectSingleFingerTripleTap || mDetectTwoFingerTripleTap || mDetectShortcutTrigger); } final void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { Loading Loading @@ -201,6 +193,13 @@ public abstract class MagnificationGestureHandler extends BaseEventStreamTransfo */ abstract void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags); /** * Called when this MagnificationGestureHandler should handle a mouse or stylus motion event, * but not re-dispatch it when completed. */ abstract void handleMouseOrStylusEvent( MotionEvent event, MotionEvent rawEvent, int policyFlags); /** * Called when the shortcut target is magnification. */ Loading
services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java +5 −1 Original line number Diff line number Diff line Loading @@ -146,10 +146,14 @@ public class WindowMagnificationGestureHandler extends MagnificationGestureHandl transitionTo(mDetectingState); } @Override void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { // Window Magnification viewport doesn't move with mouse events (yet). } @Override void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) { if (event.getSource() != SOURCE_TOUCHSCREEN) { // Window Magnification viewport doesn't move with mouse events (yet). return; } // To keep InputEventConsistencyVerifiers within GestureDetectors happy. Loading
services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java +78 −0 Original line number Diff line number Diff line Loading @@ -18,13 +18,20 @@ package com.android.server.accessibility.magnification; import static android.view.MotionEvent.ACTION_CANCEL; import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_HOVER_MOVE; import static android.view.MotionEvent.ACTION_UP; import static junit.framework.Assert.assertFalse; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.testng.AssertJUnit.assertTrue; import android.annotation.NonNull; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.provider.Settings; import android.view.InputDevice; import android.view.MotionEvent; Loading @@ -32,8 +39,10 @@ import android.view.MotionEvent; import androidx.test.runner.AndroidJUnit4; import com.android.server.accessibility.AccessibilityTraceManager; import com.android.server.accessibility.Flags; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -45,6 +54,9 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class MagnificationGestureHandlerTest { @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private TestMagnificationGestureHandler mMgh; private static final int DISPLAY_0 = 0; private static final int FULLSCREEN_MODE = Loading Loading @@ -80,6 +92,66 @@ public class MagnificationGestureHandlerTest { } } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromMouse_handleMouseOrStylusEvent() { final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); mouseEvent.setSource(InputDevice.SOURCE_MOUSE); mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0); try { assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { mouseEvent.recycle(); } } @Test @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromStylus_handleMouseOrStylusEvent() { final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); stylusEvent.setSource(InputDevice.SOURCE_STYLUS); mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0); try { assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { stylusEvent.recycle(); } } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromMouse_handleMouseOrStylusEventNotCalled() { final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); mouseEvent.setSource(InputDevice.SOURCE_MOUSE); mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0); try { assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { mouseEvent.recycle(); } } @Test @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE) public void onMotionEvent_isFromStylus_handleMouseOrStylusEventNotCalled() { final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0); stylusEvent.setSource(InputDevice.SOURCE_STYLUS); mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0); try { assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled); } finally { stylusEvent.recycle(); } } @Test public void onMotionEvent_downEvent_handleInteractionStart() { final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0); Loading Loading @@ -125,6 +197,7 @@ public class MagnificationGestureHandlerTest { private static class TestMagnificationGestureHandler extends MagnificationGestureHandler { boolean mIsInternalMethodCalled = false; boolean mIsHandleMouseOrStylusEventCalled = false; TestMagnificationGestureHandler(int displayId, boolean detectSingleFingerTripleTap, boolean detectTwoFingerTripleTap, Loading @@ -134,6 +207,11 @@ public class MagnificationGestureHandlerTest { detectShortcutTrigger, trace, callback); } @Override void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mIsHandleMouseOrStylusEventCalled = true; } @Override void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mIsInternalMethodCalled = true; Loading