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

Commit 6b5fbc58 authored by Harry Cutts's avatar Harry Cutts
Browse files

inputflinger_tests: Put `FakeInputReaderPolicy` in its own file

I would like to be able to put automated tests for the new
`TouchpadEventMapper` in their own file, rather than
InputReader_tests.cpp. To do this I'll need some of the test utilities
in their own files, too.

Bug: 251196347
Test: atest inputflinger_tests
Change-Id: Ibbe27ced5adec2186decd8fb1c359b8ed4cbf870
parent b57f170f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ cc_test {
        "BlockingQueue_test.cpp",
        "EventHub_test.cpp",
        "FakeEventHub.cpp",
        "FakeInputReaderPolicy.cpp",
        "FakePointerController.cpp",
        "FocusResolver_test.cpp",
        "InputProcessor_test.cpp",
+237 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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 "FakeInputReaderPolicy.h"

#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>

#include "TestConstants.h"

namespace android {

void FakeInputReaderPolicy::assertInputDevicesChanged() {
    waitForInputDevices([](bool devicesChanged) {
        if (!devicesChanged) {
            FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called.";
        }
    });
}

void FakeInputReaderPolicy::assertInputDevicesNotChanged() {
    waitForInputDevices([](bool devicesChanged) {
        if (devicesChanged) {
            FAIL() << "Expected notifyInputDevicesChanged() to not be called.";
        }
    });
}

void FakeInputReaderPolicy::assertStylusGestureNotified(int32_t deviceId) {
    std::scoped_lock lock(mLock);
    ASSERT_TRUE(mStylusGestureNotified);
    ASSERT_EQ(deviceId, *mStylusGestureNotified);
    mStylusGestureNotified.reset();
}

void FakeInputReaderPolicy::assertStylusGestureNotNotified() {
    std::scoped_lock lock(mLock);
    ASSERT_FALSE(mStylusGestureNotified);
}

void FakeInputReaderPolicy::clearViewports() {
    mViewports.clear();
    mConfig.setDisplayViewports(mViewports);
}

std::optional<DisplayViewport> FakeInputReaderPolicy::getDisplayViewportByUniqueId(
        const std::string& uniqueId) const {
    return mConfig.getDisplayViewportByUniqueId(uniqueId);
}
std::optional<DisplayViewport> FakeInputReaderPolicy::getDisplayViewportByType(
        ViewportType type) const {
    return mConfig.getDisplayViewportByType(type);
}

std::optional<DisplayViewport> FakeInputReaderPolicy::getDisplayViewportByPort(
        uint8_t displayPort) const {
    return mConfig.getDisplayViewportByPort(displayPort);
}

void FakeInputReaderPolicy::addDisplayViewport(DisplayViewport viewport) {
    mViewports.push_back(std::move(viewport));
    mConfig.setDisplayViewports(mViewports);
}

void FakeInputReaderPolicy::addDisplayViewport(int32_t displayId, int32_t width, int32_t height,
                                               int32_t orientation, bool isActive,
                                               const std::string& uniqueId,
                                               std::optional<uint8_t> physicalPort,
                                               ViewportType type) {
    const bool isRotated =
            (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
    DisplayViewport v;
    v.displayId = displayId;
    v.orientation = orientation;
    v.logicalLeft = 0;
    v.logicalTop = 0;
    v.logicalRight = isRotated ? height : width;
    v.logicalBottom = isRotated ? width : height;
    v.physicalLeft = 0;
    v.physicalTop = 0;
    v.physicalRight = isRotated ? height : width;
    v.physicalBottom = isRotated ? width : height;
    v.deviceWidth = isRotated ? height : width;
    v.deviceHeight = isRotated ? width : height;
    v.isActive = isActive;
    v.uniqueId = uniqueId;
    v.physicalPort = physicalPort;
    v.type = type;

    addDisplayViewport(v);
}

bool FakeInputReaderPolicy::updateViewport(const DisplayViewport& viewport) {
    size_t count = mViewports.size();
    for (size_t i = 0; i < count; i++) {
        const DisplayViewport& currentViewport = mViewports[i];
        if (currentViewport.displayId == viewport.displayId) {
            mViewports[i] = viewport;
            mConfig.setDisplayViewports(mViewports);
            return true;
        }
    }
    // no viewport found.
    return false;
}

void FakeInputReaderPolicy::addExcludedDeviceName(const std::string& deviceName) {
    mConfig.excludedDeviceNames.push_back(deviceName);
}

void FakeInputReaderPolicy::addInputPortAssociation(const std::string& inputPort,
                                                    uint8_t displayPort) {
    mConfig.portAssociations.insert({inputPort, displayPort});
}

void FakeInputReaderPolicy::addInputUniqueIdAssociation(const std::string& inputUniqueId,
                                                        const std::string& displayUniqueId) {
    mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
}

void FakeInputReaderPolicy::addDisabledDevice(int32_t deviceId) {
    mConfig.disabledDevices.insert(deviceId);
}

void FakeInputReaderPolicy::removeDisabledDevice(int32_t deviceId) {
    mConfig.disabledDevices.erase(deviceId);
}

void FakeInputReaderPolicy::setPointerController(
        std::shared_ptr<FakePointerController> controller) {
    mPointerController = std::move(controller);
}

const InputReaderConfiguration* FakeInputReaderPolicy::getReaderConfiguration() const {
    return &mConfig;
}

const std::vector<InputDeviceInfo>& FakeInputReaderPolicy::getInputDevices() const {
    return mInputDevices;
}

TouchAffineTransformation FakeInputReaderPolicy::getTouchAffineTransformation(
        const std::string& inputDeviceDescriptor, int32_t surfaceRotation) {
    return transform;
}

void FakeInputReaderPolicy::setTouchAffineTransformation(const TouchAffineTransformation t) {
    transform = t;
}

PointerCaptureRequest FakeInputReaderPolicy::setPointerCapture(bool enabled) {
    mConfig.pointerCaptureRequest = {enabled, mNextPointerCaptureSequenceNumber++};
    return mConfig.pointerCaptureRequest;
}

void FakeInputReaderPolicy::setShowTouches(bool enabled) {
    mConfig.showTouches = enabled;
}

void FakeInputReaderPolicy::setDefaultPointerDisplayId(int32_t pointerDisplayId) {
    mConfig.defaultPointerDisplayId = pointerDisplayId;
}

void FakeInputReaderPolicy::setPointerGestureEnabled(bool enabled) {
    mConfig.pointerGesturesEnabled = enabled;
}

float FakeInputReaderPolicy::getPointerGestureMovementSpeedRatio() {
    return mConfig.pointerGestureMovementSpeedRatio;
}

float FakeInputReaderPolicy::getPointerGestureZoomSpeedRatio() {
    return mConfig.pointerGestureZoomSpeedRatio;
}

void FakeInputReaderPolicy::setVelocityControlParams(const VelocityControlParameters& params) {
    mConfig.pointerVelocityControlParameters = params;
    mConfig.wheelVelocityControlParameters = params;
}

void FakeInputReaderPolicy::getReaderConfiguration(InputReaderConfiguration* outConfig) {
    *outConfig = mConfig;
}

std::shared_ptr<PointerControllerInterface> FakeInputReaderPolicy::obtainPointerController(
        int32_t /*deviceId*/) {
    return mPointerController;
}

void FakeInputReaderPolicy::notifyInputDevicesChanged(
        const std::vector<InputDeviceInfo>& inputDevices) {
    std::scoped_lock<std::mutex> lock(mLock);
    mInputDevices = inputDevices;
    mInputDevicesChanged = true;
    mDevicesChangedCondition.notify_all();
}

std::shared_ptr<KeyCharacterMap> FakeInputReaderPolicy::getKeyboardLayoutOverlay(
        const InputDeviceIdentifier&) {
    return nullptr;
}

std::string FakeInputReaderPolicy::getDeviceAlias(const InputDeviceIdentifier&) {
    return "";
}

void FakeInputReaderPolicy::waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
    std::unique_lock<std::mutex> lock(mLock);
    base::ScopedLockAssertion assumeLocked(mLock);

    const bool devicesChanged =
            mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
                return mInputDevicesChanged;
            });
    ASSERT_NO_FATAL_FAILURE(processDevicesChanged(devicesChanged));
    mInputDevicesChanged = false;
}

