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

Commit 3f3f065f authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11494200 from 9180f87b to 24Q2-release

Change-Id: Iad05b6cb31dcb606a26d87a33c96e67777523fea
parents 37d676c2 9180f87b
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@
#include "InputDispatcher.h"
#include "InputDispatcher.h"
#include "trace/InputTracer.h"
#include "trace/InputTracer.h"
#include "trace/InputTracingPerfettoBackend.h"
#include "trace/InputTracingPerfettoBackend.h"
#include "trace/ThreadedBackend.h"


#define INDENT "  "
#define INDENT "  "
#define INDENT2 "    "
#define INDENT2 "    "
@@ -86,6 +87,15 @@ bool isInputTracingEnabled() {
    return input_flags::enable_input_event_tracing() && isUserdebugOrEng;
    return input_flags::enable_input_event_tracing() && isUserdebugOrEng;
}
}


// Create the input tracing backend that writes to perfetto from a single thread.
std::unique_ptr<trace::InputTracingBackendInterface> createInputTracingBackendIfEnabled() {
    if (!isInputTracingEnabled()) {
        return nullptr;
    }
    return std::make_unique<trace::impl::ThreadedBackend<trace::impl::PerfettoBackend>>(
            trace::impl::PerfettoBackend());
}

template <class Entry>
template <class Entry>
void ensureEventTraced(const Entry& entry) {
void ensureEventTraced(const Entry& entry) {
    if (!entry.traceTracker) {
    if (!entry.traceTracker) {
@@ -832,9 +842,7 @@ std::pair<bool /*cancelPointers*/, bool /*cancelNonPointers*/> expandCancellatio
// --- InputDispatcher ---
// --- InputDispatcher ---


InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy)
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy)
      : InputDispatcher(policy,
      : InputDispatcher(policy, createInputTracingBackendIfEnabled()) {}
                        isInputTracingEnabled() ? std::make_unique<trace::impl::PerfettoBackend>()
                                                : nullptr) {}


InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
InputDispatcher::InputDispatcher(InputDispatcherPolicyInterface& policy,
                                 std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
                                 std::unique_ptr<trace::InputTracingBackendInterface> traceBackend)
@@ -1312,6 +1320,7 @@ bool InputDispatcher::enqueueInboundEventLocked(std::unique_ptr<EventEntry> newE
                ALOGD("Received a new pointer down event, stop waiting for events to process and "
                ALOGD("Received a new pointer down event, stop waiting for events to process and "
                      "just send the pending key event to the currently focused window.");
                      "just send the pending key event to the currently focused window.");
                mKeyIsWaitingForEventsTimeout = now();
                mKeyIsWaitingForEventsTimeout = now();
                needWake = true;
            }
            }
            break;
            break;
        }
        }
+57 −118
Original line number Original line Diff line number Diff line
@@ -19,12 +19,17 @@
#include "InputTracer.h"
#include "InputTracer.h"


#include <android-base/logging.h>
#include <android-base/logging.h>
#include <utils/AndroidThreads.h>


