@@ -218,6 +218,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
218218 boolean mNewSurfaceNeeded ;
219219 boolean mHasHadWindowFocus ;
220220 boolean mLastWasImTarget ;
221+ InputEventMessage mPendingInputEvents = null ;
221222
222223 boolean mWindowAttributesChanged = false ;
223224 int mWindowAttributesChangesFlag = 0 ;
@@ -832,10 +833,24 @@ public void requestTransitionStart(LayoutTransition transition) {
832833 }
833834 }
834835
836+ private void processInputEvents (boolean outOfOrder ) {
837+ while (mPendingInputEvents != null ) {
838+ handleMessage (mPendingInputEvents .mMessage );
839+ InputEventMessage tmpMessage = mPendingInputEvents ;
840+ mPendingInputEvents = mPendingInputEvents .mNext ;
841+ tmpMessage .recycle ();
842+ if (outOfOrder ) {
843+ removeMessages (PROCESS_INPUT_EVENTS );
844+ }
845+ }
846+ }
847+
835848 private void performTraversals () {
836849 // cache mView since it is used so much below...
837850 final View host = mView ;
838851
852+ processInputEvents (true );
853+
839854 if (DBG ) {
840855 System .out .println ("======================================" );
841856 System .out .println ("performTraversals" );
@@ -2336,6 +2351,7 @@ private static void forceLayout(View view) {
23362351 public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 1021 ;
23372352 public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 1022 ;
23382353 public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT = 1023 ;
2354+ public final static int PROCESS_INPUT_EVENTS = 1024 ;
23392355
23402356 @ Override
23412357 public String getMessageName (Message message ) {
@@ -2388,7 +2404,9 @@ public String getMessageName(Message message) {
23882404 return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID" ;
23892405 case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT :
23902406 return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT" ;
2391-
2407+ case PROCESS_INPUT_EVENTS :
2408+ return "PROCESS_INPUT_EVENTS" ;
2409+
23922410 }
23932411 return super .getMessageName (message );
23942412 }
@@ -2447,6 +2465,9 @@ public void handleMessage(Message msg) {
24472465 case DISPATCH_GENERIC_MOTION :
24482466 deliverGenericMotionEvent ((MotionEvent ) msg .obj , msg .arg1 != 0 );
24492467 break ;
2468+ case PROCESS_INPUT_EVENTS :
2469+ processInputEvents (false );
2470+ break ;
24502471 case DISPATCH_APP_VISIBILITY :
24512472 handleAppVisibility (msg .arg1 != 0 );
24522473 break ;
@@ -3744,7 +3765,7 @@ public void dispatchResized(int w, int h, Rect coveredInsets,
37443765 msg .obj = ri ;
37453766 sendMessage (msg );
37463767 }
3747-
3768+
37483769 private long mInputEventReceiveTimeNanos ;
37493770 private long mInputEventDeliverTimeNanos ;
37503771 private long mInputEventDeliverPostImeTimeNanos ;
@@ -3762,6 +3783,78 @@ public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finished
37623783 }
37633784 };
37643785
3786+ /**
3787+ * Utility class used to queue up input events which are then handled during
3788+ * performTraversals(). Doing it this way allows us to ensure that we are up to date with
3789+ * all input events just prior to drawing, instead of placing those events on the regular
3790+ * handler queue, potentially behind a drawing event.
3791+ */
3792+ static class InputEventMessage {
3793+ Message mMessage ;
3794+ InputEventMessage mNext ;
3795+
3796+ private static final Object sPoolSync = new Object ();
3797+ private static InputEventMessage sPool ;
3798+ private static int sPoolSize = 0 ;
3799+
3800+ private static final int MAX_POOL_SIZE = 10 ;
3801+
3802+ private InputEventMessage (Message m ) {
3803+ mMessage = m ;
3804+ mNext = null ;
3805+ }
3806+
3807+ /**
3808+ * Return a new Message instance from the global pool. Allows us to
3809+ * avoid allocating new objects in many cases.
3810+ */
3811+ public static InputEventMessage obtain (Message msg ) {
3812+ synchronized (sPoolSync ) {
3813+ if (sPool != null ) {
3814+ InputEventMessage m = sPool ;
3815+ sPool = m .mNext ;
3816+ m .mNext = null ;
3817+ sPoolSize --;
3818+ m .mMessage = msg ;
3819+ return m ;
3820+ }
3821+ }
3822+ return new InputEventMessage (msg );
3823+ }
3824+
3825+ /**
3826+ * Return the message to the pool.
3827+ */
3828+ public void recycle () {
3829+ mMessage .recycle ();
3830+ synchronized (sPoolSync ) {
3831+ if (sPoolSize < MAX_POOL_SIZE ) {
3832+ mNext = sPool ;
3833+ sPool = this ;
3834+ sPoolSize ++;
3835+ }
3836+ }
3837+
3838+ }
3839+ }
3840+
3841+ /**
3842+ * Place the input event message at the end of the current pending list
3843+ */
3844+ private void enqueueInputEvent (Message msg , long when ) {
3845+ InputEventMessage inputMessage = InputEventMessage .obtain (msg );
3846+ if (mPendingInputEvents == null ) {
3847+ mPendingInputEvents = inputMessage ;
3848+ } else {
3849+ InputEventMessage currMessage = mPendingInputEvents ;
3850+ while (currMessage .mNext != null ) {
3851+ currMessage = currMessage .mNext ;
3852+ }
3853+ currMessage .mNext = inputMessage ;
3854+ }
3855+ sendEmptyMessageAtTime (PROCESS_INPUT_EVENTS , when );
3856+ }
3857+
37653858 public void dispatchKey (KeyEvent event ) {
37663859 dispatchKey (event , false );
37673860 }
@@ -3786,7 +3879,7 @@ private void dispatchKey(KeyEvent event, boolean sendDone) {
37863879 if (LOCAL_LOGV ) Log .v (
37873880 TAG , "sending key " + event + " to " + mView );
37883881
3789- sendMessageAtTime (msg , event .getEventTime ());
3882+ enqueueInputEvent (msg , event .getEventTime ());
37903883 }
37913884
37923885 private void dispatchMotion (MotionEvent event , boolean sendDone ) {
@@ -3804,21 +3897,21 @@ private void dispatchPointer(MotionEvent event, boolean sendDone) {
38043897 Message msg = obtainMessage (DISPATCH_POINTER );
38053898 msg .obj = event ;
38063899 msg .arg1 = sendDone ? 1 : 0 ;
3807- sendMessageAtTime (msg , event .getEventTime ());
3900+ enqueueInputEvent (msg , event .getEventTime ());
38083901 }
38093902
38103903 private void dispatchTrackball (MotionEvent event , boolean sendDone ) {
38113904 Message msg = obtainMessage (DISPATCH_TRACKBALL );
38123905 msg .obj = event ;
38133906 msg .arg1 = sendDone ? 1 : 0 ;
3814- sendMessageAtTime (msg , event .getEventTime ());
3907+ enqueueInputEvent (msg , event .getEventTime ());
38153908 }
38163909
38173910 private void dispatchGenericMotion (MotionEvent event , boolean sendDone ) {
38183911 Message msg = obtainMessage (DISPATCH_GENERIC_MOTION );
38193912 msg .obj = event ;
38203913 msg .arg1 = sendDone ? 1 : 0 ;
3821- sendMessageAtTime (msg , event .getEventTime ());
3914+ enqueueInputEvent (msg , event .getEventTime ());
38223915 }
38233916
38243917 public void dispatchAppVisibility (boolean visible ) {
0 commit comments