summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/input/Input.h2
-rw-r--r--services/inputflinger/dispatcher/InputDispatcher.cpp6
-rw-r--r--services/inputflinger/dispatcher/InputEventTimeline.cpp9
-rw-r--r--services/inputflinger/dispatcher/InputEventTimeline.h26
-rw-r--r--services/inputflinger/dispatcher/LatencyTracker.cpp43
-rw-r--r--services/inputflinger/dispatcher/LatencyTracker.h5
-rw-r--r--services/inputflinger/tests/LatencyTracker_test.cpp156
-rw-r--r--services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp8
8 files changed, 204 insertions, 51 deletions
diff --git a/include/input/Input.h b/include/input/Input.h
index 1a3cb6a884..a8684bd19b 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -251,6 +251,8 @@ enum class InputEventType {
TOUCH_MODE = AINPUT_EVENT_TYPE_TOUCH_MODE,
ftl_first = KEY,
ftl_last = TOUCH_MODE,
+ // Used by LatencyTracker fuzzer
+ kMaxValue = ftl_last
};
std::string inputEventSourceToString(int32_t source);
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index fcea0f3d93..d549cbc2d1 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -52,6 +52,7 @@
#include "Connection.h"
#include "DebugConfig.h"
#include "InputDispatcher.h"
+#include "InputEventTimeline.h"
#include "trace/InputTracer.h"
#include "trace/InputTracingPerfettoBackend.h"
#include "trace/ThreadedBackend.h"
@@ -4638,10 +4639,9 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs& args) {
if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
!mInputFilterEnabled) {
- const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(args);
- mLatencyTracker.trackListener(args.id, isDown, args.eventTime, args.readTime,
- args.deviceId, sources);
+ mLatencyTracker.trackListener(args.id, args.eventTime, args.readTime, args.deviceId,
+ sources, args.action, InputEventType::MOTION);
}
needWake = enqueueInboundEventLocked(std::move(newEntry));
diff --git a/services/inputflinger/dispatcher/InputEventTimeline.cpp b/services/inputflinger/dispatcher/InputEventTimeline.cpp
index a3650030ac..31ceb8d4d3 100644
--- a/services/inputflinger/dispatcher/InputEventTimeline.cpp
+++ b/services/inputflinger/dispatcher/InputEventTimeline.cpp
@@ -68,13 +68,15 @@ bool ConnectionTimeline::operator!=(const ConnectionTimeline& rhs) const {
InputEventTimeline::InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime,
uint16_t vendorId, uint16_t productId,
- const std::set<InputDeviceUsageSource>& sources)
+ const std::set<InputDeviceUsageSource>& sources,
+ InputEventActionType inputEventActionType)
: isDown(isDown),
eventTime(eventTime),
readTime(readTime),
vendorId(vendorId),
productId(productId),
- sources(sources) {}
+ sources(sources),
+ inputEventActionType(inputEventActionType) {}
bool InputEventTimeline::operator==(const InputEventTimeline& rhs) const {
if (connectionTimelines.size() != rhs.connectionTimelines.size()) {
@@ -90,7 +92,8 @@ bool InputEventTimeline::operator==(const InputEventTimeline& rhs) const {
}
}
return isDown == rhs.isDown && eventTime == rhs.eventTime && readTime == rhs.readTime &&
- vendorId == rhs.vendorId && productId == rhs.productId && sources == rhs.sources;
+ vendorId == rhs.vendorId && productId == rhs.productId && sources == rhs.sources &&
+ inputEventActionType == rhs.inputEventActionType;
}
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputEventTimeline.h b/services/inputflinger/dispatcher/InputEventTimeline.h
index 1756944d0e..6668399af3 100644
--- a/services/inputflinger/dispatcher/InputEventTimeline.h
+++ b/services/inputflinger/dispatcher/InputEventTimeline.h
@@ -74,15 +74,39 @@ private:
bool mHasGraphicsTimeline = false;
};
+enum class InputEventActionType : int32_t {
+ UNKNOWN_INPUT_EVENT = 0,
+ MOTION_ACTION_DOWN = 1,
+ // Motion events for ACTION_MOVE (characterizes scrolling motion)
+ MOTION_ACTION_MOVE = 2,
+ // Motion events for ACTION_UP (when the pointer first goes up)
+ MOTION_ACTION_UP = 3,
+ // Motion events for ACTION_HOVER_MOVE (pointer position on screen changes but pointer is not
+ // down)
+ MOTION_ACTION_HOVER_MOVE = 4,
+ // Motion events for ACTION_SCROLL (moving the mouse wheel)
+ MOTION_ACTION_SCROLL = 5,
+ // Key events for both ACTION_DOWN and ACTION_UP (key press and key release)
+ KEY = 6,
+
+ ftl_first = UNKNOWN_INPUT_EVENT,
+ ftl_last = KEY,
+ // Used by latency fuzzer
+ kMaxValue = ftl_last
+
+};
+
struct InputEventTimeline {
InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime, uint16_t vendorId,
- uint16_t productId, const std::set<InputDeviceUsageSource>& sources);
+ uint16_t productId, const std::set<InputDeviceUsageSource>& sources,
+ InputEventActionType inputEventActionType);
const bool isDown; // True if this is an ACTION_DOWN event
const nsecs_t eventTime;
const nsecs_t readTime;
const uint16_t vendorId;
const uint16_t productId;
const std::set<InputDeviceUsageSource> sources;
+ const InputEventActionType inputEventActionType;
struct IBinderHash {
std::size_t operator()(const sp<IBinder>& b) const {
diff --git a/services/inputflinger/dispatcher/LatencyTracker.cpp b/services/inputflinger/dispatcher/LatencyTracker.cpp
index 698bd9ff08..721d009570 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.cpp
+++ b/services/inputflinger/dispatcher/LatencyTracker.cpp
@@ -67,9 +67,10 @@ LatencyTracker::LatencyTracker(InputEventTimelineProcessor* processor)
LOG_ALWAYS_FATAL_IF(processor == nullptr);
}
-void LatencyTracker::trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime,
- nsecs_t readTime, DeviceId deviceId,
- const std::set<InputDeviceUsageSource>& sources) {
+void LatencyTracker::trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime,
+ DeviceId deviceId,
+ const std::set<InputDeviceUsageSource>& sources,
+ int inputEventAction, InputEventType inputEventType) {
reportAndPruneMatureRecords(eventTime);
const auto it = mTimelines.find(inputEventId);
if (it != mTimelines.end()) {
@@ -101,9 +102,43 @@ void LatencyTracker::trackListener(int32_t inputEventId, bool isDown, nsecs_t ev
return;
}
+ const InputEventActionType inputEventActionType = [&]() {
+ switch (inputEventType) {
+ case InputEventType::MOTION: {
+ switch (inputEventAction) {
+ case AMOTION_EVENT_ACTION_DOWN:
+ return InputEventActionType::MOTION_ACTION_DOWN;
+ case AMOTION_EVENT_ACTION_MOVE:
+ return InputEventActionType::MOTION_ACTION_MOVE;
+ case AMOTION_EVENT_ACTION_UP:
+ return InputEventActionType::MOTION_ACTION_UP;
+ case AMOTION_EVENT_ACTION_HOVER_MOVE:
+ return InputEventActionType::MOTION_ACTION_HOVER_MOVE;
+ case AMOTION_EVENT_ACTION_SCROLL:
+ return InputEventActionType::MOTION_ACTION_SCROLL;
+ default:
+ return InputEventActionType::UNKNOWN_INPUT_EVENT;
+ }
+ }
+ case InputEventType::KEY: {
+ switch (inputEventAction) {
+ case AKEY_EVENT_ACTION_DOWN:
+ case AKEY_EVENT_ACTION_UP:
+ return InputEventActionType::KEY;
+ default:
+ return InputEventActionType::UNKNOWN_INPUT_EVENT;
+ }
+ }
+ default:
+ return InputEventActionType::UNKNOWN_INPUT_EVENT;
+ }
+ }();
+
+ bool isDown = inputEventType == InputEventType::MOTION &&
+ inputEventAction == AMOTION_EVENT_ACTION_DOWN;
mTimelines.emplace(inputEventId,
InputEventTimeline(isDown, eventTime, readTime, identifier->vendor,
- identifier->product, sources));
+ identifier->product, sources, inputEventActionType));
mEventTimes.emplace(eventTime, inputEventId);
}
diff --git a/services/inputflinger/dispatcher/LatencyTracker.h b/services/inputflinger/dispatcher/LatencyTracker.h
index 890d61d431..532f42290a 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.h
+++ b/services/inputflinger/dispatcher/LatencyTracker.h
@@ -52,8 +52,9 @@ public:
* duplicate events that happen to have the same eventTime and inputEventId. Therefore, we
* must drop all duplicate data.
*/
- void trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime, nsecs_t readTime,
- DeviceId deviceId, const std::set<InputDeviceUsageSource>& sources);
+ void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId,
+ const std::set<InputDeviceUsageSource>& sources, int inputEventActionType,
+ InputEventType inputEventType);
void trackFinishedEvent(int32_t inputEventId, const sp<IBinder>& connectionToken,
nsecs_t deliveryTime, nsecs_t consumeTime, nsecs_t finishTime);
void trackGraphicsLatency(int32_t inputEventId, const sp<IBinder>& connectionToken,
diff --git a/services/inputflinger/tests/LatencyTracker_test.cpp b/services/inputflinger/tests/LatencyTracker_test.cpp
index 4fcffddee2..56502861cf 100644
--- a/services/inputflinger/tests/LatencyTracker_test.cpp
+++ b/services/inputflinger/tests/LatencyTracker_test.cpp
@@ -61,12 +61,13 @@ const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds(
InputEventTimeline getTestTimeline() {
InputEventTimeline t(
- /*isDown=*/true,
+ /*isDown=*/false,
/*eventTime=*/2,
/*readTime=*/3,
/*vendorId=*/0,
/*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
ConnectionTimeline expectedCT(/*deliveryTime=*/6, /*consumeTime=*/7, /*finishTime=*/8);
std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline;
graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 9;
@@ -116,9 +117,10 @@ private:
void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) {
const nsecs_t triggerEventTime =
lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1;
- mTracker->trackListener(/*inputEventId=*/1, /*isDown=*/true, triggerEventTime,
+ mTracker->trackListener(/*inputEventId=*/1, triggerEventTime,
/*readTime=*/3, DEVICE_ID,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
}
void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) {
@@ -167,12 +169,15 @@ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTim
* any additional ConnectionTimeline's.
*/
TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) {
- mTracker->trackListener(/*inputEventId=*/1, /*isDown=*/false, /*eventTime=*/2,
- /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(/*inputEventId=*/1, /*eventTime=*/2,
+ /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
triggerEventReporting(/*eventTime=*/2);
- assertReceivedTimeline(InputEventTimeline{/*isDown=*/false, /*eventTime=*/2,
- /*readTime=*/3, /*vendorId=*/0, /*productID=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN}});
+ assertReceivedTimeline(
+ InputEventTimeline{/*isDown=*/false, /*eventTime=*/2,
+ /*readTime=*/3, /*vendorId=*/0, /*productID=*/0,
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT});
}
/**
@@ -203,8 +208,9 @@ TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) {
const auto& [connectionToken, expectedCT] = *expected.connectionTimelines.begin();
- mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime,
- DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
mTracker->trackFinishedEvent(inputEventId, connectionToken, expectedCT.deliveryTime,
expectedCT.consumeTime, expectedCT.finishTime);
mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline);
@@ -220,14 +226,16 @@ TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) {
TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) {
constexpr nsecs_t inputEventId = 1;
constexpr nsecs_t readTime = 3; // does not matter for this test
- constexpr bool isDown = true; // does not matter for this test
+ constexpr bool isDown = false; // does not matter for this test
// In the following 2 calls to trackListener, the inputEventId's are the same, but event times
// are different.
- mTracker->trackListener(inputEventId, isDown, /*eventTime=*/1, readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN});
- mTracker->trackListener(inputEventId, isDown, /*eventTime=*/2, readTime, DEVICE_ID,
- {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId, /*eventTime=*/1, readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
+ mTracker->trackListener(inputEventId, /*eventTime=*/2, readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
triggerEventReporting(/*eventTime=*/2);
// Since we sent duplicate input events, the tracker should just delete all of them, because it
@@ -238,12 +246,13 @@ TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) {
TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) {
constexpr int32_t inputEventId1 = 1;
InputEventTimeline timeline1(
- /*isDown*/ true,
+ /*isDown*/ false,
/*eventTime*/ 2,
/*readTime*/ 3,
/*vendorId=*/0,
/*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
timeline1.connectionTimelines.emplace(connection1,
ConnectionTimeline(/*deliveryTime*/ 6, /*consumeTime*/ 7,
/*finishTime*/ 8));
@@ -260,7 +269,8 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) {
/*readTime=*/30,
/*vendorId=*/0,
/*productId=*/0,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
timeline2.connectionTimelines.emplace(connection2,
ConnectionTimeline(/*deliveryTime=*/60,
/*consumeTime=*/70,
@@ -272,11 +282,13 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) {
connectionTimeline2.setGraphicsTimeline(std::move(graphicsTimeline2));
// Start processing first event
- mTracker->trackListener(inputEventId1, timeline1.isDown, timeline1.eventTime,
- timeline1.readTime, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId1, timeline1.eventTime, timeline1.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
// Start processing second event
- mTracker->trackListener(inputEventId2, timeline2.isDown, timeline2.eventTime,
- timeline2.readTime, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId2, timeline2.eventTime, timeline2.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
mTracker->trackFinishedEvent(inputEventId1, connection1, connectionTimeline1.deliveryTime,
connectionTimeline1.consumeTime, connectionTimeline1.finishTime);
@@ -301,12 +313,14 @@ TEST_F(LatencyTrackerTest, IncompleteEvents_AreHandledConsistently) {
const sp<IBinder>& token = timeline.connectionTimelines.begin()->first;
for (size_t i = 1; i <= 100; i++) {
- mTracker->trackListener(/*inputEventId=*/i, timeline.isDown, timeline.eventTime,
- timeline.readTime, /*deviceId=*/DEVICE_ID,
- /*sources=*/{InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(/*inputEventId=*/i, timeline.eventTime, timeline.readTime,
+ /*deviceId=*/DEVICE_ID,
+ /*sources=*/{InputDeviceUsageSource::UNKNOWN},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
expectedTimelines.push_back(InputEventTimeline{timeline.isDown, timeline.eventTime,
timeline.readTime, timeline.vendorId,
- timeline.productId, timeline.sources});
+ timeline.productId, timeline.sources,
+ timeline.inputEventActionType});
}
// Now, complete the first event that was sent.
mTracker->trackFinishedEvent(/*inputEventId=*/1, token, expectedCT.deliveryTime,
@@ -332,12 +346,14 @@ TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) {
expectedCT.consumeTime, expectedCT.finishTime);
mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline);
- mTracker->trackListener(inputEventId, expected.isDown, expected.eventTime, expected.readTime,
- DEVICE_ID, {InputDeviceUsageSource::UNKNOWN});
+ mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID,
+ {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL,
+ InputEventType::MOTION);
triggerEventReporting(expected.eventTime);
assertReceivedTimeline(InputEventTimeline{expected.isDown, expected.eventTime,
expected.readTime, expected.vendorId,
- expected.productId, expected.sources});
+ expected.productId, expected.sources,
+ expected.inputEventActionType});
}
/**
@@ -348,22 +364,92 @@ TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) {
TEST_F(LatencyTrackerTest, TrackListenerCheck_DeviceInfoFieldsInputEventTimeline) {
constexpr int32_t inputEventId = 1;
InputEventTimeline timeline(
- /*isDown*/ true, /*eventTime*/ 2, /*readTime*/ 3,
+ /*isDown*/ false, /*eventTime*/ 2, /*readTime*/ 3,
/*vendorId=*/50, /*productId=*/60,
/*sources=*/
- {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT});
+ {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT},
+ /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT);
InputDeviceInfo deviceInfo1 = generateTestDeviceInfo(
/*vendorId=*/5, /*productId=*/6, /*deviceId=*/DEVICE_ID + 1);
InputDeviceInfo deviceInfo2 = generateTestDeviceInfo(
/*vendorId=*/50, /*productId=*/60, /*deviceId=*/DEVICE_ID);
mTracker->setInputDevices({deviceInfo1, deviceInfo2});
- mTracker->trackListener(inputEventId, timeline.isDown, timeline.eventTime, timeline.readTime,
- DEVICE_ID,
+ mTracker->trackListener(inputEventId, timeline.eventTime, timeline.readTime, DEVICE_ID,
{InputDeviceUsageSource::TOUCHSCREEN,
- InputDeviceUsageSource::STYLUS_DIRECT});
+ InputDeviceUsageSource::STYLUS_DIRECT},
+ AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION);
triggerEventReporting(timeline.eventTime);
assertReceivedTimeline(timeline);
}
+/**
+ * Check that InputEventActionType is correctly assigned to InputEventTimeline in trackListener.
+ */
+TEST_F(LatencyTrackerTest, TrackListenerCheck_InputEventActionTypeFieldInputEventTimeline) {
+ constexpr int32_t inputEventId = 1;
+ // Create timelines for different event types (Motion, Key)
+ InputEventTimeline motionDownTimeline(
+ /*isDown*/ true, /*eventTime*/ 2, /*readTime*/ 3,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_DOWN);
+
+ InputEventTimeline motionMoveTimeline(
+ /*isDown*/ false, /*eventTime*/ 4, /*readTime*/ 5,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_MOVE);
+
+ InputEventTimeline motionUpTimeline(
+ /*isDown*/ false, /*eventTime*/ 6, /*readTime*/ 7,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_UP);
+
+ InputEventTimeline keyDownTimeline(
+ /*isDown*/ false, /*eventTime*/ 8, /*readTime*/ 9,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::KEY);
+
+ InputEventTimeline keyUpTimeline(
+ /*isDown*/ false, /*eventTime*/ 10, /*readTime*/ 11,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::KEY);
+
+ InputEventTimeline unknownTimeline(
+ /*isDown*/ false, /*eventTime*/ 12, /*readTime*/ 13,
+ /*vendorId*/ 0, /*productId*/ 0,
+ /*sources*/ {InputDeviceUsageSource::UNKNOWN},
+ /*inputEventActionType*/ InputEventActionType::UNKNOWN_INPUT_EVENT);
+
+ mTracker->trackListener(inputEventId, motionDownTimeline.eventTime, motionDownTimeline.readTime,
+ DEVICE_ID, motionDownTimeline.sources, AMOTION_EVENT_ACTION_DOWN,
+ InputEventType::MOTION);
+ mTracker->trackListener(inputEventId + 1, motionMoveTimeline.eventTime,
+ motionMoveTimeline.readTime, DEVICE_ID, motionMoveTimeline.sources,
+ AMOTION_EVENT_ACTION_MOVE, InputEventType::MOTION);
+ mTracker->trackListener(inputEventId + 2, motionUpTimeline.eventTime, motionUpTimeline.readTime,
+ DEVICE_ID, motionUpTimeline.sources, AMOTION_EVENT_ACTION_UP,
+ InputEventType::MOTION);
+ mTracker->trackListener(inputEventId + 3, keyDownTimeline.eventTime, keyDownTimeline.readTime,
+ DEVICE_ID, keyDownTimeline.sources, AKEY_EVENT_ACTION_DOWN,
+ InputEventType::KEY);
+ mTracker->trackListener(inputEventId + 4, keyUpTimeline.eventTime, keyUpTimeline.readTime,
+ DEVICE_ID, keyUpTimeline.sources, AKEY_EVENT_ACTION_UP,
+ InputEventType::KEY);
+ mTracker->trackListener(inputEventId + 5, unknownTimeline.eventTime, unknownTimeline.readTime,
+ DEVICE_ID, unknownTimeline.sources, AMOTION_EVENT_ACTION_POINTER_DOWN,
+ InputEventType::MOTION);
+
+ triggerEventReporting(unknownTimeline.eventTime);
+
+ std::vector<InputEventTimeline> expectedTimelines = {motionDownTimeline, motionMoveTimeline,
+ motionUpTimeline, keyDownTimeline,
+ keyUpTimeline, unknownTimeline};
+ assertReceivedTimelines(expectedTimelines);
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
index 6daeaafbb3..80c2213482 100644
--- a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp
@@ -18,6 +18,7 @@
#include <linux/input.h>
#include "../../InputDeviceMetricsSource.h"
+#include "../InputEventTimeline.h"
#include "dispatcher/LatencyTracker.h"
namespace android {
@@ -65,14 +66,15 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) {
fdp.PickValueInArray<std::function<void()>>({
[&]() -> void {
int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();
- int32_t isDown = fdp.ConsumeBool();
nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>();
nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>();
const DeviceId deviceId = fdp.ConsumeIntegral<int32_t>();
std::set<InputDeviceUsageSource> sources = {
fdp.ConsumeEnum<InputDeviceUsageSource>()};
- tracker.trackListener(inputEventId, isDown, eventTime, readTime, deviceId,
- sources);
+ int32_t inputEventActionType = fdp.ConsumeIntegral<int32_t>();
+ const InputEventType inputEventType = fdp.ConsumeEnum<InputEventType>();
+ tracker.trackListener(inputEventId, eventTime, readTime, deviceId, sources,
+ inputEventActionType, inputEventType);
},
[&]() -> void {
int32_t inputEventId = fdp.ConsumeIntegral<int32_t>();