Loading services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +20 −9 Original line number Diff line number Diff line Loading @@ -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() { Loading Loading @@ -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. Loading Loading @@ -648,6 +654,7 @@ public class AutoclickController extends BaseEventStreamTransformation { } mLastMotionEvent = MotionEvent.obtain(event); mEventPolicyFlags = policyFlags; mHoveredState = isHovered(); if (useAsAnchor) { final int pointerIndex = mLastMotionEvent.getActionIndex(); Loading Loading @@ -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 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( Loading services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +108 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); Loading Loading
services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +20 −9 Original line number Diff line number Diff line Loading @@ -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() { Loading Loading @@ -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. Loading Loading @@ -648,6 +654,7 @@ public class AutoclickController extends BaseEventStreamTransformation { } mLastMotionEvent = MotionEvent.obtain(event); mEventPolicyFlags = policyFlags; mHoveredState = isHovered(); if (useAsAnchor) { final int pointerIndex = mLastMotionEvent.getActionIndex(); Loading Loading @@ -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 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( Loading
services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +108 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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); Loading