/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.Parcelable; import java.util.concurrent.atomic.AtomicInteger; /** * Common base class for input events. */ public abstract class InputEvent implements Parcelable { /** @hide */ protected static final int PARCEL_TOKEN_MOTION_EVENT = 1; /** @hide */ protected static final int PARCEL_TOKEN_KEY_EVENT = 2; // Next sequence number. private static final AtomicInteger mNextSeq = new AtomicInteger(); /** @hide */ protected int mSeq; /** @hide */ protected boolean mRecycled; private static final boolean TRACK_RECYCLED_LOCATION = false; private RuntimeException mRecycledLocation; /*package*/ InputEvent() { mSeq = mNextSeq.getAndIncrement(); } /** * Gets the id for the device that this event came from. An id of * zero indicates that the event didn't come from a physical device * and maps to the default keymap. The other numbers are arbitrary and * you shouldn't depend on the values. * * @return The device id. * @see InputDevice#getDevice */ public abstract int getDeviceId(); /** * Gets the device that this event came from. * * @return The device, or null if unknown. */ public final InputDevice getDevice() { return InputDevice.getDevice(getDeviceId()); } /** * Gets the source of the event. * * @return The event source or {@link InputDevice#SOURCE_UNKNOWN} if unknown. * @see InputDevice#getSources */ public abstract int getSource(); /** * Modifies the source of the event. * * @param source The new source. * @hide */ public abstract void setSource(int source); /** * Determines whether the event is from the given source. * * @param source The input source to check against. This can be a specific device type, such as * {@link InputDevice#SOURCE_TOUCH_NAVIGATION}, or a more generic device class, such as * {@link InputDevice#SOURCE_CLASS_POINTER}. * @return Whether the event is from the given source. */ public boolean isFromSource(int source) { return (getSource() & source) == source; } /** * Gets the display id of the event. * @return The display id associated with the event. * @hide */ public abstract int getDisplayId(); /** * Modifies the display id associated with the event * @param displayId * @hide */ public abstract void setDisplayId(int displayId); /** * Copies the event. * * @return A deep copy of the event. * @hide */ public abstract InputEvent copy(); /** * Recycles the event. * This method should only be used by the system since applications do not * expect {@link KeyEvent} objects to be recycled, although {@link MotionEvent} * objects are fine. See {@link KeyEvent#recycle()} for details. * @hide */ public void recycle() { if (TRACK_RECYCLED_LOCATION) { if (mRecycledLocation != null) { throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation); } mRecycledLocation = new RuntimeException("Last recycled here"); } else { if (mRecycled) { throw new RuntimeException(toString() + " recycled twice!"); } mRecycled = true; } } /** * Conditionally recycled the event if it is appropriate to do so after * dispatching the event to an application. * * If the event is a {@link MotionEvent} then it is recycled. * * If the event is a {@link KeyEvent} then it is NOT recycled, because applications * expect key events to be immutable so once the event has been dispatched to * the application we can no longer recycle it. * @hide */ public void recycleIfNeededAfterDispatch() { recycle(); } /** * Reinitializes the event on reuse (after recycling). * @hide */ protected void prepareForReuse() { mRecycled = false; mRecycledLocation = null; mSeq = mNextSeq.getAndIncrement(); } /** * Gets a private flag that indicates when the system has detected that this input event * may be inconsistent with respect to the sequence of previously delivered input events, * such as when a key up event is sent but the key was not down or when a pointer * move event is sent but the pointer is not down. * * @return True if this event is tainted. * @hide */ public abstract boolean isTainted(); /** * Sets a private flag that indicates when the system has detected that this input event * may be inconsistent with respect to the sequence of previously delivered input events, * such as when a key up event is sent but the key was not down or when a pointer * move event is sent but the pointer is not down. * * @param tainted True if this event is tainted. * @hide */ public abstract void setTainted(boolean tainted); /** * Retrieve the time this event occurred, * in the {@link android.os.SystemClock#uptimeMillis} time base. * * @return Returns the time this event occurred, * in the {@link android.os.SystemClock#uptimeMillis} time base. */ public abstract long getEventTime(); /** * Retrieve the time this event occurred, * in the {@link android.os.SystemClock#uptimeMillis} time base but with * nanosecond (instead of millisecond) precision. *

* The value is in nanosecond precision but it may not have nanosecond accuracy. *

* * @return Returns the time this event occurred, * in the {@link android.os.SystemClock#uptimeMillis} time base but with * nanosecond (instead of millisecond) precision. * * @hide */ 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 * unique sequence number. Moreover, a new sequence number is obtained * each time an event object is recycled. * * Sequence numbers are only guaranteed to be locally unique within a process. * Sequence numbers are not preserved when events are parceled. * * @return The unique sequence number of this event. * @hide */ @UnsupportedAppUsage public int getSequenceNumber() { return mSeq; } /** * Gets the ID of this event. This is generated when an event is created and preserved until its * last stage. It won't change just because the event crosses process boundary, but should * change when making a copy with modifications. *

* To avoid exposing app usage to other processes this ID is generated from a CSPRNG. Therefore * there isn't 100% guarantee on the uniqueness of this ID, though the chance of ID collisions * is considerably low. The rule of thumb is not to rely on the uniqueness for production logic, * but a good source for tracking an event (e.g. logging and profiling). * * @return The ID of this event. * @hide */ public abstract int getId(); public int describeContents() { return 0; } public static final @android.annotation.NonNull Parcelable.Creator CREATOR = new Parcelable.Creator() { public InputEvent createFromParcel(Parcel in) { int token = in.readInt(); if (token == PARCEL_TOKEN_KEY_EVENT) { return KeyEvent.createFromParcelBody(in); } else if (token == PARCEL_TOKEN_MOTION_EVENT) { return MotionEvent.createFromParcelBody(in); } else { throw new IllegalStateException("Unexpected input event type token in parcel."); } } public InputEvent[] newArray(int size) { return new InputEvent[size]; } }; }