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

Commit 0174738c authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Add static_asserts for the size of InputMessage

Inside InputTransport.cpp, we are reading and writing InputMessages.
This is done in the following way:

read
::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);

write
::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);

We are sending a variable-length message across the socket, and
receiving a maximum of sizeof(InputMessage) when reading it.

In this CL, we are adding asserts on the _maximum_ length of the message
that we would send across the socket. Since we typically only have a few
pointers at most, while MAX_POINTERS=16, in reality the communication
between system_server and app will use much less data.

However, it's still useful to add these asserts to understand the
worst-case scenario of message transfer.

Bug: 167946763
Test: m StructLayout_test
Change-Id: I281ecea62b392dea56936d031ab9c4ee18add93f
parent 93970282
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -164,7 +164,7 @@ enum {
 * (We want at least 10 but some touch controllers obstensibly configured for 10 pointers
 * will occasionally emit 11.  There is not much harm making this constant bigger.)
 */
#define MAX_POINTERS 16
static constexpr size_t MAX_POINTERS = 16;

/*
 * Maximum number of samples supported per motion event.
+0 −18
Original line number Diff line number Diff line
@@ -500,24 +500,6 @@ public:
    status_t sendTimeline(int32_t inputEventId,
                          std::array<nsecs_t, GraphicsTimeline::SIZE> timeline);

    /* Returns true if there is a deferred event waiting.
     *
     * Should be called after calling consume() to determine whether the consumer
     * has a deferred event to be processed.  Deferred events are somewhat special in
     * that they have already been removed from the input channel.  If the input channel
     * becomes empty, the client may need to do extra work to ensure that it processes
     * the deferred event despite the fact that the input channel's file descriptor
     * is not readable.
     *
     * One option is simply to call consume() in a loop until it returns WOULD_BLOCK.
     * This guarantees that all deferred events will be processed.
     *
     * Alternately, the caller can call hasDeferredEvent() to determine whether there is
     * a deferred event waiting and then ensure that its event loop wakes up at least
     * one more time to consume the deferred event.
     */
    bool hasDeferredEvent() const;

    /* Returns true if there is a pending batch.
     *
     * Should be called after calling consume() with consumeBatches == false to determine
+0 −4
Original line number Diff line number Diff line
@@ -1318,10 +1318,6 @@ status_t InputConsumer::sendUnchainedFinishedSignal(uint32_t seq, bool handled)
    return result;
}

bool InputConsumer::hasDeferredEvent() const {
    return mMsgDeferred;
}

bool InputConsumer::hasPendingBatch() const {
    return !mBatches.empty();
}
+33 −4
Original line number Diff line number Diff line
@@ -115,12 +115,9 @@ void TestHeaderSize() {
    static_assert(sizeof(InputMessage::Header) == 8);
}

/**
 * We cannot use the Body::size() method here because it is not static for
 * the Motion type, where "pointerCount" variable affects the size and can change at runtime.
 */
void TestBodySize() {
    static_assert(sizeof(InputMessage::Body::Key) == 96);
    static_assert(sizeof(InputMessage::Body::Motion::Pointer) == 136);
    static_assert(sizeof(InputMessage::Body::Motion) ==
                  offsetof(InputMessage::Body::Motion, pointers) +
                          sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
@@ -132,6 +129,38 @@ void TestBodySize() {
    // Timeline
    static_assert(GraphicsTimeline::SIZE == 2);
    static_assert(sizeof(InputMessage::Body::Timeline) == 24);

    /**
     * We cannot use the Body::size() method here because it is not static for
     * the Motion type, where "pointerCount" variable affects the size and can change at runtime.
     */
    static_assert(sizeof(InputMessage::Body) ==
                  offsetof(InputMessage::Body::Motion, pointers) +
                          sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
    static_assert(sizeof(InputMessage::Body) == 160 + 136 * 16);
    static_assert(sizeof(InputMessage::Body) == 2336);
}

/**
 * In general, we are sending a variable-length message across the socket, because the number of
 * pointers varies. When we receive the message, we still need to allocate enough memory for the
 * entire InputMessage struct. This size is, therefore, the worst case scenario. However, it is
 * still helpful to compute to get an idea of the sizes that are involved.
 */
void TestWorstCaseInputMessageSize() {
    static_assert(sizeof(InputMessage) == /*header*/ 8 + /*body*/ 2336);
    static_assert(sizeof(InputMessage) == 2344);
}

/**
 * Assuming a single pointer, how big is the message that we are sending across the socket?
 */
void CalculateSinglePointerInputMessageSize() {
    constexpr size_t pointerCount = 1;
    constexpr size_t bodySize = offsetof(InputMessage::Body::Motion, pointers) +
            sizeof(InputMessage::Body::Motion::Pointer) * pointerCount;
    static_assert(bodySize == 160 + 136);
    static_assert(bodySize == 296); // For the total message size, add the small header
}

// --- VerifiedInputEvent ---
+1 −1
Original line number Diff line number Diff line
@@ -215,7 +215,7 @@ bool validateMotionEvent(int32_t action, int32_t actionButton, size_t pointerCou
        return false;
    }
    if (pointerCount < 1 || pointerCount > MAX_POINTERS) {
        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %d.",
        ALOGE("Motion event has invalid pointer count %zu; value must be between 1 and %zu.",
              pointerCount, MAX_POINTERS);
        return false;
    }
Loading