Loading services/inputflinger/dispatcher/InputDispatcher.cpp +11 −3 Original line number Original line Diff line number Diff line Loading @@ -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 " " Loading Loading @@ -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) { Loading Loading @@ -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) Loading services/inputflinger/dispatcher/trace/InputTracer.cpp +57 −118 Original line number Original line Diff line number Diff line Loading @@ -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, Loading Loading @@ -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) { Loading @@ -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()"; Loading @@ -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; Loading @@ -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; } } Loading @@ -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 services/inputflinger/dispatcher/trace/InputTracer.h +9 −29 Original line number Original line Diff line number Diff line Loading @@ -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" Loading @@ -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; Loading @@ -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. Loading @@ -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); Loading @@ -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 services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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 { Loading @@ -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 services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading @@ -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(); Loading @@ -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 Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +11 −3 Original line number Original line Diff line number Diff line Loading @@ -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 " " Loading Loading @@ -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) { Loading Loading @@ -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) Loading
services/inputflinger/dispatcher/trace/InputTracer.cpp +57 −118 Original line number Original line Diff line number Diff line Loading @@ -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, Loading Loading @@ -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) { Loading @@ -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()"; Loading @@ -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; Loading @@ -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; } } Loading @@ -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
services/inputflinger/dispatcher/trace/InputTracer.h +9 −29 Original line number Original line Diff line number Diff line Loading @@ -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" Loading @@ -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; Loading @@ -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. Loading @@ -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); Loading @@ -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
services/inputflinger/dispatcher/trace/InputTracingBackendInterface.h +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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 { Loading @@ -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
services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp +3 −3 Original line number Original line Diff line number Diff line Loading @@ -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(); Loading @@ -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(); Loading @@ -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