summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/InputEvent.java15
-rw-r--r--core/java/android/view/KeyEvent.java45
-rw-r--r--core/java/android/view/MotionEvent.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java10
-rw-r--r--core/jni/android_view_InputEventSender.cpp18
-rw-r--r--core/jni/android_view_KeyEvent.cpp20
-rw-r--r--core/jni/android_view_MotionEvent.cpp13
-rw-r--r--core/tests/coretests/src/android/view/KeyEventTest.java61
-rw-r--r--core/tests/coretests/src/android/view/MotionEventTest.java31
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java2
10 files changed, 191 insertions, 32 deletions
diff --git a/core/java/android/view/InputEvent.java b/core/java/android/view/InputEvent.java
index 5f9c4801ee66..cb9e746543f6 100644
--- a/core/java/android/view/InputEvent.java
+++ b/core/java/android/view/InputEvent.java
@@ -233,6 +233,21 @@ public abstract class InputEvent implements Parcelable {
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.
+ * <p>
+ * 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;
}
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 235f5e1dc970..e249c777caf6 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1265,6 +1265,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
private KeyEvent mNext;
+ private int mId;
@UnsupportedAppUsage
private int mDeviceId;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -1350,9 +1351,9 @@ public class KeyEvent extends InputEvent implements Parcelable {
private static native String nativeKeyCodeToString(int keyCode);
private static native int nativeKeyCodeFromString(String keyCode);
+ private static native int nativeNextId();
- private KeyEvent() {
- }
+ private KeyEvent() {}
/**
* Create a new key event.
@@ -1362,6 +1363,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
* @param code The key code.
*/
public KeyEvent(int action, int code) {
+ mId = nativeNextId();
mAction = action;
mKeyCode = code;
mRepeatCount = 0;
@@ -1383,6 +1385,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat) {
+ mId = nativeNextId();
mDownTime = downTime;
mEventTime = eventTime;
mAction = action;
@@ -1407,6 +1410,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState) {
+ mId = nativeNextId();
mDownTime = downTime;
mEventTime = eventTime;
mAction = action;
@@ -1435,6 +1439,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode) {
+ mId = nativeNextId();
mDownTime = downTime;
mEventTime = eventTime;
mAction = action;
@@ -1465,6 +1470,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags) {
+ mId = nativeNextId();
mDownTime = downTime;
mEventTime = eventTime;
mAction = action;
@@ -1497,6 +1503,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public KeyEvent(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags, int source) {
+ mId = nativeNextId();
mDownTime = downTime;
mEventTime = eventTime;
mAction = action;
@@ -1523,6 +1530,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
* @param flags The flags for this key event
*/
public KeyEvent(long time, String characters, int deviceId, int flags) {
+ mId = nativeNextId();
mDownTime = time;
mEventTime = time;
mCharacters = characters;
@@ -1539,6 +1547,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
* Make an exact copy of an existing key event.
*/
public KeyEvent(KeyEvent origEvent) {
+ mId = origEvent.mId;
mDownTime = origEvent.mDownTime;
mEventTime = origEvent.mEventTime;
mAction = origEvent.mAction;
@@ -1567,6 +1576,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
@Deprecated
public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) {
+ mId = nativeNextId(); // Not an exact copy so assign a new ID.
mDownTime = origEvent.mDownTime;
mEventTime = eventTime;
mAction = origEvent.mAction;
@@ -1598,15 +1608,16 @@ public class KeyEvent extends InputEvent implements Parcelable {
}
/**
- * Obtains a (potentially recycled) key event.
+ * Obtains a (potentially recycled) key event. Used by native code to create a Java object.
*
* @hide
*/
- public static KeyEvent obtain(long downTime, long eventTime, int action,
+ public static KeyEvent obtain(int id, long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags, int source, int displayId, @Nullable byte[] hmac,
String characters) {
KeyEvent ev = obtain();
+ ev.mId = id;
ev.mDownTime = downTime;
ev.mEventTime = eventTime;
ev.mAction = action;
@@ -1628,12 +1639,24 @@ public class KeyEvent extends InputEvent implements Parcelable {
*
* @hide
*/
+ public static KeyEvent obtain(long downTime, long eventTime, int action,
+ int code, int repeat, int metaState,
+ int deviceId, int scanCode, int flags, int source, int displayId, String characters) {
+ return obtain(nativeNextId(), downTime, eventTime, action, code, repeat, metaState,
+ deviceId, scanCode, flags, source, displayId, null /* hmac */, characters);
+ }
+
+ /**
+ * Obtains a (potentially recycled) key event.
+ *
+ * @hide
+ */
@UnsupportedAppUsage
public static KeyEvent obtain(long downTime, long eventTime, int action,
int code, int repeat, int metaState,
int deviceId, int scancode, int flags, int source, String characters) {
return obtain(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
- flags, source, INVALID_DISPLAY, null /* hmac */, characters);
+ flags, source, INVALID_DISPLAY, characters);
}
/**
@@ -1645,6 +1668,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
public static KeyEvent obtain(KeyEvent other) {
KeyEvent ev = obtain();
+ ev.mId = other.mId;
ev.mDownTime = other.mDownTime;
ev.mEventTime = other.mEventTime;
ev.mAction = other.mAction;
@@ -1695,6 +1719,12 @@ public class KeyEvent extends InputEvent implements Parcelable {
// Do nothing.
}
+ /** @hide */
+ @Override
+ public int getId() {
+ return mId;
+ }
+
/**
* Create a new key event that is the same as the given one, but whose
* event time and repeat count are replaced with the given value.
@@ -1723,6 +1753,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime,
int newRepeat, int newFlags) {
KeyEvent ret = new KeyEvent(event);
+ ret.mId = nativeNextId(); // Not an exact copy so assign a new ID.
ret.mEventTime = eventTime;
ret.mRepeatCount = newRepeat;
ret.mFlags = newFlags;
@@ -1736,6 +1767,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
* @param action The new action code of the event.
*/
private KeyEvent(KeyEvent origEvent, int action) {
+ mId = nativeNextId(); // Not an exact copy so assign a new ID.
mDownTime = origEvent.mDownTime;
mEventTime = origEvent.mEventTime;
mAction = action;
@@ -1772,6 +1804,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
*/
public static KeyEvent changeFlags(KeyEvent event, int flags) {
event = new KeyEvent(event);
+ event.mId = nativeNextId(); // Not an exact copy so assign a new ID.
event.mFlags = flags;
return event;
}
@@ -3095,6 +3128,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
}
private KeyEvent(Parcel in) {
+ mId = in.readInt();
mDeviceId = in.readInt();
mSource = in.readInt();
mDisplayId = in.readInt();
@@ -3114,6 +3148,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeInt(PARCEL_TOKEN_KEY_EVENT);
+ out.writeInt(mId);
out.writeInt(mDeviceId);
out.writeInt(mSource);
out.writeInt(mDisplayId);
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 006847656cac..19eff72ca814 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1550,6 +1550,8 @@ public final class MotionEvent extends InputEvent implements Parcelable {
private static native long nativeCopy(long destNativePtr, long sourceNativePtr,
boolean keepHistory);
@CriticalNative
+ private static native int nativeGetId(long nativePtr);
+ @CriticalNative
private static native int nativeGetDeviceId(long nativePtr);
@CriticalNative
private static native int nativeGetSource(long nativePtr);
@@ -2024,6 +2026,12 @@ public final class MotionEvent extends InputEvent implements Parcelable {
}
}
+ /** @hide */
+ @Override
+ public int getId() {
+ return nativeGetId(mNativePtr);
+ }
+
/** {@inheritDoc} */
@Override
public final int getDeviceId() {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4a093e6038b8..918b5a35d4db 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -5379,7 +5379,8 @@ public final class ViewRootImpl implements ViewParent,
if (mTracePrefix == null) {
mTracePrefix = getClass().getSimpleName();
}
- Trace.traceBegin(traceTag, mTracePrefix + " seq#=" + q.mEvent.getSequenceNumber());
+ Trace.traceBegin(traceTag, mTracePrefix + " id=0x"
+ + Integer.toHexString(q.mEvent.getId()));
}
}
@@ -7986,12 +7987,13 @@ public final class ViewRootImpl implements ViewParent,
private void deliverInputEvent(QueuedInputEvent q) {
Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
- q.mEvent.getSequenceNumber());
+ q.mEvent.getId());
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "deliverInputEvent src=0x"
+ Integer.toHexString(q.mEvent.getSource()) + " eventTimeNano="
- + q.mEvent.getEventTimeNano() + " seq#=" + q.mEvent.getSequenceNumber());
+ + q.mEvent.getEventTimeNano() + " id=0x"
+ + Integer.toHexString(q.mEvent.getId()));
}
try {
if (mInputEventConsistencyVerifier != null) {
@@ -8032,7 +8034,7 @@ public final class ViewRootImpl implements ViewParent,
private void finishInputEvent(QueuedInputEvent q) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, "deliverInputEvent",
- q.mEvent.getSequenceNumber());
+ q.mEvent.getId());
if (q.mReceiver != null) {
boolean handled = (q.mFlags & QueuedInputEvent.FLAG_FINISHED_HANDLED) != 0;
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index 84acf9ac6989..0a2b1d4a661f 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -114,9 +114,9 @@ status_t NativeInputEventSender::sendKeyEvent(uint32_t seq, const KeyEvent* even
uint32_t publishedSeq = mNextPublishedSeq++;
status_t status =
- mInputPublisher.publishKeyEvent(publishedSeq, event->getDeviceId(), event->getSource(),
- event->getDisplayId(), event->getHmac(),
- event->getAction(), event->getFlags(),
+ mInputPublisher.publishKeyEvent(publishedSeq, event->getId(), event->getDeviceId(),
+ event->getSource(), event->getDisplayId(),
+ event->getHmac(), event->getAction(), event->getFlags(),
event->getKeyCode(), event->getScanCode(),
event->getMetaState(), event->getRepeatCount(),
event->getDownTime(), event->getEventTime());
@@ -138,12 +138,12 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent
for (size_t i = 0; i <= event->getHistorySize(); i++) {
publishedSeq = mNextPublishedSeq++;
status_t status =
- mInputPublisher.publishMotionEvent(publishedSeq, event->getDeviceId(),
- event->getSource(), event->getDisplayId(),
- event->getHmac(), event->getAction(),
- event->getActionButton(), event->getFlags(),
- event->getEdgeFlags(), event->getMetaState(),
- event->getButtonState(),
+ mInputPublisher.publishMotionEvent(publishedSeq, event->getId(),
+ event->getDeviceId(), event->getSource(),
+ event->getDisplayId(), event->getHmac(),
+ event->getAction(), event->getActionButton(),
+ event->getFlags(), event->getEdgeFlags(),
+ event->getMetaState(), event->getButtonState(),
event->getClassification(), event->getXScale(),
event->getYScale(), event->getXOffset(),
event->getYOffset(), event->getXPrecision(),
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index bbe563e12a4c..54567e5010c5 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -75,6 +75,7 @@ static struct {
jmethodID obtain;
jmethodID recycle;
+ jfieldID mId;
jfieldID mDeviceId;
jfieldID mSource;
jfieldID mDisplayId;
@@ -96,6 +97,7 @@ jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event->getHmac());
jobject eventObj =
env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain,
+ event->getId(),
nanoseconds_to_milliseconds(event->getDownTime()),
nanoseconds_to_milliseconds(event->getEventTime()),
event->getAction(), event->getKeyCode(),
@@ -114,6 +116,7 @@ jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
KeyEvent* event) {
+ jint id = env->GetIntField(eventObj, gKeyEventClassInfo.mId);
jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
jint displayId = env->GetIntField(eventObj, gKeyEventClassInfo.mDisplayId);
@@ -131,7 +134,7 @@ status_t android_view_KeyEvent_toNative(JNIEnv* env, jobject eventObj,
jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
- event->initialize(deviceId, source, displayId, *hmac, action, flags, keyCode, scanCode,
+ event->initialize(id, deviceId, source, displayId, *hmac, action, flags, keyCode, scanCode,
metaState, repeatCount, milliseconds_to_nanoseconds(downTime),
milliseconds_to_nanoseconds(eventTime));
return OK;
@@ -159,14 +162,18 @@ static jint android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv* env, jobject c
return KeyEvent::getKeyCodeFromLabel(keyLabel.c_str());
}
+static jint android_view_KeyEvent_nativeNextId() {
+ return static_cast<jint>(InputEvent::nextId());
+}
// ----------------------------------------------------------------------------
static const JNINativeMethod g_methods[] = {
- { "nativeKeyCodeToString", "(I)Ljava/lang/String;",
- (void*)android_view_KeyEvent_nativeKeyCodeToString},
- { "nativeKeyCodeFromString", "(Ljava/lang/String;)I",
- (void*)android_view_KeyEvent_nativeKeyCodeFromString},
+ {"nativeKeyCodeToString", "(I)Ljava/lang/String;",
+ (void*)android_view_KeyEvent_nativeKeyCodeToString},
+ {"nativeKeyCodeFromString", "(Ljava/lang/String;)I",
+ (void*)android_view_KeyEvent_nativeKeyCodeFromString},
+ {"nativeNextId", "()I", (void*)android_view_KeyEvent_nativeNextId},
};
int register_android_view_KeyEvent(JNIEnv* env) {
@@ -175,10 +182,11 @@ int register_android_view_KeyEvent(JNIEnv* env) {
gKeyEventClassInfo.obtain =
GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz, "obtain",
- "(JJIIIIIIIII[BLjava/lang/String;)Landroid/view/KeyEvent;");
+ "(IJJIIIIIIIII[BLjava/lang/String;)Landroid/view/KeyEvent;");
gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
"recycle", "()V");
+ gKeyEventClassInfo.mId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mId", "I");
gKeyEventClassInfo.mDeviceId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDeviceId", "I");
gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
gKeyEventClassInfo.mDisplayId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDisplayId",
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 3335fb23cfb7..9816d713c6dc 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -369,9 +369,10 @@ static jlong android_view_MotionEvent_nativeInitialize(
env->DeleteLocalRef(pointerCoordsObj);
}
- event->initialize(deviceId, source, displayId, INVALID_HMAC, action, 0, flags, edgeFlags,
- metaState, buttonState, static_cast<MotionClassification>(classification),
- 1 /*xScale*/, 1 /*yScale*/, xOffset, yOffset, xPrecision, yPrecision,
+ event->initialize(InputEvent::nextId(), deviceId, source, displayId, INVALID_HMAC, action, 0,
+ flags, edgeFlags, metaState, buttonState,
+ static_cast<MotionClassification>(classification), 1 /*xScale*/, 1 /*yScale*/,
+ xOffset, yOffset, xPrecision, yPrecision,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
downTimeNanos, eventTimeNanos, pointerCount, pointerProperties,
rawPointerCoords);
@@ -592,6 +593,11 @@ static jlong android_view_MotionEvent_nativeCopy(jlong destNativePtr, jlong sour
return reinterpret_cast<jlong>(destEvent);
}
+static jint android_view_MotionEvent_nativeGetId(jlong nativePtr) {
+ MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
+ return event->getId();
+}
+
static jint android_view_MotionEvent_nativeGetDeviceId(jlong nativePtr) {
MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
return event->getDeviceId();
@@ -790,6 +796,7 @@ static const JNINativeMethod gMotionEventMethods[] = {
// --------------- @CriticalNative ------------------
{"nativeCopy", "(JJZ)J", (void*)android_view_MotionEvent_nativeCopy},
+ {"nativeGetId", "(J)I", (void*)android_view_MotionEvent_nativeGetId},
{"nativeGetDeviceId", "(J)I", (void*)android_view_MotionEvent_nativeGetDeviceId},
{"nativeGetSource", "(J)I", (void*)android_view_MotionEvent_nativeGetSource},
{"nativeSetSource", "(JI)V", (void*)android_view_MotionEvent_nativeSetSource},
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index 14999c7f5642..623008eafe10 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -19,6 +19,7 @@ package android.view;
import static android.view.Display.INVALID_DISPLAY;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import android.os.Parcel;
@@ -28,10 +29,14 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.HashSet;
+import java.util.Set;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KeyEventTest {
+ private static final int ID = 0xabcdef;
private static final int DOWN_TIME = 50;
private static final long EVENT_TIME = 100;
private static final int ACTION = KeyEvent.ACTION_DOWN;
@@ -45,6 +50,8 @@ public class KeyEventTest {
private static final byte[] HMAC = null;
private static final String CHARACTERS = null;
+ private static final int ID_SOURCE_MASK = 0x3 << 30;
+
@Test
public void testObtain() {
KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
@@ -75,8 +82,7 @@ public class KeyEventTest {
public void testObtainWithDisplayId() {
final int displayId = 5;
KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
- METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, null /* hmac*/,
- CHARACTERS);
+ METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, CHARACTERS);
assertEquals(DOWN_TIME, keyEvent.getDownTime());
assertEquals(EVENT_TIME, keyEvent.getEventTime());
assertEquals(ACTION, keyEvent.getAction());
@@ -91,6 +97,52 @@ public class KeyEventTest {
assertEquals(CHARACTERS, keyEvent.getCharacters());
}
+ /**
+ * Tests that it can generate 500 consecutive distinct numbers. This is a non-deterministic test
+ * but with 30 bits randomness the failure rate is roughly 4.52e-5, which is negligible enough.
+ * Probability formula: N * (N - 1) * ... * (N - n + 1) / N^n, where N = 2^30 and n = 500 for
+ * this test.
+ */
+ @Test
+ public void testObtainGeneratesUniqueId() {
+ Set<Integer> set = new HashSet<>();
+ for (int i = 0; i < 500; ++i) {
+ KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+ METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
+ assertFalse("Found duplicate ID in round " + i,
+ set.contains(keyEvent.getId()));
+ set.add(keyEvent.getSequenceNumber());
+ }
+ }
+
+ @Test
+ public void testConstructorGeneratesUniqueId() {
+ Set<Integer> set = new HashSet<>();
+ for (int i = 0; i < 500; ++i) {
+ KeyEvent keyEvent = new KeyEvent(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT);
+ assertFalse("Found duplicate sequence number in round " + i,
+ set.contains(keyEvent.getId()));
+ set.add(keyEvent.getSequenceNumber());
+ }
+ }
+
+ @Test
+ public void testObtainGeneratesIdWithRightSource() {
+ for (int i = 0; i < 500; ++i) {
+ KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+ METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
+ assertEquals(0x3 << 30, ID_SOURCE_MASK & keyEvent.getId());
+ }
+ }
+
+ @Test
+ public void testConstructorGeneratesIdWithRightSource() {
+ for (int i = 0; i < 500; ++i) {
+ KeyEvent keyEvent = new KeyEvent(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT);
+ assertEquals(0x3 << 30, ID_SOURCE_MASK & keyEvent.getId());
+ }
+ }
+
@Test
public void testParcelUnparcel() {
KeyEvent key1 = createKey();
@@ -112,11 +164,12 @@ public class KeyEventTest {
}
private static KeyEvent createKey() {
- return KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
- METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, INVALID_DISPLAY, HMAC, CHARACTERS);
+ return KeyEvent.obtain(ID, DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT, METASTATE,
+ DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, INVALID_DISPLAY, HMAC, CHARACTERS);
}
private static void compareKeys(KeyEvent key1, KeyEvent key2) {
+ assertEquals(key1.getId(), key2.getId());
assertEquals(key1.getDownTime(), key2.getDownTime());
assertEquals(key1.getEventTime(), key2.getEventTime());
assertEquals(key1.getAction(), key2.getAction());
diff --git a/core/tests/coretests/src/android/view/MotionEventTest.java b/core/tests/coretests/src/android/view/MotionEventTest.java
index 9d09830c585b..786ae89ac2ae 100644
--- a/core/tests/coretests/src/android/view/MotionEventTest.java
+++ b/core/tests/coretests/src/android/view/MotionEventTest.java
@@ -23,6 +23,7 @@ import static android.view.MotionEvent.TOOL_TYPE_FINGER;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import android.view.MotionEvent.PointerCoords;
@@ -34,9 +35,13 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.HashSet;
+import java.util.Set;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class MotionEventTest {
+ private static final int ID_SOURCE_MASK = 0x3 << 30;
@Test
public void testObtainWithDisplayId() {
@@ -138,4 +143,30 @@ public class MotionEventTest {
assertEquals(30, event.getXCursorPosition(), 0.1);
assertEquals(50, event.getYCursorPosition(), 0.1);
}
+
+ /**
+ * Tests that it can generate 500 consecutive distinct numbers. This is a non-deterministic test
+ * but with 30 bits randomness the failure rate is roughly 4.52e-5, which is negligible enough.
+ * Probability formula: N * (N - 1) * ... * (N - n + 1) / N^n, where N = 2^30 and n = 500 for
+ * this test.
+ */
+ @Test
+ public void testObtainGeneratesUniqueId() {
+ Set<Integer> set = new HashSet<>();
+ for (int i = 0; i < 500; ++i) {
+ final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
+ ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
+ assertFalse("Found duplicate ID in round " + i, set.contains(event.getId()));
+ set.add(event.getSequenceNumber());
+ }
+ }
+
+ @Test
+ public void testObtainGeneratesIdWithRightSource() {
+ for (int i = 0; i < 500; ++i) {
+ final MotionEvent event = MotionEvent.obtain(0 /* downTime */, 0 /* eventTime */,
+ ACTION_DOWN, 30 /* x */, 50 /* y */, 0 /* metaState */);
+ assertEquals(0x3 << 30, ID_SOURCE_MASK & event.getId());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b40c2c1d343b..1b5cc6a248e3 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3090,7 +3090,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
event.getAction(), fallbackAction.keyCode,
event.getRepeatCount(), fallbackAction.metaState,
event.getDeviceId(), event.getScanCode(),
- flags, event.getSource(), event.getDisplayId(), null /* hmac */, null);
+ flags, event.getSource(), event.getDisplayId(), null);
if (!interceptFallback(focusedToken, fallbackEvent, policyFlags)) {
fallbackEvent.recycle();