Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c252c2c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Metrics for touch latency"

parents c224077d 9ffab0cc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -76,7 +76,8 @@ cc_library_shared {
        "libutils",
        "libui",
        "libhardware_legacy",
        "libutils"
        "libstatslog",
        "libutils",
    ],

    header_libs: [
+21 −4
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@
#include <android-base/stringprintf.h>
#include <input/Keyboard.h>
#include <input/VirtualKeyMap.h>
#include <statslog.h>

#define INDENT "  "
#define INDENT2 "    "
@@ -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 ---

@@ -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);
    }
}
+68 −0
Original line number Diff line number Diff line
@@ -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 {
@@ -1511,6 +1574,9 @@ private:
    VelocityControl mWheelXVelocityControl;
    VelocityControl mWheelYVelocityControl;

    // Latency statistics for touch events
    struct LatencyStatistics mStatistics;

    std::optional<DisplayViewport> findViewport();

    void resetExternalStylus();
@@ -1580,6 +1646,8 @@ private:

    static void assignPointerIds(const RawState* last, RawState* current);

    void reportEventForStatistics(nsecs_t evdevTime);

    const char* modeToString(DeviceMode deviceMode);
};