InputTracer: Trace an event being dispatched to a window
Bug: 210460522
Test: manual with perfetto
Change-Id: Ie161726da294bc5c660d5062af85c9cd621c1b4c
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
index a15ad80..a61fa85 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.cpp
@@ -71,4 +71,39 @@
outProto.set_policy_flags(event.policyFlags);
}
+void AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(
+ const InputTracingBackendInterface::WindowDispatchArgs& args,
+ proto::AndroidWindowInputDispatchEvent& outProto) {
+ std::visit([&](auto entry) { outProto.set_event_id(entry.id); }, args.eventEntry);
+ outProto.set_vsync_id(args.vsyncId);
+ outProto.set_window_id(args.windowId);
+ outProto.set_resolved_flags(args.resolvedFlags);
+
+ if (auto* motion = std::get_if<TracedMotionEvent>(&args.eventEntry); motion != nullptr) {
+ for (size_t i = 0; i < motion->pointerProperties.size(); i++) {
+ auto* pointerProto = outProto.add_dispatched_pointer();
+ pointerProto->set_pointer_id(motion->pointerProperties[i].id);
+ const auto rawXY =
+ MotionEvent::calculateTransformedXY(motion->source, args.rawTransform,
+ motion->pointerCoords[i].getXYValue());
+ pointerProto->set_x_in_display(rawXY.x);
+ pointerProto->set_y_in_display(rawXY.y);
+
+ const auto& coords = motion->pointerCoords[i];
+ const auto coordsInWindow =
+ MotionEvent::calculateTransformedCoords(motion->source, args.transform, coords);
+ auto bits = BitSet64(coords.bits);
+ for (int32_t axisIndex = 0; !bits.isEmpty(); axisIndex++) {
+ const uint32_t axis = bits.clearFirstMarkedBit();
+ const float axisValueInWindow = coordsInWindow.values[axisIndex];
+ if (coords.values[axisIndex] != axisValueInWindow) {
+ auto* axisEntry = pointerProto->add_axis_value_in_window();
+ axisEntry->set_axis(axis);
+ axisEntry->set_value(axisValueInWindow);
+ }
+ }
+ }
+ }
+}
+
} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
index fd23238..8a46f15 100644
--- a/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
+++ b/services/inputflinger/dispatcher/trace/AndroidInputEventProtoConverter.h
@@ -32,6 +32,8 @@
static void toProtoMotionEvent(const TracedMotionEvent& event,
proto::AndroidMotionEvent& outProto);
static void toProtoKeyEvent(const TracedKeyEvent& event, proto::AndroidKeyEvent& outProto);
+ static void toProtoWindowDispatchEvent(const InputTracingBackendInterface::WindowDispatchArgs&,
+ proto::AndroidWindowInputDispatchEvent& outProto);
};
} // namespace android::inputdispatcher::trace
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.cpp b/services/inputflinger/dispatcher/trace/InputTracer.cpp
index 60f574d..b065729 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracer.cpp
@@ -19,6 +19,7 @@
#include "InputTracer.h"
#include <android-base/logging.h>
+#include <utils/AndroidThreads.h>
namespace android::inputdispatcher::trace::impl {
@@ -112,37 +113,76 @@
}
void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
- const EventTrackerInterface* cookie) {}
+ const EventTrackerInterface* cookie) {
+ {
+ std::scoped_lock lock(mLock);
+ const EventEntry& entry = *dispatchEntry.eventEntry;
+
+ TracedEvent traced;
+ if (entry.type == EventEntry::Type::MOTION) {
+ const auto& motion = static_cast<const MotionEntry&>(entry);
+ traced = createTracedEvent(motion);
+ } else if (entry.type == EventEntry::Type::KEY) {
+ const auto& key = static_cast<const KeyEntry&>(entry);
+ traced = createTracedEvent(key);
+ } else {
+ LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
+ }
+
+ if (!cookie) {
+ // This event was not tracked as an inbound event, so trace it now.
+ mTraceQueue.emplace_back(traced);
+ }
+
+ // The vsyncId only has meaning if the event is targeting a window.
+ const int32_t windowId = dispatchEntry.windowId.value_or(0);
+ const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;
+
+ mDispatchTraceQueue.emplace_back(std::move(traced), dispatchEntry.deliveryTime,
+ dispatchEntry.resolvedFlags, dispatchEntry.targetUid,
+ vsyncId, windowId, dispatchEntry.transform,
+ dispatchEntry.rawTransform);
+ } // release lock
+
+ mThreadWakeCondition.notify_all();
+}
std::optional<InputTracer::EventState>& InputTracer::getState(const EventTrackerInterface& cookie) {
return static_cast<const EventTrackerImpl&>(cookie).mLockedState;
}
void InputTracer::threadLoop() {
+ androidSetThreadName("InputTracer");
+
while (true) {
std::vector<const EventState> eventsToTrace;
+ std::vector<const WindowDispatchArgs> dispatchEventsToTrace;
{
std::unique_lock lock(mLock);
base::ScopedLockAssertion assumeLocked(mLock);
if (mThreadExit) {
return;
}
- if (mTraceQueue.empty()) {
+ if (mTraceQueue.empty() && mDispatchTraceQueue.empty()) {
// Wait indefinitely until the thread is awoken.
mThreadWakeCondition.wait(lock);
}
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);
+ writeEventsToBackend(eventsToTrace, dispatchEventsToTrace);
eventsToTrace.clear();
+ dispatchEventsToTrace.clear();
}
}
-void InputTracer::writeEventsToBackend(const std::vector<const EventState>& events) {
+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);
@@ -150,6 +190,10 @@
mBackend->traceKeyEvent(std::get<TracedKeyEvent>(event.event));
}
}
+
+ for (const auto& dispatchArgs : dispatchEvents) {
+ mBackend->traceWindowDispatch(dispatchArgs);
+ }
}
// --- InputTracer::EventTrackerImpl ---
diff --git a/services/inputflinger/dispatcher/trace/InputTracer.h b/services/inputflinger/dispatcher/trace/InputTracer.h
index 97f3a2b..9fe395d 100644
--- a/services/inputflinger/dispatcher/trace/InputTracer.h
+++ b/services/inputflinger/dispatcher/trace/InputTracer.h
@@ -68,6 +68,8 @@
// 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.
std::optional<EventState>& getState(const EventTrackerInterface&) REQUIRES(mLock);
@@ -90,7 +92,8 @@
};
void threadLoop();
- void writeEventsToBackend(const std::vector<const EventState>& events);
+ void writeEventsToBackend(const std::vector<const EventState>& events,
+ const std::vector<const WindowDispatchArgs>& dispatchEvents);
};
} // namespace android::inputdispatcher::trace::impl
diff --git a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
index db88726..4442ad8 100644
--- a/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
+++ b/services/inputflinger/dispatcher/trace/InputTracingPerfettoBackend.cpp
@@ -81,8 +81,14 @@
});
}
-void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs&) const {
- // TODO(b/210460522): Implement.
+void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs) const {
+ InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
+ auto tracePacket = ctx.NewTracePacket();
+ auto* inputEventProto = tracePacket->set_android_input_event();
+ auto* dispatchEventProto = inputEventProto->set_dispatcher_window_dispatch_event();
+ AndroidInputEventProtoConverter::toProtoWindowDispatchEvent(dispatchArgs,
+ *dispatchEventProto);
+ });
}
} // namespace android::inputdispatcher::trace::impl