namespace android::inputdispatcher::trace::impl {
namespace android::inputdispatcher::trace::impl {


namespace {
namespace {


// Helper to std::visit with lambdas.
template <typename... V>
struct Visitor : V... {
    using V::operator()...;
};

TracedEvent createTracedEvent(const MotionEntry& e) {
TracedEvent createTracedEvent(const MotionEntry& e) {
    return TracedMotionEvent{e.id,
    return TracedMotionEvent{e.id,
                             e.eventTime,
                             e.eventTime,
@@ -59,19 +64,9 @@ TracedEvent createTracedEvent(const KeyEntry& e) {
// --- InputTracer ---
// --- InputTracer ---


InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
      : mTracerThread(&InputTracer::threadLoop, this), mBackend(std::move(backend)) {}
      : mBackend(std::move(backend)) {}

InputTracer::~InputTracer() {
    {
        std::scoped_lock lock(mLock);
        mThreadExit = true;
    }
    mThreadWakeCondition.notify_all();
    mTracerThread.join();
}


std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
    std::scoped_lock lock(mLock);
    TracedEvent traced;
    TracedEvent traced;


    if (entry.type == EventEntry::Type::MOTION) {
    if (entry.type == EventEntry::Type::MOTION) {
@@ -89,7 +84,6 @@ std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const Even


void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
                                       const InputTarget& target) {
                                       const InputTarget& target) {
    std::scoped_lock lock(mLock);
    auto& cookieState = getState(cookie);
    auto& cookieState = getState(cookie);
    if (!cookieState) {
    if (!cookieState) {
        LOG(FATAL) << "dispatchToTargetHint() should not be called after eventProcessingComplete()";
        LOG(FATAL) << "dispatchToTargetHint() should not be called after eventProcessingComplete()";
@@ -98,24 +92,20 @@ void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
}
}


void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
    {
        std::scoped_lock lock(mLock);
    auto& cookieState = getState(cookie);
    auto& cookieState = getState(cookie);
    if (!cookieState) {
    if (!cookieState) {
        LOG(FATAL) << "Traced event was already logged. "
        LOG(FATAL) << "Traced event was already logged. "
                      "eventProcessingComplete() was likely called more than once.";
                      "eventProcessingComplete() was likely called more than once.";
    }
    }
        mTraceQueue.emplace_back(std::move(*cookieState));
        cookieState.reset();
    } // release lock


    mThreadWakeCondition.notify_all();
    std::visit(Visitor{[&](const TracedMotionEvent& e) { mBackend->traceMotionEvent(e); },
                       [&](const TracedKeyEvent& e) { mBackend->traceKeyEvent(e); }},
               cookieState->event);
    cookieState.reset();
}
}


void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
                                     const EventTrackerInterface* cookie) {
                                     const EventTrackerInterface* cookie) {
    {
        std::scoped_lock lock(mLock);
    const EventEntry& entry = *dispatchEntry.eventEntry;
    const EventEntry& entry = *dispatchEntry.eventEntry;


    TracedEvent traced;
    TracedEvent traced;
@@ -131,82 +121,32 @@ void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,


    if (!cookie) {
    if (!cookie) {
        // This event was not tracked as an inbound event, so trace it now.
        // This event was not tracked as an inbound event, so trace it now.
            mTraceQueue.emplace_back(traced);
        std::visit(Visitor{[&](const TracedMotionEvent& e) { mBackend->traceMotionEvent(e); },
                           [&](const TracedKeyEvent& e) { mBackend->traceKeyEvent(e); }},
                   traced);
    }
    }


    // The vsyncId only has meaning if the event is targeting a window.
    // The vsyncId only has meaning if the event is targeting a window.
    const int32_t windowId = dispatchEntry.windowId.value_or(0);
    const int32_t windowId = dispatchEntry.windowId.value_or(0);
    const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;
    const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;


        mDispatchTraceQueue.emplace_back(std::move(traced), dispatchEntry.deliveryTime,
    mBackend->traceWindowDispatch({std::move(traced), dispatchEntry.deliveryTime,
                                         dispatchEntry.resolvedFlags, dispatchEntry.targetUid,
                                   dispatchEntry.resolvedFlags, dispatchEntry.targetUid, vsyncId,
                                         vsyncId, windowId, dispatchEntry.transform,
                                   windowId, dispatchEntry.transform, dispatchEntry.rawTransform,
                                         dispatchEntry.rawTransform);
                                   /*hmac=*/{}});
    } // release lock

    mThreadWakeCondition.notify_all();
}
}


std::optional<InputTracer::EventState>& InputTracer::getState(const EventTrackerInterface& cookie) {
std::optional<InputTracer::EventState>& InputTracer::getState(const EventTrackerInterface& cookie) {
    return static_cast<const EventTrackerImpl&>(cookie).mLockedState;
    return static_cast<const EventTrackerImpl&>(cookie).mState;
}

void InputTracer::threadLoop() {
    androidSetThreadName("InputTracer");

    std::vector<const EventState> eventsToTrace;
    std::vector<const WindowDispatchArgs> dispatchEventsToTrace;

    while (true) {
        { // acquire lock
            std::unique_lock lock(mLock);
            base::ScopedLockAssertion assumeLocked(mLock);

            // Wait until we need to process more events or exit.
            mThreadWakeCondition.wait(lock, [&]() REQUIRES(mLock) {
                return mThreadExit || !mTraceQueue.empty() || !mDispatchTraceQueue.empty();
            });
            if (mThreadExit) {
                return;
            }

            mTraceQueue.swap(eventsToTrace);
            mDispatchTraceQueue.swap(dispatchEventsToTrace);
        } // release lock

        // Trace the events into the backend without holding the lock to reduce the amount of
        // work performed in the critical section.
        writeEventsToBackend(eventsToTrace, dispatchEventsToTrace);
        eventsToTrace.clear();
        dispatchEventsToTrace.clear();
    }
}

void InputTracer::writeEventsToBackend(
        const std::vector<const EventState>& events,
        const std::vector<const WindowDispatchArgs>& dispatchEvents) {
    for (const auto& event : events) {
        if (auto* motion = std::get_if<TracedMotionEvent>(&event.event); motion != nullptr) {
            mBackend->traceMotionEvent(*motion);
        } else {
            mBackend->traceKeyEvent(std::get<TracedKeyEvent>(event.event));
        }
    }

    for (const auto& dispatchArgs : dispatchEvents) {
        mBackend->traceWindowDispatch(dispatchArgs);
    }
}
}


// --- InputTracer::EventTrackerImpl ---
// --- InputTracer::EventTrackerImpl ---


InputTracer::EventTrackerImpl::EventTrackerImpl(InputTracer& tracer, TracedEvent&& event)
InputTracer::EventTrackerImpl::EventTrackerImpl(InputTracer& tracer, TracedEvent&& event)
      : mTracer(tracer), mLockedState(event) {}
      : mTracer(tracer), mState(event) {}


InputTracer::EventTrackerImpl::~EventTrackerImpl() {
InputTracer::EventTrackerImpl::~EventTrackerImpl() {
    {
    if (!mState) {
        std::scoped_lock lock(mTracer.mLock);
        if (!mLockedState) {
        // This event has already been written to the trace as expected.
        // This event has already been written to the trace as expected.
        return;
        return;
    }
    }
@@ -214,11 +154,10 @@ InputTracer::EventTrackerImpl::~EventTrackerImpl() {
    // Write it to the trace now.
    // Write it to the trace now.
    // TODO(b/210460522): Determine why/where the event is being destroyed before
    // TODO(b/210460522): Determine why/where the event is being destroyed before
    //   eventProcessingComplete() is called.
    //   eventProcessingComplete() is called.
        mTracer.mTraceQueue.emplace_back(std::move(*mLockedState));
    std::visit(Visitor{[&](const TracedMotionEvent& e) { mTracer.mBackend->traceMotionEvent(e); },
        mLockedState.reset();
                       [&](const TracedKeyEvent& e) { mTracer.mBackend->traceKeyEvent(e); }},
    } // release lock
               mState->event);

    mState.reset();
    mTracer.mThreadWakeCondition.notify_all();
}
}


} // namespace android::inputdispatcher::trace::impl
} // namespace android::inputdispatcher::trace::impl
+9 −29
Original line number Original line Diff line number Diff line
@@ -18,14 +18,7 @@


#include "InputTracerInterface.h"
#include "InputTracerInterface.h"


#include <android-base/thread_annotations.h>
#include <gui/WindowInfo.h>

#include <memory>
#include <memory>
#include <mutex>
#include <thread>
#include <unordered_set>
#include <vector>


#include "../Entry.h"
#include "../Entry.h"
#include "InputTracingBackendInterface.h"
#include "InputTracingBackendInterface.h"
@@ -35,17 +28,16 @@ namespace android::inputdispatcher::trace::impl {
/**
/**
 * The tracer implementation for InputDispatcher.
 * The tracer implementation for InputDispatcher.
 *
 *
 * InputTracer is thread-safe, so it can be called from any thread. Upon construction, InputTracer
 * InputTracer's responsibility is to keep track of events as they are processed by InputDispatcher,
 * will start its own thread that it uses for write events into the tracing backend. That is the
 * and to write the events to the tracing backend when enough information is collected. InputTracer
 * one and only thread that will interact with the tracing backend, since the Perfetto backend
 * is not thread-safe.
 * uses thread-local storage.
 *
 *
 * See the documentation in InputTracerInterface for the API surface.
 * See the documentation in InputTracerInterface for the API surface.
 */
 */
class InputTracer : public InputTracerInterface {
class InputTracer : public InputTracerInterface {
public:
public:
    explicit InputTracer(std::unique_ptr<InputTracingBackendInterface>);
    explicit InputTracer(std::unique_ptr<InputTracingBackendInterface>);
    ~InputTracer() override;
    ~InputTracer() = default;
    InputTracer(const InputTracer&) = delete;
    InputTracer(const InputTracer&) = delete;
    InputTracer& operator=(const InputTracer&) = delete;
    InputTracer& operator=(const InputTracer&) = delete;


@@ -55,10 +47,6 @@ public:
    void traceEventDispatch(const DispatchEntry&, const EventTrackerInterface*) override;
    void traceEventDispatch(const DispatchEntry&, const EventTrackerInterface*) override;


private:
private:
    std::mutex mLock;
    std::thread mTracerThread;
    bool mThreadExit GUARDED_BY(mLock){false};
    std::condition_variable mThreadWakeCondition;
    std::unique_ptr<InputTracingBackendInterface> mBackend;
    std::unique_ptr<InputTracingBackendInterface> mBackend;


    // The state of a tracked event.
    // The state of a tracked event.
@@ -67,14 +55,12 @@ private:
        // TODO(b/210460522): Add additional args for tracking event sensitivity and
        // TODO(b/210460522): Add additional args for tracking event sensitivity and
        //  dispatch target UIDs.
        //  dispatch target UIDs.
    };
    };
    std::vector<const EventState> mTraceQueue GUARDED_BY(mLock);
    using WindowDispatchArgs = InputTracingBackendInterface::WindowDispatchArgs;
    std::vector<const WindowDispatchArgs> mDispatchTraceQueue GUARDED_BY(mLock);


    // Provides thread-safe access to the state from an event tracker cookie.
    // Get the event state associated with a tracking cookie.
    std::optional<EventState>& getState(const EventTrackerInterface&) REQUIRES(mLock);
    std::optional<EventState>& getState(const EventTrackerInterface&);


    // Implementation of the event tracker cookie.
    // Implementation of the event tracker cookie. The cookie holds the event state directly for
    // convenience to avoid the overhead of tracking the state separately in InputTracer.
    class EventTrackerImpl : public EventTrackerInterface {
    class EventTrackerImpl : public EventTrackerInterface {
    public:
    public:
        explicit EventTrackerImpl(InputTracer&, TracedEvent&& entry);
        explicit EventTrackerImpl(InputTracer&, TracedEvent&& entry);
@@ -84,16 +70,10 @@ private:
        InputTracer& mTracer;
        InputTracer& mTracer;
        // This event tracker cookie will only hold the state as long as it has not been written
        // This event tracker cookie will only hold the state as long as it has not been written
        // to the trace. The state is released when the event is written to the trace.
        // to the trace. The state is released when the event is written to the trace.
        mutable std::optional<EventState> mLockedState;
        mutable std::optional<EventState> mState;


        // Only allow InputTracer access to the locked state through getTrackerState() to ensure
        // that the InputTracer lock is held when this is accessed.
        friend std::optional<EventState>& InputTracer::getState(const EventTrackerInterface&);
        friend std::optional<EventState>& InputTracer::getState(const EventTrackerInterface&);
    };
    };

    void threadLoop();
    void writeEventsToBackend(const std::vector<const EventState>& events,
                              const std::vector<const WindowDispatchArgs>& dispatchEvents);
};
};


} // namespace android::inputdispatcher::trace::impl
} // namespace android::inputdispatcher::trace::impl
+3 −3
Original line number Original line Diff line number Diff line
@@ -82,10 +82,10 @@ public:
    virtual ~InputTracingBackendInterface() = default;
    virtual ~InputTracingBackendInterface() = default;


