From 29c95334ebb5346c92cff9a9c928af175644ad8f Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Wed, 14 Nov 2018 20:14:11 -0800 Subject: Split InputFlinger into multiple libraries This is the InputFlinger FE/BE split as detailed in go/arc++inputflinger-split. We split libinputflinger into the following dynamic libraries: - libinputflinger: Acts as the frontend for inputflinger and implements InputDispatcher and InputManager. - libinputreader: Acts as the backend for inputflinger and impliements InputReader and EventHub, and adds a InputReaderFactory to create the InputReader. - libinputflinger_base: Contains the common logic that is shared throughout InputFlinger, and contains the definitions for InputReaderInterface (in InputReaderBase.h) and InputListenerInterface (in InputListener.h). Bug: 119264687 Test: manual: Build, run, and test input (touch, mouse) Change-Id: I8567635f48de58ee8e5bdb0f8a17a73ea6fa37ef --- services/inputflinger/InputReaderBase.cpp | 91 +++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 services/inputflinger/InputReaderBase.cpp (limited to 'services/inputflinger/InputReaderBase.cpp') diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp new file mode 100644 index 0000000000..17a116e822 --- /dev/null +++ b/services/inputflinger/InputReaderBase.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 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. + */ + +#define LOG_TAG "InputReaderBase" + +//#define LOG_NDEBUG 0 + +#include "InputReaderBase.h" + +#include +#include + +#define INDENT " " +#define INDENT2 " " +#define INDENT3 " " +#define INDENT4 " " +#define INDENT5 " " + +using android::base::StringPrintf; + +namespace android { + +// --- InputReaderThread --- + +InputReaderThread::InputReaderThread(const sp& reader) : + Thread(/*canCallJava*/ true), mReader(reader) { +} + +InputReaderThread::~InputReaderThread() { +} + +bool InputReaderThread::threadLoop() { + mReader->loopOnce(); + return true; +} + +// --- InputReaderConfiguration --- + +std::optional InputReaderConfiguration::getDisplayViewport( + ViewportType viewportType, const std::string& uniqueDisplayId) const { + for (const DisplayViewport& currentViewport : mDisplays) { + if (currentViewport.type == viewportType) { + if (uniqueDisplayId.empty() || + (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) { + return std::make_optional(currentViewport); + } + } + } + return std::nullopt; +} + +void InputReaderConfiguration::setDisplayViewports(const std::vector& viewports) { + mDisplays = viewports; +} + +void InputReaderConfiguration::dump(std::string& dump) const { + for (const DisplayViewport& viewport : mDisplays) { + dumpViewport(dump, viewport); + } +} + +void InputReaderConfiguration::dumpViewport(std::string& dump, const DisplayViewport& viewport) + const { + dump += StringPrintf(INDENT4 "%s\n", viewport.toString().c_str()); +} + + +// -- TouchAffineTransformation -- +void TouchAffineTransformation::applyTo(float& x, float& y) const { + float newX, newY; + newX = x * x_scale + y * x_ymix + x_offset; + newY = x * y_xmix + y * y_scale + y_offset; + + x = newX; + y = newY; +} + +} // namespace android \ No newline at end of file -- cgit v1.2.3-59-g8ed1b From 8158e7e33a95732b9963909b9fb471678ff8b7d4 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Mon, 15 Oct 2018 14:28:20 -0700 Subject: 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 --- include/input/DisplayViewport.h | 18 +- services/inputflinger/InputReader.cpp | 120 +++++++++---- services/inputflinger/InputReader.h | 6 + services/inputflinger/InputReaderBase.cpp | 51 +++++- services/inputflinger/include/InputReaderBase.h | 11 +- services/inputflinger/tests/InputReader_test.cpp | 215 +++++++++++++++++------ 6 files changed, 317 insertions(+), 104 deletions(-) (limited to 'services/inputflinger/InputReaderBase.cpp') diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index 0de3bb7a08..fa456bb213 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -20,6 +20,8 @@ #include #include #include +#include +#include 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 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() : "", + orientation, logicalLeft, logicalTop, logicalRight, logicalBottom, physicalLeft, physicalTop, diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp index 9dd14dc799..9e748d8975 100644 --- a/services/inputflinger/InputReader.cpp +++ b/services/inputflinger/InputReader.cpp @@ -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 += "\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& 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 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 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 TouchInputMapper::findViewport() { + if (mParameters.hasAssociatedDisplay) { + const std::optional displayPort = mDevice->getAssociatedDisplayPort(); + if (displayPort) { + // Find the viewport that contains the same port + std::optional 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; } + // Get associated display dimensions. + std::optional 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; + } + // 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 viewportToUse = - mConfig.getDisplayViewport(viewportTypeToUse, uniqueDisplayId); - if (!viewportToUse) { - ALOGI(INDENT "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; + 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. diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h index 1786fe8f26..13f1bedb65 100644 --- a/services/inputflinger/InputReader.h +++ b/services/inputflinger/InputReader.h @@ -252,6 +252,9 @@ public: inline bool isExternal() { return mIsExternal; } inline void setExternal(bool external) { mIsExternal = external; } + inline std::optional 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 mAssociatedDisplayPort; bool mHasMic; bool mDropUntilNextSync; @@ -1501,6 +1505,8 @@ private: VelocityControl mWheelXVelocityControl; VelocityControl mWheelYVelocityControl; + std::optional findViewport(); + void resetExternalStylus(); void clearStylusDataPendingFlags(); diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp index 17a116e822..f48a64551e 100644 --- a/services/inputflinger/InputReaderBase.cpp +++ b/services/inputflinger/InputReaderBase.cpp @@ -49,14 +49,51 @@ bool InputReaderThread::threadLoop() { // --- InputReaderConfiguration --- -std::optional InputReaderConfiguration::getDisplayViewport( - ViewportType viewportType, const std::string& uniqueDisplayId) const { +std::optional 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 result = std::nullopt; + for (const DisplayViewport& currentViewport : mDisplays) { + 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 InputReaderConfiguration::getDisplayViewportByType(ViewportType type) + const { + size_t count = 0; + std::optional 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 InputReaderConfiguration::getDisplayViewportByPort( + uint8_t displayPort) const { for (const DisplayViewport& currentViewport : mDisplays) { - if (currentViewport.type == viewportType) { - if (uniqueDisplayId.empty() || - (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) { - return std::make_optional(currentViewport); - } + const std::optional& physicalPort = currentViewport.physicalPort; + if (physicalPort && (*physicalPort == displayPort)) { + return std::make_optional(currentViewport); } } return std::nullopt; diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index fff8480f57..fe1c50bc75 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -32,6 +32,7 @@ #include #include #include +#include #include // Maximum supported size of a vibration pattern. @@ -164,6 +165,10 @@ struct InputReaderConfiguration { // Devices with these names will be ignored. std::vector excludedDeviceNames; + // The associations between input ports and display ports. + // Used to determine which DisplayViewport should be tied to which InputDevice. + std::unordered_map portAssociations; + // Velocity control parameters for mouse pointer movements. VelocityControlParameters pointerVelocityControlParameters; @@ -262,8 +267,10 @@ struct InputReaderConfiguration { pointerGestureZoomSpeedRatio(0.3f), showTouches(false) { } - std::optional getDisplayViewport(ViewportType viewportType, - const std::string& uniqueDisplayId) const; + std::optional getDisplayViewportByType(ViewportType type) const; + std::optional getDisplayViewportByUniqueId(const std::string& uniqueDisplayId) + const; + std::optional getDisplayViewportByPort(uint8_t physicalPort) const; void setDisplayViewports(const std::vector& viewports); diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 929424b8b9..04b87d5a33 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -28,12 +28,14 @@ static const nsecs_t ARBITRARY_TIME = 1234; // Arbitrary display properties. static const int32_t DISPLAY_ID = 0; +static const int32_t SECONDARY_DISPLAY_ID = DISPLAY_ID + 1; static const int32_t DISPLAY_WIDTH = 480; static const int32_t DISPLAY_HEIGHT = 800; static const int32_t VIRTUAL_DISPLAY_ID = 1; static const int32_t VIRTUAL_DISPLAY_WIDTH = 400; static const int32_t VIRTUAL_DISPLAY_HEIGHT = 500; static const char* VIRTUAL_DISPLAY_UNIQUE_ID = "virtual:1"; +static constexpr std::optional NO_PORT = std::nullopt; // no physical port is specified // Error tolerance for floating point assertions. static const float EPSILON = 0.001f; @@ -147,15 +149,22 @@ public: mConfig.setDisplayViewports(mViewports); } - std::optional getDisplayViewport(ViewportType viewportType, - const std::string& uniqueId) { - return mConfig.getDisplayViewport(viewportType, uniqueId); + std::optional getDisplayViewportByUniqueId(const std::string& uniqueId) const { + return mConfig.getDisplayViewportByUniqueId(uniqueId); + } + std::optional getDisplayViewportByType(ViewportType type) const { + return mConfig.getDisplayViewportByType(type); + } + + std::optional getDisplayViewportByPort(uint8_t displayPort) const { + return mConfig.getDisplayViewportByPort(displayPort); } void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation, - const std::string& uniqueId, ViewportType viewportType) { + const std::string& uniqueId, std::optional physicalPort, + ViewportType viewportType) { const DisplayViewport viewport = createDisplayViewport(displayId, width, height, - orientation, uniqueId, viewportType); + orientation, uniqueId, physicalPort, viewportType); mViewports.push_back(viewport); mConfig.setDisplayViewports(mViewports); } @@ -164,6 +173,10 @@ public: mConfig.excludedDeviceNames.push_back(deviceName); } + void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort) { + mConfig.portAssociations.insert({inputPort, displayPort}); + } + void addDisabledDevice(int32_t deviceId) { ssize_t index = mConfig.disabledDevices.indexOf(deviceId); bool currentlyEnabled = index < 0; @@ -207,7 +220,8 @@ public: private: DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height, - int32_t orientation, const std::string& uniqueId, ViewportType type) { + int32_t orientation, const std::string& uniqueId, std::optional physicalPort, + ViewportType type) { bool isRotated = (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270); DisplayViewport v; @@ -224,6 +238,7 @@ private: v.deviceWidth = isRotated ? height : width; v.deviceHeight = isRotated ? width : height; v.uniqueId = uniqueId; + v.physicalPort = physicalPort; v.type = type; return v; } @@ -1105,26 +1120,28 @@ TEST_F(InputReaderPolicyTest, Viewports_GetCleared) { // We didn't add any viewports yet, so there shouldn't be any. std::optional internalViewport = - mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, uniqueId); + mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL); ASSERT_FALSE(internalViewport); // Add an internal viewport, then clear it mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, uniqueId, ViewportType::VIEWPORT_INTERNAL); + DISPLAY_ORIENTATION_0, uniqueId, NO_PORT, ViewportType::VIEWPORT_INTERNAL); // Check matching by uniqueId - internalViewport = mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, uniqueId); + internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId); ASSERT_TRUE(internalViewport); + ASSERT_EQ(ViewportType::VIEWPORT_INTERNAL, internalViewport->type); // Check matching by viewport type - internalViewport = mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, ""); + internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL); ASSERT_TRUE(internalViewport); + ASSERT_EQ(uniqueId, internalViewport->uniqueId); mFakePolicy->clearViewports(); // Make sure nothing is found after clear - internalViewport = mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, uniqueId); + internalViewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId); ASSERT_FALSE(internalViewport); - internalViewport = mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, ""); + internalViewport = mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL); ASSERT_FALSE(internalViewport); } @@ -1138,40 +1155,42 @@ TEST_F(InputReaderPolicyTest, Viewports_GetByType) { // Add an internal viewport mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, internalUniqueId, ViewportType::VIEWPORT_INTERNAL); + DISPLAY_ORIENTATION_0, internalUniqueId, NO_PORT, ViewportType::VIEWPORT_INTERNAL); // Add an external viewport mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, externalUniqueId, ViewportType::VIEWPORT_EXTERNAL); + DISPLAY_ORIENTATION_0, externalUniqueId, NO_PORT, ViewportType::VIEWPORT_EXTERNAL); // Add an virtual viewport mFakePolicy->addDisplayViewport(virtualDisplayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, virtualUniqueId1, ViewportType::VIEWPORT_VIRTUAL); + DISPLAY_ORIENTATION_0, virtualUniqueId1, NO_PORT, ViewportType::VIEWPORT_VIRTUAL); // Add another virtual viewport mFakePolicy->addDisplayViewport(virtualDisplayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, virtualUniqueId2, ViewportType::VIEWPORT_VIRTUAL); + DISPLAY_ORIENTATION_0, virtualUniqueId2, NO_PORT, ViewportType::VIEWPORT_VIRTUAL); // Check matching by type for internal std::optional internalViewport = - mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, ""); + mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL); ASSERT_TRUE(internalViewport); ASSERT_EQ(internalUniqueId, internalViewport->uniqueId); // Check matching by type for external std::optional externalViewport = - mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_EXTERNAL, ""); + mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_EXTERNAL); ASSERT_TRUE(externalViewport); ASSERT_EQ(externalUniqueId, externalViewport->uniqueId); // Check matching by uniqueId for virtual viewport #1 std::optional virtualViewport1 = - mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_VIRTUAL, virtualUniqueId1); + mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId1); ASSERT_TRUE(virtualViewport1); + ASSERT_EQ(ViewportType::VIEWPORT_VIRTUAL, virtualViewport1->type); ASSERT_EQ(virtualUniqueId1, virtualViewport1->uniqueId); ASSERT_EQ(virtualDisplayId1, virtualViewport1->displayId); // Check matching by uniqueId for virtual viewport #2 std::optional virtualViewport2 = - mFakePolicy->getDisplayViewport(ViewportType::VIEWPORT_VIRTUAL, virtualUniqueId2); + mFakePolicy->getDisplayViewportByUniqueId(virtualUniqueId2); ASSERT_TRUE(virtualViewport2); + ASSERT_EQ(ViewportType::VIEWPORT_VIRTUAL, virtualViewport2->type); ASSERT_EQ(virtualUniqueId2, virtualViewport2->uniqueId); ASSERT_EQ(virtualDisplayId2, virtualViewport2->displayId); } @@ -1194,18 +1213,20 @@ TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) { mFakePolicy->clearViewports(); // Add a viewport mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, uniqueId1, type); + DISPLAY_ORIENTATION_0, uniqueId1, NO_PORT, type); // Add another viewport mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_0, uniqueId2, type); + DISPLAY_ORIENTATION_0, uniqueId2, NO_PORT, type); // Check that correct display viewport was returned by comparing the display IDs. - std::optional viewport1 = mFakePolicy->getDisplayViewport(type, uniqueId1); + std::optional viewport1 = + mFakePolicy->getDisplayViewportByUniqueId(uniqueId1); ASSERT_TRUE(viewport1); ASSERT_EQ(displayId1, viewport1->displayId); ASSERT_EQ(type, viewport1->type); - std::optional viewport2 = mFakePolicy->getDisplayViewport(type, uniqueId2); + std::optional viewport2 = + mFakePolicy->getDisplayViewportByUniqueId(uniqueId2); ASSERT_TRUE(viewport2); ASSERT_EQ(displayId2, viewport2->displayId); ASSERT_EQ(type, viewport2->type); @@ -1216,11 +1237,50 @@ TEST_F(InputReaderPolicyTest, Viewports_TwoOfSameType) { // is just implementation detail. // However, we can check that it still returns *a* viewport, we just cannot assert // which one specifically is returned. - std::optional someViewport = mFakePolicy->getDisplayViewport(type, ""); + std::optional someViewport = mFakePolicy->getDisplayViewportByType(type); ASSERT_TRUE(someViewport); } } +/** + * Check getDisplayViewportByPort + */ +TEST_F(InputReaderPolicyTest, Viewports_GetByPort) { + constexpr ViewportType type = ViewportType::VIEWPORT_EXTERNAL; + const std::string uniqueId1 = "uniqueId1"; + const std::string uniqueId2 = "uniqueId2"; + constexpr int32_t displayId1 = 1; + constexpr int32_t displayId2 = 2; + const uint8_t hdmi1 = 0; + const uint8_t hdmi2 = 1; + const uint8_t hdmi3 = 2; + + mFakePolicy->clearViewports(); + // Add a viewport that's associated with some display port that's not of interest. + mFakePolicy->addDisplayViewport(displayId1, DISPLAY_WIDTH, DISPLAY_HEIGHT, + DISPLAY_ORIENTATION_0, uniqueId1, hdmi3, type); + // Add another viewport, connected to HDMI1 port + mFakePolicy->addDisplayViewport(displayId2, DISPLAY_WIDTH, DISPLAY_HEIGHT, + DISPLAY_ORIENTATION_0, uniqueId2, hdmi1, type); + + // Check that correct display viewport was returned by comparing the display ports. + std::optional hdmi1Viewport = mFakePolicy->getDisplayViewportByPort(hdmi1); + ASSERT_TRUE(hdmi1Viewport); + ASSERT_EQ(displayId2, hdmi1Viewport->displayId); + ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId); + + // Check that we can still get the same viewport using the uniqueId + hdmi1Viewport = mFakePolicy->getDisplayViewportByUniqueId(uniqueId2); + ASSERT_TRUE(hdmi1Viewport); + ASSERT_EQ(displayId2, hdmi1Viewport->displayId); + ASSERT_EQ(uniqueId2, hdmi1Viewport->uniqueId); + ASSERT_EQ(type, hdmi1Viewport->type); + + // Check that we cannot find a port with "HDMI2", because we never added one + std::optional hdmi2Viewport = mFakePolicy->getDisplayViewportByPort(hdmi2); + ASSERT_FALSE(hdmi2Viewport); +} + // --- InputReaderTest --- class InputReaderTest : public testing::Test { @@ -1696,6 +1756,7 @@ TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRe class InputMapperTest : public testing::Test { protected: static const char* DEVICE_NAME; + static const char* DEVICE_LOCATION; static const int32_t DEVICE_ID; static const int32_t DEVICE_GENERATION; static const int32_t DEVICE_CONTROLLER_NUMBER; @@ -1714,10 +1775,11 @@ protected: mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener); InputDeviceIdentifier identifier; identifier.name = DEVICE_NAME; + identifier.location = DEVICE_LOCATION; mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION, DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES); - mFakeEventHub->addDevice(DEVICE_ID, DEVICE_NAME, 0); + mFakeEventHub->addDevice(mDevice->getId(), DEVICE_NAME, 0); } virtual void TearDown() { @@ -1729,7 +1791,7 @@ protected: } void addConfigurationProperty(const char* key, const char* value) { - mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8(key), String8(value)); + mFakeEventHub->addConfigurationProperty(mDevice->getId(), String8(key), String8(value)); } void configureDevice(uint32_t changes) { @@ -1743,9 +1805,10 @@ protected: } void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height, - int32_t orientation, const std::string& uniqueId, ViewportType viewportType) { + int32_t orientation, const std::string& uniqueId, + std::optional physicalPort, ViewportType viewportType) { mFakePolicy->addDisplayViewport( - displayId, width, height, orientation, uniqueId, viewportType); + displayId, width, height, orientation, uniqueId, physicalPort, viewportType); configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO); } @@ -1801,6 +1864,7 @@ protected: }; const char* InputMapperTest::DEVICE_NAME = "device"; +const char* InputMapperTest::DEVICE_LOCATION = "USB1"; const int32_t InputMapperTest::DEVICE_ID = 1; const int32_t InputMapperTest::DEVICE_GENERATION = 2; const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0; @@ -1867,7 +1931,7 @@ protected: */ void KeyboardInputMapperTest::prepareDisplay(int32_t orientation) { setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, - orientation, UNIQUE_ID, ViewportType::VIEWPORT_INTERNAL); + orientation, UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_INTERNAL); } void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper, @@ -2170,7 +2234,7 @@ TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) { // ^--- already checked by the previous test setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, - UNIQUE_ID, ViewportType::VIEWPORT_INTERNAL); + UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_INTERNAL); process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); @@ -2180,7 +2244,7 @@ TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) { constexpr int32_t newDisplayId = 2; clearViewports(); setDisplayInfoAndReconfigure(newDisplayId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, - UNIQUE_ID, ViewportType::VIEWPORT_INTERNAL); + UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_INTERNAL); process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 1); ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args)); process(mapper, ARBITRARY_TIME, EV_KEY, KEY_UP, 0); @@ -2305,11 +2369,18 @@ protected: InputMapperTest::SetUp(); mFakePointerController = new FakePointerController(); - mFakePolicy->setPointerController(DEVICE_ID, mFakePointerController); + mFakePolicy->setPointerController(mDevice->getId(), mFakePointerController); } void testMotionRotation(CursorInputMapper* mapper, int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY); + + void prepareDisplay(int32_t orientation) { + const std::string uniqueId = "local:0"; + const ViewportType viewportType = ViewportType::VIEWPORT_INTERNAL; + setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, + orientation, uniqueId, NO_PORT, viewportType); + } }; const int32_t CursorInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6; @@ -2599,12 +2670,7 @@ TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateMot addConfigurationProperty("cursor.mode", "navigation"); addMapperAndConfigure(mapper); - const std::string uniqueId = "local:0"; - const ViewportType viewportType = ViewportType::VIEWPORT_INTERNAL; - - setDisplayInfoAndReconfigure(DISPLAY_ID, - DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_ORIENTATION_90, uniqueId, viewportType); + prepareDisplay(DISPLAY_ORIENTATION_90); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0)); @@ -2621,11 +2687,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) addConfigurationProperty("cursor.orientationAware", "1"); addMapperAndConfigure(mapper); - const std::string uniqueId = "local:0"; - const ViewportType viewportType = ViewportType::VIEWPORT_INTERNAL; - - setDisplayInfoAndReconfigure(DISPLAY_ID, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, uniqueId, viewportType); + prepareDisplay(DISPLAY_ORIENTATION_0); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0)); @@ -2635,8 +2697,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1)); - setDisplayInfoAndReconfigure(DISPLAY_ID, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_90, uniqueId, viewportType); + prepareDisplay(DISPLAY_ORIENTATION_90); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1)); @@ -2646,8 +2707,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1)); - setDisplayInfoAndReconfigure(DISPLAY_ID, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_180, uniqueId, viewportType); + prepareDisplay(DISPLAY_ORIENTATION_180); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, -1, 0)); @@ -2657,8 +2717,7 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldRotateMotions) ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1)); - setDisplayInfoAndReconfigure(DISPLAY_ID, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_270, uniqueId, viewportType); + prepareDisplay(DISPLAY_ORIENTATION_270); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1)); ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1)); @@ -3104,6 +3163,7 @@ protected: static const VirtualKeyDefinition VIRTUAL_KEYS[2]; const std::string UNIQUE_ID = "local:0"; + const std::string SECONDARY_UNIQUE_ID = "local:1"; enum Axes { POSITION = 1 << 0, @@ -3119,7 +3179,8 @@ protected: TOOL_TYPE = 1 << 10, }; - void prepareDisplay(int32_t orientation); + void prepareDisplay(int32_t orientation, std::optional port = NO_PORT); + void prepareSecondaryDisplay(ViewportType type, std::optional port = NO_PORT); void prepareVirtualDisplay(int32_t orientation); void prepareVirtualKeys(); void prepareLocationCalibration(); @@ -3172,15 +3233,20 @@ const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = { { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 }, }; -void TouchInputMapperTest::prepareDisplay(int32_t orientation) { +void TouchInputMapperTest::prepareDisplay(int32_t orientation, std::optional port) { setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation, - UNIQUE_ID, ViewportType::VIEWPORT_INTERNAL); + UNIQUE_ID, port, ViewportType::VIEWPORT_INTERNAL); +} + +void TouchInputMapperTest::prepareSecondaryDisplay(ViewportType type, std::optional port) { + setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, + DISPLAY_ORIENTATION_0, SECONDARY_UNIQUE_ID, port, type); } void TouchInputMapperTest::prepareVirtualDisplay(int32_t orientation) { setDisplayInfoAndReconfigure(VIRTUAL_DISPLAY_ID, VIRTUAL_DISPLAY_WIDTH, VIRTUAL_DISPLAY_HEIGHT, orientation, - VIRTUAL_DISPLAY_UNIQUE_ID, ViewportType::VIEWPORT_VIRTUAL); + VIRTUAL_DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::VIEWPORT_VIRTUAL); } void TouchInputMapperTest::prepareVirtualKeys() { @@ -6138,5 +6204,46 @@ TEST_F(MultiTouchInputMapperTest, WhenMapperIsReset_TimestampIsCleared) { ASSERT_EQ(0U, args.deviceTimestamp); } +/** + * Set the input device port <--> display port associations, and check that the + * events are routed to the display that matches the display port. + * This can be checked by looking at the displayId of the resulting NotifyMotionArgs. + */ +TEST_F(MultiTouchInputMapperTest, Configure_AssignsDisplayPort) { + MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice); + const std::string usb2 = "USB2"; + const uint8_t hdmi1 = 0; + const uint8_t hdmi2 = 1; + const std::string secondaryUniqueId = "uniqueId2"; + constexpr ViewportType type = ViewportType::VIEWPORT_EXTERNAL; + + addConfigurationProperty("touch.deviceType", "touchScreen"); + prepareAxes(POSITION); + addMapperAndConfigure(mapper); + + mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1); + mFakePolicy->addInputPortAssociation(usb2, hdmi2); + + // We are intentionally not adding the viewport for display 1 yet. Since the port association + // for this input device is specified, and the matching viewport is not present, + // the input device should be disabled (at the mapper level). + + // Add viewport for display 2 on hdmi2 + prepareSecondaryDisplay(type, hdmi2); + // Send a touch event + processPosition(mapper, 100, 100); + processSync(mapper); + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled()); + + // Add viewport for display 1 on hdmi1 + prepareDisplay(DISPLAY_ORIENTATION_0, hdmi1); + // Send a touch event again + processPosition(mapper, 100, 100); + processSync(mapper); + + NotifyMotionArgs args; + ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args)); + ASSERT_EQ(DISPLAY_ID, args.displayId); +} } // namespace android -- cgit v1.2.3-59-g8ed1b