Let InputReader set mouse cursor's display.
InputReader was already responsible to bind device/event and display. It
makes sense to further extend it to control the display where mouse
cursor is shown.
Bug: 146385350
Test: Mouse cursor shows up at expected display.
Test: atest inputflinger_tests
Change-Id: Ie7a9546550b70c8834462b06de929472196fe713
diff --git a/services/inputflinger/InputReaderBase.cpp b/services/inputflinger/InputReaderBase.cpp
index 2d6f2c1..b2dadf8 100644
--- a/services/inputflinger/InputReaderBase.cpp
+++ b/services/inputflinger/InputReaderBase.cpp
@@ -125,6 +125,16 @@
return std::nullopt;
}
+std::optional<DisplayViewport> InputReaderConfiguration::getDisplayViewportById(
+ int32_t displayId) const {
+ for (const DisplayViewport& currentViewport : mDisplays) {
+ if (currentViewport.displayId == displayId) {
+ return std::make_optional(currentViewport);
+ }
+ }
+ return std::nullopt;
+}
+
void InputReaderConfiguration::setDisplayViewports(const std::vector<DisplayViewport>& viewports) {
mDisplays = viewports;
}
@@ -151,4 +161,4 @@
y = newY;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 56c0a73..f8d5351 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -169,6 +169,9 @@
// Used to determine which DisplayViewport should be tied to which InputDevice.
std::unordered_map<std::string, uint8_t> portAssociations;
+ // The suggested display ID to show the cursor.
+ int32_t defaultPointerDisplayId;
+
// Velocity control parameters for mouse pointer movements.
VelocityControlParameters pointerVelocityControlParameters;
@@ -273,6 +276,7 @@
std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueDisplayId)
const;
std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t physicalPort) const;
+ std::optional<DisplayViewport> getDisplayViewportById(int32_t displayId) const;
void setDisplayViewports(const std::vector<DisplayViewport>& viewports);
@@ -352,4 +356,4 @@
} // namespace android
-#endif // _UI_INPUT_READER_COMMON_H
\ No newline at end of file
+#endif // _UI_INPUT_READER_COMMON_H
diff --git a/services/inputflinger/include/PointerControllerInterface.h b/services/inputflinger/include/PointerControllerInterface.h
index 0ff28e4..194c665 100644
--- a/services/inputflinger/include/PointerControllerInterface.h
+++ b/services/inputflinger/include/PointerControllerInterface.h
@@ -17,6 +17,7 @@
#ifndef _INPUTFLINGER_POINTER_CONTROLLER_INTERFACE_H
#define _INPUTFLINGER_POINTER_CONTROLLER_INTERFACE_H
+#include <input/DisplayViewport.h>
#include <input/Input.h>
#include <utils/BitSet.h>
#include <utils/RefBase.h>
@@ -101,6 +102,9 @@
/* Gets the id of the display where the pointer should be shown. */
virtual int32_t getDisplayId() const = 0;
+
+ /* Sets the associated display of this pointer. Pointer should show on that display. */
+ virtual void setDisplayViewport(const DisplayViewport& displayViewport) = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index f69138e..69a75ba 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -189,12 +189,32 @@
// Update the PointerController if viewports changed.
if (mParameters.mode == Parameters::MODE_POINTER) {
- getPolicy()->obtainPointerController(getDeviceId());
+ updatePointerControllerDisplayViewport(*config);
}
bumpGeneration();
}
}
+void CursorInputMapper::updatePointerControllerDisplayViewport(
+ const InputReaderConfiguration& config) {
+ std::optional<DisplayViewport> viewport =
+ config.getDisplayViewportById(config.defaultPointerDisplayId);
+ if (!viewport) {
+ ALOGW("Can't find the designated viewport with ID %" PRId32 " to update cursor input "
+ "mapper. Fall back to default display",
+ config.defaultPointerDisplayId);
+ viewport = config.getDisplayViewportById(ADISPLAY_ID_DEFAULT);
+ }
+
+ if (!viewport) {
+ ALOGE("Still can't find a viable viewport to update cursor input mapper. Skip setting it to"
+ " PointerController.");
+ return;
+ }
+
+ mPointerController->setDisplayViewport(*viewport);
+}
+
void CursorInputMapper::configureParameters() {
mParameters.mode = Parameters::MODE_POINTER;
String8 cursorModeString;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 77d122a..d56f9be 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -117,8 +117,9 @@
void dumpParameters(std::string& dump);
void sync(nsecs_t when);
+ void updatePointerControllerDisplayViewport(const InputReaderConfiguration& config);
};
} // namespace android
-#endif // _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
\ No newline at end of file
+#endif // _UI_INPUTREADER_CURSOR_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index c80a2dc..b66caca 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -552,9 +552,10 @@
* 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
+ * 2. Always use the suggested viewport from WindowManagerService for pointers.
+ * 3. 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.
+ * 4. Otherwise, use a non-display viewport.
*/
std::optional<DisplayViewport> TouchInputMapper::findViewport() {
if (mParameters.hasAssociatedDisplay) {
@@ -564,6 +565,17 @@
return mDevice->getAssociatedViewport();
}
+ if (mDeviceMode == DEVICE_MODE_POINTER) {
+ std::optional<DisplayViewport> viewport =
+ mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
+ if (viewport) {
+ return viewport;
+ } else {
+ ALOGW("Can't find designated display viewport with ID %" PRId32 " for pointers.",
+ mConfig.defaultPointerDisplayId);
+ }
+ }
+
// Check if uniqueDisplayId is specified in idc file.
if (!mParameters.uniqueDisplayId.empty()) {
return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
@@ -749,6 +761,7 @@
(mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
if (mPointerController == nullptr || viewportChanged) {
mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ mPointerController->setDisplayViewport(mViewport);
}
} else {
mPointerController.clear();
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index a9d7793..8ca7e4a 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -90,10 +90,6 @@
mMaxY = maxY;
}
- void setDisplayId(int32_t displayId) {
- mDisplayId = displayId;
- }
-
virtual void setPosition(float x, float y) {
mX = x;
mY = y;
@@ -116,6 +112,10 @@
return mDisplayId;
}
+ virtual void setDisplayViewport(const DisplayViewport& viewport) {
+ mDisplayId = viewport.displayId;
+ }
+
const std::map<int32_t, std::vector<int32_t>>& getSpots() {
return mSpotsByDisplay;
}
@@ -280,6 +280,10 @@
mConfig.showTouches = enabled;
}
+ void setDefaultPointerDisplayId(int32_t pointerDisplayId) {
+ mConfig.defaultPointerDisplayId = pointerDisplayId;
+ }
+
private:
DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
int32_t orientation, const std::string& uniqueId, std::optional<uint8_t> physicalPort,
@@ -3432,12 +3436,18 @@
CursorInputMapper* mapper = new CursorInputMapper(mDevice);
addMapperAndConfigure(mapper);
- // Setup PointerController for second display.
+ // 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,
+ SECOND_DISPLAY_UNIQUE_ID, NO_PORT,
+ ViewportType::VIEWPORT_EXTERNAL);
+ mFakePolicy->setDefaultPointerDisplayId(SECOND_DISPLAY_ID);
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+
mFakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
mFakePointerController->setPosition(100, 200);
mFakePointerController->setButtonState(0);
- mFakePointerController->setDisplayId(SECOND_DISPLAY_ID);
NotifyMotionArgs args;
process(mapper, ARBITRARY_TIME, EV_REL, REL_X, 10);
@@ -6539,14 +6549,16 @@
}
TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
- // Setup PointerController for second display.
+ // Setup for second display.
sp<FakePointerController> fakePointerController = new FakePointerController();
- fakePointerController->setBounds(0, 0, 800 - 1, 480 - 1);
+ fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
fakePointerController->setPosition(100, 200);
fakePointerController->setButtonState(0);
- fakePointerController->setDisplayId(SECONDARY_DISPLAY_ID);
mFakePolicy->setPointerController(mDevice->getId(), fakePointerController);
+ mFakePolicy->setDefaultPointerDisplayId(SECONDARY_DISPLAY_ID);
+ prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL);
+
MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
prepareDisplay(DISPLAY_ORIENTATION_0);
prepareAxes(POSITION);