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

Commit e2bb1873 authored by Paul Ramirez's avatar Paul Ramirez
Browse files

Create TestInputChannel and TestLooper to better test InputConsumerNoResampling

Created TestInputChannel and TestLooper to control how InputMessages are
batched in InputConsumerNoResampling_test

Bug: 297226446
Flag: EXEMPT refactor
Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST --gtest_filter="InputConsumerTest*"
Change-Id: I036593b311a93ec301e8b9776b461505e853119f
parent 81ba7fb7
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <input/InputTransport.h>
#include <input/LooperInterface.h>
#include <input/Resampler.h>
#include <utils/Looper.h>

@@ -65,6 +66,16 @@ public:
 */
class InputConsumerNoResampling final {
public:
    /**
     * This constructor is exclusively for test code. Any real use of InputConsumerNoResampling must
     * use the constructor that takes an sp<Looper> parameter instead of
     * std::shared_ptr<LooperInterface>.
     */
    explicit InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
                                       std::shared_ptr<LooperInterface> looper,
                                       InputConsumerCallbacks& callbacks,
                                       std::unique_ptr<Resampler> resampler);

    /**
     * @param callbacks are used to interact with InputConsumerNoResampling. They're called whenever
     * the event is ready to consume.
@@ -108,7 +119,7 @@ public:

private:
    std::shared_ptr<InputChannel> mChannel;
    sp<Looper> mLooper;
    std::shared_ptr<LooperInterface> mLooper;
    InputConsumerCallbacks& mCallbacks;
    std::unique_ptr<Resampler> mResampler;

+6 −5
Original line number Diff line number Diff line
@@ -263,7 +263,7 @@ public:
     * Return DEAD_OBJECT if the channel's peer has been closed.
     * Other errors probably indicate that the channel is broken.
     */
    status_t sendMessage(const InputMessage* msg);
    virtual status_t sendMessage(const InputMessage* msg);

    /* Receive a message sent by the other endpoint.
     *
@@ -275,14 +275,14 @@ public:
     * Return DEAD_OBJECT if the channel's peer has been closed.
     * Other errors probably indicate that the channel is broken.
     */
    android::base::Result<InputMessage> receiveMessage();
    virtual android::base::Result<InputMessage> receiveMessage();

    /* Tells whether there is a message in the channel available to be received.
     *
     * This is only a performance hint and may return false negative results. Clients should not
     * rely on availability of the message based on the return value.
     */
    bool probablyHasInput() const;
    virtual bool probablyHasInput() const;

    /* Wait until there is a message in the channel.
     *
@@ -323,11 +323,12 @@ public:
     */
    sp<IBinder> getConnectionToken() const;

protected:
    InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token);

private:
    static std::unique_ptr<InputChannel> create(const std::string& name,
                                                android::base::unique_fd fd, sp<IBinder> token);

    InputChannel(const std::string name, android::base::unique_fd fd, sp<IBinder> token);
};

/*
+39 −0
Original line number Diff line number Diff line
/**
 * Copyright 2024 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.
 */

#pragma once

#include <utils/Looper.h>
#include <utils/StrongPointer.h>

namespace android {

/**
 * LooperInterface allows the use of TestLooper in InputConsumerNoResampling without reassigning to
 * Looper. LooperInterface is needed to control how InputConsumerNoResampling consumes and batches
 * InputMessages.
 */
class LooperInterface {
public:
    virtual ~LooperInterface() = default;

    virtual int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback,
                      void* data) = 0;
    virtual int removeFd(int fd) = 0;

    virtual sp<Looper> getLooper() const = 0;
};
} // namespace android
+34 −10
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

#define LOG_TAG "InputTransport"
#define LOG_TAG "InputConsumerNoResampling"
#define ATRACE_TAG ATRACE_TAG_INPUT

#include <chrono>
@@ -33,8 +33,6 @@
#include <input/PrintTools.h>
#include <input/TraceTools.h>

namespace input_flags = com::android::input::flags;

