Break down input device usage by source
Bug: 275726706
Test: atest inputflinger_tests
Test: statsd_testdrive
Change-Id: Ic652ecd7c66b9e9c3b46d84454485cf51140a14b
diff --git a/services/inputflinger/InputDeviceMetricsCollector.cpp b/services/inputflinger/InputDeviceMetricsCollector.cpp
index 71f3717..3e25cc3 100644
--- a/services/inputflinger/InputDeviceMetricsCollector.cpp
+++ b/services/inputflinger/InputDeviceMetricsCollector.cpp
@@ -53,18 +53,28 @@
nanoseconds getCurrentTime() override { return nanoseconds(systemTime(SYSTEM_TIME_MONOTONIC)); }
void logInputDeviceUsageReported(const InputDeviceIdentifier& identifier,
- nanoseconds sessionDuration) override {
+ const DeviceUsageReport& report) override {
const int32_t durationMillis =
- std::chrono::duration_cast<std::chrono::milliseconds>(sessionDuration).count();
+ std::chrono::duration_cast<std::chrono::milliseconds>(report.usageDuration).count();
const static std::vector<int32_t> empty;
ALOGD_IF(DEBUG, "Usage session reported for device: %s", identifier.name.c_str());
ALOGD_IF(DEBUG, " Total duration: %dms", durationMillis);
+ ALOGD_IF(DEBUG, " Source breakdown:");
+
+ std::vector<int32_t> sources;
+ std::vector<int32_t> durationsPerSource;
+ for (auto& [src, dur] : report.sourceBreakdown) {
+ sources.push_back(ftl::to_underlying(src));
+ int32_t durMillis = std::chrono::duration_cast<std::chrono::milliseconds>(dur).count();
+ durationsPerSource.emplace_back(durMillis);
+ ALOGD_IF(DEBUG, " - usageSource: %s\t duration: %dms",
+ ftl::enum_string(src).c_str(), durMillis);
+ }
util::stats_write(util::INPUTDEVICE_USAGE_REPORTED, identifier.vendor, identifier.product,
identifier.version, linuxBusToInputDeviceBusEnum(identifier.bus),
- durationMillis, /*usage_sources=*/empty,
- /*usage_durations_per_source=*/empty, /*uids=*/empty,
+ durationMillis, sources, durationsPerSource, /*uids=*/empty,
/*usage_durations_per_uid=*/empty);
}
} sStatsdLogger;
@@ -181,54 +191,58 @@
void InputDeviceMetricsCollector::notifyInputDevicesChanged(
const NotifyInputDevicesChangedArgs& args) {
- processUsages();
+ reportCompletedSessions();
onInputDevicesChanged(args.inputDeviceInfos);
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifyConfigurationChanged(
const NotifyConfigurationChangedArgs& args) {
- processUsages();
+ reportCompletedSessions();
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifyKey(const NotifyKeyArgs& args) {
- processUsages();
- onInputDeviceUsage(DeviceId{args.deviceId}, nanoseconds(args.eventTime));
+ reportCompletedSessions();
+ const SourceProvider getSources = [&args](const InputDeviceInfo& info) {
+ return std::set{getUsageSourceForKeyArgs(info, args)};
+ };
+ onInputDeviceUsage(DeviceId{args.deviceId}, nanoseconds(args.eventTime), getSources);
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifyMotion(const NotifyMotionArgs& args) {
- processUsages();
- onInputDeviceUsage(DeviceId{args.deviceId}, nanoseconds(args.eventTime));
+ reportCompletedSessions();
+ onInputDeviceUsage(DeviceId{args.deviceId}, nanoseconds(args.eventTime),
+ [&args](const auto&) { return getUsageSourcesForMotionArgs(args); });
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifySwitch(const NotifySwitchArgs& args) {
- processUsages();
+ reportCompletedSessions();
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifySensor(const NotifySensorArgs& args) {
- processUsages();
+ reportCompletedSessions();
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifyVibratorState(const NotifyVibratorStateArgs& args) {
- processUsages();
+ reportCompletedSessions();
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
- processUsages();
+ reportCompletedSessions();
mNextListener.notify(args);
}
void InputDeviceMetricsCollector::notifyPointerCaptureChanged(
const NotifyPointerCaptureChangedArgs& args) {
- processUsages();
+ reportCompletedSessions();
mNextListener.notify(args);
}
@@ -241,69 +255,124 @@
}
void InputDeviceMetricsCollector::onInputDevicesChanged(const std::vector<InputDeviceInfo>& infos) {
- std::map<DeviceId, InputDeviceIdentifier> newDeviceIds;
+ std::map<DeviceId, InputDeviceInfo> newDeviceInfos;
for (const InputDeviceInfo& info : infos) {
if (isIgnoredInputDeviceId(info.getId())) {
continue;
}
- newDeviceIds.emplace(info.getId(), info.getIdentifier());
+ newDeviceInfos.emplace(info.getId(), info);
}
- for (auto [deviceId, identifier] : mLoggedDeviceInfos) {
- if (newDeviceIds.count(deviceId) != 0) {
+ for (auto [deviceId, info] : mLoggedDeviceInfos) {
+ if (newDeviceInfos.count(deviceId) != 0) {
continue;
}
- onInputDeviceRemoved(deviceId, identifier);
+ onInputDeviceRemoved(deviceId, info.getIdentifier());
}
- std::swap(newDeviceIds, mLoggedDeviceInfos);
+ std::swap(newDeviceInfos, mLoggedDeviceInfos);
}
void InputDeviceMetricsCollector::onInputDeviceRemoved(DeviceId deviceId,
const InputDeviceIdentifier& identifier) {
- // Report usage for that device if there is an active session.
auto it = mActiveUsageSessions.find(deviceId);
- if (it != mActiveUsageSessions.end()) {
- mLogger.logInputDeviceUsageReported(identifier, it->second.end - it->second.start);
- mActiveUsageSessions.erase(it);
+ if (it == mActiveUsageSessions.end()) {
+ return;
}
+ // Report usage for that device if there is an active session.
+ auto& [_, activeSession] = *it;
+ mLogger.logInputDeviceUsageReported(identifier, activeSession.finishSession());
+ mActiveUsageSessions.erase(it);
+
// We don't remove this from mLoggedDeviceInfos because it will be updated in
// onInputDevicesChanged().
}
-void InputDeviceMetricsCollector::onInputDeviceUsage(DeviceId deviceId, nanoseconds eventTime) {
- if (mLoggedDeviceInfos.count(deviceId) == 0) {
+void InputDeviceMetricsCollector::onInputDeviceUsage(DeviceId deviceId, nanoseconds eventTime,
+ const SourceProvider& getSources) {
+ auto infoIt = mLoggedDeviceInfos.find(deviceId);
+ if (infoIt == mLoggedDeviceInfos.end()) {
// Do not track usage for devices that are not logged.
return;
}
- auto [it, inserted] = mActiveUsageSessions.try_emplace(deviceId, eventTime, eventTime);
- if (!inserted) {
- it->second.end = eventTime;
+ auto [sessionIt, _] =
+ mActiveUsageSessions.try_emplace(deviceId, mUsageSessionTimeout, eventTime);
+ for (InputDeviceUsageSource source : getSources(infoIt->second)) {
+ sessionIt->second.recordUsage(eventTime, source);
}
}
-void InputDeviceMetricsCollector::processUsages() {
- const auto usageSessionExpiryTime = mLogger.getCurrentTime() - mUsageSessionTimeout;
+void InputDeviceMetricsCollector::reportCompletedSessions() {
+ const auto currentTime = mLogger.getCurrentTime();
std::vector<DeviceId> completedUsageSessions;
- for (const auto& [deviceId, usageSession] : mActiveUsageSessions) {
- if (usageSession.end <= usageSessionExpiryTime) {
+ for (auto& [deviceId, activeSession] : mActiveUsageSessions) {
+ if (activeSession.checkIfCompletedAt(currentTime)) {
completedUsageSessions.emplace_back(deviceId);
}
}
for (DeviceId deviceId : completedUsageSessions) {
- const auto it = mLoggedDeviceInfos.find(deviceId);
- LOG_ALWAYS_FATAL_IF(it == mLoggedDeviceInfos.end());
+ const auto infoIt = mLoggedDeviceInfos.find(deviceId);
+ LOG_ALWAYS_FATAL_IF(infoIt == mLoggedDeviceInfos.end());
- const auto& session = mActiveUsageSessions[deviceId];
- mLogger.logInputDeviceUsageReported(it->second, session.end - session.start);
-
- mActiveUsageSessions.erase(deviceId);
+ auto activeSessionIt = mActiveUsageSessions.find(deviceId);
+ LOG_ALWAYS_FATAL_IF(activeSessionIt == mActiveUsageSessions.end());
+ auto& [_, activeSession] = *activeSessionIt;
+ mLogger.logInputDeviceUsageReported(infoIt->second.getIdentifier(),
+ activeSession.finishSession());
+ mActiveUsageSessions.erase(activeSessionIt);
}
}
+// --- InputDeviceMetricsCollector::ActiveSession ---
+
+InputDeviceMetricsCollector::ActiveSession::ActiveSession(nanoseconds usageSessionTimeout,
+ nanoseconds startTime)
+ : mUsageSessionTimeout(usageSessionTimeout), mDeviceSession({startTime, startTime}) {}
+
+void InputDeviceMetricsCollector::ActiveSession::recordUsage(nanoseconds eventTime,
+ InputDeviceUsageSource source) {
+ // We assume that event times for subsequent events are always monotonically increasing for each
+ // input device.
+ auto [activeSourceIt, inserted] =
+ mActiveSessionsBySource.try_emplace(source, eventTime, eventTime);
+ if (!inserted) {
+ activeSourceIt->second.end = eventTime;
+ }
+ mDeviceSession.end = eventTime;
+}
+
+bool InputDeviceMetricsCollector::ActiveSession::checkIfCompletedAt(nanoseconds timestamp) {
+ const auto sessionExpiryTime = timestamp - mUsageSessionTimeout;
+ std::vector<InputDeviceUsageSource> completedSourceSessionsForDevice;
+ for (auto& [source, session] : mActiveSessionsBySource) {
+ if (session.end <= sessionExpiryTime) {
+ completedSourceSessionsForDevice.emplace_back(source);
+ }
+ }
+ for (InputDeviceUsageSource source : completedSourceSessionsForDevice) {
+ auto it = mActiveSessionsBySource.find(source);
+ const auto& [_, session] = *it;
+ mSourceUsageBreakdown.emplace_back(source, session.end - session.start);
+ mActiveSessionsBySource.erase(it);
+ }
+ return mActiveSessionsBySource.empty();
+}
+
+InputDeviceMetricsLogger::DeviceUsageReport
+InputDeviceMetricsCollector::ActiveSession::finishSession() {
+ const auto deviceUsageDuration = mDeviceSession.end - mDeviceSession.start;
+
+ for (const auto& [source, sourceSession] : mActiveSessionsBySource) {
+ mSourceUsageBreakdown.emplace_back(source, sourceSession.end - sourceSession.start);
+ }
+ mActiveSessionsBySource.clear();
+
+ return {deviceUsageDuration, mSourceUsageBreakdown};
+}
+
} // namespace android