diff --git a/core/java/android/accessibilityservice/TouchInteractionController.java b/core/java/android/accessibilityservice/TouchInteractionController.java index a8ba1d33f3b40..bb2b8d45fd619 100644 --- a/core/java/android/accessibilityservice/TouchInteractionController.java +++ b/core/java/android/accessibilityservice/TouchInteractionController.java @@ -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 mCallbacks; + // A list of motion events that should be queued until a pending transition has taken place. + private Queue 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 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; } }