diff options
2 files changed, 128 insertions, 9 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java index 739ea0df87ab..cc93d0887d89 100644 --- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java @@ -248,7 +248,11 @@ public class AutoclickController extends BaseEventStreamTransformation { private boolean isPaused() { return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isPaused() - && !mAutoclickTypePanel.isHovered(); + && !isHovered(); + } + + private boolean isHovered() { + return Flags.enableAutoclickIndicator() && mAutoclickTypePanel.isHovered(); } private void cancelPendingClick() { @@ -495,6 +499,8 @@ public class AutoclickController extends BaseEventStreamTransformation { private int mEventPolicyFlags; /** Current meta state. This value will be used as meta state for click event sequence. */ private int mMetaState; + /** Last observed panel hovered state when click was scheduled. */ + private boolean mHoveredState; /** * The current anchor's coordinates. Should be ignored if #mLastMotionEvent is null. @@ -648,6 +654,7 @@ public class AutoclickController extends BaseEventStreamTransformation { } mLastMotionEvent = MotionEvent.obtain(event); mEventPolicyFlags = policyFlags; + mHoveredState = isHovered(); if (useAsAnchor) { final int pointerIndex = mLastMotionEvent.getActionIndex(); @@ -729,14 +736,18 @@ public class AutoclickController extends BaseEventStreamTransformation { final long now = SystemClock.uptimeMillis(); - // TODO(b/395094903): always triggers left-click when the cursor hovers over the - // autoclick type panel, to always allow users to change a different click type. - // Otherwise, if one chooses the right-click, this user won't be able to rely on - // autoclick to select other click types. - final int actionButton = - mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK - ? BUTTON_SECONDARY - : BUTTON_PRIMARY; + int actionButton; + if (mHoveredState) { + // Always triggers left-click when the cursor hovers over the autoclick type + // panel, to always allow users to change a different click type. Otherwise, if + // one chooses the right-click, this user won't be able to rely on autoclick to + // select other click types. + actionButton = BUTTON_PRIMARY; + } else { + actionButton = mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK + ? BUTTON_SECONDARY + : BUTTON_PRIMARY; + } MotionEvent downEvent = MotionEvent.obtain( diff --git a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java index 69877c372442..ea25e7992dd9 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java @@ -43,6 +43,7 @@ import android.view.accessibility.AccessibilityManager; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.server.accessibility.AccessibilityTraceManager; +import com.android.server.accessibility.BaseEventStreamTransformation; import org.junit.After; import org.junit.Before; @@ -70,6 +71,19 @@ public class AutoclickControllerTest { @Mock private WindowManager mMockWindowManager; private AutoclickController mController; + private static class MotionEventCaptor extends BaseEventStreamTransformation { + public MotionEvent downEvent; + + @Override + public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + downEvent = event; + break; + } + } + } + @Before public void setUp() { mTestableLooper = TestableLooper.get(this); @@ -713,6 +727,100 @@ public class AutoclickControllerTest { assertThat(mController.mAutoclickScrollPanel.isVisible()).isFalse(); } + @Test + public void sendClick_clickType_leftClick() { + MotionEventCaptor motionEventCaptor = new MotionEventCaptor(); + mController.setNext(motionEventCaptor); + + injectFakeMouseActionHoverMoveEvent(); + // Set delay to zero so click is scheduled to run immediately. + mController.mClickScheduler.updateDelay(0); + + // Send hover move event. + MotionEvent hoverMove = MotionEvent.obtain( + /* downTime= */ 0, + /* eventTime= */ 100, + /* action= */ MotionEvent.ACTION_HOVER_MOVE, + /* x= */ 30f, + /* y= */ 0f, + /* metaState= */ 0); + hoverMove.setSource(InputDevice.SOURCE_MOUSE); + mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + mTestableLooper.processAllMessages(); + + // Verify left click sent. + assertThat(motionEventCaptor.downEvent).isNotNull(); + assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo( + MotionEvent.BUTTON_PRIMARY); + } + + @Test + public void sendClick_clickType_rightClick() { + MotionEventCaptor motionEventCaptor = new MotionEventCaptor(); + mController.setNext(motionEventCaptor); + + injectFakeMouseActionHoverMoveEvent(); + // Set delay to zero so click is scheduled to run immediately. + mController.mClickScheduler.updateDelay(0); + + // Set click type to right click. + mController.clickPanelController.handleAutoclickTypeChange( + AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK); + + // Send hover move event. + MotionEvent hoverMove = MotionEvent.obtain( + /* downTime= */ 0, + /* eventTime= */ 100, + /* action= */ MotionEvent.ACTION_HOVER_MOVE, + /* x= */ 30f, + /* y= */ 0f, + /* metaState= */ 0); + hoverMove.setSource(InputDevice.SOURCE_MOUSE); + mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + mTestableLooper.processAllMessages(); + + // Verify right click sent. + assertThat(motionEventCaptor.downEvent).isNotNull(); + assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo( + MotionEvent.BUTTON_SECONDARY); + } + + @Test + @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) + public void hoverOnAutoclickPanel_rightClickType_forceTriggerLeftClick() { + MotionEventCaptor motionEventCaptor = new MotionEventCaptor(); + mController.setNext(motionEventCaptor); + + injectFakeMouseActionHoverMoveEvent(); + // Set delay to zero so click is scheduled to run immediately. + mController.mClickScheduler.updateDelay(0); + + // Set click type to right click. + mController.clickPanelController.handleAutoclickTypeChange( + AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK); + // Set mouse to hover panel. + AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); + when(mockAutoclickTypePanel.isHovered()).thenReturn(true); + mController.mAutoclickTypePanel = mockAutoclickTypePanel; + + // Send hover move event. + MotionEvent hoverMove = MotionEvent.obtain( + /* downTime= */ 0, + /* eventTime= */ 100, + /* action= */ MotionEvent.ACTION_HOVER_MOVE, + /* x= */ 30f, + /* y= */ 0f, + /* metaState= */ 0); + hoverMove.setSource(InputDevice.SOURCE_MOUSE); + mController.onMotionEvent(hoverMove, hoverMove, /* policyFlags= */ 0); + mTestableLooper.processAllMessages(); + + // Verify left click is sent due to the mouse hovering the panel. + assertThat(motionEventCaptor.downEvent).isNotNull(); + assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo( + MotionEvent.BUTTON_PRIMARY); + } + private void injectFakeMouseActionHoverMoveEvent() { MotionEvent event = getFakeMotionHoverMoveEvent(); event.setSource(InputDevice.SOURCE_MOUSE); |