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