Loading services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +25 −6 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_M import static android.view.accessibility.AccessibilityManager.AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT; import static com.android.server.accessibility.autoclick.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_SCROLL; Loading @@ -45,6 +46,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; import android.view.ViewConfiguration; import android.view.WindowManager; import androidx.annotation.VisibleForTesting; Loading Loading @@ -799,7 +801,7 @@ public class AutoclickController extends BaseEventStreamTransformation { final long now = SystemClock.uptimeMillis(); int actionButton; int actionButton = BUTTON_PRIMARY; 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 Loading @@ -807,15 +809,32 @@ public class AutoclickController extends BaseEventStreamTransformation { // select other click types. actionButton = BUTTON_PRIMARY; } else { actionButton = mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK ? BUTTON_SECONDARY : BUTTON_PRIMARY; switch (mActiveClickType) { case AUTOCLICK_TYPE_LEFT_CLICK: actionButton = BUTTON_PRIMARY; break; case AUTOCLICK_TYPE_RIGHT_CLICK: actionButton = BUTTON_SECONDARY; break; case AUTOCLICK_TYPE_DOUBLE_CLICK: actionButton = BUTTON_PRIMARY; long doubleTapMinimumTimeout = ViewConfiguration.getDoubleTapMinTime(); sendMotionEvent(actionButton, now); sendMotionEvent(actionButton, now + doubleTapMinimumTimeout); return; default: break; } } sendMotionEvent(actionButton, now); } private void sendMotionEvent(int actionButton, long eventTime) { MotionEvent downEvent = MotionEvent.obtain( /* downTime= */ now, /* eventTime= */ now, /* downTime= */ eventTime, /* eventTime= */ eventTime, MotionEvent.ACTION_DOWN, /* pointerCount= */ 1, mTempPointerProperties, Loading services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +37 −1 Original line number Diff line number Diff line Loading @@ -75,12 +75,13 @@ public class AutoclickControllerTest { private static class MotionEventCaptor extends BaseEventStreamTransformation { public MotionEvent downEvent; public int eventCount = 0; @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downEvent = event; eventCount++; break; } } Loading Loading @@ -922,6 +923,41 @@ public class AutoclickControllerTest { mController.onKeyEvent(keyEvent, /* policyFlags= */ 0); } @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void sendClick_clickType_doubleclick_triggerClickTwice() { 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 double click. mController.clickPanelController.handleAutoclickTypeChange( AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK); AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); 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 sent. assertThat(motionEventCaptor.downEvent).isNotNull(); assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo( MotionEvent.BUTTON_PRIMARY); assertThat(motionEventCaptor.eventCount).isEqualTo(2); } private MotionEvent getFakeMotionHoverMoveEvent() { return MotionEvent.obtain( /* downTime= */ 0, Loading Loading
services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +25 −6 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_M import static android.view.accessibility.AccessibilityManager.AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT; import static com.android.server.accessibility.autoclick.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_SCROLL; Loading @@ -45,6 +46,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; import android.view.ViewConfiguration; import android.view.WindowManager; import androidx.annotation.VisibleForTesting; Loading Loading @@ -799,7 +801,7 @@ public class AutoclickController extends BaseEventStreamTransformation { final long now = SystemClock.uptimeMillis(); int actionButton; int actionButton = BUTTON_PRIMARY; 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 Loading @@ -807,15 +809,32 @@ public class AutoclickController extends BaseEventStreamTransformation { // select other click types. actionButton = BUTTON_PRIMARY; } else { actionButton = mActiveClickType == AUTOCLICK_TYPE_RIGHT_CLICK ? BUTTON_SECONDARY : BUTTON_PRIMARY; switch (mActiveClickType) { case AUTOCLICK_TYPE_LEFT_CLICK: actionButton = BUTTON_PRIMARY; break; case AUTOCLICK_TYPE_RIGHT_CLICK: actionButton = BUTTON_SECONDARY; break; case AUTOCLICK_TYPE_DOUBLE_CLICK: actionButton = BUTTON_PRIMARY; long doubleTapMinimumTimeout = ViewConfiguration.getDoubleTapMinTime(); sendMotionEvent(actionButton, now); sendMotionEvent(actionButton, now + doubleTapMinimumTimeout); return; default: break; } } sendMotionEvent(actionButton, now); } private void sendMotionEvent(int actionButton, long eventTime) { MotionEvent downEvent = MotionEvent.obtain( /* downTime= */ now, /* eventTime= */ now, /* downTime= */ eventTime, /* eventTime= */ eventTime, MotionEvent.ACTION_DOWN, /* pointerCount= */ 1, mTempPointerProperties, Loading
services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +37 −1 Original line number Diff line number Diff line Loading @@ -75,12 +75,13 @@ public class AutoclickControllerTest { private static class MotionEventCaptor extends BaseEventStreamTransformation { public MotionEvent downEvent; public int eventCount = 0; @Override public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downEvent = event; eventCount++; break; } } Loading Loading @@ -922,6 +923,41 @@ public class AutoclickControllerTest { mController.onKeyEvent(keyEvent, /* policyFlags= */ 0); } @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void sendClick_clickType_doubleclick_triggerClickTwice() { 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 double click. mController.clickPanelController.handleAutoclickTypeChange( AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK); AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); 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 sent. assertThat(motionEventCaptor.downEvent).isNotNull(); assertThat(motionEventCaptor.downEvent.getButtonState()).isEqualTo( MotionEvent.BUTTON_PRIMARY); assertThat(motionEventCaptor.eventCount).isEqualTo(2); } private MotionEvent getFakeMotionHoverMoveEvent() { return MotionEvent.obtain( /* downTime= */ 0, Loading