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

Commit 1abe1a36 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "InputTracer: Trace events derived from other events separately" into main

parents f438245c a67623c3
Loading
Loading
Loading
Loading
+42 −18
Original line number Diff line number Diff line
@@ -399,7 +399,8 @@ std::unique_ptr<DispatchEntry> createDispatchEntry(const IdGenerator& idGenerato
                                                   const InputTarget& inputTarget,
                                                   std::shared_ptr<const EventEntry> eventEntry,
                                                   ftl::Flags<InputTarget::Flags> inputTargetFlags,
                                                   int64_t vsyncId) {
                                                   int64_t vsyncId,
                                                   trace::InputTracerInterface* tracer) {
    const bool zeroCoords = inputTargetFlags.test(InputTarget::Flags::ZERO_COORDS);
    const sp<WindowInfoHandle> win = inputTarget.windowHandle;
    const std::optional<int32_t> windowId =
@@ -462,6 +463,10 @@ std::unique_ptr<DispatchEntry> createDispatchEntry(const IdGenerator& idGenerato
                                          motionEntry.xCursorPosition, motionEntry.yCursorPosition,
                                          motionEntry.downTime, motionEntry.pointerProperties,
                                          pointerCoords);
    if (tracer) {
        combinedMotionEntry->traceTracker =
                tracer->traceDerivedEvent(*combinedMotionEntry, *motionEntry.traceTracker);
    }

    std::unique_ptr<DispatchEntry> dispatchEntry =
            std::make_unique<DispatchEntry>(std::move(combinedMotionEntry), inputTargetFlags,
@@ -3386,7 +3391,7 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio
    // Enqueue a new dispatch entry onto the outbound queue for this connection.
    std::unique_ptr<DispatchEntry> dispatchEntry =
            createDispatchEntry(mIdGenerator, inputTarget, eventEntry, inputTarget.flags,
                                mWindowInfosVsyncId);
                                mWindowInfosVsyncId, mTracer.get());

    // Use the eventEntry from dispatchEntry since the entry may have changed and can now be a
    // different EventEntry than what was passed in.
@@ -3469,9 +3474,10 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio
                            usingCoords = pointerInfo->second;
                        }
                    }
                    // Generate a new MotionEntry with a new eventId using the resolved action and
                    // flags.
                    resolvedMotion = std::make_shared<
                    {
                        // Generate a new MotionEntry with a new eventId using the resolved action
                        // and flags, and set it as the resolved entry.
                        auto newEntry = std::make_shared<
                                MotionEntry>(mIdGenerator.nextId(), motionEntry.injectionState,
                                             motionEntry.eventTime, motionEntry.deviceId,
                                             motionEntry.source, motionEntry.displayId,
@@ -3480,10 +3486,19 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio
                                             motionEntry.metaState, motionEntry.buttonState,
                                             motionEntry.classification, motionEntry.edgeFlags,
                                             motionEntry.xPrecision, motionEntry.yPrecision,
                                         motionEntry.xCursorPosition, motionEntry.yCursorPosition,
                                         motionEntry.downTime,
                                         usingProperties.value_or(motionEntry.pointerProperties),
                                             motionEntry.xCursorPosition,
                                             motionEntry.yCursorPosition, motionEntry.downTime,
                                             usingProperties.value_or(
                                                     motionEntry.pointerProperties),
                                             usingCoords.value_or(motionEntry.pointerCoords));
                        if (mTracer) {
                            ensureEventTraced(motionEntry);
                            newEntry->traceTracker =
                                    mTracer->traceDerivedEvent(*newEntry,
                                                               *motionEntry.traceTracker);
                        }
                        resolvedMotion = newEntry;
                    }
                    if (ATRACE_ENABLED()) {
                        std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
                                                           ") to MotionEvent(id=0x%" PRIx32 ").",
@@ -3508,7 +3523,8 @@ void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connectio
                          << cancelEvent->getDescription();
                std::unique_ptr<DispatchEntry> cancelDispatchEntry =
                        createDispatchEntry(mIdGenerator, inputTarget, std::move(cancelEvent),
                                            ftl::Flags<InputTarget::Flags>(), mWindowInfosVsyncId);
                                            ftl::Flags<InputTarget::Flags>(), mWindowInfosVsyncId,
                                            mTracer.get());

                // Send these cancel events to the queue before sending the event from the new
                // device.
