summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Siarhei Vishniakou <svv@google.com> 2018-10-15 14:28:20 -0700
committer Arthur Hung <arthurhung@google.com> 2018-11-29 15:34:22 +0800
commit8158e7e33a95732b9963909b9fb471678ff8b7d4 (patch)
tree92652d3d26f362cad92fa9a31160d500c0ecc89e
parent5363caaf84127c4661ab7489f94662fd0f038778 (diff)
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
-rw-r--r--include/input/DisplayViewport.h18
-rw-r--r--services/inputflinger/InputReader.cpp120
-rw-r--r--services/inputflinger/InputReader.h6
-rw-r--r--services/inputflinger/InputReaderBase.cpp51
-rw-r--r--services/inputflinger/include/InputReaderBase.h11
-rw-r--r--services/inputflinger/tests/InputReader_test.cpp215
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