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

Commit 8158e7e3 authored by Siarhei Vishniakou's avatar Siarhei Vishniakou Committed by Arthur Hung
Browse files

Add physical port to display viewport

DisplayViewport now also stores the physical port information of the
associated display.
The physical port of the display can be used to match an input device to
the corresponding viewport, therefore ensuring that a specific input
device generates events that go to a particular display.

The associations are provided to InputReaderConfiguration by the JNI
callback.

Change getViewport strategy once more. Now, uniqueId match by itself is
sufficient (viewport type does not need to match if the viewport with
the matching uniqueId is found).
Added a check for assumptions about the number of viewports that can
have the same type. These should be relaxed once (and if) support for
multiple internal viewports is added.

Bug: 116239493
Test: atest -a libinput_tests inputflinger_tests
Change-Id: I1c84f281e8c255f12aea0d15939c70685fe94c41
parent 5363caaf
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@
#include <android-base/stringprintf.h>
#include <ui/DisplayInfo.h>
#include <input/Input.h>
#include <inttypes.h>
#include <optional>

using android::base::StringPrintf;

@@ -66,13 +68,17 @@ struct DisplayViewport {
    int32_t deviceWidth;
    int32_t deviceHeight;
    std::string uniqueId;
    // The actual (hardware) port that the associated display is connected to.
    // Not all viewports will have this specified.
    std::optional<uint8_t> physicalPort;
    ViewportType type;

    DisplayViewport() :
            displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0),
            logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0),
            physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0),
            deviceWidth(0), deviceHeight(0), uniqueId(), type(ViewportType::VIEWPORT_INTERNAL) {
            deviceWidth(0), deviceHeight(0), uniqueId(), physicalPort(std::nullopt),
            type(ViewportType::VIEWPORT_INTERNAL) {
    }

    bool operator==(const DisplayViewport& other) const {
@@ -89,6 +95,7 @@ struct DisplayViewport {
                && deviceWidth == other.deviceWidth
                && deviceHeight == other.deviceHeight
                && uniqueId == other.uniqueId
                && physicalPort == other.physicalPort
                && type == other.type;
    }

@@ -114,16 +121,19 @@ struct DisplayViewport {
        deviceWidth = width;
        deviceHeight = height;
        uniqueId.clear();
        physicalPort = std::nullopt;
        type = ViewportType::VIEWPORT_INTERNAL;
    }

    std::string toString() const {
        return StringPrintf("Viewport %s: displayId=%d, orientation=%d, "
        return StringPrintf("Viewport %s: displayId=%d, uniqueId=%s, port=%s, orientation=%d, "
            "logicalFrame=[%d, %d, %d, %d], "
            "physicalFrame=[%d, %d, %d, %d], "
            "deviceSize=[%d, %d]",
            viewportTypeToString(type),
            displayId, orientation,
            viewportTypeToString(type), displayId,
            uniqueId.c_str(),
            physicalPort ? StringPrintf("%" PRIu8, *physicalPort).c_str() : "<none>",
            orientation,
            logicalLeft, logicalTop,
            logicalRight, logicalBottom,
            physicalLeft, physicalTop,
+83 −37
Original line number Diff line number Diff line
@@ -991,6 +991,12 @@ void InputDevice::dump(std::string& dump) {
            deviceInfo.getDisplayName().c_str());
    dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
    dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
    dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
    if (mAssociatedDisplayPort) {
        dump += StringPrintf("%" PRIu8 "\n", *mAssociatedDisplayPort);
    } else {
        dump += "<none>\n";
    }
    dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
    dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
    dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
@@ -1060,6 +1066,20 @@ void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config
            setEnabled(enabled, when);
        }

        if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
             // In most situations, no port will be specified.
            mAssociatedDisplayPort = std::nullopt;
            // Find the display port that corresponds to the current input port.
            const std::string& inputPort = mIdentifier.location;
            if (!inputPort.empty()) {
                const std::unordered_map<std::string, uint8_t>& ports = config->portAssociations;
                const auto& displayPort = ports.find(inputPort);
                if (displayPort != ports.end()) {
                    mAssociatedDisplayPort = std::make_optional(displayPort->second);
                }
            }
        }

        size_t numMappers = mMappers.size();
        for (size_t i = 0; i < numMappers; i++) {
            InputMapper* mapper = mMappers[i];
@@ -2203,7 +2223,7 @@ void KeyboardInputMapper::configure(nsecs_t when,

    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
        if (mParameters.orientationAware) {
            mViewport = config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "");
            mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
        }
    }
}
@@ -2613,7 +2633,7 @@ void CursorInputMapper::configure(nsecs_t when,
        mOrientation = DISPLAY_ORIENTATION_0;
        if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
            std::optional<DisplayViewport> internalViewport =
                    config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "");
                    config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
            if (internalViewport) {
                mOrientation = internalViewport->orientation;
            }
@@ -2929,7 +2949,7 @@ void RotaryEncoderInputMapper::configure(nsecs_t when,
    }
    if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
        std::optional<DisplayViewport> internalViewport =
                config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, "");
                config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
        if (internalViewport) {
            mOrientation = internalViewport->orientation;
        } else {
@@ -3310,6 +3330,9 @@ void TouchInputMapper::configureParameters() {
            mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
        }
    }
    if (getDevice()->getAssociatedDisplayPort()) {
        mParameters.hasAssociatedDisplay = true;
    }

    // Initial downs on external touch devices should wake the device.
    // Normally we don't do this for internal touch screens to prevent them from waking
@@ -3384,6 +3407,49 @@ bool TouchInputMapper::hasExternalStylus() const {
    return mExternalStylusConnected;
}

/**
 * Determine which DisplayViewport to use.
 * 1. If display port is specified, return the matching viewport. If matching viewport not
 * found, then return.
 * 2. If a device has associated display, get the matching viewport by either unique id or by
 * the display type (internal or external).
 * 3. Otherwise, use a non-display viewport.
 */
std::optional<DisplayViewport> TouchInputMapper::findViewport() {
    if (mParameters.hasAssociatedDisplay) {
        const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
        if (displayPort) {
            // Find the viewport that contains the same port
            std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
            if (!v) {
                ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
                        "but the corresponding viewport is not found.",
                        getDeviceName().c_str(), *displayPort);
            }
            return v;
        }

        if (!mParameters.uniqueDisplayId.empty()) {
            return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
        }

        ViewportType viewportTypeToUse;
        if (mParameters.associatedDisplayIsExternal) {
            viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
        } else {
            viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
        }
        return mConfig.getDisplayViewportByType(viewportTypeToUse);
    }

    DisplayViewport newViewport;
    // Raw width and height in the natural orientation.
    int32_t rawWidth = mRawPointerAxes.getRawWidth();
    int32_t rawHeight = mRawPointerAxes.getRawHeight();
    newViewport.setNonDisplayViewport(rawWidth, rawHeight);
    return std::make_optional(newViewport);
}