void FakeInputReaderPolicy::notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) {
    std::scoped_lock<std::mutex> lock(mLock);
    mStylusGestureNotified = deviceId;
}

} // namespace android
+101 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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 <condition_variable>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <vector>

#include <InputDevice.h>
#include <InputReaderBase.h>

#include "FakePointerController.h"
#include "input/DisplayViewport.h"
#include "input/InputDevice.h"

namespace android {

class FakeInputReaderPolicy : public InputReaderPolicyInterface {
protected:
    virtual ~FakeInputReaderPolicy() {}

public:
    FakeInputReaderPolicy() {}

    void assertInputDevicesChanged();
    void assertInputDevicesNotChanged();
    void assertStylusGestureNotified(int32_t deviceId);
    void assertStylusGestureNotNotified();

    virtual void clearViewports();
    std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const;
    std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
    std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const;
    void addDisplayViewport(DisplayViewport viewport);
    void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
                            bool isActive, const std::string& uniqueId,
                            std::optional<uint8_t> physicalPort, ViewportType type);
    bool updateViewport(const DisplayViewport& viewport);
    void addExcludedDeviceName(const std::string& deviceName);
    void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort);
    void addInputUniqueIdAssociation(const std::string& inputUniqueId,
                                     const std::string& displayUniqueId);
    void addDisabledDevice(int32_t deviceId);
    void removeDisabledDevice(int32_t deviceId);
    void setPointerController(std::shared_ptr<FakePointerController> controller);
    const InputReaderConfiguration* getReaderConfiguration() const;
    const std::vector<InputDeviceInfo>& getInputDevices() const;
    TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
                                                           int32_t surfaceRotation);
    void setTouchAffineTransformation(const TouchAffineTransformation t);
    PointerCaptureRequest setPointerCapture(bool enabled);
    void setShowTouches(bool enabled);
    void setDefaultPointerDisplayId(int32_t pointerDisplayId);
    void setPointerGestureEnabled(bool enabled);
    float getPointerGestureMovementSpeedRatio();
    float getPointerGestureZoomSpeedRatio();
    void setVelocityControlParams(const VelocityControlParameters& params);

