diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index b860bac0d0012..896a2de8b1354 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -1726,8 +1726,10 @@ public final class ViewRootImpl implements ViewParent, destroySurface(); } } + scheduleConsumeBatchedInputImmediately(); } + /** Register callbacks to be notified when the ViewRootImpl surface changes. */ interface SurfaceChangedCallback { void surfaceCreated(Transaction t); @@ -8107,7 +8109,9 @@ public final class ViewRootImpl implements ViewParent, } void scheduleConsumeBatchedInput() { - if (!mConsumeBatchedInputScheduled) { + // If anything is currently scheduled to consume batched input then there's no point in + // scheduling it again. + if (!mConsumeBatchedInputScheduled && !mConsumeBatchedInputImmediatelyScheduled) { mConsumeBatchedInputScheduled = true; mChoreographer.postCallback(Choreographer.CALLBACK_INPUT, mConsumedBatchedInputRunnable, null); @@ -8130,22 +8134,15 @@ public final class ViewRootImpl implements ViewParent, } } - void doConsumeBatchedInput(long frameTimeNanos) { - if (mConsumeBatchedInputScheduled) { - mConsumeBatchedInputScheduled = false; - if (mInputEventReceiver != null) { - if (mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos) - && frameTimeNanos != -1) { - // If we consumed a batch here, we want to go ahead and schedule the - // consumption of batched input events on the next frame. Otherwise, we would - // wait until we have more input events pending and might get starved by other - // things occurring in the process. If the frame time is -1, however, then - // we're in a non-batching mode, so there's no need to schedule this. - scheduleConsumeBatchedInput(); - } - } - doProcessInputEvents(); + boolean doConsumeBatchedInput(long frameTimeNanos) { + final boolean consumedBatches; + if (mInputEventReceiver != null) { + consumedBatches = mInputEventReceiver.consumeBatchedInputEvents(frameTimeNanos); + } else { + consumedBatches = false; } + doProcessInputEvents(); + return consumedBatches; } final class TraversalRunnable implements Runnable { @@ -8189,8 +8186,11 @@ public final class ViewRootImpl implements ViewParent, @Override public void onBatchedInputEventPending(int source) { + // mStopped: There will be no more choreographer callbacks if we are stopped, + // so we must consume all input immediately to prevent ANR final boolean unbuffered = mUnbufferedInputDispatch - || (source & mUnbufferedInputSource) != SOURCE_CLASS_NONE; + || (source & mUnbufferedInputSource) != SOURCE_CLASS_NONE + || mStopped; if (unbuffered) { if (mConsumeBatchedInputScheduled) { unscheduleConsumeBatchedInput(); @@ -8218,7 +8218,14 @@ public final class ViewRootImpl implements ViewParent, final class ConsumeBatchedInputRunnable implements Runnable { @Override public void run() { - doConsumeBatchedInput(mChoreographer.getFrameTimeNanos()); + mConsumeBatchedInputScheduled = false; + if (doConsumeBatchedInput(mChoreographer.getFrameTimeNanos())) { + // If we consumed a batch here, we want to go ahead and schedule the + // consumption of batched input events on the next frame. Otherwise, we would + // wait until we have more input events pending and might get starved by other + // things occurring in the process. + scheduleConsumeBatchedInput(); + } } } final ConsumeBatchedInputRunnable mConsumedBatchedInputRunnable = @@ -8228,6 +8235,7 @@ public final class ViewRootImpl implements ViewParent, final class ConsumeBatchedInputImmediatelyRunnable implements Runnable { @Override public void run() { + mConsumeBatchedInputImmediatelyScheduled = false; doConsumeBatchedInput(-1); } }