Loading core/java/android/view/ViewRootImpl.java +99 −6 Original line number Diff line number Diff line Loading @@ -218,6 +218,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, boolean mNewSurfaceNeeded; boolean mHasHadWindowFocus; boolean mLastWasImTarget; InputEventMessage mPendingInputEvents = null; boolean mWindowAttributesChanged = false; int mWindowAttributesChangesFlag = 0; Loading Loading @@ -832,10 +833,24 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } private void processInputEvents(boolean outOfOrder) { while (mPendingInputEvents != null) { handleMessage(mPendingInputEvents.mMessage); InputEventMessage tmpMessage = mPendingInputEvents; mPendingInputEvents = mPendingInputEvents.mNext; tmpMessage.recycle(); if (outOfOrder) { removeMessages(PROCESS_INPUT_EVENTS); } } } private void performTraversals() { // cache mView since it is used so much below... final View host = mView; processInputEvents(true); if (DBG) { System.out.println("======================================"); System.out.println("performTraversals"); Loading Loading @@ -2336,6 +2351,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 1021; public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 1022; public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT = 1023; public final static int PROCESS_INPUT_EVENTS = 1024; @Override public String getMessageName(Message message) { Loading Loading @@ -2388,6 +2404,8 @@ public final class ViewRootImpl extends Handler implements ViewParent, return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID"; case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT: return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT"; case PROCESS_INPUT_EVENTS: return "PROCESS_INPUT_EVENTS"; } return super.getMessageName(message); Loading Loading @@ -2447,6 +2465,9 @@ public final class ViewRootImpl extends Handler implements ViewParent, case DISPATCH_GENERIC_MOTION: deliverGenericMotionEvent((MotionEvent) msg.obj, msg.arg1 != 0); break; case PROCESS_INPUT_EVENTS: processInputEvents(false); break; case DISPATCH_APP_VISIBILITY: handleAppVisibility(msg.arg1 != 0); break; Loading Loading @@ -3762,6 +3783,78 @@ public final class ViewRootImpl extends Handler implements ViewParent, } }; /** * Utility class used to queue up input events which are then handled during * performTraversals(). Doing it this way allows us to ensure that we are up to date with * all input events just prior to drawing, instead of placing those events on the regular * handler queue, potentially behind a drawing event. */ static class InputEventMessage { Message mMessage; InputEventMessage mNext; private static final Object sPoolSync = new Object(); private static InputEventMessage sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 10; private InputEventMessage(Message m) { mMessage = m; mNext = null; } /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static InputEventMessage obtain(Message msg) { synchronized (sPoolSync) { if (sPool != null) { InputEventMessage m = sPool; sPool = m.mNext; m.mNext = null; sPoolSize--; m.mMessage = msg; return m; } } return new InputEventMessage(msg); } /** * Return the message to the pool. */ public void recycle() { mMessage.recycle(); synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { mNext = sPool; sPool = this; sPoolSize++; } } } } /** * Place the input event message at the end of the current pending list */ private void enqueueInputEvent(Message msg, long when) { InputEventMessage inputMessage = InputEventMessage.obtain(msg); if (mPendingInputEvents == null) { mPendingInputEvents = inputMessage; } else { InputEventMessage currMessage = mPendingInputEvents; while (currMessage.mNext != null) { currMessage = currMessage.mNext; } currMessage.mNext = inputMessage; } sendEmptyMessageAtTime(PROCESS_INPUT_EVENTS, when); } public void dispatchKey(KeyEvent event) { dispatchKey(event, false); } Loading @@ -3786,7 +3879,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, if (LOCAL_LOGV) Log.v( TAG, "sending key " + event + " to " + mView); sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } private void dispatchMotion(MotionEvent event, boolean sendDone) { Loading @@ -3804,21 +3897,21 @@ public final class ViewRootImpl extends Handler implements ViewParent, Message msg = obtainMessage(DISPATCH_POINTER); msg.obj = event; msg.arg1 = sendDone ? 1 : 0; sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } private void dispatchTrackball(MotionEvent event, boolean sendDone) { Message msg = obtainMessage(DISPATCH_TRACKBALL); msg.obj = event; msg.arg1 = sendDone ? 1 : 0; sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } private void dispatchGenericMotion(MotionEvent event, boolean sendDone) { Message msg = obtainMessage(DISPATCH_GENERIC_MOTION); msg.obj = event; msg.arg1 = sendDone ? 1 : 0; sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } public void dispatchAppVisibility(boolean visible) { Loading Loading
core/java/android/view/ViewRootImpl.java +99 −6 Original line number Diff line number Diff line Loading @@ -218,6 +218,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, boolean mNewSurfaceNeeded; boolean mHasHadWindowFocus; boolean mLastWasImTarget; InputEventMessage mPendingInputEvents = null; boolean mWindowAttributesChanged = false; int mWindowAttributesChangesFlag = 0; Loading Loading @@ -832,10 +833,24 @@ public final class ViewRootImpl extends Handler implements ViewParent, } } private void processInputEvents(boolean outOfOrder) { while (mPendingInputEvents != null) { handleMessage(mPendingInputEvents.mMessage); InputEventMessage tmpMessage = mPendingInputEvents; mPendingInputEvents = mPendingInputEvents.mNext; tmpMessage.recycle(); if (outOfOrder) { removeMessages(PROCESS_INPUT_EVENTS); } } } private void performTraversals() { // cache mView since it is used so much below... final View host = mView; processInputEvents(true); if (DBG) { System.out.println("======================================"); System.out.println("performTraversals"); Loading Loading @@ -2336,6 +2351,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_ACCESSIBILITY_ID = 1021; public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 1022; public final static int DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT = 1023; public final static int PROCESS_INPUT_EVENTS = 1024; @Override public String getMessageName(Message message) { Loading Loading @@ -2388,6 +2404,8 @@ public final class ViewRootImpl extends Handler implements ViewParent, return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID"; case DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT: return "DO_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_TEXT"; case PROCESS_INPUT_EVENTS: return "PROCESS_INPUT_EVENTS"; } return super.getMessageName(message); Loading Loading @@ -2447,6 +2465,9 @@ public final class ViewRootImpl extends Handler implements ViewParent, case DISPATCH_GENERIC_MOTION: deliverGenericMotionEvent((MotionEvent) msg.obj, msg.arg1 != 0); break; case PROCESS_INPUT_EVENTS: processInputEvents(false); break; case DISPATCH_APP_VISIBILITY: handleAppVisibility(msg.arg1 != 0); break; Loading Loading @@ -3762,6 +3783,78 @@ public final class ViewRootImpl extends Handler implements ViewParent, } }; /** * Utility class used to queue up input events which are then handled during * performTraversals(). Doing it this way allows us to ensure that we are up to date with * all input events just prior to drawing, instead of placing those events on the regular * handler queue, potentially behind a drawing event. */ static class InputEventMessage { Message mMessage; InputEventMessage mNext; private static final Object sPoolSync = new Object(); private static InputEventMessage sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 10; private InputEventMessage(Message m) { mMessage = m; mNext = null; } /** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static InputEventMessage obtain(Message msg) { synchronized (sPoolSync) { if (sPool != null) { InputEventMessage m = sPool; sPool = m.mNext; m.mNext = null; sPoolSize--; m.mMessage = msg; return m; } } return new InputEventMessage(msg); } /** * Return the message to the pool. */ public void recycle() { mMessage.recycle(); synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { mNext = sPool; sPool = this; sPoolSize++; } } } } /** * Place the input event message at the end of the current pending list */ private void enqueueInputEvent(Message msg, long when) { InputEventMessage inputMessage = InputEventMessage.obtain(msg); if (mPendingInputEvents == null) { mPendingInputEvents = inputMessage; } else { InputEventMessage currMessage = mPendingInputEvents; while (currMessage.mNext != null) { currMessage = currMessage.mNext; } currMessage.mNext = inputMessage; } sendEmptyMessageAtTime(PROCESS_INPUT_EVENTS, when); } public void dispatchKey(KeyEvent event) { dispatchKey(event, false); } Loading @@ -3786,7 +3879,7 @@ public final class ViewRootImpl extends Handler implements ViewParent, if (LOCAL_LOGV) Log.v( TAG, "sending key " + event + " to " + mView); sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } private void dispatchMotion(MotionEvent event, boolean sendDone) { Loading @@ -3804,21 +3897,21 @@ public final class ViewRootImpl extends Handler implements ViewParent, Message msg = obtainMessage(DISPATCH_POINTER); msg.obj = event; msg.arg1 = sendDone ? 1 : 0; sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } private void dispatchTrackball(MotionEvent event, boolean sendDone) { Message msg = obtainMessage(DISPATCH_TRACKBALL); msg.obj = event; msg.arg1 = sendDone ? 1 : 0; sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } private void dispatchGenericMotion(MotionEvent event, boolean sendDone) { Message msg = obtainMessage(DISPATCH_GENERIC_MOTION); msg.obj = event; msg.arg1 = sendDone ? 1 : 0; sendMessageAtTime(msg, event.getEventTime()); enqueueInputEvent(msg, event.getEventTime()); } public void dispatchAppVisibility(boolean visible) { Loading