diff options
author | 2024-10-09 00:07:23 +0000 | |
---|---|---|
committer | 2024-10-17 15:57:52 +0000 | |
commit | 93ee540fcf178c7a852841e861ff10d704cb5f71 (patch) | |
tree | 208f7d0ff14d36cb663f905e98e50346d52e2a6f | |
parent | b7e4701ca848e2d018ba68ff5dd96e31d96051bb (diff) |
Use a single trackListener method in LatencyTracker
This simplifies the code for the caller (InputDispatcher) and reduces the API surface of LatencyTracker.
Bug: 270049345
Change-Id: Ia25e95a24b5e89abcfce8060893ec3cce0c7892e
Flag: EXEMPT refactor
Test: atest inputflinger_tests
8 files changed, 280 insertions, 154 deletions
diff --git a/services/inputflinger/InputDeviceMetricsSource.cpp b/services/inputflinger/InputDeviceMetricsSource.cpp index dee4cb836e..70262fbb04 100644 --- a/services/inputflinger/InputDeviceMetricsSource.cpp +++ b/services/inputflinger/InputDeviceMetricsSource.cpp @@ -50,6 +50,18 @@ InputDeviceUsageSource getUsageSourceForKeyArgs(int32_t keyboardType, return InputDeviceUsageSource::BUTTONS; } +std::set<InputDeviceUsageSource> getUsageSourcesForKeyArgs( + const NotifyKeyArgs& args, const std::vector<InputDeviceInfo>& inputDevices) { + int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NONE; + for (const InputDeviceInfo& inputDevice : inputDevices) { + if (args.deviceId == inputDevice.getId()) { + keyboardType = inputDevice.getKeyboardType(); + break; + } + } + return std::set{getUsageSourceForKeyArgs(keyboardType, args)}; +} + std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs& motionArgs) { LOG_ALWAYS_FATAL_IF(motionArgs.getPointerCount() < 1, "Received motion args without pointers"); std::set<InputDeviceUsageSource> sources; diff --git a/services/inputflinger/InputDeviceMetricsSource.h b/services/inputflinger/InputDeviceMetricsSource.h index a6be8f42cc..702baddc37 100644 --- a/services/inputflinger/InputDeviceMetricsSource.h +++ b/services/inputflinger/InputDeviceMetricsSource.h @@ -54,6 +54,10 @@ enum class InputDeviceUsageSource : int32_t { /** Returns the InputDeviceUsageSource that corresponds to the key event. */ InputDeviceUsageSource getUsageSourceForKeyArgs(int32_t keyboardType, const NotifyKeyArgs&); +/** Returns the InputDeviceUsageSources that correspond to the key event. */ +std::set<InputDeviceUsageSource> getUsageSourcesForKeyArgs( + const NotifyKeyArgs&, const std::vector<InputDeviceInfo>& inputDevices); + /** Returns the InputDeviceUsageSources that correspond to the motion event. */ std::set<InputDeviceUsageSource> getUsageSourcesForMotionArgs(const NotifyMotionArgs&); diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 602904f562..4f9d9e43a3 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -4551,7 +4551,7 @@ void InputDispatcher::notifyKey(const NotifyKeyArgs& args) { if (args.id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID && IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER && !mInputFilterEnabled) { - mLatencyTracker.trackNotifyKey(args); + mLatencyTracker.trackListener(args); } } @@ -4687,7 +4687,7 @@ 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) { - mLatencyTracker.trackNotifyMotion(args); + mLatencyTracker.trackListener(args); } needWake = enqueueInboundEventLocked(std::move(newEntry)); diff --git a/services/inputflinger/dispatcher/LatencyTracker.cpp b/services/inputflinger/dispatcher/LatencyTracker.cpp index 0852026823..0921e37d03 100644 --- a/services/inputflinger/dispatcher/LatencyTracker.cpp +++ b/services/inputflinger/dispatcher/LatencyTracker.cpp @@ -20,6 +20,7 @@ #include <inttypes.h> +#include <android-base/logging.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android/os/IInputConstants.h> @@ -32,6 +33,8 @@ using android::base::StringPrintf; namespace android::inputdispatcher { +namespace { + /** * Events that are older than this time will be considered mature, at which point we will stop * waiting for the apps to provide further information about them. @@ -62,27 +65,25 @@ static void eraseByValue(std::multimap<K, V>& map, const V& value) { } } +} // namespace + LatencyTracker::LatencyTracker(InputEventTimelineProcessor& processor) : mTimelineProcessor(&processor) {} -void LatencyTracker::trackNotifyMotion(const NotifyMotionArgs& args) { - std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(args); - trackListener(args.id, args.eventTime, args.readTime, args.deviceId, sources, args.action, - InputEventType::MOTION); -} - -void LatencyTracker::trackNotifyKey(const NotifyKeyArgs& args) { - int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NONE; - for (auto& inputDevice : mInputDevices) { - if (args.deviceId == inputDevice.getId()) { - keyboardType = inputDevice.getKeyboardType(); - break; - } +void LatencyTracker::trackListener(const NotifyArgs& args) { + if (const NotifyKeyArgs* keyArgs = std::get_if<NotifyKeyArgs>(&args)) { + std::set<InputDeviceUsageSource> sources = + getUsageSourcesForKeyArgs(*keyArgs, mInputDevices); + trackListener(keyArgs->id, keyArgs->eventTime, keyArgs->readTime, keyArgs->deviceId, + sources, keyArgs->action, InputEventType::KEY); + + } else if (const NotifyMotionArgs* motionArgs = std::get_if<NotifyMotionArgs>(&args)) { + std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(*motionArgs); + trackListener(motionArgs->id, motionArgs->eventTime, motionArgs->readTime, + motionArgs->deviceId, sources, motionArgs->action, InputEventType::MOTION); + } else { + LOG(FATAL) << "Unexpected NotifyArgs type: " << args.index(); } - std::set<InputDeviceUsageSource> sources = - std::set{getUsageSourceForKeyArgs(keyboardType, args)}; - trackListener(args.id, args.eventTime, args.readTime, args.deviceId, sources, args.action, - InputEventType::KEY); } void LatencyTracker::trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, diff --git a/services/inputflinger/dispatcher/LatencyTracker.h b/services/inputflinger/dispatcher/LatencyTracker.h index eb58222ce6..79ea14c4fb 100644 --- a/services/inputflinger/dispatcher/LatencyTracker.h +++ b/services/inputflinger/dispatcher/LatencyTracker.h @@ -44,28 +44,20 @@ public: */ LatencyTracker(InputEventTimelineProcessor& processor); /** - * Start keeping track of an event identified by inputEventId. This must be called first. + * Start keeping track of an event identified by the args. This must be called first. * If duplicate events are encountered (events that have the same eventId), none of them will be - * tracked. This is because there is not enough information to correctly track them. The api's - * 'trackFinishedEvent' and 'trackGraphicsLatency' only contain the inputEventId, and not the - * eventTime. Even if eventTime was provided, there would still be a possibility of having - * duplicate events that happen to have the same eventTime and inputEventId. Therefore, we - * must drop all duplicate data. + * tracked. This is because there is not enough information to correctly track them. It is + * always possible that two different events are generated with the same inputEventId and the + * same eventTime, so there aren't ways to distinguish those. Therefore, we must drop all + * duplicate data. + * For that reason, the APIs 'trackFinishedEvent' and 'trackGraphicsLatency' only receive the + * inputEventId as input. */ - void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId, - const std::set<InputDeviceUsageSource>& sources, int32_t inputEventAction, - InputEventType inputEventType); + void trackListener(const NotifyArgs& args); 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, std::array<nsecs_t, GraphicsTimeline::SIZE> timeline); - /** - * trackNotifyMotion and trackNotifyKeys are intermediates between InputDispatcher and - * trackListener. They compute the InputDeviceUsageSource set and call trackListener with - * the relevant parameters for latency computation. - */ - void trackNotifyMotion(const NotifyMotionArgs& args); - void trackNotifyKey(const NotifyKeyArgs& args); std::string dump(const char* prefix) const; void setInputDevices(const std::vector<InputDeviceInfo>& inputDevices); @@ -90,6 +82,10 @@ private: InputEventTimelineProcessor* mTimelineProcessor; std::vector<InputDeviceInfo> mInputDevices; + + void trackListener(int32_t inputEventId, nsecs_t eventTime, nsecs_t readTime, DeviceId deviceId, + const std::set<InputDeviceUsageSource>& sources, int32_t inputEventAction, + InputEventType inputEventType); void reportAndPruneMatureRecords(nsecs_t newEventTime); }; diff --git a/services/inputflinger/include/NotifyArgsBuilders.h b/services/inputflinger/include/NotifyArgsBuilders.h index 5b94d57b8e..13eaaf3be9 100644 --- a/services/inputflinger/include/NotifyArgsBuilders.h +++ b/services/inputflinger/include/NotifyArgsBuilders.h @@ -24,13 +24,15 @@ #include <input/Keyboard.h> #include <utils/Timers.h> // for nsecs_t, systemTime +#include <cstdint> #include <vector> namespace android { class MotionArgsBuilder { public: - MotionArgsBuilder(int32_t action, int32_t source) : mEventId(InputEvent::nextId()) { + MotionArgsBuilder(int32_t action, int32_t source, int32_t eventId = InputEvent::nextId()) + : mEventId(eventId) { mAction = action; if (mAction == AMOTION_EVENT_ACTION_CANCEL) { addFlag(AMOTION_EVENT_FLAG_CANCELED); @@ -55,6 +57,11 @@ public: return *this; } + MotionArgsBuilder& readTime(nsecs_t readTime) { + mReadTime = readTime; + return *this; + } + MotionArgsBuilder& displayId(ui::LogicalDisplayId displayId) { mDisplayId = displayId; return *this; @@ -121,7 +128,7 @@ public: return {mEventId, mEventTime, - /*readTime=*/mEventTime, + mReadTime.value_or(mEventTime), mDeviceId, mSource, mDisplayId, @@ -151,6 +158,7 @@ private: uint32_t mSource; nsecs_t mDownTime; nsecs_t mEventTime; + std::optional<nsecs_t> mReadTime; ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT}; uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS; int32_t mActionButton{0}; @@ -165,7 +173,8 @@ private: class KeyArgsBuilder { public: - KeyArgsBuilder(int32_t action, int32_t source) : mEventId(InputEvent::nextId()) { + KeyArgsBuilder(int32_t action, int32_t source, int32_t eventId = InputEvent::nextId()) + : mEventId(eventId) { mAction = action; mSource = source; mEventTime = systemTime(SYSTEM_TIME_MONOTONIC); @@ -187,6 +196,11 @@ public: return *this; } + KeyArgsBuilder& readTime(nsecs_t readTime) { + mReadTime = readTime; + return *this; + } + KeyArgsBuilder& displayId(ui::LogicalDisplayId displayId) { mDisplayId = displayId; return *this; @@ -214,18 +228,10 @@ public: } NotifyKeyArgs build() const { - return {mEventId, - mEventTime, - /*readTime=*/mEventTime, - mDeviceId, - mSource, - mDisplayId, - mPolicyFlags, - mAction, - mFlags, - mKeyCode, - mScanCode, - mMetaState, + return {mEventId, mEventTime, mReadTime.value_or(mEventTime), + mDeviceId, mSource, mDisplayId, + mPolicyFlags, mAction, mFlags, + mKeyCode, mScanCode, mMetaState, mDownTime}; } @@ -236,6 +242,7 @@ private: uint32_t mSource; nsecs_t mDownTime; nsecs_t mEventTime; + std::optional<nsecs_t> mReadTime; ui::LogicalDisplayId mDisplayId{ui::LogicalDisplayId::DEFAULT}; uint32_t mPolicyFlags = DEFAULT_POLICY_FLAGS; int32_t mFlags{0}; diff --git a/services/inputflinger/tests/LatencyTracker_test.cpp b/services/inputflinger/tests/LatencyTracker_test.cpp index 3f14c2312b..ca0f1e8999 100644 --- a/services/inputflinger/tests/LatencyTracker_test.cpp +++ b/services/inputflinger/tests/LatencyTracker_test.cpp @@ -16,10 +16,14 @@ #include "../dispatcher/LatencyTracker.h" #include "../InputDeviceMetricsSource.h" +#include "NotifyArgsBuilders.h" +#include "android/input.h" +#include <android-base/logging.h> #include <android-base/properties.h> #include <binder/Binder.h> #include <gtest/gtest.h> +#include <input/PrintTools.h> #include <inttypes.h> #include <linux/input.h> #include <log/log.h> @@ -48,11 +52,44 @@ static InputDeviceInfo generateTestDeviceInfo(uint16_t vendorId, uint16_t produc } void setDefaultInputDeviceInfo(LatencyTracker& tracker) { - InputDeviceInfo deviceInfo = generateTestDeviceInfo( - /*vendorId=*/0, /*productId=*/0, DEVICE_ID); + InputDeviceInfo deviceInfo = generateTestDeviceInfo(/*vendorId=*/0, /*productId=*/0, DEVICE_ID); tracker.setInputDevices({deviceInfo}); } +const auto FIRST_TOUCH_POINTER = PointerBuilder(/*id=*/0, ToolType::FINGER).x(100).y(200); + +/** + * This is a convenience method for comparing timelines that also prints the difference between + * the two structures. This helps debugging when the timelines don't match. + * @param received the timeline that was actually received + * @param expected the timeline that we expected to receive + * @return true if the two timelines match, false otherwise. + */ +bool timelinesAreEqual(const InputEventTimeline& received, const InputEventTimeline& expected) { + LOG_IF(ERROR, expected.eventTime != received.eventTime) + << "Received timeline with eventTime=" << received.eventTime + << " instead of expected eventTime=" << expected.eventTime; + LOG_IF(ERROR, expected.readTime != received.readTime) + << "Received timeline with readTime=" << received.readTime + << " instead of expected readTime=" << expected.readTime; + LOG_IF(ERROR, expected.vendorId != received.vendorId) + << "Received timeline with vendorId=" << received.vendorId + << " instead of expected vendorId=" << expected.vendorId; + LOG_IF(ERROR, expected.productId != received.productId) + << "Received timeline with productId=" << received.productId + << " instead of expected productId=" << expected.productId; + LOG_IF(ERROR, expected.sources != received.sources) + << "Received timeline with sources=" << dumpSet(received.sources, ftl::enum_string) + << " instead of expected sources=" << dumpSet(expected.sources, ftl::enum_string); + LOG_IF(ERROR, expected.inputEventActionType != received.inputEventActionType) + << "Received timeline with inputEventActionType=" + << ftl::enum_string(received.inputEventActionType) + << " instead of expected inputEventActionType=" + << ftl::enum_string(expected.inputEventActionType); + + return received == expected; +} + } // namespace const std::chrono::duration ANR_TIMEOUT = std::chrono::milliseconds( @@ -64,15 +101,14 @@ InputEventTimeline getTestTimeline() { /*eventTime=*/2, /*readTime=*/3, /*vendorId=*/0, - /*productId=*/0, - /*sources=*/{InputDeviceUsageSource::UNKNOWN}, + /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN}, /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT); ConnectionTimeline expectedCT(/*deliveryTime=*/6, /*consumeTime=*/7, /*finishTime=*/8); - std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline; + std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline{}; graphicsTimeline[GraphicsTimeline::GPU_COMPLETED_TIME] = 9; graphicsTimeline[GraphicsTimeline::PRESENT_TIME] = 10; - expectedCT.setGraphicsTimeline(std::move(graphicsTimeline)); - t.connectionTimelines.emplace(sp<BBinder>::make(), std::move(expectedCT)); + expectedCT.setGraphicsTimeline(graphicsTimeline); + t.connectionTimelines.emplace(sp<BBinder>::make(), expectedCT); return t; } @@ -118,16 +154,19 @@ private: void LatencyTrackerTest::triggerEventReporting(nsecs_t lastEventTime) { const nsecs_t triggerEventTime = lastEventTime + std::chrono::nanoseconds(ANR_TIMEOUT).count() + 1; - mTracker->trackListener(/*inputEventId=*/1, triggerEventTime, - /*readTime=*/3, DEVICE_ID, - /*sources=*/{InputDeviceUsageSource::UNKNOWN}, - AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION); + mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, + AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/1) + .eventTime(triggerEventTime) + .readTime(3) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); } -void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& timeline) { +void LatencyTrackerTest::assertReceivedTimeline(const InputEventTimeline& expectedTimeline) { ASSERT_FALSE(mReceivedTimelines.empty()); - const InputEventTimeline& t = mReceivedTimelines.front(); - ASSERT_EQ(timeline, t); + const InputEventTimeline& received = mReceivedTimelines.front(); + ASSERT_TRUE(timelinesAreEqual(received, expectedTimeline)); mReceivedTimelines.pop_front(); } @@ -148,6 +187,11 @@ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTim break; } } + if (!found) { + for (const InputEventTimeline& receivedTimeline : mReceivedTimelines) { + LOG(ERROR) << "Received timeline with eventTime=" << receivedTimeline.eventTime; + } + } ASSERT_TRUE(found) << "Could not find expected timeline with eventTime=" << expectedTimeline.eventTime; } @@ -170,14 +214,20 @@ void LatencyTrackerTest::assertReceivedTimelines(const std::vector<InputEventTim * any additional ConnectionTimeline's. */ TEST_F(LatencyTrackerTest, TrackListener_DoesNotTriggerReporting) { - mTracker->trackListener(/*inputEventId=*/1, /*eventTime=*/2, - /*readTime=*/3, DEVICE_ID, {InputDeviceUsageSource::UNKNOWN}, - AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION); + mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, + AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/1) + .eventTime(2) + .readTime(3) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); triggerEventReporting(/*eventTime=*/2); assertReceivedTimeline( InputEventTimeline{/*eventTime=*/2, - /*readTime=*/3, /*vendorId=*/0, /*productID=*/0, - /*sources=*/{InputDeviceUsageSource::UNKNOWN}, + /*readTime=*/3, + /*vendorId=*/0, + /*productID=*/0, + {InputDeviceUsageSource::TOUCHSCREEN}, /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT}); } @@ -209,9 +259,13 @@ TEST_F(LatencyTrackerTest, TrackAllParameters_ReportsFullTimeline) { const auto& [connectionToken, expectedCT] = *expected.connectionTimelines.begin(); - mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID, - {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL, - InputEventType::MOTION); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId) + .eventTime(expected.eventTime) + .readTime(expected.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); mTracker->trackFinishedEvent(inputEventId, connectionToken, expectedCT.deliveryTime, expectedCT.consumeTime, expectedCT.finishTime); mTracker->trackGraphicsLatency(inputEventId, connectionToken, expectedCT.graphicsTimeline); @@ -230,12 +284,20 @@ TEST_F(LatencyTrackerTest, WhenDuplicateEventsAreReported_DoesNotCrash) { // In the following 2 calls to trackListener, the inputEventId's are the same, but event times // are different. - 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); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId) + .eventTime(1) + .readTime(readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId) + .eventTime(2) + .readTime(readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); triggerEventReporting(/*eventTime=*/2); // Since we sent duplicate input events, the tracker should just delete all of them, because it @@ -249,8 +311,7 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { /*eventTime*/ 2, /*readTime*/ 3, /*vendorId=*/0, - /*productId=*/0, - /*sources=*/{InputDeviceUsageSource::UNKNOWN}, + /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN}, /*inputEventType=*/InputEventActionType::UNKNOWN_INPUT_EVENT); timeline1.connectionTimelines.emplace(connection1, ConnectionTimeline(/*deliveryTime*/ 6, /*consumeTime*/ 7, @@ -266,8 +327,7 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { /*eventTime=*/20, /*readTime=*/30, /*vendorId=*/0, - /*productId=*/0, - /*sources=*/{InputDeviceUsageSource::UNKNOWN}, + /*productId=*/0, {InputDeviceUsageSource::TOUCHSCREEN}, /*inputEventActionType=*/InputEventActionType::UNKNOWN_INPUT_EVENT); timeline2.connectionTimelines.emplace(connection2, ConnectionTimeline(/*deliveryTime=*/60, @@ -280,13 +340,21 @@ TEST_F(LatencyTrackerTest, MultipleEvents_AreReportedConsistently) { connectionTimeline2.setGraphicsTimeline(std::move(graphicsTimeline2)); // Start processing first event - mTracker->trackListener(inputEventId1, timeline1.eventTime, timeline1.readTime, DEVICE_ID, - {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL, - InputEventType::MOTION); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId1) + .eventTime(timeline1.eventTime) + .readTime(timeline1.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); // Start processing second event - mTracker->trackListener(inputEventId2, timeline2.eventTime, timeline2.readTime, DEVICE_ID, - {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL, - InputEventType::MOTION); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId2) + .eventTime(timeline2.eventTime) + .readTime(timeline2.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); mTracker->trackFinishedEvent(inputEventId1, connection1, connectionTimeline1.deliveryTime, connectionTimeline1.consumeTime, connectionTimeline1.finishTime); @@ -311,10 +379,13 @@ 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.eventTime, timeline.readTime, - /*deviceId=*/DEVICE_ID, - /*sources=*/{InputDeviceUsageSource::UNKNOWN}, - AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION); + mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, + AINPUT_SOURCE_TOUCHSCREEN, /*inputEventId=*/i) + .eventTime(timeline.eventTime) + .readTime(timeline.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); expectedTimelines.push_back(InputEventTimeline{timeline.eventTime, timeline.readTime, timeline.vendorId, timeline.productId, timeline.sources, @@ -344,9 +415,13 @@ TEST_F(LatencyTrackerTest, EventsAreTracked_WhenTrackListenerIsCalledFirst) { expectedCT.consumeTime, expectedCT.finishTime); mTracker->trackGraphicsLatency(inputEventId, connection1, expectedCT.graphicsTimeline); - mTracker->trackListener(inputEventId, expected.eventTime, expected.readTime, DEVICE_ID, - {InputDeviceUsageSource::UNKNOWN}, AMOTION_EVENT_ACTION_CANCEL, - InputEventType::MOTION); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, AINPUT_SOURCE_TOUCHSCREEN, inputEventId) + .eventTime(expected.eventTime) + .readTime(expected.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); triggerEventReporting(expected.eventTime); assertReceivedTimeline(InputEventTimeline{expected.eventTime, expected.readTime, expected.vendorId, expected.productId, @@ -362,20 +437,25 @@ TEST_F(LatencyTrackerTest, TrackListenerCheck_DeviceInfoFieldsInputEventTimeline constexpr int32_t inputEventId = 1; InputEventTimeline timeline( /*eventTime*/ 2, /*readTime*/ 3, - /*vendorId=*/50, /*productId=*/60, - /*sources=*/ - {InputDeviceUsageSource::TOUCHSCREEN, InputDeviceUsageSource::STYLUS_DIRECT}, + /*vendorId=*/50, /*productId=*/60, {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); + deviceInfo2.addSource(AINPUT_SOURCE_TOUCHSCREEN); + deviceInfo2.addSource(AINPUT_SOURCE_STYLUS); mTracker->setInputDevices({deviceInfo1, deviceInfo2}); - mTracker->trackListener(inputEventId, timeline.eventTime, timeline.readTime, DEVICE_ID, - {InputDeviceUsageSource::TOUCHSCREEN, - InputDeviceUsageSource::STYLUS_DIRECT}, - AMOTION_EVENT_ACTION_CANCEL, InputEventType::MOTION); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_CANCEL, + AINPUT_SOURCE_TOUCHSCREEN | AINPUT_SOURCE_STYLUS, inputEventId) + + .eventTime(timeline.eventTime) + .readTime(timeline.readTime) + .deviceId(DEVICE_ID) + .pointer(PointerBuilder(/*id=*/0, ToolType::STYLUS).x(100).y(200)) + .build()); triggerEventReporting(timeline.eventTime); assertReceivedTimeline(timeline); } @@ -388,58 +468,74 @@ TEST_F(LatencyTrackerTest, TrackListenerCheck_InputEventActionTypeFieldInputEven // Create timelines for different event types (Motion, Key) InputEventTimeline motionDownTimeline( /*eventTime*/ 2, /*readTime*/ 3, - /*vendorId*/ 0, /*productId*/ 0, - /*sources*/ {InputDeviceUsageSource::UNKNOWN}, - /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_DOWN); + /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN}, + InputEventActionType::MOTION_ACTION_DOWN); InputEventTimeline motionMoveTimeline( /*eventTime*/ 4, /*readTime*/ 5, - /*vendorId*/ 0, /*productId*/ 0, - /*sources*/ {InputDeviceUsageSource::UNKNOWN}, - /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_MOVE); + /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN}, + InputEventActionType::MOTION_ACTION_MOVE); InputEventTimeline motionUpTimeline( /*eventTime*/ 6, /*readTime*/ 7, - /*vendorId*/ 0, /*productId*/ 0, - /*sources*/ {InputDeviceUsageSource::UNKNOWN}, - /*inputEventActionType*/ InputEventActionType::MOTION_ACTION_UP); + /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN}, + InputEventActionType::MOTION_ACTION_UP); InputEventTimeline keyDownTimeline( /*eventTime*/ 8, /*readTime*/ 9, - /*vendorId*/ 0, /*productId*/ 0, - /*sources*/ {InputDeviceUsageSource::UNKNOWN}, - /*inputEventActionType*/ InputEventActionType::KEY); + /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS}, + InputEventActionType::KEY); InputEventTimeline keyUpTimeline( /*eventTime*/ 10, /*readTime*/ 11, - /*vendorId*/ 0, /*productId*/ 0, - /*sources*/ {InputDeviceUsageSource::UNKNOWN}, - /*inputEventActionType*/ InputEventActionType::KEY); + /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::BUTTONS}, + InputEventActionType::KEY); InputEventTimeline unknownTimeline( /*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); + /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN}, + InputEventActionType::UNKNOWN_INPUT_EVENT); + + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, inputEventId) + .eventTime(motionDownTimeline.eventTime) + .readTime(motionDownTimeline.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); + mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, + inputEventId + 1) + .eventTime(motionMoveTimeline.eventTime) + .readTime(motionMoveTimeline.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); + mTracker->trackListener( + MotionArgsBuilder(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 2) + .eventTime(motionUpTimeline.eventTime) + .readTime(motionUpTimeline.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); + mTracker->trackListener( + KeyArgsBuilder(AKEY_EVENT_ACTION_DOWN, AINPUT_SOURCE_KEYBOARD, inputEventId + 3) + .eventTime(keyDownTimeline.eventTime) + .readTime(keyDownTimeline.readTime) + .deviceId(DEVICE_ID) + .build()); + mTracker->trackListener( + KeyArgsBuilder(AKEY_EVENT_ACTION_UP, AINPUT_SOURCE_KEYBOARD, inputEventId + 4) + .eventTime(keyUpTimeline.eventTime) + .readTime(keyUpTimeline.readTime) + .deviceId(DEVICE_ID) + .build()); + mTracker->trackListener(MotionArgsBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN, + AINPUT_SOURCE_TOUCHSCREEN, inputEventId + 5) + .eventTime(unknownTimeline.eventTime) + .readTime(unknownTimeline.readTime) + .deviceId(DEVICE_ID) + .pointer(FIRST_TOUCH_POINTER) + .build()); triggerEventReporting(unknownTimeline.eventTime); diff --git a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp index 908fa40f05..157a3338da 100644 --- a/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/LatencyTrackerFuzzer.cpp @@ -19,6 +19,7 @@ #include "../../InputDeviceMetricsSource.h" #include "../InputEventTimeline.h" +#include "NotifyArgsBuilders.h" #include "dispatcher/LatencyTracker.h" namespace android { @@ -61,40 +62,49 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { // Make some pre-defined tokens to ensure that some timelines are complete. std::array<sp<IBinder> /*token*/, 10> predefinedTokens; - for (size_t i = 0; i < predefinedTokens.size(); i++) { - predefinedTokens[i] = sp<BBinder>::make(); + for (sp<IBinder>& token : predefinedTokens) { + token = sp<BBinder>::make(); } // Randomly invoke LatencyTracker api's until randomness is exhausted. while (fdp.remaining_bytes() > 0) { fdp.PickValueInArray<std::function<void()>>({ [&]() -> void { - int32_t inputEventId = fdp.ConsumeIntegral<int32_t>(); - nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>(); - nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>(); + const int32_t inputEventId = fdp.ConsumeIntegral<int32_t>(); + const nsecs_t eventTime = fdp.ConsumeIntegral<nsecs_t>(); + const nsecs_t readTime = fdp.ConsumeIntegral<nsecs_t>(); const DeviceId deviceId = fdp.ConsumeIntegral<int32_t>(); + const int32_t source = fdp.ConsumeIntegral<int32_t>(); std::set<InputDeviceUsageSource> sources = { fdp.ConsumeEnum<InputDeviceUsageSource>()}; const int32_t inputEventActionType = fdp.ConsumeIntegral<int32_t>(); const InputEventType inputEventType = fdp.ConsumeEnum<InputEventType>(); - tracker.trackListener(inputEventId, eventTime, readTime, deviceId, sources, - inputEventActionType, inputEventType); + const NotifyMotionArgs args = + MotionArgsBuilder(inputEventActionType, source, inputEventId) + .eventTime(eventTime) + .readTime(readTime) + .deviceId(deviceId) + .pointer(PointerBuilder(/*id=*/0, ToolType::FINGER) + .x(100) + .y(200)) + .build(); + tracker.trackListener(args); }, [&]() -> void { - int32_t inputEventId = fdp.ConsumeIntegral<int32_t>(); + const int32_t inputEventId = fdp.ConsumeIntegral<int32_t>(); sp<IBinder> connectionToken = getConnectionToken(fdp, predefinedTokens); - nsecs_t deliveryTime = fdp.ConsumeIntegral<nsecs_t>(); - nsecs_t consumeTime = fdp.ConsumeIntegral<nsecs_t>(); - nsecs_t finishTime = fdp.ConsumeIntegral<nsecs_t>(); + const nsecs_t deliveryTime = fdp.ConsumeIntegral<nsecs_t>(); + const nsecs_t consumeTime = fdp.ConsumeIntegral<nsecs_t>(); + const nsecs_t finishTime = fdp.ConsumeIntegral<nsecs_t>(); tracker.trackFinishedEvent(inputEventId, connectionToken, deliveryTime, consumeTime, finishTime); }, [&]() -> void { - int32_t inputEventId = fdp.ConsumeIntegral<int32_t>(); + const int32_t inputEventId = fdp.ConsumeIntegral<int32_t>(); sp<IBinder> connectionToken = getConnectionToken(fdp, predefinedTokens); - std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline; - for (size_t i = 0; i < graphicsTimeline.size(); i++) { - graphicsTimeline[i] = fdp.ConsumeIntegral<nsecs_t>(); + std::array<nsecs_t, GraphicsTimeline::SIZE> graphicsTimeline{}; + for (nsecs_t& t : graphicsTimeline) { + t = fdp.ConsumeIntegral<nsecs_t>(); } tracker.trackGraphicsLatency(inputEventId, connectionToken, graphicsTimeline); }, |