From 8384682fd25b54921fd74288788f2a9299dd8dba Mon Sep 17 00:00:00 2001 From: Atif Niyaz Date: Thu, 18 Jul 2019 15:17:40 -0700 Subject: Seperate LatencyStatistics from InputReader Test: atest LatencyStatisticsTest Change-Id: I22a39cd5bef7fa9180bc1ee1fd9478a2cf872e83 --- libs/input/LatencyStatistics.cpp | 90 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 libs/input/LatencyStatistics.cpp (limited to 'libs/input/LatencyStatistics.cpp') diff --git a/libs/input/LatencyStatistics.cpp b/libs/input/LatencyStatistics.cpp new file mode 100644 index 0000000000..e343578e00 --- /dev/null +++ b/libs/input/LatencyStatistics.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include + +namespace android { + +LatencyStatistics::LatencyStatistics(std::chrono::seconds period) : mReportPeriod(period) { + reset(); +} + +/** + * Add a raw value to the statistics + */ +void LatencyStatistics::addValue(float value) { + if (value < mMin) { + mMin = value; + } + if (value > mMax) { + mMax = value; + } + mSum += value; + mSum2 += value * value; + mCount++; +} + +/** + * Get the mean. Should not be called if no samples have been added. + */ +float LatencyStatistics::getMean() { + return mSum / mCount; +} + +/** + * Get the standard deviation. Should not be called if no samples have been added. + */ +float LatencyStatistics::getStDev() { + float mean = getMean(); + return sqrt(mSum2 / mCount - mean * mean); +} + +float LatencyStatistics::getMin() { + return mMin; +} + +float LatencyStatistics::getMax() { + return mMax; +} + +size_t LatencyStatistics::getCount() { + return mCount; +} + +/** + * Reset internal state. The variable 'when' is the time when the data collection started. + * Call this to start a new data collection window. + */ +void LatencyStatistics::reset() { + mMax = std::numeric_limits::lowest(); + mMin = std::numeric_limits::max(); + mSum = 0; + mSum2 = 0; + mCount = 0; + mLastReportTime = std::chrono::steady_clock::now(); +} + +bool LatencyStatistics::shouldReport() { + std::chrono::duration timeSinceReport = std::chrono::steady_clock::now() - mLastReportTime; + return mCount != 0 && timeSinceReport > mReportPeriod; +} + +} // namespace android -- cgit v1.2.3-59-g8ed1b From de4bf150c5685643daa1fa17f697e8b1cf3ea9ec Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Fri, 16 Aug 2019 11:12:52 -0500 Subject: Do not report latency for injected events When reporting the latency of touch events, ensure that injected events are excluded. These events can have arbitrary timestamps, and would not result in meaningful data. Also do not report events for statistics if inputfilter is enabled. Move the statistics reporting from InputTransport to InputDispatcher. This ensures that there's only 1 instance of the mStatistics object. This also provides easy access to the inputfilterenabled state. Bug: 13894199 Test: Change the reporting period to 0 (to report every event immediately) Inject events in various ways and ensure they don't go to statsd $ m statsd_testdrive && ./out/host/linux-x86/bin/statsd_testdrive 34 $ adb shell input tap 100 100 $ adb shell monkey 1000 Next, relaunch the statsd_testdrive script and touch the screen Observe that events are reported. Change-Id: Ief8040599a347e084e75584ed3164c60a6dbc4ad --- include/input/InputTransport.h | 5 ---- libs/input/Android.bp | 1 - libs/input/InputTransport.cpp | 15 ----------- libs/input/LatencyStatistics.cpp | 2 +- services/inputflinger/Android.bp | 1 + services/inputflinger/dispatcher/Android.bp | 1 + services/inputflinger/dispatcher/Entry.h | 18 +++++++++++++ .../inputflinger/dispatcher/InputDispatcher.cpp | 30 ++++++++++++++++++++++ services/inputflinger/dispatcher/InputDispatcher.h | 5 ++++ services/inputflinger/dispatcher/InputState.h | 3 --- 10 files changed, 56 insertions(+), 25 deletions(-) (limited to 'libs/input/LatencyStatistics.cpp') diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 28b8d80074..c056c972d2 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -289,12 +288,8 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: - static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min; sp mChannel; - LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD}; - - void reportTouchEventForStatistics(nsecs_t evdevTime); }; /* diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 7749e66c4d..8efaf3d90b 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -57,7 +57,6 @@ cc_library { "libutils", "libbinder", "libui", - "libstatslog", ], sanitize: { diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp index 8a2fc2a2d0..366c93cf1f 100644 --- a/libs/input/InputTransport.cpp +++ b/libs/input/InputTransport.cpp @@ -34,7 +34,6 @@ #include #include -#include using android::base::StringPrintf; @@ -538,9 +537,6 @@ status_t InputPublisher::publishMotionEvent( msg.body.motion.pointers[i].coords.copyFrom(pointerCoords[i]); } - if (source == AINPUT_SOURCE_TOUCHSCREEN) { - reportTouchEventForStatistics(eventTime); - } return mChannel->sendMessage(&msg); } @@ -567,17 +563,6 @@ status_t InputPublisher::receiveFinishedSignal(uint32_t* outSeq, bool* outHandle return OK; } -void InputPublisher::reportTouchEventForStatistics(nsecs_t evdevTime) { - if (mTouchStatistics.shouldReport()) { - android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(), - mTouchStatistics.getMax(), mTouchStatistics.getMean(), - mTouchStatistics.getStDev(), mTouchStatistics.getCount()); - mTouchStatistics.reset(); - } - nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime); - mTouchStatistics.addValue(latency); -} - // --- InputConsumer --- InputConsumer::InputConsumer(const sp& channel) : diff --git a/libs/input/LatencyStatistics.cpp b/libs/input/LatencyStatistics.cpp index e343578e00..394da22a62 100644 --- a/libs/input/LatencyStatistics.cpp +++ b/libs/input/LatencyStatistics.cpp @@ -84,7 +84,7 @@ void LatencyStatistics::reset() { bool LatencyStatistics::shouldReport() { std::chrono::duration timeSinceReport = std::chrono::steady_clock::now() - mLastReportTime; - return mCount != 0 && timeSinceReport > mReportPeriod; + return mCount != 0 && timeSinceReport >= mReportPeriod; } } // namespace android diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp index 11578c393e..f6b5935bcf 100644 --- a/services/inputflinger/Android.bp +++ b/services/inputflinger/Android.bp @@ -44,6 +44,7 @@ cc_library_shared { "libhidlbase", "libinput", "liblog", + "libstatslog", "libutils", "libui", "server_configurable_flags", diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp index b8c3a808f1..9185e00272 100644 --- a/services/inputflinger/dispatcher/Android.bp +++ b/services/inputflinger/dispatcher/Android.bp @@ -34,6 +34,7 @@ cc_library_static { "libinputreporter", "libinputflinger_base", "liblog", + "libstatslog", "libui", "libutils", ], diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h index a9e22f19f1..28c2799477 100644 --- a/services/inputflinger/dispatcher/Entry.h +++ b/services/inputflinger/dispatcher/Entry.h @@ -29,6 +29,9 @@ namespace android::inputdispatcher { +// Sequence number for synthesized or injected events. +constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0; + struct EventEntry { enum { TYPE_CONFIGURATION_CHANGED, TYPE_DEVICE_RESET, TYPE_KEY, TYPE_MOTION }; @@ -41,8 +44,23 @@ struct EventEntry { bool dispatchInProgress; // initially false, set to true while dispatching + /** + * Injected keys are events from an external (probably untrusted) application + * and are not related to real hardware state. They come in via + * InputDispatcher::injectInputEvent, which sets policy flag POLICY_FLAG_INJECTED. + */ inline bool isInjected() const { return injectionState != nullptr; } + /** + * Synthesized events are either injected events, or events that come + * from real hardware, but aren't directly attributable to a specific hardware event. + * Key repeat is a synthesized event, because it is related to an actual hardware state + * (a key is currently pressed), but the repeat itself is generated by the framework. + */ + inline bool isSynthesized() const { + return isInjected() || sequenceNum == SYNTHESIZED_EVENT_SEQUENCE_NUM; + } + void release(); virtual void appendDescription(std::string& msg) const = 0; diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 039462e23b..2361867e62 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -2274,6 +2275,7 @@ void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, motionEntry->downTime, motionEntry->eventTime, motionEntry->pointerCount, motionEntry->pointerProperties, usingCoords); + reportTouchEventForStatistics(*motionEntry); break; } @@ -4478,6 +4480,34 @@ void InputDispatcher::updateDispatchStatistics(nsecs_t currentTime, const EventE // TODO Write some statistics about how long we spend waiting. } +/** + * Report the touch event latency to the statsd server. + * Input events are reported for statistics if: + * - This is a touchscreen event + * - InputFilter is not enabled + * - Event is not injected or synthesized + * + * Statistics should be reported before calling addValue, to prevent a fresh new sample + * from getting aggregated with the "old" data. + */ +void InputDispatcher::reportTouchEventForStatistics(const MotionEntry& motionEntry) + REQUIRES(mLock) { + const bool reportForStatistics = (motionEntry.source == AINPUT_SOURCE_TOUCHSCREEN) && + !(motionEntry.isSynthesized()) && !mInputFilterEnabled; + if (!reportForStatistics) { + return; + } + + if (mTouchStatistics.shouldReport()) { + android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mTouchStatistics.getMin(), + mTouchStatistics.getMax(), mTouchStatistics.getMean(), + mTouchStatistics.getStDev(), mTouchStatistics.getCount()); + mTouchStatistics.reset(); + } + const float latencyMicros = nanoseconds_to_microseconds(now() - motionEntry.eventTime); + mTouchStatistics.addValue(latencyMicros); +} + void InputDispatcher::traceInboundQueueLengthLocked() { if (ATRACE_ENABLED()) { ATRACE_INT("iq", mInboundQueue.size()); diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h index f2c04028e4..0d9d6b0c15 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.h +++ b/services/inputflinger/dispatcher/InputDispatcher.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -455,6 +456,10 @@ private: void doOnPointerDownOutsideFocusLockedInterruptible(CommandEntry* commandEntry) REQUIRES(mLock); // Statistics gathering. + static constexpr std::chrono::duration TOUCH_STATS_REPORT_PERIOD = 5min; + LatencyStatistics mTouchStatistics{TOUCH_STATS_REPORT_PERIOD}; + + void reportTouchEventForStatistics(const MotionEntry& entry); void updateDispatchStatistics(nsecs_t currentTime, const EventEntry* entry, int32_t injectionResult, nsecs_t timeSpentWaitingForApplication); void traceInboundQueueLengthLocked() REQUIRES(mLock); diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h index bccef0fca3..47e9b36219 100644 --- a/services/inputflinger/dispatcher/InputState.h +++ b/services/inputflinger/dispatcher/InputState.h @@ -24,9 +24,6 @@ namespace android::inputdispatcher { -// Sequence number for synthesized or injected events. -constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0; - /* Tracks dispatched key and motion event state so that cancellation events can be * synthesized when events are dropped. */ class InputState { -- cgit v1.2.3-59-g8ed1b