private:
    void getReaderConfiguration(InputReaderConfiguration* outConfig) override;
    std::shared_ptr<PointerControllerInterface> obtainPointerController(
            int32_t /*deviceId*/) override;
    void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override;
    std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
            const InputDeviceIdentifier&) override;
    std::string getDeviceAlias(const InputDeviceIdentifier&) override;
    void waitForInputDevices(std::function<void(bool)> processDevicesChanged);
    void notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) override;

    std::mutex mLock;
    std::condition_variable mDevicesChangedCondition;

    InputReaderConfiguration mConfig;
    std::shared_ptr<FakePointerController> mPointerController;
    std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
    bool mInputDevicesChanged GUARDED_BY(mLock){false};
    std::vector<DisplayViewport> mViewports;
    TouchAffineTransformation transform;
    std::optional<int32_t /*deviceId*/> mStylusGestureNotified GUARDED_BY(mLock){};

    uint32_t mNextPointerCaptureSequenceNumber{0};
};

} // namespace android
+1 −216
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@

#include <thread>
#include "FakeEventHub.h"
#include "FakeInputReaderPolicy.h"
#include "FakePointerController.h"
#include "TestConstants.h"
#include "android/hardware/input/InputDeviceCountryCode.h"
@@ -149,222 +150,6 @@ static void assertAxisNotPresent(MultiTouchInputMapper& mapper, int axis) {
    }
}

// --- FakeInputReaderPolicy ---

class FakeInputReaderPolicy : public InputReaderPolicyInterface {
    std::mutex mLock;
    std::condition_variable mDevicesChangedCondition;

    InputReaderConfiguration mConfig;
    std::shared_ptr<FakePointerController> mPointerController;
    std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
    bool mInputDevicesChanged GUARDED_BY(mLock){false};
    std::vector<DisplayViewport> mViewports;
    TouchAffineTransformation transform;
    std::optional<int32_t /*deviceId*/> mStylusGestureNotified GUARDED_BY(mLock){};

protected:
    virtual ~FakeInputReaderPolicy() {}

public:
    FakeInputReaderPolicy() {
    }

    void assertInputDevicesChanged() {
        waitForInputDevices([](bool devicesChanged) {
            if (!devicesChanged) {
                FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called.";
            }
        });
    }

    void assertInputDevicesNotChanged() {
        waitForInputDevices([](bool devicesChanged) {
            if (devicesChanged) {
                FAIL() << "Expected notifyInputDevicesChanged() to not be called.";
            }
        });
    }

    void assertStylusGestureNotified(int32_t deviceId) {
        std::scoped_lock lock(mLock);
        ASSERT_TRUE(mStylusGestureNotified);
        ASSERT_EQ(deviceId, *mStylusGestureNotified);
        mStylusGestureNotified.reset();
    }

    void assertStylusGestureNotNotified() {
        std::scoped_lock lock(mLock);
        ASSERT_FALSE(mStylusGestureNotified);
    }

    virtual void clearViewports() {
        mViewports.clear();
        mConfig.setDisplayViewports(mViewports);
    }

    std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const {
        return mConfig.getDisplayViewportByUniqueId(uniqueId);
    }
    std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const {
        return mConfig.getDisplayViewportByType(type);
    }

    std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const {
        return mConfig.getDisplayViewportByPort(displayPort);
    }

