Loading services/inputflinger/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -76,7 +76,8 @@ cc_library_shared { "libutils", "libui", "libhardware_legacy", "libutils" "libstatslog", "libutils", ], header_libs: [ Loading services/inputflinger/InputReader.cpp +21 −4 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ #include <android-base/stringprintf.h> #include <input/Keyboard.h> #include <input/VirtualKeyMap.h> #include <statslog.h> #define INDENT " " #define INDENT2 " " Loading @@ -71,18 +72,21 @@ namespace android { // --- Constants --- // Maximum number of slots supported when using the slot-based Multitouch Protocol B. static const size_t MAX_SLOTS = 32; static constexpr size_t MAX_SLOTS = 32; // Maximum amount of latency to add to touch events while waiting for data from an // external stylus. static const nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72); static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72); // Maximum amount of time to wait on touch data before pushing out new pressure data. static const nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); // Artificial latency on synthetic events created from stylus data without corresponding touch // data. static const nsecs_t STYLUS_DATA_LATENCY = ms2ns(10); 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 --- Loading Loading @@ -4287,12 +4291,25 @@ void TouchInputMapper::clearStylusDataPendingFlags() { mExternalStylusFusionTimeout = LLONG_MAX; } 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.reset(now); } } void TouchInputMapper::process(const RawEvent* rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { reportEventForStatistics(rawEvent->when); sync(rawEvent->when); } } Loading services/inputflinger/InputReader.h +68 −0 Original line number Diff line number Diff line Loading @@ -567,6 +567,69 @@ 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 { Loading Loading @@ -1511,6 +1574,9 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; // Latency statistics for touch events struct LatencyStatistics mStatistics; std::optional<DisplayViewport> findViewport(); void resetExternalStylus(); Loading Loading @@ -1580,6 +1646,8 @@ private: static void assignPointerIds(const RawState* last, RawState* current); void reportEventForStatistics(nsecs_t evdevTime); const char* modeToString(DeviceMode deviceMode); }; Loading Loading
services/inputflinger/Android.bp +2 −1 Original line number Diff line number Diff line Loading @@ -76,7 +76,8 @@ cc_library_shared { "libutils", "libui", "libhardware_legacy", "libutils" "libstatslog", "libutils", ], header_libs: [ Loading
services/inputflinger/InputReader.cpp +21 −4 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ #include <android-base/stringprintf.h> #include <input/Keyboard.h> #include <input/VirtualKeyMap.h> #include <statslog.h> #define INDENT " " #define INDENT2 " " Loading @@ -71,18 +72,21 @@ namespace android { // --- Constants --- // Maximum number of slots supported when using the slot-based Multitouch Protocol B. static const size_t MAX_SLOTS = 32; static constexpr size_t MAX_SLOTS = 32; // Maximum amount of latency to add to touch events while waiting for data from an // external stylus. static const nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72); static constexpr nsecs_t EXTERNAL_STYLUS_DATA_TIMEOUT = ms2ns(72); // Maximum amount of time to wait on touch data before pushing out new pressure data. static const nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); static constexpr nsecs_t TOUCH_DATA_TIMEOUT = ms2ns(20); // Artificial latency on synthetic events created from stylus data without corresponding touch // data. static const nsecs_t STYLUS_DATA_LATENCY = ms2ns(10); 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 --- Loading Loading @@ -4287,12 +4291,25 @@ void TouchInputMapper::clearStylusDataPendingFlags() { mExternalStylusFusionTimeout = LLONG_MAX; } 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.reset(now); } } void TouchInputMapper::process(const RawEvent* rawEvent) { mCursorButtonAccumulator.process(rawEvent); mCursorScrollAccumulator.process(rawEvent); mTouchButtonAccumulator.process(rawEvent); if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) { reportEventForStatistics(rawEvent->when); sync(rawEvent->when); } } Loading
services/inputflinger/InputReader.h +68 −0 Original line number Diff line number Diff line Loading @@ -567,6 +567,69 @@ 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 { Loading Loading @@ -1511,6 +1574,9 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; // Latency statistics for touch events struct LatencyStatistics mStatistics; std::optional<DisplayViewport> findViewport(); void resetExternalStylus(); Loading Loading @@ -1580,6 +1646,8 @@ private: static void assignPointerIds(const RawState* last, RawState* current); void reportEventForStatistics(nsecs_t evdevTime); const char* modeToString(DeviceMode deviceMode); }; Loading