diff options
author | 2019-07-18 15:17:40 -0700 | |
---|---|---|
committer | 2019-08-05 16:12:17 -0700 | |
commit | 8384682fd25b54921fd74288788f2a9299dd8dba (patch) | |
tree | 62127da5a3deadeb05df1f20078c043521cadec1 | |
parent | ddd78a0f67d322c3fce866aa3ec00b936e5b0688 (diff) |
Seperate LatencyStatistics from InputReader
Test: atest LatencyStatisticsTest
Change-Id: I22a39cd5bef7fa9180bc1ee1fd9478a2cf872e83
-rw-r--r-- | include/input/LatencyStatistics.h | 59 | ||||
-rw-r--r-- | libs/input/Android.bp | 1 | ||||
-rw-r--r-- | libs/input/LatencyStatistics.cpp | 90 | ||||
-rw-r--r-- | libs/input/tests/Android.bp | 1 | ||||
-rw-r--r-- | libs/input/tests/LatencyStatistics_test.cpp | 72 | ||||
-rw-r--r-- | services/inputflinger/InputReader.cpp | 21 | ||||
-rw-r--r-- | services/inputflinger/InputReader.h | 72 |
7 files changed, 237 insertions, 79 deletions
diff --git a/include/input/LatencyStatistics.h b/include/input/LatencyStatistics.h new file mode 100644 index 0000000000..bd86266901 --- /dev/null +++ b/include/input/LatencyStatistics.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef _UI_INPUT_STATISTICS_H +#define _UI_INPUT_STATISTICS_H + +#include <android-base/chrono_utils.h> + +#include <stddef.h> + +namespace android { + +class LatencyStatistics { +private: + /* Minimum sample recorded */ + float mMin; + /* Maximum sample recorded */ + float mMax; + /* Sum of all samples recorded */ + float mSum; + /* Sum of all the squares of samples recorded */ + float mSum2; + /* Count of all samples recorded */ + size_t mCount; + /* The last time statistics were reported */ + std::chrono::steady_clock::time_point mLastReportTime; + /* Statistics Report Frequency */ + const std::chrono::seconds mReportPeriod; + +public: + LatencyStatistics(std::chrono::seconds period); + + void addValue(float); + void reset(); + bool shouldReport(); + + float getMean(); + float getMin(); + float getMax(); + float getStDev(); + size_t getCount(); +}; + +} // namespace android + +#endif // _UI_INPUT_STATISTICS_H diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 2d788119cd..17138506e5 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -48,6 +48,7 @@ cc_library { "InputTransport.cpp", "InputWindow.cpp", "ISetInputWindowsListener.cpp", + "LatencyStatistics.cpp", "VelocityControl.cpp", "VelocityTracker.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 <input/LatencyStatistics.h> + +#include <android-base/chrono_utils.h> + +#include <cmath> +#include <limits> + +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<float>::lowest(); + mMin = std::numeric_limits<float>::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 diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp index ade931e01a..c1c35e1b89 100644 --- a/libs/input/tests/Android.bp +++ b/libs/input/tests/Android.bp @@ -7,6 +7,7 @@ cc_test { "InputEvent_test.cpp", "InputPublisherAndConsumer_test.cpp", "InputWindow_test.cpp", + "LatencyStatistics_test.cpp", "TouchVideoFrame_test.cpp", "VelocityTracker_test.cpp", ], diff --git a/libs/input/tests/LatencyStatistics_test.cpp b/libs/input/tests/LatencyStatistics_test.cpp new file mode 100644 index 0000000000..6d1cab4187 --- /dev/null +++ b/libs/input/tests/LatencyStatistics_test.cpp @@ -0,0 +1,72 @@ +/* + * 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 <gtest/gtest.h> +#include <input/LatencyStatistics.h> +#include <cmath> +#include <limits> + +namespace android { +namespace test { + +TEST(LatencyStatisticsTest, ResetStats) { + LatencyStatistics stats{5min}; + stats.addValue(5.0); + stats.addValue(19.3); + stats.addValue(20); + stats.reset(); + + ASSERT_EQ(stats.getCount(), 0u); + ASSERT_EQ(std::isnan(stats.getStDev()), true); + ASSERT_EQ(std::isnan(stats.getMean()), true); +} + +TEST(LatencyStatisticsTest, AddStatsValue) { + LatencyStatistics stats{5min}; + stats.addValue(5.0); + + ASSERT_EQ(stats.getMin(), 5.0); + ASSERT_EQ(stats.getMax(), 5.0); + ASSERT_EQ(stats.getCount(), 1u); + ASSERT_EQ(stats.getMean(), 5.0); + ASSERT_EQ(stats.getStDev(), 0.0); +} + +TEST(LatencyStatisticsTest, AddMultipleStatsValue) { + LatencyStatistics stats{5min}; + stats.addValue(4.0); + stats.addValue(6.0); + stats.addValue(8.0); + stats.addValue(10.0); + + float stdev = stats.getStDev(); + + ASSERT_EQ(stats.getMin(), 4.0); + ASSERT_EQ(stats.getMax(), 10.0); + ASSERT_EQ(stats.getCount(), 4u); + ASSERT_EQ(stats.getMean(), 7.0); + ASSERT_EQ(stdev * stdev, 5.0); +} + +TEST(LatencyStatisticsTest, ShouldReportStats) { + LatencyStatistics stats{0min}; + stats.addValue(5.0); + + ASSERT_EQ(stats.shouldReport(), true); +} + +} // namespace test +} // namespace android
\ No newline at end of file diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index eee49d5e2a..df5dcafec9 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -85,9 +85,6 @@ static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); // data. static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10); -// How often to report input event statistics -static constexpr nsecs_t STATISTICS_REPORT_FREQUENCY = seconds_to_nanoseconds(5 * 60); - // --- Static Functions --- template<typename T> @@ -4314,16 +4311,14 @@ void TouchInputMapper::clearStylusDataPendingFlags() { } void TouchInputMapper::reportEventForStatistics(nsecs_t evdevTime) { - nsecs_t now = systemTime(CLOCK_MONOTONIC); - nsecs_t latency = now - evdevTime; - mStatistics.addValue(nanoseconds_to_microseconds(latency)); - nsecs_t timeSinceLastReport = now - mStatistics.lastReportTime; - if (timeSinceLastReport > STATISTICS_REPORT_FREQUENCY) { - android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, - mStatistics.min, mStatistics.max, - mStatistics.mean(), mStatistics.stdev(), mStatistics.count); - mStatistics.reset(now); - } + if (mStatistics.shouldReport()) { + android::util::stats_write(android::util::TOUCH_EVENT_REPORTED, mStatistics.getMin(), + mStatistics.getMax(), mStatistics.getMean(), + mStatistics.getStDev(), mStatistics.getCount()); + mStatistics.reset(); + } + nsecs_t latency = nanoseconds_to_microseconds(systemTime(CLOCK_MONOTONIC) - evdevTime); + mStatistics.addValue(latency); } void TouchInputMapper::process(const RawEvent* rawEvent) { diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 0c08e7da38..33763b6cdf 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -24,14 +24,15 @@ #include <input/DisplayViewport.h> #include <input/Input.h> +#include <input/LatencyStatistics.h> #include <input/VelocityControl.h> #include <input/VelocityTracker.h> #include <ui/DisplayInfo.h> -#include <utils/KeyedVector.h> +#include <utils/BitSet.h> #include <utils/Condition.h> +#include <utils/KeyedVector.h> #include <utils/Mutex.h> #include <utils/Timers.h> -#include <utils/BitSet.h> #include <optional> #include <stddef.h> @@ -569,69 +570,6 @@ struct CookedPointerData { } }; -/** - * Basic statistics information. - * Keep track of min, max, average, and standard deviation of the received samples. - * Used to report latency information about input events. - */ -struct LatencyStatistics { - float min; - float max; - // Sum of all samples - float sum; - // Sum of squares of all samples - float sum2; - // The number of samples - size_t count; - // The last time statistics were reported. - nsecs_t lastReportTime; - - LatencyStatistics() { - reset(systemTime(SYSTEM_TIME_MONOTONIC)); - } - - inline void addValue(float x) { - if (x < min) { - min = x; - } - if (x > max) { - max = x; - } - sum += x; - sum2 += x * x; - count++; - } - - // Get the average value. Should not be called if no samples have been added. - inline float mean() { - if (count == 0) { - return 0; - } - return sum / count; - } - - // Get the standard deviation. Should not be called if no samples have been added. - inline float stdev() { - if (count == 0) { - return 0; - } - float average = mean(); - return sqrt(sum2 / count - average * average); - } - - /** - * Reset internal state. The variable 'when' is the time when the data collection started. - * Call this to start a new data collection window. - */ - inline void reset(nsecs_t when) { - max = 0; - min = std::numeric_limits<float>::max(); - sum = 0; - sum2 = 0; - count = 0; - lastReportTime = when; - } -}; /* Keeps track of the state of single-touch protocol. */ class SingleTouchMotionAccumulator { @@ -1571,8 +1509,10 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; + static constexpr std::chrono::duration STATS_REPORT_PERIOD = 5min; + // Latency statistics for touch events - struct LatencyStatistics mStatistics; + LatencyStatistics mStatistics{STATS_REPORT_PERIOD}; std::optional<DisplayViewport> findViewport(); |