1 /* 2 * Copyright (C) 2020 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 static java.lang.annotation.RetentionPolicy.SOURCE; 20 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.SuppressLint; 25 import android.os.Parcel; 26 import android.os.Parcelable; 27 28 import java.lang.annotation.Retention; 29 30 31 /** 32 * Base class for verified events. 33 * Verified events contain the subset of an InputEvent that the system can verify. 34 * Data contained inside VerifiedInputEvent's should be considered trusted and contain only 35 * the original event data that first came from the system. 36 * 37 * @see android.hardware.input.InputManager#verifyInputEvent(InputEvent) 38 */ 39 @SuppressLint("ParcelNotFinal") 40 public abstract class VerifiedInputEvent implements Parcelable { 41 private static final String TAG = "VerifiedInputEvent"; 42 43 /** @hide */ 44 protected static final int VERIFIED_KEY = 1; 45 /** @hide */ 46 protected static final int VERIFIED_MOTION = 2; 47 48 /** @hide */ 49 @Retention(SOURCE) 50 @IntDef(prefix = "VERIFIED", value = {VERIFIED_KEY, VERIFIED_MOTION}) 51 public @interface VerifiedInputEventType {}; 52 53 @VerifiedInputEventType 54 private int mType; 55 56 private int mDeviceId; 57 private long mEventTimeNanos; 58 private int mSource; 59 private int mDisplayId; 60 61 /** @hide */ VerifiedInputEvent(int type, int deviceId, long eventTimeNanos, int source, int displayId)62 protected VerifiedInputEvent(int type, int deviceId, long eventTimeNanos, int source, 63 int displayId) { 64 mType = type; 65 mDeviceId = deviceId; 66 mEventTimeNanos = eventTimeNanos; 67 mSource = source; 68 mDisplayId = displayId; 69 } 70 /** @hide */ VerifiedInputEvent(@onNull Parcel in, int expectedType)71 protected VerifiedInputEvent(@NonNull Parcel in, int expectedType) { 72 mType = in.readInt(); 73 if (mType != expectedType) { 74 throw new IllegalArgumentException("Unexpected input event type token in parcel."); 75 } 76 mDeviceId = in.readInt(); 77 mEventTimeNanos = in.readLong(); 78 mSource = in.readInt(); 79 mDisplayId = in.readInt(); 80 } 81 82 /** 83 * Get the id of the device that generated this event. 84 * 85 * @see InputEvent#getDeviceId() 86 */ getDeviceId()87 public int getDeviceId() { 88 return mDeviceId; 89 } 90 91 /** 92 * Get the time this event occurred, in the {@link android.os.SystemClock#uptimeMillis()} 93 * time base. 94 * 95 * @see InputEvent#getEventTime() 96 */ 97 @SuppressLint("MethodNameUnits") getEventTimeNanos()98 public long getEventTimeNanos() { 99 return mEventTimeNanos; 100 } 101 102 /** 103 * Get the source of the event. 104 * 105 * @see InputEvent#getSource() 106 */ getSource()107 public int getSource() { 108 return mSource; 109 } 110 111 /** 112 * Get the display id that is associated with this event. 113 * 114 * @see Display#getDisplayId() 115 */ getDisplayId()116 public int getDisplayId() { 117 return mDisplayId; 118 } 119 120 /** {@inheritDoc} */ 121 @Override writeToParcel(@onNull Parcel dest, int flags)122 public void writeToParcel(@NonNull Parcel dest, int flags) { 123 dest.writeInt(mType); 124 dest.writeInt(mDeviceId); 125 dest.writeLong(mEventTimeNanos); 126 dest.writeInt(mSource); 127 dest.writeInt(mDisplayId); 128 } 129 130 /** {@inheritDoc} */ 131 @Override describeContents()132 public int describeContents() { 133 return 0; 134 } 135 peekInt(@onNull Parcel parcel)136 private static int peekInt(@NonNull Parcel parcel) { 137 final int initialDataPosition = parcel.dataPosition(); 138 int data = parcel.readInt(); 139 parcel.setDataPosition(initialDataPosition); 140 return data; 141 } 142 143 public static final @NonNull Parcelable.Creator<VerifiedInputEvent> CREATOR = 144 new Parcelable.Creator<VerifiedInputEvent>() { 145 @Override 146 public VerifiedInputEvent[] newArray(int size) { 147 return new VerifiedInputEvent[size]; 148 } 149 150 @Override 151 public VerifiedInputEvent createFromParcel(@NonNull Parcel in) { 152 final int type = peekInt(in); 153 if (type == VERIFIED_KEY) { 154 return VerifiedKeyEvent.CREATOR.createFromParcel(in); 155 } else if (type == VERIFIED_MOTION) { 156 return VerifiedMotionEvent.CREATOR.createFromParcel(in); 157 } 158 throw new IllegalArgumentException("Unexpected input event type in parcel."); 159 } 160 }; 161 162 @Override equals(@ullable Object o)163 public boolean equals(@Nullable Object o) { 164 if (this == o) return true; 165 if (o == null || getClass() != o.getClass()) return false; 166 @SuppressWarnings("unchecked") 167 VerifiedInputEvent that = (VerifiedInputEvent) o; 168 return mType == that.mType 169 && getDeviceId() == that.getDeviceId() 170 && getEventTimeNanos() == that.getEventTimeNanos() 171 && getSource() == that.getSource() 172 && getDisplayId() == that.getDisplayId(); 173 } 174 175 @Override hashCode()176 public int hashCode() { 177 int _hash = 1; 178 _hash = 31 * _hash + mType; 179 _hash = 31 * _hash + getDeviceId(); 180 _hash = 31 * _hash + Long.hashCode(getEventTimeNanos()); 181 _hash = 31 * _hash + getSource(); 182 _hash = 31 * _hash + getDisplayId(); 183 return _hash; 184 } 185 } 186