    /** Trace a KeyEvent. */
    /** Trace a KeyEvent. */
    virtual void traceKeyEvent(const TracedKeyEvent&) const = 0;
    virtual void traceKeyEvent(const TracedKeyEvent&) = 0;


    /** Trace a MotionEvent. */
    /** Trace a MotionEvent. */
    virtual void traceMotionEvent(const TracedMotionEvent&) const = 0;
    virtual void traceMotionEvent(const TracedMotionEvent&) = 0;


    /** Trace an event being sent to a window. */
    /** Trace an event being sent to a window. */
    struct WindowDispatchArgs {
    struct WindowDispatchArgs {
@@ -99,7 +99,7 @@ public:
        ui::Transform rawTransform;
        ui::Transform rawTransform;
        std::array<uint8_t, 32> hmac;
        std::array<uint8_t, 32> hmac;
    };
    };
    virtual void traceWindowDispatch(const WindowDispatchArgs&) const = 0;
    virtual void traceWindowDispatch(const WindowDispatchArgs&) = 0;
};
};


} // namespace android::inputdispatcher::trace
} // namespace android::inputdispatcher::trace
+3 −3
Original line number Original line Diff line number Diff line
@@ -63,7 +63,7 @@ PerfettoBackend::PerfettoBackend() {
    });
    });
}
}


void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event) const {
void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event) {
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
        auto tracePacket = ctx.NewTracePacket();
        auto tracePacket = ctx.NewTracePacket();
        auto* inputEvent = tracePacket->set_android_input_event();
        auto* inputEvent = tracePacket->set_android_input_event();
@@ -72,7 +72,7 @@ void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event) const {
    });
    });
}
}


void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event) const {
void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event) {
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
        auto tracePacket = ctx.NewTracePacket();
        auto tracePacket = ctx.NewTracePacket();
        auto* inputEvent = tracePacket->set_android_input_event();
        auto* inputEvent = tracePacket->set_android_input_event();
@@ -81,7 +81,7 @@ void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event) const {
    });
    });
}
}


void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs) const {
void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs) {
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
        auto tracePacket = ctx.NewTracePacket();
        auto tracePacket = ctx.NewTracePacket();
        auto* inputEventProto = tracePacket->set_android_input_event();
        auto* inputEventProto = tracePacket->set_android_input_event();
Loading