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

Commit 4c49aad7 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

InputTracer: Track inbound events

Track whether an event is an inbound event or a synthesized event. Then
read the config flags from the perfetto backend, and decide whether to
ignore events in the trace depending on the flags that are enabled.

Bug: 210460522
Test: manual with perfetto
Change-Id: I665644f026fca4ab823221656c7b519893e2a1eb
parent 58f19f68
Loading
Loading
Loading
Loading
+28 −23
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ struct Visitor : V... {
    using V::operator()...;
};

TracedEvent createTracedEvent(const MotionEntry& e) {
TracedEvent createTracedEvent(const MotionEntry& e, EventType type) {
    return TracedMotionEvent{e.id,
                             e.eventTime,
                             e.policyFlags,
@@ -50,13 +50,14 @@ TracedEvent createTracedEvent(const MotionEntry& e) {
                             e.yCursorPosition,
                             e.downTime,
                             e.pointerProperties,
                             e.pointerCoords};
                             e.pointerCoords,
                             type};
}

TracedEvent createTracedEvent(const KeyEntry& e) {
TracedEvent createTracedEvent(const KeyEntry& e, EventType type) {
    return TracedKeyEvent{e.id,        e.eventTime, e.policyFlags, e.deviceId, e.source,
                          e.displayId, e.action,    e.keyCode,     e.scanCode, e.metaState,
                          e.downTime,  e.flags,     e.repeatCount};
                          e.downTime,  e.flags,     e.repeatCount, type};
}

void writeEventToBackend(const TracedEvent& event, const TracedEventArgs args,
@@ -83,10 +84,10 @@ std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const Even

    if (entry.type == EventEntry::Type::MOTION) {
        const auto& motion = static_cast<const MotionEntry&>(entry);
        eventState->events.emplace_back(createTracedEvent(motion));
        eventState->events.emplace_back(createTracedEvent(motion, EventType::INBOUND));
    } else if (entry.type == EventEntry::Type::KEY) {
        const auto& key = static_cast<const KeyEntry&>(entry);
        eventState->events.emplace_back(createTracedEvent(key));
        eventState->events.emplace_back(createTracedEvent(key, EventType::INBOUND));
    } else {
        LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
    }
@@ -138,10 +139,10 @@ std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(

    if (entry.type == EventEntry::Type::MOTION) {
        const auto& motion = static_cast<const MotionEntry&>(entry);
        eventState->events.emplace_back(createTracedEvent(motion));
        eventState->events.emplace_back(createTracedEvent(motion, EventType::SYNTHESIZED));
    } else if (entry.type == EventEntry::Type::KEY) {
        const auto& key = static_cast<const KeyEntry&>(entry);
        eventState->events.emplace_back(createTracedEvent(key));
        eventState->events.emplace_back(createTracedEvent(key, EventType::SYNTHESIZED));
    } else {
        LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
    }
@@ -150,8 +151,9 @@ std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(
        // It is possible for a derived event to be dispatched some time after the original event
        // is dispatched, such as in the case of key fallback events. To account for these cases,
        // derived events can be traced after the processing is complete for the original event.
        const auto& event = eventState->events.back();
        const TracedEventArgs traceArgs{.isSecure = eventState->isSecure};
        writeEventToBackend(eventState->events.back(), traceArgs, *mBackend);
        writeEventToBackend(event, traceArgs, *mBackend);
    }
    return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/true);
}
@@ -160,26 +162,18 @@ void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
                                     const EventTrackerInterface& cookie) {
    auto& eventState = getState(cookie);
    const EventEntry& entry = *dispatchEntry.eventEntry;
    const int32_t eventId = entry.id;
    // TODO(b/328618922): Remove resolved key repeats after making repeatCount non-mutable.
    // The KeyEntry's repeatCount is mutable and can be modified after an event is initially traced,
    // so we need to find the repeatCount at the time of dispatching to trace it accurately.
    int32_t resolvedKeyRepeatCount = 0;

    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);
        resolvedKeyRepeatCount = key.repeatCount;
        traced = createTracedEvent(key);
    } else {
        LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
    if (entry.type == EventEntry::Type::KEY) {
        resolvedKeyRepeatCount = static_cast<const KeyEntry&>(entry).repeatCount;
    }

    auto tracedEventIt =
            std::find_if(eventState->events.begin(), eventState->events.end(),
                         [&traced](const auto& event) { return getId(traced) == getId(event); });
                         [eventId](const auto& event) { return eventId == getId(event); });
    if (tracedEventIt == eventState->events.end()) {
        LOG(FATAL)
                << __func__
@@ -191,7 +185,7 @@ void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
    const int32_t vsyncId = dispatchEntry.windowId.has_value() ? dispatchEntry.vsyncId : 0;

    // TODO(b/210460522): Pass HMAC into traceEventDispatch.
    const WindowDispatchArgs windowDispatchArgs{std::move(traced),
    const WindowDispatchArgs windowDispatchArgs{*tracedEventIt,
                                                dispatchEntry.deliveryTime,
                                                dispatchEntry.resolvedFlags,
                                                dispatchEntry.targetUid,
@@ -222,12 +216,23 @@ bool InputTracer::isDerivedCookie(const EventTrackerInterface& cookie) {

void InputTracer::EventState::onEventProcessingComplete() {
    // Write all of the events known so far to the trace.
    const TracedEventArgs traceArgs{.isSecure = isSecure};
    for (const auto& event : events) {
        const TracedEventArgs traceArgs{.isSecure = isSecure};
        writeEventToBackend(event, traceArgs, *tracer.mBackend);
    }
    // Write all pending dispatch args to the trace.
    for (const auto& windowDispatchArgs : pendingDispatchArgs) {
        auto tracedEventIt =
                std::find_if(events.begin(), events.end(),
                             [id = getId(windowDispatchArgs.eventEntry)](const auto& event) {
                                 return id == getId(event);
                             });
        if (tracedEventIt == events.end()) {
            LOG(FATAL) << __func__
                       << ": Failed to find a previously traced event that matches the dispatched "
                          "event";
        }
        const TracedEventArgs traceArgs{.isSecure = isSecure};
        tracer.mBackend->traceWindowDispatch(windowDispatchArgs, traceArgs);
    }
    pendingDispatchArgs.clear();
+16 −0
Original line number Diff line number Diff line
@@ -26,6 +26,20 @@

namespace android::inputdispatcher::trace {

/**
 * Describes the type of this event being traced, with respect to InputDispatcher.
 */
enum class EventType {
    // This is an event that was reported through the InputListener interface or was injected.
    INBOUND,
    // This is an event that was synthesized within InputDispatcher; either being derived
    // from an inbound event (e.g. a split motion event), or synthesized completely
    // (e.g. a CANCEL event generated when the inbound stream is not canceled).
    SYNTHESIZED,

    ftl_last = SYNTHESIZED,
};

/**
 * A representation of an Android KeyEvent used by the tracing backend.
 */
@@ -43,6 +57,7 @@ struct TracedKeyEvent {
    nsecs_t downTime;
    int32_t flags;
    int32_t repeatCount;
    EventType eventType;
};

/**
@@ -69,6 +84,7 @@ struct TracedMotionEvent {
    nsecs_t downTime;
    std::vector<PointerProperties> pointerProperties;
    std::vector<PointerCoords> pointerCoords;
    EventType eventType;
};

/** A representation of a traced input event. */
+26 −0
Original line number Diff line number Diff line
@@ -55,6 +55,20 @@ void PerfettoBackend::InputEventDataSource::OnStop(const InputEventDataSource::S
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) { ctx.Flush(); });
}

bool PerfettoBackend::InputEventDataSource::shouldIgnoreTracedInputEvent(
        const EventType& type) const {
    if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_INPUT_EVENTS)) {
        // Ignore all input events.
        return true;
    }
    if (!getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH) &&
        type != EventType::INBOUND) {
        // When window dispatch tracing is disabled, ignore any events that are not inbound events.
        return true;
    }
    return false;
}

// --- PerfettoBackend ---

std::once_flag PerfettoBackend::sDataSourceRegistrationFlag{};
@@ -85,6 +99,10 @@ void PerfettoBackend::traceMotionEvent(const TracedMotionEvent& event,
        return;
    }
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
        auto dataSource = ctx.GetDataSourceLocked();
        if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
            return;
        }
        auto tracePacket = ctx.NewTracePacket();
        auto* inputEvent = tracePacket->set_android_input_event();
        auto* dispatchMotion = inputEvent->set_dispatcher_motion_event();