@@ -4316,6 +4332,10 @@ std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(
                                          originalMotionEntry.xCursorPosition,
                                          originalMotionEntry.yCursorPosition, splitDownTime,
                                          pointerProperties, pointerCoords);
    if (mTracer) {
        splitMotionEntry->traceTracker =
                mTracer->traceDerivedEvent(*splitMotionEntry, *originalMotionEntry.traceTracker);
    }

    return splitMotionEntry;
}
@@ -6614,6 +6634,10 @@ std::unique_ptr<const KeyEntry> InputDispatcher::afterKeyEventLockedInterruptabl
                                               *fallbackKeyCode, event.getScanCode(),
                                               event.getMetaState(), event.getRepeatCount(),
                                               event.getDownTime());
            if (mTracer) {
                newEntry->traceTracker =
                        mTracer->traceDerivedEvent(*newEntry, *keyEntry.traceTracker);
            }
            if (DEBUG_OUTBOUND_EVENT_DETAILS) {
                ALOGD("Unhandled key event: Dispatching fallback key.  "
                      "originalKeyCode=%d, fallbackKeyCode=%d, fallbackMetaState=%08x",
+63 −24
Original line number Diff line number Diff line
@@ -59,6 +59,12 @@ TracedEvent createTracedEvent(const KeyEntry& e) {
                          e.downTime,  e.flags,     e.repeatCount};
}

void writeEventToBackend(const TracedEvent& event, InputTracingBackendInterface& backend) {
    std::visit(Visitor{[&](const TracedMotionEvent& e) { backend.traceMotionEvent(e); },
                       [&](const TracedKeyEvent& e) { backend.traceKeyEvent(e); }},
               event);
}

} // namespace

// --- InputTracer ---
@@ -67,41 +73,74 @@ InputTracer::InputTracer(std::unique_ptr<InputTracingBackendInterface> backend)
      : mBackend(std::move(backend)) {}

std::unique_ptr<EventTrackerInterface> InputTracer::traceInboundEvent(const EventEntry& entry) {
    TracedEvent traced;
    // This is a newly traced inbound event. Create a new state to track it and its derived events.
    auto eventState = std::make_shared<EventState>(*this);

    if (entry.type == EventEntry::Type::MOTION) {
        const auto& motion = static_cast<const MotionEntry&>(entry);
        traced = createTracedEvent(motion);
        eventState->events.emplace_back(createTracedEvent(motion));
    } else if (entry.type == EventEntry::Type::KEY) {
        const auto& key = static_cast<const KeyEntry&>(entry);
        traced = createTracedEvent(key);
        eventState->events.emplace_back(createTracedEvent(key));
    } else {
        LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
    }

    return std::make_unique<EventTrackerImpl>(*this, std::move(traced));
    return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/false);
}

void InputTracer::dispatchToTargetHint(const EventTrackerInterface& cookie,
                                       const InputTarget& target) {
    if (isDerivedCookie(cookie)) {
        LOG(FATAL) << "Event target cannot be updated from a derived cookie.";
    }
    auto& eventState = getState(cookie);
    if (eventState.isEventProcessingComplete) {
        LOG(FATAL) << "dispatchToTargetHint() should not be called after eventProcessingComplete()";
    if (eventState->isEventProcessingComplete) {
        // TODO(b/210460522): Disallow adding new targets after eventProcessingComplete() is called.
        return;
    }
    // TODO(b/210460522): Determine if the event is sensitive based on the target.
}

void InputTracer::eventProcessingComplete(const EventTrackerInterface& cookie) {
    if (isDerivedCookie(cookie)) {
        LOG(FATAL) << "Event processing cannot be set from a derived cookie.";
    }
    auto& eventState = getState(cookie);
    if (eventState.isEventProcessingComplete) {
    if (eventState->isEventProcessingComplete) {
        LOG(FATAL) << "Traced event was already logged. "
                      "eventProcessingComplete() was likely called more than once.";
    }

    std::visit(Visitor{[&](const TracedMotionEvent& e) { mBackend->traceMotionEvent(e); },
                       [&](const TracedKeyEvent& e) { mBackend->traceKeyEvent(e); }},
               eventState.event);
    eventState.isEventProcessingComplete = true;
    for (const auto& event : eventState->events) {
        writeEventToBackend(event, *mBackend);
    }
    eventState->isEventProcessingComplete = true;
}

std::unique_ptr<EventTrackerInterface> InputTracer::traceDerivedEvent(
        const EventEntry& entry, const EventTrackerInterface& originalEventCookie) {
    // This is an event derived from an already-established event. Use the same state to track
    // this event too.
    auto eventState = getState(originalEventCookie);

    if (entry.type == EventEntry::Type::MOTION) {
        const auto& motion = static_cast<const MotionEntry&>(entry);
        eventState->events.emplace_back(createTracedEvent(motion));
    } else if (entry.type == EventEntry::Type::KEY) {
        const auto& key = static_cast<const KeyEntry&>(entry);
        eventState->events.emplace_back(createTracedEvent(key));
    } else {
        LOG(FATAL) << "Cannot trace EventEntry of type: " << ftl::enum_string(entry.type);
    }

    if (eventState->isEventProcessingComplete) {
        // 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.
        writeEventToBackend(eventState->events.back(), *mBackend);
    }
    return std::make_unique<EventTrackerImpl>(std::move(eventState), /*isDerived=*/true);
}

void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
@@ -126,9 +165,7 @@ void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,

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

    // The vsyncId only has meaning if the event is targeting a window.
@@ -141,27 +178,29 @@ void InputTracer::traceEventDispatch(const DispatchEntry& dispatchEntry,
                                   /*hmac=*/{}, resolvedKeyRepeatCount});
}

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

