Loading services/inputflinger/dispatcher/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ filegroup { "InputState.cpp", "InputTarget.cpp", "LatencyAggregator.cpp", "LatencyAggregatorWithHistograms.cpp", "LatencyTracker.cpp", "Monitor.cpp", "TouchedWindow.cpp", Loading services/inputflinger/dispatcher/InputDispatcher.cpp +32 −3 Original line number Diff line number Diff line Loading @@ -155,6 +155,10 @@ constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms; // Number of recent events to keep for debugging purposes. constexpr size_t RECENT_QUEUE_MAX_SIZE = 10; // Interval at which we should push the atom gathering input event latencies in // LatencyAggregatorWithHistograms constexpr nsecs_t LATENCY_STATISTICS_PUSH_INTERVAL = 6 * 3600 * 1000000000LL; // 6 hours // Event log tags. See EventLogTags.logtags for reference. constexpr int LOGTAG_INPUT_INTERACTION = 62000; constexpr int LOGTAG_INPUT_FOCUS = 62001; Loading Loading @@ -947,8 +951,13 @@ InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy, mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT), mWindowTokenWithPointerCapture(nullptr), mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID), mLatencyAggregator(), mLatencyTracker(&mLatencyAggregator) { mInputEventTimelineProcessor( input_flags::enable_per_device_input_latency_metrics() ? std::move(std::unique_ptr<InputEventTimelineProcessor>( new LatencyAggregatorWithHistograms())) : std::move(std::unique_ptr<InputEventTimelineProcessor>( new LatencyAggregator()))), mLatencyTracker(*mInputEventTimelineProcessor) { mLooper = sp<Looper>::make(false); mReporter = createInputReporter(); Loading Loading @@ -1020,6 +1029,11 @@ void InputDispatcher::dispatchOnce() { const nsecs_t nextAnrCheck = processAnrsLocked(); nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck); if (input_flags::enable_per_device_input_latency_metrics()) { const nsecs_t nextStatisticsPush = processLatencyStatisticsLocked(); nextWakeupTime = std::min(nextWakeupTime, nextStatisticsPush); } // We are about to enter an infinitely long sleep, because we have no commands or // pending or queued events if (nextWakeupTime == LLONG_MAX) { Loading Loading @@ -1100,6 +1114,21 @@ nsecs_t InputDispatcher::processAnrsLocked() { return LLONG_MIN; } /** * Check if enough time has passed since the last latency statistics push. * Return the time at which we should wake up next. */ nsecs_t InputDispatcher::processLatencyStatisticsLocked() { const nsecs_t currentTime = now(); // Log the atom recording latency statistics if more than 6 hours passed from the last // push if (currentTime - mLastStatisticPushTime >= LATENCY_STATISTICS_PUSH_INTERVAL) { mInputEventTimelineProcessor->pushLatencyStatistics(); mLastStatisticPushTime = currentTime; } return mLastStatisticPushTime + LATENCY_STATISTICS_PUSH_INTERVAL; } std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked( const std::shared_ptr<Connection>& connection) { if (connection->monitor) { Loading Loading @@ -6089,7 +6118,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %" PRId64 "ms\n", ns2ms(mConfig.keyRepeatTimeout)); dump += mLatencyTracker.dump(INDENT2); dump += mLatencyAggregator.dump(INDENT2); dump += mInputEventTimelineProcessor->dump(INDENT2); dump += INDENT "InputTracer: "; dump += mTracer == nullptr ? "Disabled" : "Enabled"; } Loading services/inputflinger/dispatcher/InputDispatcher.h +4 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "InputTarget.h" #include "InputThread.h" #include "LatencyAggregator.h" #include "LatencyAggregatorWithHistograms.h" #include "LatencyTracker.h" #include "Monitor.h" #include "TouchState.h" Loading Loading @@ -326,6 +327,7 @@ private: std::chrono::nanoseconds mMonitorDispatchingTimeout GUARDED_BY(mLock); nsecs_t processAnrsLocked() REQUIRES(mLock); nsecs_t processLatencyStatisticsLocked() REQUIRES(mLock); std::chrono::nanoseconds getDispatchingTimeoutLocked( const std::shared_ptr<Connection>& connection) REQUIRES(mLock); Loading Loading @@ -697,7 +699,8 @@ private: DeviceId deviceId) const REQUIRES(mLock); // Statistics gathering. LatencyAggregator mLatencyAggregator GUARDED_BY(mLock); nsecs_t mLastStatisticPushTime = 0; std::unique_ptr<InputEventTimelineProcessor> mInputEventTimelineProcessor GUARDED_BY(mLock); LatencyTracker mLatencyTracker GUARDED_BY(mLock); void traceInboundQueueLengthLocked() REQUIRES(mLock); void traceOutboundQueueLength(const Connection& connection); Loading services/inputflinger/dispatcher/InputEventTimeline.h +9 −1 Original line number Diff line number Diff line Loading @@ -121,13 +121,21 @@ struct InputEventTimeline { class InputEventTimelineProcessor { protected: InputEventTimelineProcessor() {} virtual ~InputEventTimelineProcessor() {} public: virtual ~InputEventTimelineProcessor() {} /** * Process the provided timeline */ virtual void processTimeline(const InputEventTimeline& timeline) = 0; /** * Trigger a push for the input event latency statistics */ virtual void pushLatencyStatistics() = 0; virtual std::string dump(const char* prefix) const = 0; }; } // namespace inputdispatcher Loading services/inputflinger/dispatcher/LatencyAggregator.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ using android::base::StringPrintf; using dist_proc::aggregation::KllQuantile; using std::chrono_literals::operator""ms; namespace { // Convert the provided nanoseconds into hundreds of microseconds. // Use hundreds of microseconds (as opposed to microseconds) to preserve space. static inline int64_t ns2hus(nsecs_t nanos) { Loading Loading @@ -74,6 +76,8 @@ static std::chrono::milliseconds getSlowEventMinReportingInterval() { return std::chrono::milliseconds(std::stoi(millis)); } } // namespace namespace android::inputdispatcher { /** Loading Loading @@ -125,6 +129,9 @@ void LatencyAggregator::processTimeline(const InputEventTimeline& timeline) { processSlowEvent(timeline); } // This version of LatencyAggregator doesn't push any atoms void LatencyAggregator::pushLatencyStatistics() {} void LatencyAggregator::processStatistics(const InputEventTimeline& timeline) { std::scoped_lock lock(mLock); // Before we do any processing, check that we have not yet exceeded MAX_SIZE Loading Loading
services/inputflinger/dispatcher/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ filegroup { "InputState.cpp", "InputTarget.cpp", "LatencyAggregator.cpp", "LatencyAggregatorWithHistograms.cpp", "LatencyTracker.cpp", "Monitor.cpp", "TouchedWindow.cpp", Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +32 −3 Original line number Diff line number Diff line Loading @@ -155,6 +155,10 @@ constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms; // Number of recent events to keep for debugging purposes. constexpr size_t RECENT_QUEUE_MAX_SIZE = 10; // Interval at which we should push the atom gathering input event latencies in // LatencyAggregatorWithHistograms constexpr nsecs_t LATENCY_STATISTICS_PUSH_INTERVAL = 6 * 3600 * 1000000000LL; // 6 hours // Event log tags. See EventLogTags.logtags for reference. constexpr int LOGTAG_INPUT_INTERACTION = 62000; constexpr int LOGTAG_INPUT_FOCUS = 62001; Loading Loading @@ -947,8 +951,13 @@ InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy, mFocusedDisplayId(ui::LogicalDisplayId::DEFAULT), mWindowTokenWithPointerCapture(nullptr), mAwaitedApplicationDisplayId(ui::LogicalDisplayId::INVALID), mLatencyAggregator(), mLatencyTracker(&mLatencyAggregator) { mInputEventTimelineProcessor( input_flags::enable_per_device_input_latency_metrics() ? std::move(std::unique_ptr<InputEventTimelineProcessor>( new LatencyAggregatorWithHistograms())) : std::move(std::unique_ptr<InputEventTimelineProcessor>( new LatencyAggregator()))), mLatencyTracker(*mInputEventTimelineProcessor) { mLooper = sp<Looper>::make(false); mReporter = createInputReporter(); Loading Loading @@ -1020,6 +1029,11 @@ void InputDispatcher::dispatchOnce() { const nsecs_t nextAnrCheck = processAnrsLocked(); nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck); if (input_flags::enable_per_device_input_latency_metrics()) { const nsecs_t nextStatisticsPush = processLatencyStatisticsLocked(); nextWakeupTime = std::min(nextWakeupTime, nextStatisticsPush); } // We are about to enter an infinitely long sleep, because we have no commands or // pending or queued events if (nextWakeupTime == LLONG_MAX) { Loading Loading @@ -1100,6 +1114,21 @@ nsecs_t InputDispatcher::processAnrsLocked() { return LLONG_MIN; } /** * Check if enough time has passed since the last latency statistics push. * Return the time at which we should wake up next. */ nsecs_t InputDispatcher::processLatencyStatisticsLocked() { const nsecs_t currentTime = now(); // Log the atom recording latency statistics if more than 6 hours passed from the last // push if (currentTime - mLastStatisticPushTime >= LATENCY_STATISTICS_PUSH_INTERVAL) { mInputEventTimelineProcessor->pushLatencyStatistics(); mLastStatisticPushTime = currentTime; } return mLastStatisticPushTime + LATENCY_STATISTICS_PUSH_INTERVAL; } std::chrono::nanoseconds InputDispatcher::getDispatchingTimeoutLocked( const std::shared_ptr<Connection>& connection) { if (connection->monitor) { Loading Loading @@ -6089,7 +6118,7 @@ void InputDispatcher::dumpDispatchStateLocked(std::string& dump) const { dump += StringPrintf(INDENT2 "KeyRepeatTimeout: %" PRId64 "ms\n", ns2ms(mConfig.keyRepeatTimeout)); dump += mLatencyTracker.dump(INDENT2); dump += mLatencyAggregator.dump(INDENT2); dump += mInputEventTimelineProcessor->dump(INDENT2); dump += INDENT "InputTracer: "; dump += mTracer == nullptr ? "Disabled" : "Enabled"; } Loading
services/inputflinger/dispatcher/InputDispatcher.h +4 −1 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ #include "InputTarget.h" #include "InputThread.h" #include "LatencyAggregator.h" #include "LatencyAggregatorWithHistograms.h" #include "LatencyTracker.h" #include "Monitor.h" #include "TouchState.h" Loading Loading @@ -326,6 +327,7 @@ private: std::chrono::nanoseconds mMonitorDispatchingTimeout GUARDED_BY(mLock); nsecs_t processAnrsLocked() REQUIRES(mLock); nsecs_t processLatencyStatisticsLocked() REQUIRES(mLock); std::chrono::nanoseconds getDispatchingTimeoutLocked( const std::shared_ptr<Connection>& connection) REQUIRES(mLock); Loading Loading @@ -697,7 +699,8 @@ private: DeviceId deviceId) const REQUIRES(mLock); // Statistics gathering. LatencyAggregator mLatencyAggregator GUARDED_BY(mLock); nsecs_t mLastStatisticPushTime = 0; std::unique_ptr<InputEventTimelineProcessor> mInputEventTimelineProcessor GUARDED_BY(mLock); LatencyTracker mLatencyTracker GUARDED_BY(mLock); void traceInboundQueueLengthLocked() REQUIRES(mLock); void traceOutboundQueueLength(const Connection& connection); Loading
services/inputflinger/dispatcher/InputEventTimeline.h +9 −1 Original line number Diff line number Diff line Loading @@ -121,13 +121,21 @@ struct InputEventTimeline { class InputEventTimelineProcessor { protected: InputEventTimelineProcessor() {} virtual ~InputEventTimelineProcessor() {} public: virtual ~InputEventTimelineProcessor() {} /** * Process the provided timeline */ virtual void processTimeline(const InputEventTimeline& timeline) = 0; /** * Trigger a push for the input event latency statistics */ virtual void pushLatencyStatistics() = 0; virtual std::string dump(const char* prefix) const = 0; }; } // namespace inputdispatcher Loading
services/inputflinger/dispatcher/LatencyAggregator.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ using android::base::StringPrintf; using dist_proc::aggregation::KllQuantile; using std::chrono_literals::operator""ms; namespace { // Convert the provided nanoseconds into hundreds of microseconds. // Use hundreds of microseconds (as opposed to microseconds) to preserve space. static inline int64_t ns2hus(nsecs_t nanos) { Loading Loading @@ -74,6 +76,8 @@ static std::chrono::milliseconds getSlowEventMinReportingInterval() { return std::chrono::milliseconds(std::stoi(millis)); } } // namespace namespace android::inputdispatcher { /** Loading Loading @@ -125,6 +129,9 @@ void LatencyAggregator::processTimeline(const InputEventTimeline& timeline) { processSlowEvent(timeline); } // This version of LatencyAggregator doesn't push any atoms void LatencyAggregator::pushLatencyStatistics() {} void LatencyAggregator::processStatistics(const InputEventTimeline& timeline) { std::scoped_lock lock(mLock); // Before we do any processing, check that we have not yet exceeded MAX_SIZE Loading