Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 31ea5707 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am 9afb2e1a: Optimize focused input event dispatch in view root. DO NOT MERGE

* commit '9afb2e1a':
  Optimize focused input event dispatch in view root. DO NOT MERGE
parents 2439c921 9afb2e1a
Loading
Loading
Loading
Loading
+125 −121
Original line number Diff line number Diff line
@@ -232,6 +232,13 @@ public final class ViewRootImpl implements ViewParent,
    int mLastSystemUiVisibility;
    int mClientWindowLayoutFlags;

    /** @hide */
    public static final int EVENT_NOT_HANDLED = 0;
    /** @hide */
    public static final int EVENT_HANDLED = 1;
    /** @hide */
    public static final int EVENT_IN_PROGRESS = 2;

    // Pool of queued input events.
    private static final int MAX_QUEUED_INPUT_EVENT_POOL_SIZE = 10;
    private QueuedInputEvent mQueuedInputEventPool;
@@ -3157,19 +3164,19 @@ public final class ViewRootImpl implements ViewParent,
        return false;
    }

    private void deliverInputEvent(QueuedInputEvent q) {
    private int deliverInputEvent(QueuedInputEvent q) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent");
        try {
            if (q.mEvent instanceof KeyEvent) {
                deliverKeyEvent(q);
                return deliverKeyEvent(q);
            } else {
                final int source = q.mEvent.getSource();
                if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
                    deliverPointerEvent(q);
                    return deliverPointerEvent(q);
                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                    deliverTrackballEvent(q);
                    return deliverTrackballEvent(q);
                } else {
                    deliverGenericMotionEvent(q);
                    return deliverGenericMotionEvent(q);
                }
            }
        } finally {
@@ -3177,7 +3184,25 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    private void deliverPointerEvent(QueuedInputEvent q) {
    private int deliverInputEventPostIme(QueuedInputEvent q) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEventPostIme");
        try {
            if (q.mEvent instanceof KeyEvent) {
                return deliverKeyEventPostIme(q);
            } else {
                final int source = q.mEvent.getSource();
                if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                    return deliverTrackballEventPostIme(q);
                } else {
                    return deliverGenericMotionEventPostIme(q);
                }
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }

    private int deliverPointerEvent(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent)q.mEvent;
        final boolean isTouchEvent = event.isTouchEvent();
        if (mInputEventConsistencyVerifier != null) {
@@ -3190,8 +3215,7 @@ public final class ViewRootImpl implements ViewParent,

        // If there is no view, then the event will not be handled.
        if (mView == null || !mAdded) {
            finishInputEvent(q, false);
            return;
            return EVENT_NOT_HANDLED;
        }

        // Translate the pointer event for compatibility, if needed.
@@ -3224,16 +3248,10 @@ public final class ViewRootImpl implements ViewParent,
        if (MEASURE_LATENCY) {
            lt.sample("B Dispatched PointerEvents ", System.nanoTime() - event.getEventTimeNano());
        }
        if (handled) {
            finishInputEvent(q, true);
            return;
        }

        // Pointer event was unhandled.
        finishInputEvent(q, false);
        return handled ? EVENT_HANDLED : EVENT_NOT_HANDLED;
    }

    private void deliverTrackballEvent(QueuedInputEvent q) {
    private int deliverTrackballEvent(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent)q.mEvent;
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
@@ -3252,24 +3270,25 @@ public final class ViewRootImpl implements ViewParent,
                    if (DEBUG_IMF)
                        Log.v(TAG, "Sending trackball event to IME: seq="
                                + seq + " event=" + event);
                    imm.dispatchTrackballEvent(mView.getContext(), seq, event,
                    int result = imm.dispatchTrackballEvent(mView.getContext(), seq, event,
                            mInputMethodCallback);
                    return;
                    if (result != EVENT_NOT_HANDLED) {
                        return result;
                    }
                }
            }
        }

        // Not dispatching to IME, continue with post IME actions.
        deliverTrackballEventPostIme(q);
        return deliverTrackballEventPostIme(q);
    }

    private void deliverTrackballEventPostIme(QueuedInputEvent q) {
    private int deliverTrackballEventPostIme(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent) q.mEvent;

        // If there is no view, then the event will not be handled.
        if (mView == null || !mAdded) {
            finishInputEvent(q, false);
            return;
            return EVENT_NOT_HANDLED;
        }

        // Deliver the trackball event to the view.
@@ -3279,10 +3298,8 @@ public final class ViewRootImpl implements ViewParent,
            // event into a key event, touch mode will not exit, so we exit
            // touch mode here.
            ensureTouchMode(false);

            finishInputEvent(q, true);
            mLastTrackballTime = Integer.MIN_VALUE;
            return;
            return EVENT_HANDLED;
        }

        // Translate the trackball event into DPAD keys and try to deliver those.