// --- InputTracer::EventTrackerImpl ---
bool InputTracer::isDerivedCookie(const EventTrackerInterface& cookie) {
    return static_cast<const EventTrackerImpl&>(cookie).mIsDerived;
}

InputTracer::EventTrackerImpl::EventTrackerImpl(InputTracer& tracer, TracedEvent&& event)
      : mTracer(tracer), mState(event) {}
// --- InputTracer::EventState ---

InputTracer::EventTrackerImpl::~EventTrackerImpl() {
    if (mState.isEventProcessingComplete) {
InputTracer::EventState::~EventState() {
    if (isEventProcessingComplete) {
        // This event has already been written to the trace as expected.
        return;
    }
    // The event processing was never marked as complete, so do it now.
    // TODO(b/210460522): Determine why/where the event is being destroyed before
    //   eventProcessingComplete() is called.
    std::visit(Visitor{[&](const TracedMotionEvent& e) { mTracer.mBackend->traceMotionEvent(e); },
                       [&](const TracedKeyEvent& e) { mTracer.mBackend->traceKeyEvent(e); }},
               mState.event);
    mState.isEventProcessingComplete = true;
    for (const auto& event : events) {
        writeEventToBackend(event, *tracer.mBackend);
    }
    isEventProcessingComplete = true;
}

} // namespace android::inputdispatcher::trace::impl
+16 −9
Original line number Diff line number Diff line
@@ -44,36 +44,43 @@ public:
    std::unique_ptr<EventTrackerInterface> traceInboundEvent(const EventEntry&) override;
    void dispatchToTargetHint(const EventTrackerInterface&, const InputTarget&) override;
    void eventProcessingComplete(const EventTrackerInterface&) override;
    std::unique_ptr<EventTrackerInterface> traceDerivedEvent(const EventEntry&,
                                                             const EventTrackerInterface&) override;
    void traceEventDispatch(const DispatchEntry&, const EventTrackerInterface*) override;

private:
    std::unique_ptr<InputTracingBackendInterface> mBackend;

    // The state of a tracked event.
    // The state of a tracked event, shared across all events derived from the original event.
    struct EventState {
        explicit inline EventState(TracedEvent event) : event(std::move(event)){};
        explicit inline EventState(InputTracer& tracer) : tracer(tracer){};
        ~EventState();

        const TracedEvent event;
        InputTracer& tracer;
        std::vector<const TracedEvent> events;
        bool isEventProcessingComplete{false};
        // TODO(b/210460522): Add additional args for tracking event sensitivity and
        //  dispatch target UIDs.
    };

    // Get the event state associated with a tracking cookie.
    EventState& getState(const EventTrackerInterface&);
    std::shared_ptr<EventState>& getState(const EventTrackerInterface&);
    bool isDerivedCookie(const EventTrackerInterface&);

    // 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 {
    public:
        explicit EventTrackerImpl(InputTracer&, TracedEvent&& entry);
        virtual ~EventTrackerImpl() override;
        inline EventTrackerImpl(const std::shared_ptr<EventState>& state, bool isDerivedEvent)
              : mState(state), mIsDerived(isDerivedEvent) {}
        EventTrackerImpl(const EventTrackerImpl&) = default;

    private:
        InputTracer& mTracer;
        mutable EventState mState;
        mutable std::shared_ptr<EventState> mState;
        const bool mIsDerived;

        friend EventState& InputTracer::getState(const EventTrackerInterface&);
        friend std::shared_ptr<EventState>& InputTracer::getState(const EventTrackerInterface&);
        friend bool InputTracer::isDerivedCookie(const EventTrackerInterface&);
    };
};

+13 −1
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ public:
     * to track the event's lifecycle inside InputDispatcher.
     */
    virtual std::unique_ptr<EventTrackerInterface> traceInboundEvent(const EventEntry&) = 0;

    /**
     * Notify the tracer that the traced event will be sent to the given InputTarget.
     * The tracer may change how the event is logged depending on the target. For example,
@@ -75,6 +74,19 @@ public:
     */
    virtual void eventProcessingComplete(const EventTrackerInterface&) = 0;

    /**
     * Trace an input event that is derived from another event. This is used in cases where an event
     * is modified from the original, such as when a touch is split across multiple windows, or
     * when a HOVER_MOVE event is modified to be a HOVER_EXIT, etc. The original event's tracker
     * must be provided, and a new EventTracker is returned that should be used to track the event's
     * lifecycle.
     *
     * NOTE: The derived tracker cannot be used to change the targets of the original event, meaning
     * it cannot be used with {@link #dispatchToTargetHint} or {@link eventProcessingComplete}.
     */
    virtual std::unique_ptr<EventTrackerInterface> traceDerivedEvent(
            const EventEntry&, const EventTrackerInterface& originalEventTracker) = 0;

    /**
     * Trace an input event being successfully dispatched to a window. The dispatched event may
     * be a previously traced inbound event, or it may be a synthesized event that has not been