1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.view; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 import android.os.Parcel; 21 import android.os.Parcelable; 22 23 import java.util.concurrent.atomic.AtomicInteger; 24 25 /** 26 * Common base class for input events. 27 */ 28 public abstract class InputEvent implements Parcelable { 29 /** @hide */ 30 protected static final int PARCEL_TOKEN_MOTION_EVENT = 1; 31 /** @hide */ 32 protected static final int PARCEL_TOKEN_KEY_EVENT = 2; 33 34 // Next sequence number. 35 private static final AtomicInteger mNextSeq = new AtomicInteger(); 36 37 /** @hide */ 38 protected int mSeq; 39 40 /** @hide */ 41 protected boolean mRecycled; 42 43 private static final boolean TRACK_RECYCLED_LOCATION = false; 44 private RuntimeException mRecycledLocation; 45 InputEvent()46 /*package*/ InputEvent() { 47 mSeq = mNextSeq.getAndIncrement(); 48 } 49 50 /** 51 * Gets the id for the device that this event came from. An id of 52 * zero indicates that the event didn't come from a physical device 53 * and maps to the default keymap. The other numbers are arbitrary and 54 * you shouldn't depend on the values. 55 * 56 * @return The device id. 57 * @see InputDevice#getDevice 58 */ getDeviceId()59 public abstract int getDeviceId(); 60 61 /** 62 * Gets the device that this event came from. 63 * 64 * @return The device, or null if unknown. 65 */ getDevice()66 public final InputDevice getDevice() { 67 return InputDevice.getDevice(getDeviceId()); 68 } 69 70 /** 71 * Gets the source of the event. 72 * 73 * @return The event source or {@link InputDevice#SOURCE_UNKNOWN} if unknown. 74 * @see InputDevice#getSources 75 */ getSource()76 public abstract int getSource(); 77 78 /** 79 * Modifies the source of the event. 80 * 81 * @param source The new source. 82 * @hide 83 */ setSource(int source)84 public abstract void setSource(int source); 85 86 /** 87 * Determines whether the event is from the given source. 88 * 89 * @param source The input source to check against. This can be a specific device type, such as 90 * {@link InputDevice#SOURCE_TOUCH_NAVIGATION}, or a more generic device class, such as 91 * {@link InputDevice#SOURCE_CLASS_POINTER}. 92 * @return Whether the event is from the given source. 93 */ isFromSource(int source)94 public boolean isFromSource(int source) { 95 return (getSource() & source) == source; 96 } 97 98 /** 99 * Gets the display id of the event. 100 * @return The display id associated with the event. 101 * @hide 102 */ getDisplayId()103 public abstract int getDisplayId(); 104 105 /** 106 * Modifies the display id associated with the event 107 * @param displayId 108 * @hide 109 */ setDisplayId(int displayId)110 public abstract void setDisplayId(int displayId); 111 /** 112 * Copies the event. 113 * 114 * @return A deep copy of the event. 115 * @hide 116 */ copy()117 public abstract InputEvent copy(); 118 119 /** 120 * Recycles the event. 121 * This method should only be used by the system since applications do not 122 * expect {@link KeyEvent} objects to be recycled, although {@link MotionEvent} 123 * objects are fine. See {@link KeyEvent#recycle()} for details. 124 * @hide 125 */ recycle()126 public void recycle() { 127 if (TRACK_RECYCLED_LOCATION) { 128 if (mRecycledLocation != null) { 129 throw new RuntimeException(toString() + " recycled twice!", mRecycledLocation); 130 } 131 mRecycledLocation = new RuntimeException("Last recycled here"); 132 } else { 133 if (mRecycled) { 134 throw new RuntimeException(toString() + " recycled twice!"); 135 } 136 mRecycled = true; 137 } 138 } 139 140 /** 141 * Conditionally recycled the event if it is appropriate to do so after 142 * dispatching the event to an application. 143 * 144 * If the event is a {@link MotionEvent} then it is recycled. 145 * 146 * If the event is a {@link KeyEvent} then it is NOT recycled, because applications 147 * expect key events to be immutable so once the event has been dispatched to 148 * the application we can no longer recycle it. 149 * @hide 150 */ recycleIfNeededAfterDispatch()151 public void recycleIfNeededAfterDispatch() { 152 recycle(); 153 } 154 155 /** 156 * Reinitializes the event on reuse (after recycling). 157 * @hide 158 */ prepareForReuse()159 protected void prepareForReuse() { 160 mRecycled = false; 161 mRecycledLocation = null; 162 mSeq = mNextSeq.getAndIncrement(); 163 } 164 165 /** 166 * Gets a private flag that indicates when the system has detected that this input event 167 * may be inconsistent with respect to the sequence of previously delivered input events, 168 * such as when a key up event is sent but the key was not down or when a pointer 169 * move event is sent but the pointer is not down. 170 * 171 * @return True if this event is tainted. 172 * @hide 173 */ isTainted()174 public abstract boolean isTainted(); 175 176 /** 177 * Sets a private flag that indicates when the system has detected that this input event 178 * may be inconsistent with respect to the sequence of previously delivered input events, 179 * such as when a key up event is sent but the key was not down or when a pointer 180 * move event is sent but the pointer is not down. 181 * 182 * @param tainted True if this event is tainted. 183 * @hide 184 */ setTainted(boolean tainted)185 public abstract void setTainted(boolean tainted); 186 187 /** 188 * Retrieve the time this event occurred, 189 * in the {@link android.os.SystemClock#uptimeMillis} time base. 190 * 191 * @return Returns the time this event occurred, 192 * in the {@link android.os.SystemClock#uptimeMillis} time base. 193 */ getEventTime()194 public abstract long getEventTime(); 195 196 /** 197 * Retrieve the time this event occurred, 198 * in the {@link android.os.SystemClock#uptimeMillis} time base but with 199 * nanosecond (instead of millisecond) precision. 200 * <p> 201 * The value is in nanosecond precision but it may not have nanosecond accuracy. 202 * </p> 203 * 204 * @return Returns the time this event occurred, 205 * in the {@link android.os.SystemClock#uptimeMillis} time base but with 206 * nanosecond (instead of millisecond) precision. 207 * 208 * @hide 209 */ getEventTimeNano()210 public abstract long getEventTimeNano(); 211 212 /** 213 * Marks the input event as being canceled. 214 * 215 * @hide 216 */ cancel()217 public abstract void cancel(); 218 219 /** 220 * Gets the unique sequence number of this event. 221 * Every input event that is created or received by a process has a 222 * unique sequence number. Moreover, a new sequence number is obtained 223 * each time an event object is recycled. 224 * 225 * Sequence numbers are only guaranteed to be locally unique within a process. 226 * Sequence numbers are not preserved when events are parceled. 227 * 228 * @return The unique sequence number of this event. 229 * @hide 230 */ 231 @UnsupportedAppUsage getSequenceNumber()232 public int getSequenceNumber() { 233 return mSeq; 234 } 235 236 /** 237 * Gets the ID of this event. This is generated when an event is created and preserved until its 238 * last stage. It won't change just because the event crosses process boundary, but should 239 * change when making a copy with modifications. 240 * <p> 241 * To avoid exposing app usage to other processes this ID is generated from a CSPRNG. Therefore 242 * there isn't 100% guarantee on the uniqueness of this ID, though the chance of ID collisions 243 * is considerably low. The rule of thumb is not to rely on the uniqueness for production logic, 244 * but a good source for tracking an event (e.g. logging and profiling). 245 * 246 * @return The ID of this event. 247 * @hide 248 */ getId()249 public abstract int getId(); 250 describeContents()251 public int describeContents() { 252 return 0; 253 } 254 255 public static final @android.annotation.NonNull Parcelable.Creator<InputEvent> CREATOR 256 = new Parcelable.Creator<InputEvent>() { 257 public InputEvent createFromParcel(Parcel in) { 258 int token = in.readInt(); 259 if (token == PARCEL_TOKEN_KEY_EVENT) { 260 return KeyEvent.createFromParcelBody(in); 261 } else if (token == PARCEL_TOKEN_MOTION_EVENT) { 262 return MotionEvent.createFromParcelBody(in); 263 } else { 264 throw new IllegalStateException("Unexpected input event type token in parcel."); 265 } 266 } 267 268 public InputEvent[] newArray(int size) { 269 return new InputEvent[size]; 270 } 271 }; 272 } 273