@@ -3390,10 +3407,10 @@ public final class ViewRootImpl implements ViewParent,

        // Unfortunately we can't tell whether the application consumed the keys, so
        // we always consider the trackball event handled.
        finishInputEvent(q, true);
        return EVENT_HANDLED;
    }

    private void deliverGenericMotionEvent(QueuedInputEvent q) {
    private int deliverGenericMotionEvent(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent)q.mEvent;
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
@@ -3411,18 +3428,20 @@ public final class ViewRootImpl implements ViewParent,
                    if (DEBUG_IMF)
                        Log.v(TAG, "Sending generic motion event to IME: seq="
                                + seq + " event=" + event);
                    imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
                    int result = imm.dispatchGenericMotionEvent(mView.getContext(), seq, event,
                            mInputMethodCallback);
                    return;
                    if (result != EVENT_NOT_HANDLED) {
                        return result;
                    }
                }
            }
        }

        // Not dispatching to IME, continue with post IME actions.
        deliverGenericMotionEventPostIme(q);
        return deliverGenericMotionEventPostIme(q);
    }

    private void deliverGenericMotionEventPostIme(QueuedInputEvent q) {
    private int deliverGenericMotionEventPostIme(QueuedInputEvent q) {
        final MotionEvent event = (MotionEvent) q.mEvent;
        final int source = event.getSource();
        final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
@@ -3436,8 +3455,7 @@ public final class ViewRootImpl implements ViewParent,
              //Convert TouchPad motion into a TrackBall event
              mSimulatedTrackball.updateTrackballDirection(this, event);
            }
            finishInputEvent(q, false);
            return;
            return EVENT_NOT_HANDLED;
        }

        // Deliver the event to the view.
