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

Commit ad16bf27 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Protect pulled data in LatencyAggregator with a lock

The data pull happens on a binder thread, which is different from the
thread where the sketches are collected.

Before this CL, the data was modified by the puller, so it could
potentially be corrupted if the user happened to use the device at the
same time.

This is a speculative fix to the infinite loop that we are observing
inside CompactStack.

Bug: 298423577
Test: atest libinput_tests inputflinger_tests
Change-Id: I624fb3bd59e3c314edc3b1facf424c306e95b71e
parent 19b1c65c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ void LatencyAggregator::processTimeline(const InputEventTimeline& timeline) {
}

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
    if (mNumSketchEventsProcessed >= MAX_EVENTS_FOR_STATISTICS) {
        return;
@@ -167,6 +168,7 @@ void LatencyAggregator::processStatistics(const InputEventTimeline& timeline) {
}

AStatsManager_PullAtomCallbackReturn LatencyAggregator::pullData(AStatsEventList* data) {
    std::scoped_lock lock(mLock);
    std::array<std::unique_ptr<SafeBytesField>, SketchIndex::SIZE> serializedDownData;
    std::array<std::unique_ptr<SafeBytesField>, SketchIndex::SIZE> serializedMoveData;
    for (size_t i = 0; i < SketchIndex::SIZE; i++) {
@@ -257,6 +259,7 @@ void LatencyAggregator::processSlowEvent(const InputEventTimeline& timeline) {
}

std::string LatencyAggregator::dump(const char* prefix) const {
    std::scoped_lock lock(mLock);
    std::string sketchDump = StringPrintf("%s  Sketches:\n", prefix);
    for (size_t i = 0; i < SketchIndex::SIZE; i++) {
        const int64_t numDown = mDownSketches[i]->num_values();
+10 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <android-base/thread_annotations.h>
#include <kll.h>
#include <statslog.h>
#include <utils/Timers.h>
@@ -61,10 +62,13 @@ public:
    ~LatencyAggregator();

private:
    // Binder call -- called on a binder thread. This is different from the thread where the rest of
    // the public API is called.
    static AStatsManager_PullAtomCallbackReturn pullAtomCallback(int32_t atom_tag,
                                                                 AStatsEventList* data,
                                                                 void* cookie);
    AStatsManager_PullAtomCallbackReturn pullData(AStatsEventList* data);

    // ---------- Slow event handling ----------
    void processSlowEvent(const InputEventTimeline& timeline);
    nsecs_t mLastSlowEventTime = 0;
@@ -74,14 +78,17 @@ private:
    size_t mNumEventsSinceLastSlowEventReport = 0;

    // ---------- Statistics handling ----------
    // Statistics is pulled rather than pushed. It's pulled on a binder thread, and therefore will
    // be accessed by two different threads. The lock is needed to protect the pulled data.
    mutable std::mutex mLock;
    void processStatistics(const InputEventTimeline& timeline);
    // Sketches
    std::array<std::unique_ptr<dist_proc::aggregation::KllQuantile>, SketchIndex::SIZE>
            mDownSketches;
            mDownSketches GUARDED_BY(mLock);
    std::array<std::unique_ptr<dist_proc::aggregation::KllQuantile>, SketchIndex::SIZE>
            mMoveSketches;
            mMoveSketches GUARDED_BY(mLock);
    // How many events have been processed so far
    size_t mNumSketchEventsProcessed = 0;
    size_t mNumSketchEventsProcessed GUARDED_BY(mLock) = 0;
};

} // namespace android::inputdispatcher