Pass ProductId+VendorId+Source info to LatencyTracker

Currently InputEventLatencySketch captures the aggregated latency over
all devices, and it doesn't capture per-device latency.
In order to capture latency metrics per device, we track the timeline
for latency information for each Product Id, Vendor Id and Source
individually.

Bug: 270049345
Test: atest inputflinger_tests:LatencyTrackerTest
Change-Id: Ic3265e25ff95266e8cfe8542d4f4afb7b6ac16b1
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 6226a19..16ce1e4 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -46,6 +46,8 @@
 #include <queue>
 #include <sstream>
 
+#include "../InputDeviceMetricsSource.h"
+
 #include "Connection.h"
 #include "DebugConfig.h"
 #include "InputDispatcher.h"
@@ -4183,6 +4185,11 @@
     return splitMotionEntry;
 }
 
+void InputDispatcher::notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) {
+    std::scoped_lock _l(mLock);
+    mLatencyTracker.setInputDevices(args.inputDeviceInfos);
+}
+
 void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) {
     if (debugInboundEventDetails()) {
         ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args.eventTime);
@@ -4395,7 +4402,9 @@
             IdGenerator::getSource(args.id) == IdGenerator::Source::INPUT_READER &&
             !mInputFilterEnabled) {
             const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
-            mLatencyTracker.trackListener(args.id, isDown, args.eventTime, args.readTime);
+            std::set<InputDeviceUsageSource> sources = getUsageSourcesForMotionArgs(args);
+            mLatencyTracker.trackListener(args.id, isDown, args.eventTime, args.readTime,
+                                          args.deviceId, sources);
         }
 
         needWake = enqueueInboundEventLocked(std::move(newEntry));
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 62e2d58..ee5a797 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -92,7 +92,7 @@
     status_t start() override;
     status_t stop() override;
 
-    void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override{};
+    void notifyInputDevicesChanged(const NotifyInputDevicesChangedArgs& args) override;
     void notifyConfigurationChanged(const NotifyConfigurationChangedArgs& args) override;
     void notifyKey(const NotifyKeyArgs& args) override;
     void notifyMotion(const NotifyMotionArgs& args) override;
diff --git a/services/inputflinger/dispatcher/InputEventTimeline.cpp b/services/inputflinger/dispatcher/InputEventTimeline.cpp
index 3edb638..a7c6d16 100644
--- a/services/inputflinger/dispatcher/InputEventTimeline.cpp
+++ b/services/inputflinger/dispatcher/InputEventTimeline.cpp
@@ -16,6 +16,8 @@
 
 #include "InputEventTimeline.h"
 
+#include "../InputDeviceMetricsSource.h"
+
 namespace android::inputdispatcher {
 
 ConnectionTimeline::ConnectionTimeline(nsecs_t deliveryTime, nsecs_t consumeTime,
@@ -64,8 +66,15 @@
     return !operator==(rhs);
 }
 
-InputEventTimeline::InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime)
-      : isDown(isDown), eventTime(eventTime), readTime(readTime) {}
+InputEventTimeline::InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime,
+                                       uint16_t vendorId, uint16_t productId,
+                                       std::set<InputDeviceUsageSource> sources)
+      : isDown(isDown),
+        eventTime(eventTime),
+        readTime(readTime),
+        vendorId(vendorId),
+        productId(productId),
+        sources(sources) {}
 
 bool InputEventTimeline::operator==(const InputEventTimeline& rhs) const {
     if (connectionTimelines.size() != rhs.connectionTimelines.size()) {
@@ -80,7 +89,8 @@
             return false;
         }
     }
-    return isDown == rhs.isDown && eventTime == rhs.eventTime && readTime == rhs.readTime;
+    return isDown == rhs.isDown && eventTime == rhs.eventTime && readTime == rhs.readTime &&
+            vendorId == rhs.vendorId && productId == rhs.productId && sources == rhs.sources;
 }
 
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputEventTimeline.h b/services/inputflinger/dispatcher/InputEventTimeline.h
index daf375d..e9deb2d 100644
--- a/services/inputflinger/dispatcher/InputEventTimeline.h
+++ b/services/inputflinger/dispatcher/InputEventTimeline.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "../InputDeviceMetricsSource.h"
+
 #include <binder/IBinder.h>
 #include <input/Input.h>
 #include <unordered_map>
