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

Commit 7cb26674 authored by Ameer Armaly's avatar Ameer Armaly
Browse files

TouchExplorer: allow service to initiate touch exploration and there are no pointers on the screen

We need to be able to initiate touch exploration even if there are no pointers on the screen in order to reliably cover the case where a user just taps the screen.
The user expects to hear if they have tapped on anything.
Bug: 223673301
Test: manual. Tap on the screen and confirm that talkback reads the item in that position.

Change-Id: Id96fa8bd7f000ea153f45024e06915a43ca80826
parent 035a0252
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -262,7 +262,7 @@ public final class TouchInteractionController {
     * interaction.
     */
    public void requestTouchExploration() {
        checkState();
        validateTransitionRequest();
        final IAccessibilityServiceConnection connection =
                AccessibilityInteractionClient.getInstance()
                        .getConnection(mService.getConnectionId());
@@ -288,7 +288,7 @@ public final class TouchInteractionController {
     * @throws IllegalArgumentException if the pointer id is outside of the allowed range.
     */
    public void requestDragging(int pointerId) {
        checkState();
        validateTransitionRequest();
        if (pointerId < 0 || pointerId > MAX_POINTER_COUNT) {
            throw new IllegalArgumentException("Invalid pointer id: " + pointerId);
        }
@@ -313,7 +313,7 @@ public final class TouchInteractionController {
     * the duration of this interaction.
     */
    public void requestDelegating() {
        checkState();
        validateTransitionRequest();
        final IAccessibilityServiceConnection connection =
                AccessibilityInteractionClient.getInstance()
                        .getConnection(mService.getConnectionId());
@@ -371,14 +371,14 @@ public final class TouchInteractionController {
        }
    }

    private void checkState() {
    private void validateTransitionRequest() {
        if (!mServiceDetectsGestures || mCallbacks.size() == 0) {
            throw new IllegalStateException(
                    "State transitions are not allowed without first adding a callback.");
        }
        if (mState != STATE_TOUCH_INTERACTING && mState != STATE_DRAGGING) {
        if ((mState == STATE_DELEGATING || mState == STATE_TOUCH_EXPLORING)) {
            throw new IllegalStateException(
                    "State transitions are not allowed in " + stateToString(mState));
                    "State transition requests are not allowed in " + stateToString(mState));
        }
    }

+16 −1
Original line number Diff line number Diff line
@@ -1329,13 +1329,28 @@ public class TouchExplorer extends BaseEventStreamTransformation
        if (mState.isServiceDetectingGestures() && mState.isTouchInteracting()) {
            // Cancel without deleting events.
            mHandler.removeCallbacks(mSendHoverEnterAndMoveDelayed);
            final int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
            int pointerId = mReceivedPointerTracker.getPrimaryPointerId();
            if (pointerId == INVALID_POINTER_ID) {
                MotionEvent event = mState.getLastReceivedEvent();
                if (event != null) {
                    // Use the first pointer of the most recent event.
                    pointerId = event.getPointerId(0);
                }
            }
            if (pointerId == INVALID_POINTER_ID) {
                Slog.e(LOG_TAG, "Unable to find a valid pointer for touch exploration.");
                return;
            }
            final int pointerIdBits = (1 << pointerId);
            final int policyFlags = mState.getLastReceivedPolicyFlags();
            mSendHoverEnterAndMoveDelayed.setPointerIdBits(pointerIdBits);
            mSendHoverEnterAndMoveDelayed.setPolicyFlags(policyFlags);
            mSendHoverEnterAndMoveDelayed.run();
            mSendHoverEnterAndMoveDelayed.clear();
            if (mReceivedPointerTracker.getReceivedPointerDownCount() == 0) {
                // We need to send hover exit because there will be no future ACTION_UP
                sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
            }
        }
    }