void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
    int32_t oldDeviceMode = mDeviceMode;

@@ -3417,50 +3483,30 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {

    // Ensure we have valid X and Y axes.
    if (!mRawPointerAxes.x.valid || !mRawPointerAxes.y.valid) {
        ALOGW(INDENT "Touch device '%s' did not report support for X or Y axis!  "
        ALOGW("Touch device '%s' did not report support for X or Y axis!  "
                "The device will be inoperable.", getDeviceName().c_str());
        mDeviceMode = DEVICE_MODE_DISABLED;
        return;
    }

    // Raw width and height in the natural orientation.
    int32_t rawWidth = mRawPointerAxes.getRawWidth();
    int32_t rawHeight = mRawPointerAxes.getRawHeight();

    // Get associated display dimensions.
    DisplayViewport newViewport;
    if (mParameters.hasAssociatedDisplay) {
        std::string uniqueDisplayId;
        ViewportType viewportTypeToUse;

        if (mParameters.associatedDisplayIsExternal) {
            viewportTypeToUse = ViewportType::VIEWPORT_EXTERNAL;
        } else if (!mParameters.uniqueDisplayId.empty()) {
            // If the IDC file specified a unique display Id, then it expects to be linked to a
            // virtual display with the same unique ID.
            uniqueDisplayId = mParameters.uniqueDisplayId;
            viewportTypeToUse = ViewportType::VIEWPORT_VIRTUAL;
        } else {
            viewportTypeToUse = ViewportType::VIEWPORT_INTERNAL;
        }

        std::optional<DisplayViewport> viewportToUse =
                mConfig.getDisplayViewport(viewportTypeToUse, uniqueDisplayId);
        if (!viewportToUse) {
            ALOGI(INDENT "Touch device '%s' could not query the properties of its associated "
    std::optional<DisplayViewport> newViewport = findViewport();
    if (!newViewport) {
        ALOGI("Touch device '%s' could not query the properties of its associated "
                "display.  The device will be inoperable until the display size "
                "becomes available.",
                getDeviceName().c_str());
        mDeviceMode = DEVICE_MODE_DISABLED;
        return;
    }
        newViewport = *viewportToUse;
    } else {
        newViewport.setNonDisplayViewport(rawWidth, rawHeight);
    }
    bool viewportChanged = mViewport != newViewport;

    // Raw width and height in the natural orientation.
    int32_t rawWidth = mRawPointerAxes.getRawWidth();
    int32_t rawHeight = mRawPointerAxes.getRawHeight();

    bool viewportChanged = mViewport != *newViewport;
    if (viewportChanged) {
        mViewport = newViewport;
        mViewport = *newViewport;

        if (mDeviceMode == DEVICE_MODE_DIRECT || mDeviceMode == DEVICE_MODE_POINTER) {
            // Convert rotated viewport to natural surface coordinates.
+6 −0
Original line number Diff line number Diff line
@@ -252,6 +252,9 @@ public:

    inline bool isExternal() { return mIsExternal; }
    inline void setExternal(bool external) { mIsExternal = external; }
    inline std::optional<uint8_t> getAssociatedDisplayPort() const {
        return mAssociatedDisplayPort;
    }

    inline void setMic(bool hasMic) { mHasMic = hasMic; }
    inline bool hasMic() const { return mHasMic; }
@@ -324,6 +327,7 @@ private:

    uint32_t mSources;
    bool mIsExternal;
    std::optional<uint8_t> mAssociatedDisplayPort;
    bool mHasMic;
    bool mDropUntilNextSync;

@@ -1501,6 +1505,8 @@ private:
    VelocityControl mWheelXVelocityControl;
    VelocityControl mWheelYVelocityControl;

    std::optional<DisplayViewport> findViewport();

    void resetExternalStylus();
    void clearStylusDataPendingFlags();

+44 −7
Original line number Diff line number Diff line
@@ -49,14 +49,51 @@ bool InputReaderThread::threadLoop() {

// --- InputReaderConfiguration ---

std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewport(
        ViewportType viewportType, const std::string& uniqueDisplayId) const {
std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportByUniqueId(
        const std::string& uniqueDisplayId) const {
    if (uniqueDisplayId.empty()) {
        ALOGE("Empty string provided to %s", __func__);
        return std::nullopt;
    }
    size_t count = 0;
    std::optional<DisplayViewport> result = std::nullopt;
    for (const DisplayViewport& currentViewport : mDisplays) {
        if (currentViewport.type == viewportType) {
            if (uniqueDisplayId.empty() ||
                    (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) {
                return std::make_optional(currentViewport);
        if (uniqueDisplayId == currentViewport.uniqueId) {
            result = std::make_optional(currentViewport);
            count++;
        }
    }
    if (count > 1) {
        ALOGE("Found %zu viewports with uniqueId %s, but expected 1 at most",
            count, uniqueDisplayId.c_str());
    }
    return result;
}

std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportByType(ViewportType type)
        const {
    size_t count = 0;
    std::optional<DisplayViewport> result = std::nullopt;
    for (const DisplayViewport& currentViewport : mDisplays) {
        // Return the first match
        if (currentViewport.type == type && !result) {
            result = std::make_optional(currentViewport);
            count++;
        }
    }
    if (count > 1) {
        ALOGE("Found %zu viewports with type %s, but expected 1 at most",
                count, viewportTypeToString(type));
    }
    return result;
}

std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportByPort(
        uint8_t displayPort) const {
    for (const DisplayViewport& currentViewport : mDisplays) {
        const std::optional<uint8_t>& physicalPort = currentViewport.physicalPort;
        if (physicalPort && (*physicalPort == displayPort)) {
            return std::make_optional(currentViewport);
        }
    }
    return std::nullopt;
+9 −2
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <optional>
#include <stddef.h>
#include <unistd.h>
#include <unordered_map>
#include <vector>

// Maximum supported size of a vibration pattern.
@@ -164,6 +165,10 @@ struct InputReaderConfiguration {
    // Devices with these names will be ignored.
    std::vector<std::string> excludedDeviceNames;

    // The associations between input ports and display ports.
    // Used to determine which DisplayViewport should be tied to which InputDevice.
    std::unordered_map<std::string, uint8_t> portAssociations;

    // Velocity control parameters for mouse pointer movements.
    VelocityControlParameters pointerVelocityControlParameters;

@@ -262,8 +267,10 @@ struct InputReaderConfiguration {
            pointerGestureZoomSpeedRatio(0.3f),
            showTouches(false) { }

    std::optional<DisplayViewport> getDisplayViewport(ViewportType viewportType,
            const std::string& uniqueDisplayId) const;
    std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const;
    std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId)
            const;
    std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t physicalPort) const;
    void setDisplayViewports(const std::vector<DisplayViewport>& viewports);


Loading