@@ -3448,22 +3466,21 @@ public final class ViewRootImpl implements ViewParent,
              //Convert TouchPad motion into a TrackBall event
              mSimulatedTrackball.updateTrackballDirection(this, event);
            }
            finishInputEvent(q, true);
            return;
            return EVENT_HANDLED;
        }

        if (isJoystick) {
            // Translate the joystick event into DPAD keys and try to deliver
            // those.
            updateJoystickDirection(event, true);
            finishInputEvent(q, true);
        } else if (isTouchPad) {
            return EVENT_HANDLED;
        }
        if (isTouchPad) {
            //Convert TouchPad motion into a TrackBall event
            mSimulatedTrackball.updateTrackballDirection(this, event);
            finishInputEvent(q, true);
        } else {
            finishInputEvent(q, false);
            return EVENT_HANDLED;
        }
        return EVENT_NOT_HANDLED;
    }

    private void updateJoystickDirection(MotionEvent event, boolean synthesizeNewKeys) {
@@ -3607,7 +3624,7 @@ public final class ViewRootImpl implements ViewParent,
        return false;
    }

    private void deliverKeyEvent(QueuedInputEvent q) {
    private int deliverKeyEvent(QueuedInputEvent q) {
        final KeyEvent event = (KeyEvent)q.mEvent;
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
@@ -3618,8 +3635,7 @@ public final class ViewRootImpl implements ViewParent,

            // Perform predispatching before the IME.
            if (mView.dispatchKeyEventPreIme(event)) {
                finishInputEvent(q, true);
                return;
                return EVENT_HANDLED;
            }

            // Dispatch to the IME before propagating down the view hierarchy.
@@ -3630,81 +3646,30 @@ 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);
                    imm.dispatchKeyEvent(mView.getContext(), seq, event, mInputMethodCallback);
                    return;
                    int result = imm.dispatchKeyEvent(mView.getContext(), seq, event,
                            mInputMethodCallback);
                    if (result != EVENT_NOT_HANDLED) {
                        return result;
                    }
                }
            }

        // Not dispatching to IME, continue with post IME actions.
        deliverKeyEventPostIme(q);
        }

    void handleImeFinishedEvent(int seq, boolean handled) {
        final QueuedInputEvent q = mCurrentInputEvent;
        if (q != null && q.mEvent.getSequenceNumber() == seq) {
            if (DEBUG_IMF) {
                Log.v(TAG, "IME finished event: seq=" + seq
                        + " handled=" + handled + " event=" + q);
            }
            if (handled) {
                finishInputEvent(q, true);
            } else {
                if (q.mEvent instanceof KeyEvent) {
                    KeyEvent event = (KeyEvent)q.mEvent;
                    if (event.getAction() != KeyEvent.ACTION_UP) {
                        // If the window doesn't currently have input focus, then drop
                        // this event.  This could be an event that came back from the
                        // IME dispatch but the window has lost focus in the meantime.
                        if (!mAttachInfo.mHasWindowFocus) {
                            Slog.w(TAG, "Dropping event due to no window focus: " + event);
                            finishInputEvent(q, true);
                            return;
                        }
                    }
                    deliverKeyEventPostIme(q);
                } else {
                    MotionEvent event = (MotionEvent)q.mEvent;
                    if (event.getAction() != MotionEvent.ACTION_CANCEL
                            && event.getAction() != MotionEvent.ACTION_UP) {
                        // If the window doesn't currently have input focus, then drop
                        // this event.  This could be an event that came back from the
                        // IME dispatch but the window has lost focus in the meantime.
                        if (!mAttachInfo.mHasWindowFocus) {
                            Slog.w(TAG, "Dropping event due to no window focus: " + event);
                            finishInputEvent(q, true);
                            return;
                        }
                    }
                    final int source = q.mEvent.getSource();
                    if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
                        deliverTrackballEventPostIme(q);
                    } else {
                        deliverGenericMotionEventPostIme(q);
                    }
                }
            }
        } else {
            if (DEBUG_IMF) {
                Log.v(TAG, "IME finished event: seq=" + seq
                        + " handled=" + handled + ", event not found!");
            }
        }
        // Not dispatching to IME, continue with post IME actions.
        return deliverKeyEventPostIme(q);
    }

    private void deliverKeyEventPostIme(QueuedInputEvent q) {
    private int deliverKeyEventPostIme(QueuedInputEvent q) {
        final KeyEvent event = (KeyEvent)q.mEvent;

        // If the view went away, then the event will not be handled.
        if (mView == null || !mAdded) {
            finishInputEvent(q, false);
            return;
            return EVENT_NOT_HANDLED;
        }

        // If the key's purpose is to exit touch mode then we consume it and consider it handled.
        if (checkForLeavingTouchModeAndConsume(event)) {
            finishInputEvent(q, true);
            return;
            return EVENT_HANDLED;
        }

        // Make sure the fallback event policy sees all keys that will be delivered to the
@@ -3713,8 +3678,7 @@ public final class ViewRootImpl implements ViewParent,

        // Deliver the key to the view hierarchy.
        if (mView.dispatchKeyEvent(event)) {
            finishInputEvent(q, true);
            return;
            return EVENT_HANDLED;
        }

        // If the Control modifier is held, try to interpret the key as a shortcut.
@@ -3723,15 +3687,13 @@ public final class ViewRootImpl implements ViewParent,
                && event.getRepeatCount() == 0
                && !KeyEvent.isModifierKey(event.getKeyCode())) {
            if (mView.dispatchKeyShortcutEvent(event)) {
                finishInputEvent(q, true);
                return;
                return EVENT_HANDLED;
            }
        }

        // Apply the fallback event policy.
        if (mFallbackEventHandler.dispatchKeyEvent(event)) {
            finishInputEvent(q, true);
            return;
            return EVENT_HANDLED;
        }

        // Handle automatic focus changes.
@@ -3784,22 +3746,20 @@ public final class ViewRootImpl implements ViewParent,
                        if (v.requestFocus(direction, mTempRect)) {
                            playSoundEffect(SoundEffectConstants
                                    .getContantForFocusDirection(direction));
                            finishInputEvent(q, true);
                            return;
                            return EVENT_HANDLED;
                        }
                    }

                    // Give the focused view a last chance to handle the dpad key.
                    if (mView.dispatchUnhandledMove(focused, direction)) {
                        finishInputEvent(q, true);
                        return;
                        return EVENT_HANDLED;
                    }
                }
            }
        }

        // Key was unhandled.
        finishInputEvent(q, false);
        return EVENT_NOT_HANDLED;
    }

    /* drag/drop */
