Loading services/inputflinger/InputDeviceMetricsCollector.cpp +16 −8 Original line number Diff line number Diff line Loading @@ -41,7 +41,13 @@ const bool DEBUG = __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID constexpr size_t INTERACTIONS_QUEUE_CAPACITY = 500; int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) { int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus, bool isUsiStylus) { if (isUsiStylus) { // This is a stylus connected over the Universal Stylus Initiative (USI) protocol. // For metrics purposes, we treat this protocol as a separate bus. return util::INPUT_DEVICE_USAGE_REPORTED__DEVICE_BUS__USI; } // When adding cases to this switch, also add them to the copy of this method in // TouchpadInputMapper.cpp. // TODO(b/286394420): deduplicate this method with the one in TouchpadInputMapper.cpp. Loading @@ -58,11 +64,12 @@ int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) { class : public InputDeviceMetricsLogger { nanoseconds getCurrentTime() override { return nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC)); } void logInputDeviceUsageReported(const InputDeviceIdentifier& identifier, void logInputDeviceUsageReported(const InputDeviceInfo& info, const DeviceUsageReport& report) override { const int32_t durationMillis = std::chrono::duration_cast<std::chrono::milliseconds>(report.usageDuration).count(); const static std::vector<int32_t> empty; const auto& identifier = info.getIdentifier(); ALOGD_IF(DEBUG, "Usage session reported for device: %s", identifier.name.c_str()); ALOGD_IF(DEBUG, " Total duration: %dms", durationMillis); Loading Loading @@ -90,7 +97,9 @@ class : public InputDeviceMetricsLogger { durMillis); } util::stats_write(util::INPUTDEVICE_USAGE_REPORTED, identifier.vendor, identifier.product, identifier.version, linuxBusToInputDeviceBusEnum(identifier.bus), identifier.version, linuxBusToInputDeviceBusEnum(identifier.bus, info.getUsiVersion().has_value()), durationMillis, sources, durationsPerSource, uids, durationsPerUid); } } sStatsdLogger; Loading Loading @@ -295,21 +304,21 @@ void InputDeviceMetricsCollector::onInputDevicesChanged(const std::vector<InputD if (newDeviceInfos.count(deviceId) != 0) { continue; } onInputDeviceRemoved(deviceId, info.getIdentifier()); onInputDeviceRemoved(deviceId, info); } std::swap(newDeviceInfos, mLoggedDeviceInfos); } void InputDeviceMetricsCollector::onInputDeviceRemoved(DeviceId deviceId, const InputDeviceIdentifier& identifier) { const InputDeviceInfo& info) { auto it = mActiveUsageSessions.find(deviceId); if (it == mActiveUsageSessions.end()) { return; } // Report usage for that device if there is an active session. auto& [_, activeSession] = *it; mLogger.logInputDeviceUsageReported(identifier, activeSession.finishSession()); mLogger.logInputDeviceUsageReported(info, activeSession.finishSession()); mActiveUsageSessions.erase(it); // We don't remove this from mLoggedDeviceInfos because it will be updated in Loading Loading @@ -365,8 +374,7 @@ void InputDeviceMetricsCollector::reportCompletedSessions() { auto activeSessionIt = mActiveUsageSessions.find(deviceId); LOG_ALWAYS_FATAL_IF(activeSessionIt == mActiveUsageSessions.end()); auto& [_, activeSession] = *activeSessionIt; mLogger.logInputDeviceUsageReported(infoIt->second.getIdentifier(), activeSession.finishSession()); mLogger.logInputDeviceUsageReported(infoIt->second, activeSession.finishSession()); mActiveUsageSessions.erase(activeSessionIt); } } Loading services/inputflinger/InputDeviceMetricsCollector.h +2 −3 Original line number Diff line number Diff line Loading @@ -110,8 +110,7 @@ public: UidUsageBreakdown uidBreakdown; }; virtual void logInputDeviceUsageReported(const InputDeviceIdentifier&, const DeviceUsageReport&) = 0; virtual void logInputDeviceUsageReported(const InputDeviceInfo&, const DeviceUsageReport&) = 0; virtual ~InputDeviceMetricsLogger() = default; }; Loading Loading @@ -189,7 +188,7 @@ private: std::map<DeviceId, ActiveSession> mActiveUsageSessions; void onInputDevicesChanged(const std::vector<InputDeviceInfo>& infos); void onInputDeviceRemoved(DeviceId deviceId, const InputDeviceIdentifier& identifier); void onInputDeviceRemoved(DeviceId deviceId, const InputDeviceInfo& info); using SourceProvider = std::function<std::set<InputDeviceUsageSource>(const InputDeviceInfo&)>; void onInputDeviceUsage(DeviceId deviceId, std::chrono::nanoseconds eventTime, const SourceProvider& getSources); Loading services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -125,7 +125,13 @@ void gestureInterpreterCallback(void* clientData, const Gesture* gesture) { mapper->consumeGesture(gesture); } int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) { int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus, bool isUsiStylus) { if (isUsiStylus) { // This is a stylus connected over the Universal Stylus Initiative (USI) protocol. // For metrics purposes, we treat this protocol as a separate bus. return util::INPUT_DEVICE_USAGE_REPORTED__DEVICE_BUS__USI; } // When adding cases to this switch, also add them to the copy of this method in // InputDeviceMetricsCollector.cpp. // TODO(b/286394420): deduplicate this method with the one in InputDeviceMetricsCollector.cpp. Loading Loading @@ -199,8 +205,8 @@ private: for (auto& [id, counters] : mCounters) { auto [busId, vendorId, productId, versionId] = id; addAStatsEvent(outEventList, android::util::TOUCHPAD_USAGE, vendorId, productId, versionId, linuxBusToInputDeviceBusEnum(busId), counters.fingers, counters.palms, counters.twoFingerSwipeGestures, versionId, linuxBusToInputDeviceBusEnum(busId, /*isUsi=*/false), counters.fingers, counters.palms, counters.twoFingerSwipeGestures, counters.threeFingerSwipeGestures, counters.fourFingerSwipeGestures, counters.pinchGestures); } Loading services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp +39 −35 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ constexpr uint32_t KEY_SOURCES = constexpr int32_t POINTER_1_DOWN = AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); InputDeviceIdentifier getIdentifier(int32_t id = DEVICE_ID) { InputDeviceIdentifier generateTestIdentifier(int32_t id = DEVICE_ID) { InputDeviceIdentifier identifier; identifier.name = DEVICE_NAME + "_" + std::to_string(id); identifier.location = LOCATION; Loading @@ -69,8 +69,8 @@ InputDeviceInfo generateTestDeviceInfo(int32_t id = DEVICE_ID, uint32_t sources = TOUCHSCREEN | STYLUS, bool isAlphabetic = false) { auto info = InputDeviceInfo(); info.initialize(id, /*generation=*/1, /*controllerNumber=*/1, getIdentifier(id), "alias", /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE); info.initialize(id, /*generation=*/1, /*controllerNumber=*/1, generateTestIdentifier(id), "alias", /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE); info.addSource(sources); info.setKeyboardType(isAlphabetic ? AINPUT_KEYBOARD_TYPE_ALPHABETIC : AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC); Loading @@ -81,6 +81,8 @@ const InputDeviceInfo ALPHABETIC_KEYBOARD_INFO = generateTestDeviceInfo(DEVICE_ID, KEY_SOURCES, /*isAlphabetic=*/true); const InputDeviceInfo NON_ALPHABETIC_KEYBOARD_INFO = generateTestDeviceInfo(DEVICE_ID, KEY_SOURCES, /*isAlphabetic=*/false); const InputDeviceInfo TOUCHSCREEN_STYLUS_INFO = generateTestDeviceInfo(DEVICE_ID); const InputDeviceInfo SECOND_TOUCHSCREEN_STYLUS_INFO = generateTestDeviceInfo(DEVICE_ID_2); std::set<gui::Uid> uids(std::initializer_list<int32_t> vals) { std::set<gui::Uid> set; Loading Loading @@ -351,12 +353,12 @@ protected: TestInputListener mTestListener; InputDeviceMetricsCollector mMetricsCollector{mTestListener, *this, USAGE_TIMEOUT}; void assertUsageLogged(InputDeviceIdentifier identifier, nanoseconds duration, void assertUsageLogged(const InputDeviceInfo& info, nanoseconds duration, std::optional<SourceUsageBreakdown> sourceBreakdown = {}, std::optional<UidUsageBreakdown> uidBreakdown = {}) { ASSERT_GE(mLoggedUsageSessions.size(), 1u); const auto& [loggedIdentifier, report] = *mLoggedUsageSessions.begin(); ASSERT_EQ(identifier, loggedIdentifier); const auto& [loggedInfo, report] = *mLoggedUsageSessions.begin(); ASSERT_EQ(info.getIdentifier(), loggedInfo.getIdentifier()); ASSERT_EQ(duration, report.usageDuration); if (sourceBreakdown) { ASSERT_EQ(sourceBreakdown, report.sourceBreakdown); Loading Loading @@ -387,14 +389,14 @@ protected: } private: std::vector<std::tuple<InputDeviceIdentifier, DeviceUsageReport>> mLoggedUsageSessions; std::vector<std::tuple<InputDeviceInfo, DeviceUsageReport>> mLoggedUsageSessions; nanoseconds mCurrentTime{TIME}; nanoseconds getCurrentTime() override { return mCurrentTime; } void logInputDeviceUsageReported(const InputDeviceIdentifier& identifier, void logInputDeviceUsageReported(const InputDeviceInfo& info, const DeviceUsageReport& report) override { mLoggedUsageSessions.emplace_back(identifier, report); mLoggedUsageSessions.emplace_back(info, report); } }; Loading Loading @@ -438,7 +440,7 @@ TEST_F(InputDeviceMetricsCollectorTest, DontLogUsageForIgnoredDevices) { } TEST_F(InputDeviceMetricsCollectorTest, LogsSingleEventUsageSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Device was used. mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -448,11 +450,11 @@ TEST_F(InputDeviceMetricsCollectorTest, LogsSingleEventUsageSession) { setCurrentTime(TIME + USAGE_TIMEOUT); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); // The usage session has zero duration because it consisted of only one event. ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 0ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 0ns)); } TEST_F(InputDeviceMetricsCollectorTest, LogsMultipleEventUsageSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Device was used. mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -468,11 +470,11 @@ TEST_F(InputDeviceMetricsCollectorTest, LogsMultipleEventUsageSession) { // Device was used again after the usage timeout. setCurrentTime(TIME + 42ns + 2 * USAGE_TIMEOUT); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 42ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 42ns)); } TEST_F(InputDeviceMetricsCollectorTest, RemovingDeviceEndsUsageSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Device was used. mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -485,12 +487,12 @@ TEST_F(InputDeviceMetricsCollectorTest, RemovingDeviceEndsUsageSession) { // The device was removed before the usage timeout expired. setCurrentTime(TIME + 42ns); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {}}); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 21ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 21ns)); } TEST_F(InputDeviceMetricsCollectorTest, TracksUsageFromDifferentDevicesIndependently) { mMetricsCollector.notifyInputDevicesChanged( {/*id=*/0, {generateTestDeviceInfo(), generateTestDeviceInfo(DEVICE_ID_2)}}); {/*id=*/0, {TOUCHSCREEN_STYLUS_INFO, SECOND_TOUCHSCREEN_STYLUS_INFO}}); // Device 1 was used. setCurrentTime(TIME); Loading @@ -509,7 +511,7 @@ TEST_F(InputDeviceMetricsCollectorTest, TracksUsageFromDifferentDevicesIndepende // Device 1 was used after its usage timeout expired. Its usage session is reported. setCurrentTime(TIME + 300ns + USAGE_TIMEOUT); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID), 100ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 100ns)); // Device 2 was used. setCurrentTime(TIME + 350ns + USAGE_TIMEOUT); Loading @@ -525,13 +527,14 @@ TEST_F(InputDeviceMetricsCollectorTest, TracksUsageFromDifferentDevicesIndepende setCurrentTime(TIME + 400ns + (2 * USAGE_TIMEOUT)); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); // Since Device 2's usage session ended, its usage should be reported. ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID_2), 150ns + USAGE_TIMEOUT)); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(SECOND_TOUCHSCREEN_STYLUS_INFO, 150ns + USAGE_TIMEOUT)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown; // Use touchscreen. Loading Loading @@ -576,7 +579,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource) { 100ns + USAGE_TIMEOUT); // Verify that only one usage session was logged for the device, and that session was broken // down by source correctly. ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 400ns + USAGE_TIMEOUT + USAGE_TIMEOUT, expectedSourceBreakdown)); Loading @@ -585,7 +588,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource) { TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_TrackSourceByDevice) { mMetricsCollector.notifyInputDevicesChanged( {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID), generateTestDeviceInfo(DEVICE_ID_2)}}); {/*id=*/0, {TOUCHSCREEN_STYLUS_INFO, SECOND_TOUCHSCREEN_STYLUS_INFO}}); InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown1; InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown2; Loading @@ -602,15 +605,15 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_TrackSourceByDevi expectedSourceBreakdown1.emplace_back(InputDeviceUsageSource::TOUCHSCREEN, 100ns); expectedSourceBreakdown2.emplace_back(InputDeviceUsageSource::STYLUS_DIRECT, 100ns); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(getIdentifier(DEVICE_ID), 100ns, expectedSourceBreakdown1)); assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 100ns, expectedSourceBreakdown1)); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(getIdentifier(DEVICE_ID_2), 100ns, expectedSourceBreakdown2)); assertUsageLogged(SECOND_TOUCHSCREEN_STYLUS_INFO, 100ns, expectedSourceBreakdown2)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_MultiSourceEvent) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo(DEVICE_ID)}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown; mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID, TOUCHSCREEN | STYLUS, // Loading @@ -634,13 +637,13 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_MultiSourceEvent) expectedSourceBreakdown.emplace_back(InputDeviceUsageSource::STYLUS_DIRECT, 200ns); expectedSourceBreakdown.emplace_back(InputDeviceUsageSource::TOUCHSCREEN, 300ns); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(getIdentifier(DEVICE_ID), 400ns, expectedSourceBreakdown)); assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 400ns, expectedSourceBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, UidsNotTrackedWhenThereIsNoActiveSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Notify interaction with UIDs before the device is used. mMetricsCollector.notifyDeviceInteraction(DEVICE_ID, currentTime(), uids({1})); Loading @@ -665,14 +668,15 @@ TEST_F(InputDeviceMetricsCollectorTest, UidsNotTrackedWhenThereIsNoActiveSession // The first usage session is logged. static const UidUsageBreakdown emptyBreakdown; ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 100ns, /*sourceBreakdown=*/{}, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 100ns, /*sourceBreakdown=*/{}, /*uidBreakdown=*/emptyBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); UidUsageBreakdown expectedUidBreakdown; mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -691,14 +695,14 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid) { // Remove the device to force the usage session to be logged. mMetricsCollector.notifyInputDevicesChanged({}); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 200ns, /*sourceBreakdown=*/{}, expectedUidBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 200ns, /*sourceBreakdown=*/{}, expectedUidBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksMultipleSessionsForUid) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); UidUsageBreakdown expectedUidBreakdown; mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading Loading @@ -742,7 +746,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksMultipleSessio expectedUidBreakdown.emplace_back(2, 0ns); expectedUidBreakdown.emplace_back(3, 100ns); expectedUidBreakdown.emplace_back(4, 100ns); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 500ns + USAGE_TIMEOUT, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 500ns + USAGE_TIMEOUT, /*sourceBreakdown=*/{}, expectedUidBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); Loading @@ -750,7 +754,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksMultipleSessio TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksUidsByDevice) { mMetricsCollector.notifyInputDevicesChanged( {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID), generateTestDeviceInfo(DEVICE_ID_2)}}); {/*id=*/0, {TOUCHSCREEN_STYLUS_INFO, SECOND_TOUCHSCREEN_STYLUS_INFO}}); UidUsageBreakdown expectedUidBreakdown1; UidUsageBreakdown expectedUidBreakdown2; Loading @@ -773,9 +777,9 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksUidsByDevice) expectedUidBreakdown2.emplace_back(1, 100ns); expectedUidBreakdown2.emplace_back(3, 100ns); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID), 200ns, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 200ns, /*sourceBreakdown=*/{}, expectedUidBreakdown1)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID_2), 100ns, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(SECOND_TOUCHSCREEN_STYLUS_INFO, 100ns, /*sourceBreakdown=*/{}, expectedUidBreakdown2)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); Loading Loading
services/inputflinger/InputDeviceMetricsCollector.cpp +16 −8 Original line number Diff line number Diff line Loading @@ -41,7 +41,13 @@ const bool DEBUG = __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID constexpr size_t INTERACTIONS_QUEUE_CAPACITY = 500; int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) { int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus, bool isUsiStylus) { if (isUsiStylus) { // This is a stylus connected over the Universal Stylus Initiative (USI) protocol. // For metrics purposes, we treat this protocol as a separate bus. return util::INPUT_DEVICE_USAGE_REPORTED__DEVICE_BUS__USI; } // When adding cases to this switch, also add them to the copy of this method in // TouchpadInputMapper.cpp. // TODO(b/286394420): deduplicate this method with the one in TouchpadInputMapper.cpp. Loading @@ -58,11 +64,12 @@ int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) { class : public InputDeviceMetricsLogger { nanoseconds getCurrentTime() override { return nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC)); } void logInputDeviceUsageReported(const InputDeviceIdentifier& identifier, void logInputDeviceUsageReported(const InputDeviceInfo& info, const DeviceUsageReport& report) override { const int32_t durationMillis = std::chrono::duration_cast<std::chrono::milliseconds>(report.usageDuration).count(); const static std::vector<int32_t> empty; const auto& identifier = info.getIdentifier(); ALOGD_IF(DEBUG, "Usage session reported for device: %s", identifier.name.c_str()); ALOGD_IF(DEBUG, " Total duration: %dms", durationMillis); Loading Loading @@ -90,7 +97,9 @@ class : public InputDeviceMetricsLogger { durMillis); } util::stats_write(util::INPUTDEVICE_USAGE_REPORTED, identifier.vendor, identifier.product, identifier.version, linuxBusToInputDeviceBusEnum(identifier.bus), identifier.version, linuxBusToInputDeviceBusEnum(identifier.bus, info.getUsiVersion().has_value()), durationMillis, sources, durationsPerSource, uids, durationsPerUid); } } sStatsdLogger; Loading Loading @@ -295,21 +304,21 @@ void InputDeviceMetricsCollector::onInputDevicesChanged(const std::vector<InputD if (newDeviceInfos.count(deviceId) != 0) { continue; } onInputDeviceRemoved(deviceId, info.getIdentifier()); onInputDeviceRemoved(deviceId, info); } std::swap(newDeviceInfos, mLoggedDeviceInfos); } void InputDeviceMetricsCollector::onInputDeviceRemoved(DeviceId deviceId, const InputDeviceIdentifier& identifier) { const InputDeviceInfo& info) { auto it = mActiveUsageSessions.find(deviceId); if (it == mActiveUsageSessions.end()) { return; } // Report usage for that device if there is an active session. auto& [_, activeSession] = *it; mLogger.logInputDeviceUsageReported(identifier, activeSession.finishSession()); mLogger.logInputDeviceUsageReported(info, activeSession.finishSession()); mActiveUsageSessions.erase(it); // We don't remove this from mLoggedDeviceInfos because it will be updated in Loading Loading @@ -365,8 +374,7 @@ void InputDeviceMetricsCollector::reportCompletedSessions() { auto activeSessionIt = mActiveUsageSessions.find(deviceId); LOG_ALWAYS_FATAL_IF(activeSessionIt == mActiveUsageSessions.end()); auto& [_, activeSession] = *activeSessionIt; mLogger.logInputDeviceUsageReported(infoIt->second.getIdentifier(), activeSession.finishSession()); mLogger.logInputDeviceUsageReported(infoIt->second, activeSession.finishSession()); mActiveUsageSessions.erase(activeSessionIt); } } Loading
services/inputflinger/InputDeviceMetricsCollector.h +2 −3 Original line number Diff line number Diff line Loading @@ -110,8 +110,7 @@ public: UidUsageBreakdown uidBreakdown; }; virtual void logInputDeviceUsageReported(const InputDeviceIdentifier&, const DeviceUsageReport&) = 0; virtual void logInputDeviceUsageReported(const InputDeviceInfo&, const DeviceUsageReport&) = 0; virtual ~InputDeviceMetricsLogger() = default; }; Loading Loading @@ -189,7 +188,7 @@ private: std::map<DeviceId, ActiveSession> mActiveUsageSessions; void onInputDevicesChanged(const std::vector<InputDeviceInfo>& infos); void onInputDeviceRemoved(DeviceId deviceId, const InputDeviceIdentifier& identifier); void onInputDeviceRemoved(DeviceId deviceId, const InputDeviceInfo& info); using SourceProvider = std::function<std::set<InputDeviceUsageSource>(const InputDeviceInfo&)>; void onInputDeviceUsage(DeviceId deviceId, std::chrono::nanoseconds eventTime, const SourceProvider& getSources); Loading
services/inputflinger/reader/mapper/TouchpadInputMapper.cpp +9 −3 Original line number Diff line number Diff line Loading @@ -125,7 +125,13 @@ void gestureInterpreterCallback(void* clientData, const Gesture* gesture) { mapper->consumeGesture(gesture); } int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus) { int32_t linuxBusToInputDeviceBusEnum(int32_t linuxBus, bool isUsiStylus) { if (isUsiStylus) { // This is a stylus connected over the Universal Stylus Initiative (USI) protocol. // For metrics purposes, we treat this protocol as a separate bus. return util::INPUT_DEVICE_USAGE_REPORTED__DEVICE_BUS__USI; } // When adding cases to this switch, also add them to the copy of this method in // InputDeviceMetricsCollector.cpp. // TODO(b/286394420): deduplicate this method with the one in InputDeviceMetricsCollector.cpp. Loading Loading @@ -199,8 +205,8 @@ private: for (auto& [id, counters] : mCounters) { auto [busId, vendorId, productId, versionId] = id; addAStatsEvent(outEventList, android::util::TOUCHPAD_USAGE, vendorId, productId, versionId, linuxBusToInputDeviceBusEnum(busId), counters.fingers, counters.palms, counters.twoFingerSwipeGestures, versionId, linuxBusToInputDeviceBusEnum(busId, /*isUsi=*/false), counters.fingers, counters.palms, counters.twoFingerSwipeGestures, counters.threeFingerSwipeGestures, counters.fourFingerSwipeGestures, counters.pinchGestures); } Loading
services/inputflinger/tests/InputDeviceMetricsCollector_test.cpp +39 −35 Original line number Diff line number Diff line Loading @@ -53,7 +53,7 @@ constexpr uint32_t KEY_SOURCES = constexpr int32_t POINTER_1_DOWN = AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); InputDeviceIdentifier getIdentifier(int32_t id = DEVICE_ID) { InputDeviceIdentifier generateTestIdentifier(int32_t id = DEVICE_ID) { InputDeviceIdentifier identifier; identifier.name = DEVICE_NAME + "_" + std::to_string(id); identifier.location = LOCATION; Loading @@ -69,8 +69,8 @@ InputDeviceInfo generateTestDeviceInfo(int32_t id = DEVICE_ID, uint32_t sources = TOUCHSCREEN | STYLUS, bool isAlphabetic = false) { auto info = InputDeviceInfo(); info.initialize(id, /*generation=*/1, /*controllerNumber=*/1, getIdentifier(id), "alias", /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE); info.initialize(id, /*generation=*/1, /*controllerNumber=*/1, generateTestIdentifier(id), "alias", /*isExternal=*/false, /*hasMic=*/false, ADISPLAY_ID_NONE); info.addSource(sources); info.setKeyboardType(isAlphabetic ? AINPUT_KEYBOARD_TYPE_ALPHABETIC : AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC); Loading @@ -81,6 +81,8 @@ const InputDeviceInfo ALPHABETIC_KEYBOARD_INFO = generateTestDeviceInfo(DEVICE_ID, KEY_SOURCES, /*isAlphabetic=*/true); const InputDeviceInfo NON_ALPHABETIC_KEYBOARD_INFO = generateTestDeviceInfo(DEVICE_ID, KEY_SOURCES, /*isAlphabetic=*/false); const InputDeviceInfo TOUCHSCREEN_STYLUS_INFO = generateTestDeviceInfo(DEVICE_ID); const InputDeviceInfo SECOND_TOUCHSCREEN_STYLUS_INFO = generateTestDeviceInfo(DEVICE_ID_2); std::set<gui::Uid> uids(std::initializer_list<int32_t> vals) { std::set<gui::Uid> set; Loading Loading @@ -351,12 +353,12 @@ protected: TestInputListener mTestListener; InputDeviceMetricsCollector mMetricsCollector{mTestListener, *this, USAGE_TIMEOUT}; void assertUsageLogged(InputDeviceIdentifier identifier, nanoseconds duration, void assertUsageLogged(const InputDeviceInfo& info, nanoseconds duration, std::optional<SourceUsageBreakdown> sourceBreakdown = {}, std::optional<UidUsageBreakdown> uidBreakdown = {}) { ASSERT_GE(mLoggedUsageSessions.size(), 1u); const auto& [loggedIdentifier, report] = *mLoggedUsageSessions.begin(); ASSERT_EQ(identifier, loggedIdentifier); const auto& [loggedInfo, report] = *mLoggedUsageSessions.begin(); ASSERT_EQ(info.getIdentifier(), loggedInfo.getIdentifier()); ASSERT_EQ(duration, report.usageDuration); if (sourceBreakdown) { ASSERT_EQ(sourceBreakdown, report.sourceBreakdown); Loading Loading @@ -387,14 +389,14 @@ protected: } private: std::vector<std::tuple<InputDeviceIdentifier, DeviceUsageReport>> mLoggedUsageSessions; std::vector<std::tuple<InputDeviceInfo, DeviceUsageReport>> mLoggedUsageSessions; nanoseconds mCurrentTime{TIME}; nanoseconds getCurrentTime() override { return mCurrentTime; } void logInputDeviceUsageReported(const InputDeviceIdentifier& identifier, void logInputDeviceUsageReported(const InputDeviceInfo& info, const DeviceUsageReport& report) override { mLoggedUsageSessions.emplace_back(identifier, report); mLoggedUsageSessions.emplace_back(info, report); } }; Loading Loading @@ -438,7 +440,7 @@ TEST_F(InputDeviceMetricsCollectorTest, DontLogUsageForIgnoredDevices) { } TEST_F(InputDeviceMetricsCollectorTest, LogsSingleEventUsageSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Device was used. mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -448,11 +450,11 @@ TEST_F(InputDeviceMetricsCollectorTest, LogsSingleEventUsageSession) { setCurrentTime(TIME + USAGE_TIMEOUT); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); // The usage session has zero duration because it consisted of only one event. ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 0ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 0ns)); } TEST_F(InputDeviceMetricsCollectorTest, LogsMultipleEventUsageSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Device was used. mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -468,11 +470,11 @@ TEST_F(InputDeviceMetricsCollectorTest, LogsMultipleEventUsageSession) { // Device was used again after the usage timeout. setCurrentTime(TIME + 42ns + 2 * USAGE_TIMEOUT); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 42ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 42ns)); } TEST_F(InputDeviceMetricsCollectorTest, RemovingDeviceEndsUsageSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Device was used. mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -485,12 +487,12 @@ TEST_F(InputDeviceMetricsCollectorTest, RemovingDeviceEndsUsageSession) { // The device was removed before the usage timeout expired. setCurrentTime(TIME + 42ns); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {}}); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 21ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 21ns)); } TEST_F(InputDeviceMetricsCollectorTest, TracksUsageFromDifferentDevicesIndependently) { mMetricsCollector.notifyInputDevicesChanged( {/*id=*/0, {generateTestDeviceInfo(), generateTestDeviceInfo(DEVICE_ID_2)}}); {/*id=*/0, {TOUCHSCREEN_STYLUS_INFO, SECOND_TOUCHSCREEN_STYLUS_INFO}}); // Device 1 was used. setCurrentTime(TIME); Loading @@ -509,7 +511,7 @@ TEST_F(InputDeviceMetricsCollectorTest, TracksUsageFromDifferentDevicesIndepende // Device 1 was used after its usage timeout expired. Its usage session is reported. setCurrentTime(TIME + 300ns + USAGE_TIMEOUT); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID), 100ns)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 100ns)); // Device 2 was used. setCurrentTime(TIME + 350ns + USAGE_TIMEOUT); Loading @@ -525,13 +527,14 @@ TEST_F(InputDeviceMetricsCollectorTest, TracksUsageFromDifferentDevicesIndepende setCurrentTime(TIME + 400ns + (2 * USAGE_TIMEOUT)); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); // Since Device 2's usage session ended, its usage should be reported. ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID_2), 150ns + USAGE_TIMEOUT)); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(SECOND_TOUCHSCREEN_STYLUS_INFO, 150ns + USAGE_TIMEOUT)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown; // Use touchscreen. Loading Loading @@ -576,7 +579,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource) { 100ns + USAGE_TIMEOUT); // Verify that only one usage session was logged for the device, and that session was broken // down by source correctly. ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 400ns + USAGE_TIMEOUT + USAGE_TIMEOUT, expectedSourceBreakdown)); Loading @@ -585,7 +588,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource) { TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_TrackSourceByDevice) { mMetricsCollector.notifyInputDevicesChanged( {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID), generateTestDeviceInfo(DEVICE_ID_2)}}); {/*id=*/0, {TOUCHSCREEN_STYLUS_INFO, SECOND_TOUCHSCREEN_STYLUS_INFO}}); InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown1; InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown2; Loading @@ -602,15 +605,15 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_TrackSourceByDevi expectedSourceBreakdown1.emplace_back(InputDeviceUsageSource::TOUCHSCREEN, 100ns); expectedSourceBreakdown2.emplace_back(InputDeviceUsageSource::STYLUS_DIRECT, 100ns); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(getIdentifier(DEVICE_ID), 100ns, expectedSourceBreakdown1)); assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 100ns, expectedSourceBreakdown1)); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(getIdentifier(DEVICE_ID_2), 100ns, expectedSourceBreakdown2)); assertUsageLogged(SECOND_TOUCHSCREEN_STYLUS_INFO, 100ns, expectedSourceBreakdown2)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_MultiSourceEvent) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo(DEVICE_ID)}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); InputDeviceMetricsLogger::SourceUsageBreakdown expectedSourceBreakdown; mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID, TOUCHSCREEN | STYLUS, // Loading @@ -634,13 +637,13 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageBySource_MultiSourceEvent) expectedSourceBreakdown.emplace_back(InputDeviceUsageSource::STYLUS_DIRECT, 200ns); expectedSourceBreakdown.emplace_back(InputDeviceUsageSource::TOUCHSCREEN, 300ns); ASSERT_NO_FATAL_FAILURE( assertUsageLogged(getIdentifier(DEVICE_ID), 400ns, expectedSourceBreakdown)); assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 400ns, expectedSourceBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, UidsNotTrackedWhenThereIsNoActiveSession) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); // Notify interaction with UIDs before the device is used. mMetricsCollector.notifyDeviceInteraction(DEVICE_ID, currentTime(), uids({1})); Loading @@ -665,14 +668,15 @@ TEST_F(InputDeviceMetricsCollectorTest, UidsNotTrackedWhenThereIsNoActiveSession // The first usage session is logged. static const UidUsageBreakdown emptyBreakdown; ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 100ns, /*sourceBreakdown=*/{}, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 100ns, /*sourceBreakdown=*/{}, /*uidBreakdown=*/emptyBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); UidUsageBreakdown expectedUidBreakdown; mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading @@ -691,14 +695,14 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid) { // Remove the device to force the usage session to be logged. mMetricsCollector.notifyInputDevicesChanged({}); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 200ns, /*sourceBreakdown=*/{}, expectedUidBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 200ns, /*sourceBreakdown=*/{}, expectedUidBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); } TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksMultipleSessionsForUid) { mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {generateTestDeviceInfo()}}); mMetricsCollector.notifyInputDevicesChanged({/*id=*/0, {TOUCHSCREEN_STYLUS_INFO}}); UidUsageBreakdown expectedUidBreakdown; mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); Loading Loading @@ -742,7 +746,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksMultipleSessio expectedUidBreakdown.emplace_back(2, 0ns); expectedUidBreakdown.emplace_back(3, 100ns); expectedUidBreakdown.emplace_back(4, 100ns); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(), 500ns + USAGE_TIMEOUT, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 500ns + USAGE_TIMEOUT, /*sourceBreakdown=*/{}, expectedUidBreakdown)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); Loading @@ -750,7 +754,7 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksMultipleSessio TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksUidsByDevice) { mMetricsCollector.notifyInputDevicesChanged( {/*id=*/0, {generateTestDeviceInfo(DEVICE_ID), generateTestDeviceInfo(DEVICE_ID_2)}}); {/*id=*/0, {TOUCHSCREEN_STYLUS_INFO, SECOND_TOUCHSCREEN_STYLUS_INFO}}); UidUsageBreakdown expectedUidBreakdown1; UidUsageBreakdown expectedUidBreakdown2; Loading @@ -773,9 +777,9 @@ TEST_F(InputDeviceMetricsCollectorTest, BreakdownUsageByUid_TracksUidsByDevice) expectedUidBreakdown2.emplace_back(1, 100ns); expectedUidBreakdown2.emplace_back(3, 100ns); mMetricsCollector.notifyMotion(generateMotionArgs(DEVICE_ID)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID), 200ns, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(TOUCHSCREEN_STYLUS_INFO, 200ns, /*sourceBreakdown=*/{}, expectedUidBreakdown1)); ASSERT_NO_FATAL_FAILURE(assertUsageLogged(getIdentifier(DEVICE_ID_2), 100ns, ASSERT_NO_FATAL_FAILURE(assertUsageLogged(SECOND_TOUCHSCREEN_STYLUS_INFO, 100ns, /*sourceBreakdown=*/{}, expectedUidBreakdown2)); ASSERT_NO_FATAL_FAILURE(assertUsageNotLogged()); Loading