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

Commit b8278d9b authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Add event ID generator. am: bd25f1ca am: 2cb0a6eb am: d0ba60b9

Change-Id: I74771805612b5e24f5205b824d073002f0db62ce
parents 219643ee d0ba60b9
Loading
Loading
Loading
Loading
+32 −0
Original line number Original line Diff line number Diff line
@@ -265,6 +265,38 @@ enum class MotionClassification : uint8_t {
 */
 */
const char* motionClassificationToString(MotionClassification classification);
const char* motionClassificationToString(MotionClassification classification);


/**
 * Generator of unique numbers used to identify input events.
 *
 * Layout of ID:
 *     |--------------------------|---------------------------|
 *     |   2 bits for source      | 30 bits for random number |
 *     |--------------------------|---------------------------|
 */
class IdGenerator {
private:
    static constexpr uint32_t SOURCE_SHIFT = 30;

public:
    // Used to divide integer space to ensure no conflict among these sources./
    enum class Source : int32_t {
        INPUT_READER = 0x0 << SOURCE_SHIFT,
        INPUT_DISPATCHER = 0x1 << SOURCE_SHIFT,
        OTHER = 0x3 << SOURCE_SHIFT, // E.g. app injected events
    };
    IdGenerator(Source source);

    int32_t nextId() const;

    // Extract source from given id.
    static inline Source getSource(int32_t id) { return static_cast<Source>(SOURCE_MASK & id); }

private:
    const Source mSource;

    static constexpr int32_t SOURCE_MASK = 0x3 << SOURCE_SHIFT;
};

/**
/**
 * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't
 * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't
 * use it for direct comparison with any other value, because NaN isn't equal to itself according to
 * use it for direct comparison with any other value, because NaN isn't equal to itself according to
+29 −0
Original line number Original line Diff line number Diff line
@@ -17,7 +17,9 @@
#define LOG_TAG "Input"
#define LOG_TAG "Input"
//#define LOG_NDEBUG 0
//#define LOG_NDEBUG 0


#include <cutils/compiler.h>
#include <limits.h>
#include <limits.h>
#include <string.h>


#include <input/Input.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/InputDevice.h>
@@ -25,6 +27,7 @@


#ifdef __ANDROID__
#ifdef __ANDROID__
#include <binder/Parcel.h>
#include <binder/Parcel.h>
#include <sys/random.h>
#endif
#endif


namespace android {
namespace android {
@@ -40,6 +43,32 @@ const char* motionClassificationToString(MotionClassification classification) {
    }
    }
}
}


// --- IdGenerator ---
IdGenerator::IdGenerator(Source source) : mSource(source) {}

int32_t IdGenerator::nextId() const {
    constexpr uint32_t SEQUENCE_NUMBER_MASK = ~SOURCE_MASK;
    int32_t id = 0;

// Avoid building against syscall getrandom(2) on host, which will fail build on Mac. Host doesn't
// use sequence number so just always return mSource.
#ifdef __ANDROID__
    constexpr size_t BUF_LEN = sizeof(id);
    size_t totalBytes = 0;
    while (totalBytes < BUF_LEN) {
        ssize_t bytes = TEMP_FAILURE_RETRY(getrandom(&id, BUF_LEN, GRND_NONBLOCK));
        if (CC_UNLIKELY(bytes < 0)) {
            ALOGW("Failed to fill in random number for sequence number: %s.", strerror(errno));
            id = 0;
            break;
        }
        totalBytes += bytes;
    }
#endif // __ANDROID__

    return (id & SEQUENCE_NUMBER_MASK) | static_cast<int32_t>(mSource);
}

// --- InputEvent ---
// --- InputEvent ---


const char* inputEventTypeToString(int32_t type) {
const char* inputEventTypeToString(int32_t type) {
+1 −0
Original line number Original line Diff line number Diff line
@@ -2,6 +2,7 @@
cc_test {
cc_test {
    name: "libinput_tests",
    name: "libinput_tests",
    srcs: [
    srcs: [
        "IdGenerator_test.cpp",
        "InputChannel_test.cpp",
        "InputChannel_test.cpp",
        "InputDevice_test.cpp",
        "InputDevice_test.cpp",
        "InputEvent_test.cpp",
        "InputEvent_test.cpp",
+52 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>
#include <input/Input.h>
#include <ios>
#include <memory>
#include <unordered_set>

namespace android::test {

class IdGeneratorTest : public testing::TestWithParam<IdGenerator::Source> {
protected:
    void SetUp() override { mGenerator.reset(new IdGenerator(GetParam())); }

    std::unique_ptr<IdGenerator> mGenerator;
};

TEST_P(IdGeneratorTest, GenerateRandomNumber) {
    for (int i = 0; i < 500; ++i) {
        mGenerator->nextId();
    }
}

TEST_P(IdGeneratorTest, GenerateRandomNumberWithProperFlag) {
    for (int i = 0; i < 500; ++i) {
        int32_t id = mGenerator->nextId();
        IdGenerator::Source source = IdGenerator::getSource(id);
        EXPECT_EQ(source, GetParam())
                << std::hex << "Generator generated a value with wrong source. Value: 0x" << id
                << " Source: 0x" << static_cast<int32_t>(source);
    }
}

INSTANTIATE_TEST_SUITE_P(SourceInstantiation, IdGeneratorTest,
                         testing::Values(IdGenerator::Source::INPUT_READER,
                                         IdGenerator::Source::INPUT_DISPATCHER,
                                         IdGenerator::Source::OTHER));
} // namespace android::test