    void addDisplayViewport(DisplayViewport viewport) {
        mViewports.push_back(std::move(viewport));
        mConfig.setDisplayViewports(mViewports);
    }

    void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
                            bool isActive, const std::string& uniqueId,
                            std::optional<uint8_t> physicalPort, ViewportType type) {
        const bool isRotated =
                (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
        DisplayViewport v;
        v.displayId = displayId;
        v.orientation = orientation;
        v.logicalLeft = 0;
        v.logicalTop = 0;
        v.logicalRight = isRotated ? height : width;
        v.logicalBottom = isRotated ? width : height;
        v.physicalLeft = 0;
        v.physicalTop = 0;
        v.physicalRight = isRotated ? height : width;
        v.physicalBottom = isRotated ? width : height;
        v.deviceWidth = isRotated ? height : width;
        v.deviceHeight = isRotated ? width : height;
        v.isActive = isActive;
        v.uniqueId = uniqueId;
        v.physicalPort = physicalPort;
        v.type = type;

        addDisplayViewport(v);
    }

    bool updateViewport(const DisplayViewport& viewport) {
        size_t count = mViewports.size();
        for (size_t i = 0; i < count; i++) {
            const DisplayViewport& currentViewport = mViewports[i];
            if (currentViewport.displayId == viewport.displayId) {
                mViewports[i] = viewport;
                mConfig.setDisplayViewports(mViewports);
                return true;
            }
        }
        // no viewport found.
        return false;
    }

    void addExcludedDeviceName(const std::string& deviceName) {
        mConfig.excludedDeviceNames.push_back(deviceName);
    }

    void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort) {
        mConfig.portAssociations.insert({inputPort, displayPort});
    }

    void addInputUniqueIdAssociation(const std::string& inputUniqueId,
                                     const std::string& displayUniqueId) {
        mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
    }

    void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }

    void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }

    void setPointerController(std::shared_ptr<FakePointerController> controller) {
        mPointerController = std::move(controller);
    }

    const InputReaderConfiguration* getReaderConfiguration() const {
        return &mConfig;
    }

    const std::vector<InputDeviceInfo>& getInputDevices() const {
        return mInputDevices;
    }

    TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
            int32_t surfaceRotation) {
        return transform;
    }

    void setTouchAffineTransformation(const TouchAffineTransformation t) {
        transform = t;
    }

    PointerCaptureRequest setPointerCapture(bool enabled) {
        mConfig.pointerCaptureRequest = {enabled, mNextPointerCaptureSequenceNumber++};
        return mConfig.pointerCaptureRequest;
    }

    void setShowTouches(bool enabled) {
        mConfig.showTouches = enabled;
    }

    void setDefaultPointerDisplayId(int32_t pointerDisplayId) {
        mConfig.defaultPointerDisplayId = pointerDisplayId;
    }

    void setPointerGestureEnabled(bool enabled) { mConfig.pointerGesturesEnabled = enabled; }

    float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }

    float getPointerGestureZoomSpeedRatio() { return mConfig.pointerGestureZoomSpeedRatio; }

    void setVelocityControlParams(const VelocityControlParameters& params) {
        mConfig.pointerVelocityControlParameters = params;
        mConfig.wheelVelocityControlParameters = params;
    }

private:
    uint32_t mNextPointerCaptureSequenceNumber = 0;

    void getReaderConfiguration(InputReaderConfiguration* outConfig) override {
        *outConfig = mConfig;
    }

    std::shared_ptr<PointerControllerInterface> obtainPointerController(
            int32_t /*deviceId*/) override {
        return mPointerController;
    }

    void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {
        std::scoped_lock<std::mutex> lock(mLock);
        mInputDevices = inputDevices;
        mInputDevicesChanged = true;
        mDevicesChangedCondition.notify_all();
    }

    std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
            const InputDeviceIdentifier&) override {
        return nullptr;
    }

    std::string getDeviceAlias(const InputDeviceIdentifier&) override { return ""; }

    void waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
        std::unique_lock<std::mutex> lock(mLock);
        base::ScopedLockAssertion assumeLocked(mLock);

        const bool devicesChanged =
                mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
                    return mInputDevicesChanged;
                });
        ASSERT_NO_FATAL_FAILURE(processDevicesChanged(devicesChanged));
        mInputDevicesChanged = false;
    }

    void notifyStylusGestureStarted(int32_t deviceId, nsecs_t eventTime) override {
        std::scoped_lock<std::mutex> lock(mLock);
        mStylusGestureNotified = deviceId;
    }
};

// --- FakeInputMapper ---

class FakeInputMapper : public InputMapper {