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

Commit 65a071a7 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

InputDispatcher_test: Verify all traced events match exactly

Bug: 210460522
Test: atest inputflinger_tests
Change-Id: I2ab660ed0a6888c23bc711fb8494385c22b3c404
parent 9d5f9ce1
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ static constexpr size_t MAX_POINTERS = 16;
 */
struct AInputEvent {
    virtual ~AInputEvent() {}
    bool operator==(const AInputEvent&) const = default;
};

/*
@@ -545,6 +546,8 @@ public:

    static int32_t nextId();

    bool operator==(const InputEvent&) const = default;

protected:
    void initialize(int32_t id, DeviceId deviceId, uint32_t source, int32_t displayId,
                    std::array<uint8_t, 32> hmac);
@@ -598,6 +601,8 @@ public:

    static const char* actionToString(int32_t action);

    bool operator==(const KeyEvent&) const = default;

protected:
    int32_t mAction;
    int32_t mFlags;
@@ -917,6 +922,9 @@ public:
    // The rounding precision for transformed motion events.
    static constexpr float ROUNDING_PRECISION = 0.001f;

    bool operator==(const MotionEvent&) const;
    inline bool operator!=(const MotionEvent& o) const { return !(*this == o); };

protected:
    int32_t mAction;
    int32_t mActionButton;
+27 −0
Original line number Diff line number Diff line
@@ -1007,6 +1007,33 @@ PointerCoords MotionEvent::calculateTransformedCoords(uint32_t source,
    return out;
}

bool MotionEvent::operator==(const android::MotionEvent& o) const {
    // We use NaN values to represent invalid cursor positions. Since NaN values are not equal
    // to themselves according to IEEE 754, we cannot use the default equality operator to compare
    // MotionEvents. Therefore we define a custom equality operator with special handling for NaNs.
    // clang-format off
    return InputEvent::operator==(static_cast<const InputEvent&>(o)) &&
            mAction == o.mAction &&
            mActionButton == o.mActionButton &&
            mFlags == o.mFlags &&
            mEdgeFlags == o.mEdgeFlags &&
            mMetaState == o.mMetaState &&
            mButtonState == o.mButtonState &&
            mClassification == o.mClassification &&
            mTransform == o.mTransform &&
            mXPrecision == o.mXPrecision &&
            mYPrecision == o.mYPrecision &&
            ((std::isnan(mRawXCursorPosition) && std::isnan(o.mRawXCursorPosition)) ||
                mRawXCursorPosition == o.mRawXCursorPosition) &&
            ((std::isnan(mRawYCursorPosition) && std::isnan(o.mRawYCursorPosition)) ||
                mRawYCursorPosition == o.mRawYCursorPosition) &&
            mRawTransform == o.mRawTransform && mDownTime == o.mDownTime &&
            mPointerProperties == o.mPointerProperties &&
            mSampleEventTimes == o.mSampleEventTimes &&
            mSamplePointerCoords == o.mSamplePointerCoords;
    // clang-format on
}

std::ostream& operator<<(std::ostream& out, const MotionEvent& event) {
    out << "MotionEvent { action=" << MotionEvent::actionToString(event.getAction());
    if (event.getActionButton() != 0) {
+57 −5
Original line number Diff line number Diff line
@@ -37,6 +37,30 @@ inline auto getId(const trace::TracedEvent& v) {
    return std::visit([](const auto& event) { return event.id; }, v);
}

MotionEvent toInputEvent(
        const trace::TracedMotionEvent& e,
        const trace::InputTracingBackendInterface::WindowDispatchArgs& dispatchArgs,
        const std::array<uint8_t, 32>& hmac) {
    MotionEvent traced;
    traced.initialize(e.id, e.deviceId, e.source, e.displayId, hmac, e.action, e.actionButton,
                      dispatchArgs.resolvedFlags, e.edgeFlags, e.metaState, e.buttonState,
                      e.classification, dispatchArgs.transform, e.xPrecision, e.yPrecision,
                      e.xCursorPosition, e.yCursorPosition, dispatchArgs.rawTransform, e.downTime,
                      e.eventTime, e.pointerProperties.size(), e.pointerProperties.data(),
                      e.pointerCoords.data());
    return traced;
}

KeyEvent toInputEvent(const trace::TracedKeyEvent& e,
                      const trace::InputTracingBackendInterface::WindowDispatchArgs& dispatchArgs,
                      const std::array<uint8_t, 32>& hmac) {
    KeyEvent traced;
    traced.initialize(e.id, e.deviceId, e.source, e.displayId, hmac, e.action,
                      dispatchArgs.resolvedFlags, e.keyCode, e.scanCode, e.metaState, e.repeatCount,
                      e.downTime, e.eventTime);
    return traced;
}

} // namespace

// --- VerifyingTrace ---
@@ -55,6 +79,7 @@ void VerifyingTrace::verifyExpectedEventsTraced() {
    std::unique_lock lock(mLock);
    base::ScopedLockAssertion assumeLocked(mLock);

    // Poll for all expected events to be traced, and keep track of the latest poll result.
    base::Result<void> result;
    mEventTracedCondition.wait_for(lock, TRACE_TIMEOUT, [&]() REQUIRES(mLock) {
        for (const auto& [expectedEvent, windowId] : mExpectedEvents) {
@@ -101,12 +126,39 @@ base::Result<void> VerifyingTrace::verifyEventTraced(const Event& expectedEvent,
                         });
    if (tracedDispatchesIt == mTracedWindowDispatches.end()) {
        msg << "Expected dispatch of event with ID 0x" << std::hex << expectedEvent.getId()
            << " to window with ID 0x" << expectedWindowId << " to be traced, but it was not."
            << "\nExpected event: " << expectedEvent;
            << " to window with ID 0x" << expectedWindowId << " to be traced, but it was not.\n"
            << "Expected event: " << expectedEvent;
        return error(msg);
    }

    // Verify that the traced event matches the expected event exactly.
    return std::visit(
            [&](const auto& traced) -> base::Result<void> {
                Event tracedEvent;
                using T = std::decay_t<decltype(traced)>;
                if constexpr (std::is_same_v<Event, MotionEvent> &&
                              std::is_same_v<T, trace::TracedMotionEvent>) {
                    tracedEvent =
                            toInputEvent(traced, *tracedDispatchesIt, expectedEvent.getHmac());
                } else if constexpr (std::is_same_v<Event, KeyEvent> &&
                                     std::is_same_v<T, trace::TracedKeyEvent>) {
                    tracedEvent =
                            toInputEvent(traced, *tracedDispatchesIt, expectedEvent.getHmac());
                } else {
                    msg << "Received the wrong event type!\n"
                        << "Expected event: " << expectedEvent;
                    return error(msg);
                }

                const auto result = testing::internal::CmpHelperEQ("expectedEvent", "tracedEvent",
                                                                   expectedEvent, tracedEvent);
                if (!result) {
                    msg << result.failure_message();
                    return error(msg);
                }
                return {};
            },
            tracedEventsIt->second);
}

// --- FakeInputTracingBackend ---
@@ -114,7 +166,7 @@ base::Result<void> VerifyingTrace::verifyEventTraced(const Event& expectedEvent,
void FakeInputTracingBackend::traceKeyEvent(const trace::TracedKeyEvent& event) const {
    {
        std::scoped_lock lock(mTrace->mLock);
        mTrace->mTracedEvents.emplace(event.id);
        mTrace->mTracedEvents.emplace(event.id, event);
    }
    mTrace->mEventTracedCondition.notify_all();
}
@@ -122,7 +174,7 @@ void FakeInputTracingBackend::traceKeyEvent(const trace::TracedKeyEvent& event)
void FakeInputTracingBackend::traceMotionEvent(const trace::TracedMotionEvent& event) const {
    {
        std::scoped_lock lock(mTrace->mLock);
        mTrace->mTracedEvents.emplace(event.id);
        mTrace->mTracedEvents.emplace(event.id, event);
    }
    mTrace->mEventTracedCondition.notify_all();
}
+2 −2
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
#include <condition_variable>
#include <memory>
#include <mutex>
#include <unordered_set>
#include <unordered_map>
#include <vector>

namespace android::inputdispatcher {
@@ -58,7 +58,7 @@ public:
private:
    std::mutex mLock;
    std::condition_variable mEventTracedCondition;
    std::unordered_set<uint32_t /*eventId*/> mTracedEvents GUARDED_BY(mLock);
    std::unordered_map<uint32_t /*eventId*/, trace::TracedEvent> mTracedEvents GUARDED_BY(mLock);
    using WindowDispatchArgs = trace::InputTracingBackendInterface::WindowDispatchArgs;
    std::vector<WindowDispatchArgs> mTracedWindowDispatches GUARDED_BY(mLock);
    std::vector<std::pair<std::variant<KeyEvent, MotionEvent>, int32_t /*windowId*/>>