@@ -98,6 +116,10 @@ void PerfettoBackend::traceKeyEvent(const TracedKeyEvent& event, const TracedEve
        return;
    }
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
        auto dataSource = ctx.GetDataSourceLocked();
        if (dataSource->shouldIgnoreTracedInputEvent(event.eventType)) {
            return;
        }
        auto tracePacket = ctx.NewTracePacket();
        auto* inputEvent = tracePacket->set_android_input_event();
        auto* dispatchKey = inputEvent->set_dispatcher_key_event();
@@ -112,6 +134,10 @@ void PerfettoBackend::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs
        return;
    }
    InputEventDataSource::Trace([&](InputEventDataSource::TraceContext ctx) {
        auto dataSource = ctx.GetDataSourceLocked();
        if (!dataSource->getFlags().test(TraceFlag::TRACE_DISPATCHER_WINDOW_DISPATCH)) {
            return;
        }
        auto tracePacket = ctx.NewTracePacket();
        auto* inputEvent = tracePacket->set_android_input_event();
        auto* dispatchEvent = inputEvent->set_dispatcher_window_dispatch_event();
+4 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include "InputTracingPerfettoBackendConfig.h"

#include <ftl/flags.h>
#include <perfetto/tracing.h>
#include <mutex>

@@ -65,6 +66,9 @@ private:
        void OnStart(const StartArgs&) override;
        void OnStop(const StopArgs&) override;

        bool shouldIgnoreTracedInputEvent(const EventType&) const;
        inline ftl::Flags<TraceFlag> getFlags() const { return mConfig.flags; }

    private:
        const int32_t mInstanceId;
        TraceConfig mConfig;