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

Commit 0e96bcf1 authored by Ameer Armaly's avatar Ameer Armaly
Browse files

TouchInteractionController: cache motion events when transitioning between states.

When transitioning between states, TouchInteractionController will queue motion events  and not deliver them until the state transition has been confirmed.
This avoids the case where a service will request a state transition twice because it processes a motion event after sending the transition request but before the transition completes.
Bug: 159651900
Test: atest TouchInteractionControllerTest

Change-Id: I2437b635a8053de28212d93e67c7144134c1dc08
parent ffa37936
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.util.ArrayMap;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityInteractionClient;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Executor;

/**
@@ -102,6 +104,11 @@ public final class TouchInteractionController {
    private boolean mServiceDetectsGestures;
    /** Map of callbacks to executors. Lazily created when adding the first callback. */
    private ArrayMap<Callback, Executor> mCallbacks;
    // A list of motion events that should be queued until a pending transition has taken place.
    private Queue<MotionEvent> mQueuedMotionEvents = new LinkedList<>();
    // Whether this controller is waiting for a state transition.
    // Motion events will be queued and sent to listeners after the transition has taken place.
    private boolean mStateChangeRequested = false;

    // The current state of the display.
    private int mState = STATE_CLEAR;
@@ -169,6 +176,14 @@ public final class TouchInteractionController {
     * main thread.
     */
    void onMotionEvent(MotionEvent event) {
        if (mStateChangeRequested) {
            mQueuedMotionEvents.add(event);
        } else {
            sendEventToAllListeners(event);
        }
    }

    private void sendEventToAllListeners(MotionEvent event) {
        final ArrayMap<Callback, Executor> entries;
        synchronized (mLock) {
            // callbacks may remove themselves. Perform a shallow copy to avoid concurrent
@@ -209,6 +224,10 @@ public final class TouchInteractionController {
                callback.onStateChanged(state);
            }
        }
        mStateChangeRequested = false;
        while (mQueuedMotionEvents.size() > 0) {
            sendEventToAllListeners(mQueuedMotionEvents.poll());
        }
    }

    /**
@@ -253,6 +272,7 @@ public final class TouchInteractionController {
            } catch (RemoteException re) {
                throw new RuntimeException(re);
            }
            mStateChangeRequested = true;
        }
    }

@@ -281,6 +301,7 @@ public final class TouchInteractionController {
            } catch (RemoteException re) {
                throw new RuntimeException(re);
            }
            mStateChangeRequested = true;
        }
    }

@@ -302,6 +323,7 @@ public final class TouchInteractionController {
            } catch (RemoteException re) {
                throw new RuntimeException(re);
            }
            mStateChangeRequested = true;
        }
    }