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

Commit fe304b89 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Some accessibility events not sent from touch explorer if apps misbehave.

1. The touch explorer is relying on the hover exit accessibility event to be sent
   from the app's view tree before sending the exploration end and last touch
   accessibility events. However, if the app is buggy and does not send the hover
   exit event, then the interaction ending events are never sent. Now there is a
   timeout in which we wait for the hover exit accessibility event before sending
   the gesture end and last touch accessibility events. Hence, we are making a
   best effort to have a consistent event stream.

2. Sneaking in the new nine patch for the border around the magnified region
   since the current one is engineering art.

bug:7233616

Change-Id: Ie64f23659c25ab914565d50537b9a82bdc6a44a0
parent 95841ac3
Loading
Loading
Loading
Loading
+190 B
Loading image diff...
+172 B
Loading image diff...
−741 B
Loading image diff...
+205 B
Loading image diff...
+58 −0
Original line number Diff line number Diff line
@@ -102,6 +102,10 @@ class TouchExplorer implements EventStreamTransformation {
    // The timeout after which we are no longer trying to detect a gesture.
    private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;

    // The timeout to send interaction end events in case we did not
    // receive the expected hover exit event due to a misbehaving app.
    private static final int SEND_INTERACTION_END_EVENTS_TIMEOUT = 200;

    // Temporary array for storing pointer IDs.
    private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];

@@ -135,6 +139,9 @@ class TouchExplorer implements EventStreamTransformation {
    // Command for delayed sending of a hover exit event.
    private final SendHoverDelayed mSendHoverExitDelayed;

    // Command for delayed sending of interaction ending events.
    private final SendInteractionEndEventsDelayed mSendInteractionEndEventsDelayed;

    // Command for delayed sending of a long press.
    private final PerformLongPressDelayed mPerformLongPressDelayed;

@@ -233,6 +240,7 @@ class TouchExplorer implements EventStreamTransformation {
        mGestureLibrary.load();
        mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
        mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
        mSendInteractionEndEventsDelayed = new SendInteractionEndEventsDelayed();
        mDoubleTapDetector = new DoubleTapDetector();
        final float density = context.getResources().getDisplayMetrics().density;
        mScaledMinPointerDistanceToUseMiddleLocation =
@@ -278,6 +286,7 @@ class TouchExplorer implements EventStreamTransformation {
        mSendHoverExitDelayed.remove();
        mPerformLongPressDelayed.remove();
        mExitGestureDetectionModeDelayed.remove();
        mSendInteractionEndEventsDelayed.remove();
        // Reset the pointer trackers.
        mReceivedPointerTracker.clear();
        mInjectedPointerTracker.clear();
@@ -334,6 +343,7 @@ class TouchExplorer implements EventStreamTransformation {
        // last hover exit event.
        if (mTouchExplorationGestureEnded
                && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
            mSendInteractionEndEventsDelayed.remove();
            mTouchExplorationGestureEnded = false;
            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
        }
@@ -342,6 +352,7 @@ class TouchExplorer implements EventStreamTransformation {
        // last hover exit and the touch exploration gesture end events.
        if (mTouchInteractionEnded
                && eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
            mSendInteractionEndEventsDelayed.remove();
            mTouchInteractionEnded = false;
            sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
        }
@@ -416,6 +427,10 @@ class TouchExplorer implements EventStreamTransformation {
                            mSendHoverExitDelayed.remove();
                        }

                        if (mSendInteractionEndEventsDelayed.isPending()) {
                            mSendInteractionEndEventsDelayed.forceSendAndRemove();
                        }

                        mPerformLongPressDelayed.remove();

                        // If we have the first tap schedule a long press and break
@@ -873,6 +888,9 @@ class TouchExplorer implements EventStreamTransformation {
            final int pointerIdBits = event.getPointerIdBits();
            mTouchExplorationGestureEnded = true;
            mTouchInteractionEnded = true;
            if (!mSendInteractionEndEventsDelayed.isPending()) {
                mSendInteractionEndEventsDelayed.post();
            }
            sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags);
        }
    }
@@ -1484,10 +1502,16 @@ class TouchExplorer implements EventStreamTransformation {
                } else {
                    mTouchExplorationGestureEnded = true;
                    mTouchInteractionEnded = true;
                    if (!mSendInteractionEndEventsDelayed.isPending()) {
                        mSendInteractionEndEventsDelayed.post();
                    }
                }
            } else {
                if (!mGestureStarted) {
                    mTouchInteractionEnded = true;
                    if (!mSendInteractionEndEventsDelayed.isPending()) {
                        mSendInteractionEndEventsDelayed.post();
                    }
                }
            }
            sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
@@ -1495,6 +1519,40 @@ class TouchExplorer implements EventStreamTransformation {
        }
    }

    private class SendInteractionEndEventsDelayed implements Runnable {

        public void remove() {
            mHandler.removeCallbacks(this);
        }

        public void post() {
            mHandler.postDelayed(this, SEND_INTERACTION_END_EVENTS_TIMEOUT);
        }

        public boolean isPending() {
            return mHandler.hasCallbacks(this);
        }

        public void forceSendAndRemove() {
            if (isPending()) {
                run();
                remove();
            }
        }

        @Override
        public void run() {
            if (mTouchExplorationGestureEnded) {
                mTouchExplorationGestureEnded = false;
                sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
            }
            if (mTouchInteractionEnded) {
                mTouchInteractionEnded = false;
                sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
            }
        }
    }

    @Override
    public String toString() {
        return LOG_TAG;