namespace android {

namespace {
@@ -46,6 +44,27 @@ namespace {
const bool DEBUG_TRANSPORT_CONSUMER =
        __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Consumer", ANDROID_LOG_INFO);

/**
 * RealLooper is a wrapper of Looper. All the member functions exclusively call the internal looper.
 * This class' behavior is the same as Looper.
 */
class RealLooper final : public LooperInterface {
public:
    RealLooper(sp<Looper> looper) : mLooper{looper} {}

    int addFd(int fd, int ident, int events, const sp<LooperCallback>& callback,
              void* data) override {
        return mLooper->addFd(fd, ident, events, callback, data);
    }

    int removeFd(int fd) override { return mLooper->removeFd(fd); }

    sp<Looper> getLooper() const override { return mLooper; }

private:
    sp<Looper> mLooper;
};

std::unique_ptr<KeyEvent> createKeyEvent(const InputMessage& msg) {
    std::unique_ptr<KeyEvent> event = std::make_unique<KeyEvent>();
    event->initialize(msg.body.key.eventId, msg.body.key.deviceId, msg.body.key.source,
@@ -173,22 +192,20 @@ InputMessage createTimelineMessage(int32_t inputEventId, nsecs_t gpuCompletedTim
bool isPointerEvent(const MotionEvent& motionEvent) {
    return (motionEvent.getSource() & AINPUT_SOURCE_CLASS_POINTER) == AINPUT_SOURCE_CLASS_POINTER;
}

} // namespace

using android::base::Result;
using android::base::StringPrintf;

// --- InputConsumerNoResampling ---

InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
                                                     sp<Looper> looper,
                                                     std::shared_ptr<LooperInterface> looper,
                                                     InputConsumerCallbacks& callbacks,
                                                     std::unique_ptr<Resampler> resampler)
      : mChannel(channel),
        mLooper(looper),
      : mChannel{channel},
        mLooper{looper},
        mCallbacks(callbacks),
        mResampler(std::move(resampler)),
        mResampler{std::move(resampler)},
        mFdEvents(0) {
    LOG_ALWAYS_FATAL_IF(mLooper == nullptr);
    mCallback = sp<LooperEventCallback>::make(
@@ -199,6 +216,13 @@ InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<Input
    setFdEvents(ALOOPER_EVENT_INPUT);
}

InputConsumerNoResampling::InputConsumerNoResampling(const std::shared_ptr<InputChannel>& channel,
                                                     sp<Looper> looper,
                                                     InputConsumerCallbacks& callbacks,
                                                     std::unique_ptr<Resampler> resampler)
      : InputConsumerNoResampling(channel, std::make_shared<RealLooper>(looper), callbacks,
                                  std::move(resampler)) {}

InputConsumerNoResampling::~InputConsumerNoResampling() {
    ensureCalledOnLooperThread(__func__);
    consumeBatchedInputEvents(std::nullopt);
@@ -513,7 +537,7 @@ bool InputConsumerNoResampling::consumeBatchedInputEvents(

void InputConsumerNoResampling::ensureCalledOnLooperThread(const char* func) const {
    sp<Looper> callingThreadLooper = Looper::getForThread();
    if (callingThreadLooper != mLooper) {
    if (callingThreadLooper != mLooper->getLooper()) {
        LOG(FATAL) << "The function " << func << " can only be called on the looper thread";
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ cc_test {
        "BlockingQueue_test.cpp",
        "IdGenerator_test.cpp",
        "InputChannel_test.cpp",
        "InputConsumer_test.cpp",
        "InputDevice_test.cpp",
        "InputEvent_test.cpp",
        "InputPublisherAndConsumer_test.cpp",
@@ -25,6 +26,8 @@ cc_test {
        "MotionPredictorMetricsManager_test.cpp",
        "Resampler_test.cpp",
        "RingBuffer_test.cpp",
        "TestInputChannel.cpp",
        "TestLooper.cpp",
        "TfLiteMotionPredictor_test.cpp",
        "TouchResampling_test.cpp",
        "TouchVideoFrame_test.cpp",
Loading