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
diff --git a/services/inputflinger/InputDeviceMetricsSource.cpp b/services/inputflinger/InputDeviceMetricsSource.cpp
index dee4cb8..70262fb 100644
--- a/services/inputflinger/InputDeviceMetricsSource.cpp
+++ b/services/inputflinger/InputDeviceMetricsSource.cpp
@@ -50,6 +50,18 @@
     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 a6be8f4..702badd 100644
--- a/services/inputflinger/InputDeviceMetricsSource.h
+++ b/services/inputflinger/InputDeviceMetricsSource.h
@@ -54,6 +54,10 @@
 /** 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 602904f..4f9d9e4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4551,7 +4551,7 @@
             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 @@
         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 0852026..0921e37 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 @@
 
 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 @@
     }
 }
 
+} // 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::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);
 
-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;
-        }
+    } 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 eb58222..79ea14c 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.h
+++ b/services/inputflinger/dispatcher/LatencyTracker.h
@@ -44,28 +44,20 @@
      */
     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 @@
 
     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 5b94d57..13eaaf3 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 @@
         return *this;
     }
 
+    MotionArgsBuilder& readTime(nsecs_t readTime) {
+        mReadTime = readTime;
+        return *this;
+    }
+
     MotionArgsBuilder& displayId(ui::LogicalDisplayId displayId) {
         mDisplayId = displayId;
         return *this;
@@ -121,7 +128,7 @@
 
         return {mEventId,
                 mEventTime,
-                /*readTime=*/mEventTime,
+                mReadTime.value_or(mEventTime),
                 mDeviceId,
                 mSource,
                 mDisplayId,
@@ -151,6 +158,7 @@
     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 @@
 
 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 @@
         return *this;
     }
 
+    KeyArgsBuilder& readTime(nsecs_t readTime) {
+        mReadTime = readTime;
+        return *this;
+    }
+
     KeyArgsBuilder& displayId(ui::LogicalDisplayId displayId) {
         mDisplayId = displayId;
         return *this;
@@ -214,18 +228,10 @@
     }
 
     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 @@
     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 3f14c23..ca0f1e8 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 @@
 }
 
 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 @@
             /*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 @@
 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 @@
                 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 @@
  * 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 @@
 
     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 @@
 
     // 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 @@
             /*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 @@
             /*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 @@
     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 @@
     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 @@
                                  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 @@
     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 @@
     // 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);
+            /*vendorId*/ 0, /*productId*/ 0, {InputDeviceUsageSource::TOUCHSCREEN},
+            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);
+    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 908fa40..157a333 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 @@
 
     // 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);
                 },