@@ -4303,7 +4263,11 @@ public final class ViewRootImpl implements ViewParent,
            mFirstPendingInputEvent = q.mNext;
            q.mNext = null;
            mCurrentInputEvent = q;
            deliverInputEvent(q);

            final int result = deliverInputEvent(q);
            if (result != EVENT_IN_PROGRESS) {
                finishCurrentInputEvent(result == EVENT_HANDLED);
            }
        }

        // We are done processing all input events that we can process right now
@@ -4314,11 +4278,43 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    private void finishInputEvent(QueuedInputEvent q, boolean handled) {
        if (q != mCurrentInputEvent) {
            throw new IllegalStateException("finished input event out of order");
    void handleImeFinishedEvent(int seq, boolean handled) {
        final QueuedInputEvent q = mCurrentInputEvent;
        if (q != null && q.mEvent.getSequenceNumber() == seq) {
            if (DEBUG_IMF) {
                Log.v(TAG, "IME finished event: seq=" + seq
                        + " handled=" + handled + " event=" + q);
            }

            if (!handled) {
                // If the window doesn't currently have input focus, then drop
                // this event.  This could be an event that came back from the
                // IME dispatch but the window has lost focus in the meantime.
                if (!mAttachInfo.mHasWindowFocus && !isTerminalInputEvent(q.mEvent)) {
                    Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent);
                } else {
                    final int result = deliverInputEventPostIme(q);
                    if (result == EVENT_HANDLED) {
                        handled = true;
                    }
                }
            }
            finishCurrentInputEvent(handled);

            // Immediately start processing the next input event.
            doProcessInputEvents();
        } 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;

        if (q.mReceiver != null) {
            q.mReceiver.finishInputEvent(q.mEvent, handled);
        } else {
@@ -4326,10 +4322,18 @@ public final class ViewRootImpl implements ViewParent,
        }

        recycleQueuedInputEvent(q);
    }

        mCurrentInputEvent = null;
        if (mFirstPendingInputEvent != null) {
            scheduleProcessInputEvents();
    private static boolean isTerminalInputEvent(InputEvent event) {
        if (event instanceof KeyEvent) {
            final KeyEvent keyEvent = (KeyEvent)event;
            return keyEvent.getAction() == KeyEvent.ACTION_UP;
        } else {
            final MotionEvent motionEvent = (MotionEvent)event;
            final int action = motionEvent.getAction();
            return action == MotionEvent.ACTION_UP
                    || action == MotionEvent.ACTION_CANCEL
                    || action == MotionEvent.ACTION_HOVER_EXIT;
        }
    }

+21 −25
Original line number Diff line number Diff line
@@ -334,7 +334,7 @@ public final class InputMethodManager {
    
    class H extends Handler {
        H(Looper looper) {
            super(looper);
            super(looper, null, true);
        }
        
        @Override
@@ -1565,38 +1565,36 @@ public final class InputMethodManager {
    /**
     * @hide
     */
    public void dispatchKeyEvent(Context context, int seq, KeyEvent key,
    public int dispatchKeyEvent(Context context, int seq, KeyEvent key,
            FinishedEventCallback callback) {
        boolean handled = false;
        synchronized (mH) {
            if (DEBUG) Log.d(TAG, "dispatchKeyEvent");

            if (mCurMethod != null) {
                if (key.getAction() == KeyEvent.ACTION_DOWN
                        && key.getKeyCode() == KeyEvent.KEYCODE_SYM) {
                        && key.getKeyCode() == KeyEvent.KEYCODE_SYM
                        && key.getRepeatCount() == 0) {
                    showInputMethodPickerLocked();
                    handled = true;
                } else {
                    return ViewRootImpl.EVENT_HANDLED;
                }
                try {
                    if (DEBUG) Log.v(TAG, "DISPATCH KEY: " + mCurMethod);
                    final long startTime = SystemClock.uptimeMillis();
                    enqueuePendingEventLocked(startTime, seq, mCurId, callback);
                    mCurMethod.dispatchKeyEvent(seq, key, mInputMethodCallback);
                        return;
                    return ViewRootImpl.EVENT_IN_PROGRESS;
                } catch (RemoteException e) {
                    Log.w(TAG, "IME died: " + mCurId + " dropping: " + key, e);
                }
            }
        }
        }

        callback.finishedEvent(seq, handled);
        return ViewRootImpl.EVENT_NOT_HANDLED;
    }

    /**
     * @hide
     */
    public void dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
    public int dispatchTrackballEvent(Context context, int seq, MotionEvent motion,
            FinishedEventCallback callback) {
        synchronized (mH) {
            if (DEBUG) Log.d(TAG, "dispatchTrackballEvent");
@@ -1607,20 +1605,19 @@ public final class InputMethodManager {
                    final long startTime = SystemClock.uptimeMillis();
                    enqueuePendingEventLocked(startTime, seq, mCurId, callback);
                    mCurMethod.dispatchTrackballEvent(seq, motion, mInputMethodCallback);
                    return;
                    return ViewRootImpl.EVENT_IN_PROGRESS;
                } catch (RemoteException e) {
                    Log.w(TAG, "IME died: " + mCurId + " dropping trackball: " + motion, e);
                }
            }
        }

        callback.finishedEvent(seq, false);
        return ViewRootImpl.EVENT_NOT_HANDLED;
    }

    /**
     * @hide
     */
    public void dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
    public int dispatchGenericMotionEvent(Context context, int seq, MotionEvent motion,
            FinishedEventCallback callback) {
        synchronized (mH) {
            if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent");
@@ -1631,14 +1628,13 @@ public final class InputMethodManager {
                    final long startTime = SystemClock.uptimeMillis();
                    enqueuePendingEventLocked(startTime, seq, mCurId, callback);
                    mCurMethod.dispatchGenericMotionEvent(seq, motion, mInputMethodCallback);
                    return;
                    return ViewRootImpl.EVENT_IN_PROGRESS;
                } catch (RemoteException e) {
                    Log.w(TAG, "IME died: " + mCurId + " dropping generic motion: " + motion, e);
                }
            }
        }

        callback.finishedEvent(seq, false);
        return ViewRootImpl.EVENT_NOT_HANDLED;
    }

    void finishedEvent(int seq, boolean handled) {