diff options
| author | 2018-11-30 01:49:43 +0000 | |
|---|---|---|
| committer | 2018-11-30 01:49:43 +0000 | |
| commit | bd63715a39f577107a23d9068d6b71a3ea0e1c62 (patch) | |
| tree | 42c9410838f44e9d098147f236f2d2a5c455f360 | |
| parent | 1d9bcec52aec326fda0cb545feeb44f982ed8637 (diff) | |
| parent | 8158e7e33a95732b9963909b9fb471678ff8b7d4 (diff) | |
Merge "Add physical port to display viewport"
| -rw-r--r-- | include/input/DisplayViewport.h | 18 | ||||
| -rw-r--r-- | services/inputflinger/InputReader.cpp | 120 | ||||
| -rw-r--r-- | services/inputflinger/InputReader.h | 6 | ||||
| -rw-r--r-- | services/inputflinger/InputReaderBase.cpp | 51 | ||||
| -rw-r--r-- | services/inputflinger/include/InputReaderBase.h | 11 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 215 |
6 files changed, 317 insertions, 104 deletions
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 <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, 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 += "<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; } + // Get associated display dimensions. + 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; + } + // 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 " - "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<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(); 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<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 (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) { - if (currentViewport.type == viewportType) { - if (uniqueDisplayId.empty() || - (!uniqueDisplayId.empty() && uniqueDisplayId == currentViewport.uniqueId)) { - return std::make_optional(currentViewport); - } + const std::optional<uint8_t>& 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 <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); 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<uint8_t> 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<DisplayViewport> getDisplayViewport(ViewportType viewportType, - const std::string& uniqueId) { - return mConfig.getDisplayViewport(viewportType, uniqueId); + 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(int32_t displayId, int32_t width, int32_t height, int32_t orientation, - const std::string& uniqueId, ViewportType viewportType) { + const std::string& uniqueId, std::optional<uint8_t> 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<uint8_t> 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<DisplayViewport> 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<DisplayViewport> 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<DisplayViewport> 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<DisplayViewport> 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<DisplayViewport> 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<DisplayViewport> viewport1 = mFakePolicy->getDisplayViewport(type, uniqueId1); + std::optional<DisplayViewport> viewport1 = + mFakePolicy->getDisplayViewportByUniqueId(uniqueId1); ASSERT_TRUE(viewport1); ASSERT_EQ(displayId1, viewport1->displayId); ASSERT_EQ(type, viewport1->type); - std::optional<DisplayViewport> viewport2 = mFakePolicy->getDisplayViewport(type, uniqueId2); + std::optional<DisplayViewport> 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<DisplayViewport> someViewport = mFakePolicy->getDisplayViewport(type, ""); + std::optional<DisplayViewport> 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<DisplayViewport> 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<DisplayViewport> 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<uint8_t> 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<uint8_t> port = NO_PORT); + void prepareSecondaryDisplay(ViewportType type, std::optional<uint8_t> 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<uint8_t> 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<uint8_t> 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 |