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

Commit 714ff200 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

ViewGroup: Split ACTION_CANCEL events during dispatch

Cancel events were previously not split while being dispatched to
children. This means cancel events can be inconsistent with the rest of
the split gesture stream, since the number of pointers and the down time
of the event can change after the event is split.

To keep the stream consistent, always split cancel events when
disptching events to children. We also ensure that we don't drop
cancel events during dispatch.

Bug: 327503168
Test: Unit tests added in follow-up CLs
Flag: EXEMPT bug fix
Change-Id: I7a72506a2b8e70f90efd9ba2e2ec0d12b7fb098d
parent 7f292d96
Loading
Loading
Loading
Loading
+55 −55
Original line number Diff line number Diff line
@@ -3093,30 +3093,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     */
    private boolean dispatchTransformedTouchEvent(MotionEvent event, boolean cancel,
            View child, int desiredPointerIdBits) {
        final boolean handled;

        // Canceling motions is a special case.  We don't need to perform any transformations
        // or filtering.  The important part is the action, not the contents.
        final int oldAction = event.getAction();
        if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
        try {
            final boolean handled;
            if (cancel) {
                event.setAction(MotionEvent.ACTION_CANCEL);
            if (child == null) {
                handled = super.dispatchTouchEvent(event);
            } else {
                handled = child.dispatchTouchEvent(event);
            }
            event.setAction(oldAction);
            return handled;
            }

            // Calculate the number of pointers to deliver.
            final int oldPointerIdBits = event.getPointerIdBits();
        final int newPointerIdBits = oldPointerIdBits & desiredPointerIdBits;
            int newPointerIdBits = oldPointerIdBits & desiredPointerIdBits;

            // If for some reason we ended up in an inconsistent state where it looks like we
        // might produce a motion event with no pointers in it, then drop the event.
            // might produce a non-cancel motion event with no pointers in it, then drop the event.
            // Make sure that we don't drop any cancel events.
            if (newPointerIdBits == 0) {
                if (event.getAction() != MotionEvent.ACTION_CANCEL) {
                    return false;
                } else {
                    newPointerIdBits = oldPointerIdBits;
                }
            }

            // If the number of pointers is the same and we don't need to perform any fancy
@@ -3161,6 +3157,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
            // Done.
            transformedEvent.recycle();
            return handled;

        } finally {
            event.setAction(oldAction);
        }
    }

    /**