diff options
author | Michael Wright <michaelwr@google.com> | 2013-03-22 22:49:53 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-03-22 22:49:53 +0000 |
commit | 88a0765dd4f18ce367f2874f5972816644090b0d (patch) | |
tree | 1f275418ab904bcd211b645c6b4d27142a6ba55d | |
parent | 57b0f3638297242baca5db3e8ab4b5aab151f09e (diff) | |
parent | c8a7e54fefbb70341427fe5b384447f30e1816f2 (diff) | |
download | frameworks_base-88a0765dd4f18ce367f2874f5972816644090b0d.zip frameworks_base-88a0765dd4f18ce367f2874f5972816644090b0d.tar.gz frameworks_base-88a0765dd4f18ce367f2874f5972816644090b0d.tar.bz2 |
Merge "Add pipelining optimization to IME dispatching" into jb-mr2-dev
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 149 | ||||
-rw-r--r-- | core/java/android/view/inputmethod/InputMethodManager.java | 12 |
2 files changed, 110 insertions, 51 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f06387c..69e2d1a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -107,6 +107,7 @@ public final class ViewRootImpl implements ViewParent, private static final boolean DEBUG_IMF = false || LOCAL_LOGV; private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV; private static final boolean DEBUG_FPS = false; + private static final boolean DEBUG_INPUT_PROCESSING = false || LOCAL_LOGV; private static final boolean USE_RENDER_THREAD = false; @@ -231,24 +232,38 @@ public final class ViewRootImpl implements ViewParent, int mClientWindowLayoutFlags; boolean mLastOverscanRequested; - /** @hide */ + /** Event was not handled and is finished. + * @hide */ public static final int EVENT_NOT_HANDLED = 0; - /** @hide */ + /** Event was handled and is finished. + * @hide */ public static final int EVENT_HANDLED = 1; - /** @hide */ - public static final int EVENT_IN_PROGRESS = 2; + /** Event is waiting on the IME. + * @hide */ + public static final int EVENT_PENDING_IME = 2; + /** Event requires post-IME dispatch. + * @hide */ + public static final int EVENT_POST_IME = 3; // Pool of queued input events. private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10; private QueuedInputEvent mQueuedInputEventPool; private int mQueuedInputEventPoolSize; - // Input event queue. - QueuedInputEvent mFirstPendingInputEvent; + /* Input event queue. + * Pending input events are input events waiting to be handled by the application. Current + * input events are input events which are being handled but are waiting on some action by the + * IME, even if they themselves may not need to be handled by the IME. + */ + QueuedInputEvent mPendingInputEventHead; + QueuedInputEvent mPendingInputEventTail; int mPendingInputEventCount; - QueuedInputEvent mCurrentInputEvent; + QueuedInputEvent mCurrentInputEventHead; + QueuedInputEvent mCurrentInputEventTail; + int mCurrentInputEventCount; boolean mProcessInputEventsScheduled; String mPendingInputEventQueueLengthCounterName = "pq"; + String mCurrentInputEventQueueLengthCounterName = "cq"; boolean mWindowAttributesChanged = false; int mWindowAttributesChangesFlag = 0; @@ -646,6 +661,7 @@ public final class ViewRootImpl implements ViewParent, } mPendingInputEventQueueLengthCounterName = "pq:" + attrs.getTitle(); + mCurrentInputEventQueueLengthCounterName = "cq:" + attrs.getTitle(); } } } @@ -3438,17 +3454,13 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_IMF) Log.v(TAG, "Sending trackball event to IME: seq=" + seq + " event=" + event); - int result = imm.dispatchTrackballEvent(mView.getContext(), seq, event, + return imm.dispatchTrackballEvent(mView.getContext(), seq, event, mInputMethodCallback); - if (result != EVENT_NOT_HANDLED) { - return result; - } } } } - // Not dispatching to IME, continue with post IME actions. - return deliverTrackballEventPostIme(q); + return EVENT_POST_IME; } private int deliverTrackballEventPostIme(QueuedInputEvent q) { @@ -3596,17 +3608,13 @@ public final class ViewRootImpl implements ViewParent, if (DEBUG_IMF) Log.v(TAG, "Sending generic motion event to IME: seq=" + seq + " event=" + event); - int result = imm.dispatchGenericMotionEvent(mView.getContext(), seq, event, + return imm.dispatchGenericMotionEvent(mView.getContext(), seq, event, mInputMethodCallback); - if (result != EVENT_NOT_HANDLED) { - return result; - } } } } - // Not dispatching to IME, continue with post IME actions. - return deliverGenericMotionEventPostIme(q); + return EVENT_POST_IME; } private int deliverGenericMotionEventPostIme(QueuedInputEvent q) { @@ -3811,17 +3819,13 @@ public final class ViewRootImpl implements ViewParent, final int seq = event.getSequenceNumber(); if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq=" + seq + " event=" + event); - int result = imm.dispatchKeyEvent(mView.getContext(), seq, event, + return imm.dispatchKeyEvent(mView.getContext(), seq, event, mInputMethodCallback); - if (result != EVENT_NOT_HANDLED) { - return result; - } } } } - // Not dispatching to IME, continue with post IME actions. - return deliverKeyEventPostIme(q); + return EVENT_POST_IME; } private int deliverKeyEventPostIme(QueuedInputEvent q) { @@ -4422,14 +4426,13 @@ public final class ViewRootImpl implements ViewParent, // in response to touch events and we want to ensure that the injected keys // are processed in the order they were received and we cannot trust that // the time stamp of injected events are monotonic. - QueuedInputEvent last = mFirstPendingInputEvent; + QueuedInputEvent last = mPendingInputEventTail; if (last == null) { - mFirstPendingInputEvent = q; + mPendingInputEventHead = q; + mPendingInputEventTail = q; } else { - while (last.mNext != null) { - last = last.mNext; - } last.mNext = q; + mPendingInputEventTail = q; } mPendingInputEventCount += 1; Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName, @@ -4452,19 +4455,44 @@ public final class ViewRootImpl implements ViewParent, } void doProcessInputEvents() { - while (mCurrentInputEvent == null && mFirstPendingInputEvent != null) { - QueuedInputEvent q = mFirstPendingInputEvent; - mFirstPendingInputEvent = q.mNext; + // Handle all of the available pending input events. Currently this will immediately + // process all of the events it can until it encounters one that must go through the IME. + // After that it will continue adding events to the current input queue but will wait for a + // response from the IME, regardless of whether that particular event needs it or not, in + // order to guarantee ordering consistency. This could be slightly improved by only + // queueing events whose source has previously encountered something that needs to be + // handled by the IME, and otherwise handling them immediately since we only need to + // guarantee ordering within a given source. + while (mPendingInputEventHead != null) { + QueuedInputEvent q = mPendingInputEventHead; + mPendingInputEventHead = q.mNext; + if (mPendingInputEventHead == null) { + mPendingInputEventTail = null; + } q.mNext = null; - mCurrentInputEvent = q; mPendingInputEventCount -= 1; Trace.traceCounter(Trace.TRACE_TAG_INPUT, mPendingInputEventQueueLengthCounterName, mPendingInputEventCount); - final int result = deliverInputEvent(q); - if (result != EVENT_IN_PROGRESS) { - finishCurrentInputEvent(result == EVENT_HANDLED); + int result = deliverInputEvent(q); + + if (result == EVENT_HANDLED || result == EVENT_NOT_HANDLED) { + finishInputEvent(q, result == EVENT_HANDLED); + } else if (result == EVENT_PENDING_IME) { + enqueueCurrentInputEvent(q); + } else { + q.mFlags |= QueuedInputEvent.FLAG_DELIVER_POST_IME; + // If the IME decided not to handle this event, and we have no events already being + // handled by the IME, go ahead and handle this one and then continue to the next + // input event. Otherwise, queue it up and handle it after whatever in front of it + // in the queue has been handled. + if (mCurrentInputEventHead == null) { + result = deliverInputEventPostIme(q); + finishInputEvent(q, result == EVENT_HANDLED); + } else { + enqueueCurrentInputEvent(q); + } } } @@ -4476,9 +4504,36 @@ public final class ViewRootImpl implements ViewParent, } } + private void enqueueCurrentInputEvent(QueuedInputEvent q) { + if (mCurrentInputEventHead == null) { + mCurrentInputEventHead = q; + mCurrentInputEventTail = q; + } else { + mCurrentInputEventTail.mNext = q; + mCurrentInputEventTail = q; + } + mCurrentInputEventCount += 1; + Trace.traceCounter(Trace.TRACE_TAG_INPUT, mCurrentInputEventQueueLengthCounterName, + mCurrentInputEventCount); + } + + private QueuedInputEvent dequeueCurrentInputEvent() { + QueuedInputEvent q = mCurrentInputEventHead; + mCurrentInputEventHead = q.mNext; + if (mCurrentInputEventHead == null) { + mCurrentInputEventTail = null; + } + q.mNext = null; + mCurrentInputEventCount -= 1; + Trace.traceCounter(Trace.TRACE_TAG_INPUT, mCurrentInputEventQueueLengthCounterName, + mCurrentInputEventCount); + return q; + } + void handleImeFinishedEvent(int seq, boolean handled) { - final QueuedInputEvent q = mCurrentInputEvent; + QueuedInputEvent q = mCurrentInputEventHead; if (q != null && q.mEvent.getSequenceNumber() == seq) { + dequeueCurrentInputEvent(); if (DEBUG_IMF) { Log.v(TAG, "IME finished event: seq=" + seq + " handled=" + handled + " event=" + q); @@ -4497,22 +4552,26 @@ public final class ViewRootImpl implements ViewParent, } } } - finishCurrentInputEvent(handled); - // Immediately start processing the next input event. - doProcessInputEvents(); + finishInputEvent(q, handled); + + // Flush all of the input events that are no longer waiting on the IME + while (mCurrentInputEventHead != null && (mCurrentInputEventHead.mFlags & + QueuedInputEvent.FLAG_DELIVER_POST_IME) != 0) { + q = dequeueCurrentInputEvent(); + final int result = deliverInputEventPostIme(q); + finishInputEvent(q, result == EVENT_HANDLED); + } } else { if (DEBUG_IMF) { Log.v(TAG, "IME finished event: seq=" + seq + " handled=" + handled + ", event not found!"); } } - } - private void finishCurrentInputEvent(boolean handled) { - final QueuedInputEvent q = mCurrentInputEvent; - mCurrentInputEvent = null; + } + private void finishInputEvent(QueuedInputEvent q, boolean handled) { if (q.mReceiver != null) { q.mReceiver.finishInputEvent(q.mEvent, handled); } else { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index dba2354..e602eb7 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -1577,13 +1577,13 @@ public final class InputMethodManager { final long startTime = SystemClock.uptimeMillis(); enqueuePendingEventLocked(startTime, seq, mCurId, callback); mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback); - return ViewRootImpl.EVENT_IN_PROGRESS; + return ViewRootImpl.EVENT_PENDING_IME; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e); } } } - return ViewRootImpl.EVENT_NOT_HANDLED; + return ViewRootImpl.EVENT_POST_IME; } /** @@ -1600,13 +1600,13 @@ public final class InputMethodManager { final long startTime = SystemClock.uptimeMillis(); enqueuePendingEventLocked(startTime, seq, mCurId, callback); mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback); - return ViewRootImpl.EVENT_IN_PROGRESS; + return ViewRootImpl.EVENT_PENDING_IME; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e); } } } - return ViewRootImpl.EVENT_NOT_HANDLED; + return ViewRootImpl.EVENT_POST_IME; } /** @@ -1623,13 +1623,13 @@ public final class InputMethodManager { final long startTime = SystemClock.uptimeMillis(); enqueuePendingEventLocked(startTime, seq, mCurId, callback); mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback); - return ViewRootImpl.EVENT_IN_PROGRESS; + return ViewRootImpl.EVENT_PENDING_IME; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e); } } } - return ViewRootImpl.EVENT_NOT_HANDLED; + return ViewRootImpl.EVENT_POST_IME; } void finishedEvent(int seq, boolean handled) { |