diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java index 1ecdf3071281c..e2ad3ad45c649 100644 --- a/core/java/android/view/InputEvent.java +++ b/core/java/android/view/InputEvent.java @@ -195,6 +195,13 @@ public abstract class InputEvent implements Parcelable { */ public abstract long getEventTimeNano(); + /** + * Marks the input event as being canceled. + * + * @hide + */ + public abstract void cancel(); + /** * Gets the unique sequence number of this event. * Every input event that is created or received by a process has a diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 0701b53e41479..243a0fc17e52d 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -2303,6 +2303,16 @@ public class KeyEvent extends InputEvent implements Parcelable { return (mFlags&FLAG_CANCELED) != 0; } + /** + * Set {@link #FLAG_CANCELED} flag for the key event. + * + * @hide + */ + @Override + public final void cancel() { + mFlags |= FLAG_CANCELED; + } + /** * Call this during {@link Callback#onKeyDown} to have the system track * the key through its final up (possibly including a long press). Note diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index ae39b7aeee6de..1c5c41c74905a 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -3168,6 +3168,12 @@ public final class MotionEvent extends InputEvent implements Parcelable { return ev; } + /** @hide */ + @Override + public final void cancel() { + setAction(ACTION_CANCEL); + } + public void writeToParcel(Parcel out, int flags) { out.writeInt(PARCEL_TOKEN_MOTION_EVENT); nativeWriteToParcel(mNativePtr, out); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 5d2a24be51db0..fe174175567bd 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3596,12 +3596,19 @@ public final class ViewRootImpl implements ViewParent, if (mView == null || !mAdded) { Slog.w(TAG, "Dropping event due to root view being removed: " + q.mEvent); return true; - } else if (!mAttachInfo.mHasWindowFocus && - !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER) && - !isTerminalInputEvent(q.mEvent)) { - // If this is a focused event and the window doesn't currently have input focus, - // then drop this event. This could be an event that came back from the previous - // stage but the window has lost focus in the meantime. + } else if ((!mAttachInfo.mHasWindowFocus || mStopped) + && !q.mEvent.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) { + // This is a focus event and the window doesn't currently have input focus or + // has stopped. This could be an event that came back from the previous stage + // but the window has lost focus or stopped in the meantime. + if (isTerminalInputEvent(q.mEvent)) { + // Don't drop terminal input events, however mark them as canceled. + q.mEvent.cancel(); + Slog.w(TAG, "Cancelling event due to no window focus: " + q.mEvent); + return false; + } + + // Drop non-terminal input events. Slog.w(TAG, "Dropping event due to no window focus: " + q.mEvent); return true; }