Merge "Improve Launcher drag performance." into ics-mr1
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 24423c3..f7078ec 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -218,6 +218,7 @@
boolean mNewSurfaceNeeded;
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
+ InputEventMessage mPendingInputEvents = null;
boolean mWindowAttributesChanged = false;
int mWindowAttributesChangesFlag = 0;
@@ -832,10 +833,24 @@
}
}
+ 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");
@@ -2336,6 +2351,7 @@
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) {
@@ -2388,7 +2404,9 @@
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);
}
@@ -2447,6 +2465,9 @@
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;
@@ -3744,7 +3765,7 @@
msg.obj = ri;
sendMessage(msg);
}
-
+
private long mInputEventReceiveTimeNanos;
private long mInputEventDeliverTimeNanos;
private long mInputEventDeliverPostImeTimeNanos;
@@ -3762,6 +3783,78 @@
}
};
+ /**
+ * 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);
}
@@ -3786,7 +3879,7 @@
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) {
@@ -3804,21 +3897,21 @@
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) {