Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0efdbda authored by Yuhan Yang's avatar Yuhan Yang Committed by Android (Google) Code Review
Browse files

Merge "Implement double click as autoclick type" into main

parents b535bbbe 241cd23d
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
@@ -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,
+37 −1
Original line number Diff line number Diff line
@@ -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;
            }
        }
@@ -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,