summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPrabir Pradhan <prabirmsp@google.com>2022-09-12 20:35:01 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2022-09-12 20:35:01 +0000
commitff41b63eb28a991a80669b4a466f9b29a8cbfe78 (patch)
treedde11615484d5611a5f8af169dffdbe801b1ad9d
parent4bce2e19ea8893805eae836b85730ffd302d9f3b (diff)
parentc04d04de31c346c1ccfa9f94fed715c07ac42986 (diff)
downloadnative-ff41b63eb28a991a80669b4a466f9b29a8cbfe78.tar.gz
Merge "Resolve associated display and pointer display in CursorInputMapper" into tm-qpr-dev
-rw-r--r--include/input/PrintTools.h10
-rw-r--r--services/inputflinger/reader/mapper/CursorInputMapper.cpp60
-rw-r--r--services/inputflinger/reader/mapper/CursorInputMapper.h4
-rw-r--r--services/inputflinger/tests/InputReader_test.cpp115
4 files changed, 142 insertions, 47 deletions
diff --git a/include/input/PrintTools.h b/include/input/PrintTools.h
index 0a75278494..55f730b287 100644
--- a/include/input/PrintTools.h
+++ b/include/input/PrintTools.h
@@ -17,6 +17,7 @@
#pragma once
#include <map>
+#include <optional>
#include <set>
#include <string>
@@ -28,6 +29,15 @@ std::string constToString(const T& v) {
}
/**
+ * Convert an optional type to string.
+ */
+template <typename T>
+std::string toString(const std::optional<T>& optional,
+ std::string (*toString)(const T&) = constToString) {
+ return optional ? toString(*optional) : "<not set>";
+}
+
+/**
* Convert a set of integral types to string.
*/
template <typename T>
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 91dc61923b..8233682a32 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -25,6 +25,8 @@
#include "PointerControllerInterface.h"
#include "TouchCursorInputMapperCommon.h"
+#include "input/PrintTools.h"
+
namespace android {
// The default velocity control parameters that has no effect.
@@ -113,6 +115,7 @@ void CursorInputMapper::dump(std::string& dump) {
toString(mCursorScrollAccumulator.haveRelativeHWheel()));
dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
+ dump += StringPrintf(INDENT3 "DisplayId: %s\n", toString(mDisplayId).c_str());
dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
@@ -201,21 +204,34 @@ void CursorInputMapper::configure(nsecs_t when, const InputReaderConfiguration*
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) ||
configurePointerCapture) {
+ const bool isPointer = mParameters.mode == Parameters::Mode::POINTER;
+
+ mDisplayId = ADISPLAY_ID_NONE;
+ if (auto viewport = mDeviceContext.getAssociatedViewport(); viewport) {
+ // This InputDevice is associated with a viewport.
+ // Only generate events for the associated display.
+ const bool mismatchedPointerDisplay =
+ isPointer && (viewport->displayId != mPointerController->getDisplayId());
+ mDisplayId = mismatchedPointerDisplay ? std::nullopt
+ : std::make_optional(viewport->displayId);
+ } else if (isPointer) {
+ // The InputDevice is not associated with a viewport, but it controls the mouse pointer.
+ mDisplayId = mPointerController->getDisplayId();
+ }
+
mOrientation = DISPLAY_ORIENTATION_0;
const bool isOrientedDevice =
(mParameters.orientationAware && mParameters.hasAssociatedDisplay);
-
// InputReader works in the un-rotated display coordinate space, so we don't need to do
// anything if the device is already orientation-aware. If the device is not
// orientation-aware, then we need to apply the inverse rotation of the display so that
// when the display rotation is applied later as a part of the per-window transform, we
// get the expected screen coordinates. When pointer capture is enabled, we do not apply any
// rotations and report values directly from the input device.
- if (!isOrientedDevice && mParameters.mode != Parameters::Mode::POINTER_RELATIVE) {
- std::optional<DisplayViewport> internalViewport =
- config->getDisplayViewportByType(ViewportType::INTERNAL);
- if (internalViewport) {
- mOrientation = getInverseRotation(internalViewport->orientation);
+ if (!isOrientedDevice && mDisplayId &&
+ mParameters.mode != Parameters::Mode::POINTER_RELATIVE) {
+ if (auto viewport = config->getDisplayViewportById(*mDisplayId); viewport) {
+ mOrientation = getInverseRotation(viewport->orientation);
}
}
@@ -279,6 +295,11 @@ void CursorInputMapper::process(const RawEvent* rawEvent) {
}
void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
+ if (!mDisplayId) {
+ // Ignore events when there is no target display configured.
+ return;
+ }
+
int32_t lastButtonState = mButtonState;
int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
mButtonState = currentButtonState;
@@ -324,7 +345,6 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
mPointerVelocityControl.move(when, &deltaX, &deltaY);
- int32_t displayId = ADISPLAY_ID_NONE;
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
if (mSource == AINPUT_SOURCE_MOUSE) {
@@ -348,7 +368,6 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, yCursorPosition);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
- displayId = mPointerController->getDisplayId();
} else {
// Pointer capture and navigation modes
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
@@ -370,7 +389,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
// Synthesize key down from buttons if needed.
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, readTime, getDeviceId(),
- mSource, displayId, policyFlags, lastButtonState, currentButtonState);
+ mSource, *mDisplayId, policyFlags, lastButtonState, currentButtonState);
// Send motion event.
if (downChanged || moved || scrolled || buttonsChanged) {
@@ -391,7 +410,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
buttonState &= ~actionButton;
NotifyMotionArgs releaseArgs(getContext()->getNextId(), when, readTime,
- getDeviceId(), mSource, displayId, policyFlags,
+ getDeviceId(), mSource, *mDisplayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
metaState, buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
@@ -403,7 +422,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
}
NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(), mSource,
- displayId, policyFlags, motionEventAction, 0, 0, metaState,
+ *mDisplayId, policyFlags, motionEventAction, 0, 0, metaState,
currentButtonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
@@ -416,7 +435,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
buttonState |= actionButton;
NotifyMotionArgs pressArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
- mSource, displayId, policyFlags,
+ mSource, *mDisplayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
metaState, buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
@@ -432,7 +451,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
// Send hover move after UP to tell the application that the mouse is hovering now.
if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
NotifyMotionArgs hoverArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
- mSource, displayId, policyFlags,
+ mSource, *mDisplayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
currentButtonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
@@ -447,7 +466,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, readTime, getDeviceId(),
- mSource, displayId, policyFlags,
+ mSource, *mDisplayId, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
currentButtonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
@@ -459,7 +478,7 @@ void CursorInputMapper::sync(nsecs_t when, nsecs_t readTime) {
// Synthesize key up from buttons if needed.
synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(), mSource,
- displayId, policyFlags, lastButtonState, currentButtonState);
+ *mDisplayId, policyFlags, lastButtonState, currentButtonState);
mCursorMotionAccumulator.finishSync();
mCursorScrollAccumulator.finishSync();
@@ -474,16 +493,7 @@ int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCod
}
std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() {
- if (mParameters.hasAssociatedDisplay) {
- if (mParameters.mode == Parameters::Mode::POINTER) {
- return std::make_optional(mPointerController->getDisplayId());
- } else {
- // If the device is orientationAware and not a mouse,
- // it expects to dispatch events to any display
- return std::make_optional(ADISPLAY_ID_NONE);
- }
- }
- return std::nullopt;
+ return mDisplayId;
}
} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 75aeffb846..60b3dd9ee0 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -111,6 +111,10 @@ private:
VelocityControl mWheelXVelocityControl;
VelocityControl mWheelYVelocityControl;
+ // The display that events generated by this mapper should target. This can be set to
+ // ADISPLAY_ID_NONE to target the focused display. If there is no display target (i.e.
+ // std::nullopt), all events will be ignored.
+ std::optional<int32_t> mDisplayId;
int32_t mOrientation;
std::shared_ptr<PointerControllerInterface> mPointerController;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 75b8dd1953..e1befedcff 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -56,7 +56,9 @@ static constexpr nsecs_t READ_TIME = 4321;
// Arbitrary display properties.
static constexpr int32_t DISPLAY_ID = 0;
+static const std::string DISPLAY_UNIQUE_ID = "local:1";
static constexpr int32_t SECONDARY_DISPLAY_ID = DISPLAY_ID + 1;
+static const std::string SECONDARY_DISPLAY_UNIQUE_ID = "local:2";
static constexpr int32_t DISPLAY_WIDTH = 480;
static constexpr int32_t DISPLAY_HEIGHT = 800;
static constexpr int32_t VIRTUAL_DISPLAY_ID = 1;
@@ -91,6 +93,24 @@ static constexpr int32_t ACTION_POINTER_1_UP =
// Error tolerance for floating point assertions.
static const float EPSILON = 0.001f;
+using ::testing::AllOf;
+
+MATCHER_P(WithAction, action, "InputEvent with specified action") {
+ return arg.action == action;
+}
+
+MATCHER_P(WithSource, source, "InputEvent with specified source") {
+ return arg.source == source;
+}
+
+MATCHER_P(WithDisplayId, displayId, "InputEvent with specified displayId") {
+ return arg.displayId == displayId;
+}
+
+MATCHER_P2(WithCoords, x, y, "MotionEvent with specified action") {
+ return arg.pointerCoords[0].getX() == x && arg.pointerCoords[0].getY();
+}
+
template<typename T>
static inline T min(T a, T b) {
return a < b ? a : b;
@@ -2872,7 +2892,6 @@ TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
// Device should be disabled because it is associated with a specific display, but the
// corresponding display is not found.
- const std::string DISPLAY_UNIQUE_ID = "displayUniqueId";
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
InputReaderConfiguration::CHANGE_DISPLAY_INFO);
@@ -2903,7 +2922,6 @@ TEST_F(InputDeviceTest, Configure_UniqueId_CorrectlyMatches) {
mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
- const std::string DISPLAY_UNIQUE_ID = "displayUniqueId";
mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
DISPLAY_ORIENTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
@@ -4188,10 +4206,14 @@ protected:
int32_t rotatedX, int32_t rotatedY);
void prepareDisplay(int32_t orientation) {
- const std::string uniqueId = "local:0";
- const ViewportType viewportType = ViewportType::INTERNAL;
- setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- orientation, uniqueId, NO_PORT, viewportType);
+ setDisplayInfoAndReconfigure(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation,
+ DISPLAY_UNIQUE_ID, NO_PORT, ViewportType::INTERNAL);
+ }
+
+ void prepareSecondaryDisplay() {
+ setDisplayInfoAndReconfigure(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ DISPLAY_ORIENTATION_0, SECONDARY_DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::EXTERNAL);
}
static void assertCursorPointerCoords(const PointerCoords& coords, float x, float y,
@@ -4468,6 +4490,7 @@ TEST_F(CursorInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
}
TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldNotRotateMotions) {
+ mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
addConfigurationProperty("cursor.mode", "navigation");
// InputReader works in the un-rotated coordinate space, so orientation-aware devices do not
// need to be rotated.
@@ -4486,11 +4509,13 @@ TEST_F(CursorInputMapperTest, Process_WhenOrientationAware_ShouldNotRotateMotion
}
TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldRotateMotions) {
+ mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, DISPLAY_UNIQUE_ID);
addConfigurationProperty("cursor.mode", "navigation");
// Since InputReader works in the un-rotated coordinate space, only devices that are not
// orientation-aware are affected by display rotation.
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+ clearViewports();
prepareDisplay(DISPLAY_ORIENTATION_0);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
@@ -4501,6 +4526,7 @@ TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldRotateMotion
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
+ clearViewports();
prepareDisplay(DISPLAY_ORIENTATION_90);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1));
@@ -4511,6 +4537,7 @@ TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldRotateMotion
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1));
+ clearViewports();
prepareDisplay(DISPLAY_ORIENTATION_180);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1));
@@ -4521,6 +4548,7 @@ TEST_F(CursorInputMapperTest, Process_WhenNotOrientationAware_ShouldRotateMotion
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1));
+ clearViewports();
prepareDisplay(DISPLAY_ORIENTATION_270);
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0));
ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1));
@@ -5017,33 +5045,76 @@ TEST_F(CursorInputMapperTest, PointerCaptureDisablesOrientationChanges) {
ASSERT_EQ(20, args.pointerCoords[0].getY());
}
-TEST_F(CursorInputMapperTest, Process_ShouldHandleDisplayId) {
+TEST_F(CursorInputMapperTest, ConfigureDisplayId_NoAssociatedViewport) {
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
- // Setup for second display.
- constexpr int32_t SECOND_DISPLAY_ID = 1;
- const std::string SECOND_DISPLAY_UNIQUE_ID = "local:1";
- mFakePolicy->addDisplayViewport(SECOND_DISPLAY_ID, 800, 480, DISPLAY_ORIENTATION_0,
- true /*isActive*/, SECOND_DISPLAY_UNIQUE_ID, NO_PORT,
- ViewportType::EXTERNAL);
- mFakePolicy->setDefaultPointerDisplayId(SECOND_DISPLAY_ID);
+ // Set up the default display.
+ prepareDisplay(DISPLAY_ORIENTATION_90);
+
+ // Set up the secondary display as the display on which the pointer should be shown.
+ // The InputDevice is not associated with any display.
+ prepareSecondaryDisplay();
+ mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+ mFakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
mFakePointerController->setPosition(100, 200);
mFakePointerController->setButtonState(0);
- NotifyMotionArgs args;
+ // Ensure input events are generated for the secondary display.
process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20);
process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
- ASSERT_EQ(AINPUT_SOURCE_MOUSE, args.source);
- ASSERT_EQ(AMOTION_EVENT_ACTION_HOVER_MOVE, args.action);
- ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
- 110.0f, 220.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
+ WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(110.0f, 220.0f))));
ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 110.0f, 220.0f));
- ASSERT_EQ(SECOND_DISPLAY_ID, args.displayId);
+}
+
+TEST_F(CursorInputMapperTest, ConfigureDisplayId_WithAssociatedViewport) {
+ CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+
+ // Set up the default display.
+ prepareDisplay(DISPLAY_ORIENTATION_90);
+
+ // Set up the secondary display as the display on which the pointer should be shown,
+ // and associate the InputDevice with the secondary display.
+ prepareSecondaryDisplay();
+ mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
+ mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, SECONDARY_DISPLAY_UNIQUE_ID);
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ mFakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
+ mFakePointerController->setPosition(100, 200);
+ mFakePointerController->setButtonState(0);
+
+ process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10);
+ process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20);
+ process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
+ AllOf(WithAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE),
+ WithDisplayId(SECONDARY_DISPLAY_ID), WithCoords(110.0f, 220.0f))));
+ ASSERT_NO_FATAL_FAILURE(assertPosition(*mFakePointerController, 110.0f, 220.0f));
+}
+
+TEST_F(CursorInputMapperTest, ConfigureDisplayId_IgnoresEventsForMismatchedPointerDisplay) {
+ CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
+
+ // Set up the default display as the display on which the pointer should be shown.
+ prepareDisplay(DISPLAY_ORIENTATION_90);
+ mFakePolicy->setDefaultPointerDisplayId(DISPLAY_ID);
+
+ // Associate the InputDevice with the secondary display.
+ prepareSecondaryDisplay();
+ mFakePolicy->addInputUniqueIdAssociation(DEVICE_LOCATION, SECONDARY_DISPLAY_UNIQUE_ID);
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
+ // The mapper should not generate any events because it is associated with a display that is
+ // different from the pointer display.
+ process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_X, 10);
+ process(mapper, ARBITRARY_TIME, READ_TIME, EV_REL, REL_Y, 20);
+ process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
}
// --- TouchInputMapperTest ---