@@ -73,10 +75,14 @@
 };
 
 struct InputEventTimeline {
-    InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime);
+    InputEventTimeline(bool isDown, nsecs_t eventTime, nsecs_t readTime, uint16_t vendorId,
+                       uint16_t productId, std::set<InputDeviceUsageSource> sources);
     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;
 
     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 b7c36a8..698bd9f 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.cpp
+++ b/services/inputflinger/dispatcher/LatencyTracker.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "LatencyTracker"
 #include "LatencyTracker.h"
+#include "../InputDeviceMetricsSource.h"
 
 #include <inttypes.h>
 
@@ -23,6 +24,7 @@
 #include <android-base/stringprintf.h>
 #include <android/os/IInputConstants.h>
 #include <input/Input.h>
+#include <input/InputDevice.h>
 #include <log/log.h>
 
 using android::base::HwTimeoutMultiplier;
@@ -66,7 +68,8 @@
 }
 
 void LatencyTracker::trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime,
-                                   nsecs_t readTime) {
+                                   nsecs_t readTime, DeviceId deviceId,
+                                   const std::set<InputDeviceUsageSource>& sources) {
     reportAndPruneMatureRecords(eventTime);
     const auto it = mTimelines.find(inputEventId);
     if (it != mTimelines.end()) {
@@ -78,7 +81,29 @@
         eraseByValue(mEventTimes, inputEventId);
         return;
     }
-    mTimelines.emplace(inputEventId, InputEventTimeline(isDown, eventTime, readTime));
+
+    // Create an InputEventTimeline for the device ID. The vendorId and productId
+    // can be obtained from the InputDeviceIdentifier of the particular device.
+    const InputDeviceIdentifier* identifier = nullptr;
+    for (auto& inputDevice : mInputDevices) {
+        if (deviceId == inputDevice.getId()) {
+            identifier = &inputDevice.getIdentifier();
+            break;
+        }
+    }
+
+    // If no matching ids can be found for the device from among the input devices connected,
+    // the call to trackListener will be dropped.
+    // Note: there generally isn't expected to be a situation where we can't find an InputDeviceInfo
+    // but a possibility of it is handled in case of race conditions
+    if (identifier == nullptr) {
+        ALOGE("Could not find input device identifier. Dropping call to LatencyTracker.");
+        return;
+    }
+
+    mTimelines.emplace(inputEventId,
+                       InputEventTimeline(isDown, eventTime, readTime, identifier->vendor,
+                                          identifier->product, sources));
     mEventTimes.emplace(eventTime, inputEventId);
 }
 
@@ -171,4 +196,8 @@
             StringPrintf("%s  mEventTimes.size() = %zu\n", prefix, mEventTimes.size());
 }
 
+void LatencyTracker::setInputDevices(const std::vector<InputDeviceInfo>& inputDevices) {
+    mInputDevices = inputDevices;
+}
+
 } // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/LatencyTracker.h b/services/inputflinger/dispatcher/LatencyTracker.h
index 4212da8..890d61d 100644
--- a/services/inputflinger/dispatcher/LatencyTracker.h
+++ b/services/inputflinger/dispatcher/LatencyTracker.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include "../InputDeviceMetricsSource.h"
+
 #include <map>
 #include <unordered_map>
 
@@ -23,6 +25,7 @@
 #include <input/Input.h>
 
 #include "InputEventTimeline.h"
+#include "NotifyArgs.h"
 
 namespace android::inputdispatcher {
 
@@ -49,13 +52,15 @@
      * 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);
+    void trackListener(int32_t inputEventId, bool isDown, nsecs_t eventTime, nsecs_t readTime,
+                       DeviceId deviceId, const std::set<InputDeviceUsageSource>& sources);
     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);
 
     std::string dump(const char* prefix) const;
+    void setInputDevices(const std::vector<InputDeviceInfo>& inputDevices);
 
 private:
     /**
@@ -76,6 +81,7 @@
     std::multimap<nsecs_t /*eventTime*/, int32_t /*inputEventId*/> mEventTimes;
 
     InputEventTimelineProcessor* mTimelineProcessor;
+    std::vector<InputDeviceInfo> mInputDevices;
     void reportAndPruneMatureRecords(nsecs_t newEventTime);
 };