Loading services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +47 −1 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.view.MotionEvent.BUTTON_SECONDARY; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; 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.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK; Loading Loading @@ -159,7 +160,8 @@ public class AutoclickController extends BaseEventStreamTransformation { initiateAutoclickIndicator(handler); initiateAutoclickIndicator(handler); } } mClickScheduler = new ClickScheduler(handler, AUTOCLICK_DELAY_DEFAULT); mClickScheduler = new ClickScheduler( handler, AUTOCLICK_DELAY_DEFAULT); mAutoclickSettingsObserver = new AutoclickSettingsObserver(mUserId, handler); mAutoclickSettingsObserver = new AutoclickSettingsObserver(mUserId, handler); mAutoclickSettingsObserver.start( mAutoclickSettingsObserver.start( mContext.getContentResolver(), mContext.getContentResolver(), Loading Loading @@ -304,6 +306,10 @@ public class AutoclickController extends BaseEventStreamTransformation { Settings.Secure.getUriFor( Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT); Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT); private final Uri mAutoclickRevertToLeftClickSettingUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK); private ContentResolver mContentResolver; private ContentResolver mContentResolver; private ClickScheduler mClickScheduler; private ClickScheduler mClickScheduler; private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; Loading Loading @@ -368,6 +374,13 @@ public class AutoclickController extends BaseEventStreamTransformation { /* observer= */ this, /* observer= */ this, mUserId); mUserId); onChange(/* selfChange= */ true, mAutoclickIgnoreMinorCursorMovementSettingUri); onChange(/* selfChange= */ true, mAutoclickIgnoreMinorCursorMovementSettingUri); mContentResolver.registerContentObserver( mAutoclickRevertToLeftClickSettingUri, /* notifyForDescendants= */ false, /* observer= */ this, mUserId); onChange(/* selfChange= */ true, mAutoclickRevertToLeftClickSettingUri); } } } } Loading Loading @@ -424,6 +437,20 @@ public class AutoclickController extends BaseEventStreamTransformation { == AccessibilityUtils.State.ON; == AccessibilityUtils.State.ON; mClickScheduler.setIgnoreMinorCursorMovement(ignoreMinorCursorMovement); mClickScheduler.setIgnoreMinorCursorMovement(ignoreMinorCursorMovement); } } if (mAutoclickRevertToLeftClickSettingUri.equals(uri)) { boolean revertToLeftClick = Settings.Secure.getIntForUser( mContentResolver, Settings.Secure .ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT ? AccessibilityUtils.State.ON : AccessibilityUtils.State.OFF, mUserId) == AccessibilityUtils.State.ON; mClickScheduler.setRevertToLeftClick(revertToLeftClick); } } } } } } } Loading Loading @@ -505,6 +532,9 @@ public class AutoclickController extends BaseEventStreamTransformation { /** Whether the minor cursor movement should be ignored. */ /** Whether the minor cursor movement should be ignored. */ private boolean mIgnoreMinorCursorMovement = AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; private boolean mIgnoreMinorCursorMovement = AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; /** Whether the autoclick type reverts to left click once performing an action. */ private boolean mRevertToLeftClick = AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT; /** Whether there is pending click. */ /** Whether there is pending click. */ private boolean mActive; private boolean mActive; /** If active, time at which pending click is scheduled. */ /** If active, time at which pending click is scheduled. */ Loading Loading @@ -555,6 +585,7 @@ public class AutoclickController extends BaseEventStreamTransformation { sendClick(); sendClick(); resetInternalState(); resetInternalState(); resetSelectedClickTypeIfNecessary(); } } /** /** Loading Loading @@ -633,6 +664,11 @@ public class AutoclickController extends BaseEventStreamTransformation { return mDelay; return mDelay; } } @VisibleForTesting boolean getRevertToLeftClickForTesting() { return mRevertToLeftClick; } /** /** * Updates the time at which click sequence should occur. * Updates the time at which click sequence should occur. * * Loading Loading @@ -692,6 +728,12 @@ public class AutoclickController extends BaseEventStreamTransformation { } } } } private void resetSelectedClickTypeIfNecessary() { if (mRevertToLeftClick && mActiveClickType != AUTOCLICK_TYPE_LEFT_CLICK) { mAutoclickTypePanel.resetSelectedClickType(); } } /** /** * @param event Observed motion event. * @param event Observed motion event. * @return Whether the event coords are far enough from the anchor for the event not to be * @return Whether the event coords are far enough from the anchor for the event not to be Loading @@ -716,6 +758,10 @@ public class AutoclickController extends BaseEventStreamTransformation { mIgnoreMinorCursorMovement = ignoreMinorCursorMovement; mIgnoreMinorCursorMovement = ignoreMinorCursorMovement; } } public void setRevertToLeftClick(boolean revertToLeftClick) { mRevertToLeftClick = revertToLeftClick; } private void updateMovementSlop(double slop) { private void updateMovementSlop(double slop) { mMovementSlop = slop; mMovementSlop = slop; } } Loading services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -283,7 +283,11 @@ public class AutoclickTypePanel { // The pause button calls `togglePause()` directly so it does not need extra logic. // The pause button calls `togglePause()` directly so it does not need extra logic. mPauseButton.setOnClickListener(v -> togglePause()); mPauseButton.setOnClickListener(v -> togglePause()); // Initializes panel as collapsed state and only displays the left click button. resetSelectedClickType(); } /** Reset panel as collapsed state and only displays the left click button. */ public void resetSelectedClickType() { hideAllClickTypeButtons(); hideAllClickTypeButtons(); mLeftClickButton.setVisibility(View.VISIBLE); mLeftClickButton.setVisibility(View.VISIBLE); setSelectedClickType(AUTOCLICK_TYPE_LEFT_CLICK); setSelectedClickType(AUTOCLICK_TYPE_LEFT_CLICK); Loading services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +26 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.accessibility.autoclick; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK; import static com.android.server.testutils.MockitoUtilsKt.eq; import static com.android.server.testutils.MockitoUtilsKt.eq; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -545,6 +546,29 @@ public class AutoclickControllerTest { assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); } } @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void triggerRightClickWithRevertToLeftClickEnabled_resetClickType() { // Move mouse to initialize autoclick panel. injectFakeMouseActionHoverMoveEvent(); AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); mController.mAutoclickTypePanel = mockAutoclickTypePanel; mController.clickPanelController.handleAutoclickTypeChange(AUTOCLICK_TYPE_RIGHT_CLICK); // Set ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK to true. Settings.Secure.putIntForUser(mTestableContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, AccessibilityUtils.State.ON, mTestableContext.getUserId()); mController.onChangeForTesting(/* selfChange= */ true, Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK)); when(mockAutoclickTypePanel.isPaused()).thenReturn(false); mController.mClickScheduler.run(); assertThat(mController.mClickScheduler.getRevertToLeftClickForTesting()).isTrue(); } @Test @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void pauseButton_flagOn_clickNotTriggeredWhenPaused() { public void pauseButton_flagOn_clickNotTriggeredWhenPaused() { Loading Loading @@ -766,6 +790,8 @@ public class AutoclickControllerTest { // Set click type to right click. // Set click type to right click. mController.clickPanelController.handleAutoclickTypeChange( mController.clickPanelController.handleAutoclickTypeChange( AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK); AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK); AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. // Send hover move event. MotionEvent hoverMove = MotionEvent.obtain( MotionEvent hoverMove = MotionEvent.obtain( Loading Loading
services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java +47 −1 Original line number Original line Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.view.MotionEvent.BUTTON_SECONDARY; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_CURSOR_AREA_SIZE_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_DELAY_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; import static android.view.accessibility.AccessibilityManager.AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; 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.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK; Loading Loading @@ -159,7 +160,8 @@ public class AutoclickController extends BaseEventStreamTransformation { initiateAutoclickIndicator(handler); initiateAutoclickIndicator(handler); } } mClickScheduler = new ClickScheduler(handler, AUTOCLICK_DELAY_DEFAULT); mClickScheduler = new ClickScheduler( handler, AUTOCLICK_DELAY_DEFAULT); mAutoclickSettingsObserver = new AutoclickSettingsObserver(mUserId, handler); mAutoclickSettingsObserver = new AutoclickSettingsObserver(mUserId, handler); mAutoclickSettingsObserver.start( mAutoclickSettingsObserver.start( mContext.getContentResolver(), mContext.getContentResolver(), Loading Loading @@ -304,6 +306,10 @@ public class AutoclickController extends BaseEventStreamTransformation { Settings.Secure.getUriFor( Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT); Settings.Secure.ACCESSIBILITY_AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT); private final Uri mAutoclickRevertToLeftClickSettingUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK); private ContentResolver mContentResolver; private ContentResolver mContentResolver; private ClickScheduler mClickScheduler; private ClickScheduler mClickScheduler; private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; Loading Loading @@ -368,6 +374,13 @@ public class AutoclickController extends BaseEventStreamTransformation { /* observer= */ this, /* observer= */ this, mUserId); mUserId); onChange(/* selfChange= */ true, mAutoclickIgnoreMinorCursorMovementSettingUri); onChange(/* selfChange= */ true, mAutoclickIgnoreMinorCursorMovementSettingUri); mContentResolver.registerContentObserver( mAutoclickRevertToLeftClickSettingUri, /* notifyForDescendants= */ false, /* observer= */ this, mUserId); onChange(/* selfChange= */ true, mAutoclickRevertToLeftClickSettingUri); } } } } Loading Loading @@ -424,6 +437,20 @@ public class AutoclickController extends BaseEventStreamTransformation { == AccessibilityUtils.State.ON; == AccessibilityUtils.State.ON; mClickScheduler.setIgnoreMinorCursorMovement(ignoreMinorCursorMovement); mClickScheduler.setIgnoreMinorCursorMovement(ignoreMinorCursorMovement); } } if (mAutoclickRevertToLeftClickSettingUri.equals(uri)) { boolean revertToLeftClick = Settings.Secure.getIntForUser( mContentResolver, Settings.Secure .ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT ? AccessibilityUtils.State.ON : AccessibilityUtils.State.OFF, mUserId) == AccessibilityUtils.State.ON; mClickScheduler.setRevertToLeftClick(revertToLeftClick); } } } } } } } Loading Loading @@ -505,6 +532,9 @@ public class AutoclickController extends BaseEventStreamTransformation { /** Whether the minor cursor movement should be ignored. */ /** Whether the minor cursor movement should be ignored. */ private boolean mIgnoreMinorCursorMovement = AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; private boolean mIgnoreMinorCursorMovement = AUTOCLICK_IGNORE_MINOR_CURSOR_MOVEMENT_DEFAULT; /** Whether the autoclick type reverts to left click once performing an action. */ private boolean mRevertToLeftClick = AUTOCLICK_REVERT_TO_LEFT_CLICK_DEFAULT; /** Whether there is pending click. */ /** Whether there is pending click. */ private boolean mActive; private boolean mActive; /** If active, time at which pending click is scheduled. */ /** If active, time at which pending click is scheduled. */ Loading Loading @@ -555,6 +585,7 @@ public class AutoclickController extends BaseEventStreamTransformation { sendClick(); sendClick(); resetInternalState(); resetInternalState(); resetSelectedClickTypeIfNecessary(); } } /** /** Loading Loading @@ -633,6 +664,11 @@ public class AutoclickController extends BaseEventStreamTransformation { return mDelay; return mDelay; } } @VisibleForTesting boolean getRevertToLeftClickForTesting() { return mRevertToLeftClick; } /** /** * Updates the time at which click sequence should occur. * Updates the time at which click sequence should occur. * * Loading Loading @@ -692,6 +728,12 @@ public class AutoclickController extends BaseEventStreamTransformation { } } } } private void resetSelectedClickTypeIfNecessary() { if (mRevertToLeftClick && mActiveClickType != AUTOCLICK_TYPE_LEFT_CLICK) { mAutoclickTypePanel.resetSelectedClickType(); } } /** /** * @param event Observed motion event. * @param event Observed motion event. * @return Whether the event coords are far enough from the anchor for the event not to be * @return Whether the event coords are far enough from the anchor for the event not to be Loading @@ -716,6 +758,10 @@ public class AutoclickController extends BaseEventStreamTransformation { mIgnoreMinorCursorMovement = ignoreMinorCursorMovement; mIgnoreMinorCursorMovement = ignoreMinorCursorMovement; } } public void setRevertToLeftClick(boolean revertToLeftClick) { mRevertToLeftClick = revertToLeftClick; } private void updateMovementSlop(double slop) { private void updateMovementSlop(double slop) { mMovementSlop = slop; mMovementSlop = slop; } } Loading
services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -283,7 +283,11 @@ public class AutoclickTypePanel { // The pause button calls `togglePause()` directly so it does not need extra logic. // The pause button calls `togglePause()` directly so it does not need extra logic. mPauseButton.setOnClickListener(v -> togglePause()); mPauseButton.setOnClickListener(v -> togglePause()); // Initializes panel as collapsed state and only displays the left click button. resetSelectedClickType(); } /** Reset panel as collapsed state and only displays the left click button. */ public void resetSelectedClickType() { hideAllClickTypeButtons(); hideAllClickTypeButtons(); mLeftClickButton.setVisibility(View.VISIBLE); mLeftClickButton.setVisibility(View.VISIBLE); setSelectedClickType(AUTOCLICK_TYPE_LEFT_CLICK); setSelectedClickType(AUTOCLICK_TYPE_LEFT_CLICK); Loading
services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickControllerTest.java +26 −0 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.accessibility.autoclick; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK; import static com.android.server.testutils.MockitoUtilsKt.eq; import static com.android.server.testutils.MockitoUtilsKt.eq; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -545,6 +546,29 @@ public class AutoclickControllerTest { assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); assertThat(mController.mClickScheduler.getIsActiveForTesting()).isFalse(); } } @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void triggerRightClickWithRevertToLeftClickEnabled_resetClickType() { // Move mouse to initialize autoclick panel. injectFakeMouseActionHoverMoveEvent(); AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); mController.mAutoclickTypePanel = mockAutoclickTypePanel; mController.clickPanelController.handleAutoclickTypeChange(AUTOCLICK_TYPE_RIGHT_CLICK); // Set ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK to true. Settings.Secure.putIntForUser(mTestableContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK, AccessibilityUtils.State.ON, mTestableContext.getUserId()); mController.onChangeForTesting(/* selfChange= */ true, Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_AUTOCLICK_REVERT_TO_LEFT_CLICK)); when(mockAutoclickTypePanel.isPaused()).thenReturn(false); mController.mClickScheduler.run(); assertThat(mController.mClickScheduler.getRevertToLeftClickForTesting()).isTrue(); } @Test @Test @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) @EnableFlags(com.android.server.accessibility.Flags.FLAG_ENABLE_AUTOCLICK_INDICATOR) public void pauseButton_flagOn_clickNotTriggeredWhenPaused() { public void pauseButton_flagOn_clickNotTriggeredWhenPaused() { Loading Loading @@ -766,6 +790,8 @@ public class AutoclickControllerTest { // Set click type to right click. // Set click type to right click. mController.clickPanelController.handleAutoclickTypeChange( mController.clickPanelController.handleAutoclickTypeChange( AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK); AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK); AutoclickTypePanel mockAutoclickTypePanel = mock(AutoclickTypePanel.class); mController.mAutoclickTypePanel = mockAutoclickTypePanel; // Send hover move event. // Send hover move event. MotionEvent hoverMove = MotionEvent.obtain( MotionEvent hoverMove = MotionEvent.obtain( Loading