Loading services/inputflinger/InputReader.cpp +61 −4 Original line number Diff line number Diff line Loading @@ -805,6 +805,30 @@ bool InputReader::isInputDeviceEnabled(int32_t deviceId) { return false; } bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) { AutoMutex _l(mLock); ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) { ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId); return false; } InputDevice* device = mDevices.valueAt(deviceIndex); std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay(); // No associated display. By default, can dispatch to all displays. if (!associatedDisplayId) { return true; } if (*associatedDisplayId == ADISPLAY_ID_NONE) { ALOGW("Device has associated, but no associated display id."); return true; } return *associatedDisplayId == displayId; } void InputReader::dump(std::string& dump) { AutoMutex _l(mLock); Loading Loading @@ -1275,6 +1299,18 @@ void InputDevice::notifyReset(nsecs_t when) { mContext->getListener()->notifyDeviceReset(&args); } std::optional<int32_t> InputDevice::getAssociatedDisplay() { size_t numMappers = mMappers.size(); for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay(); if (associatedDisplayId) { return associatedDisplayId; } } return std::nullopt; } // --- CursorButtonAccumulator --- Loading Loading @@ -2647,7 +2683,7 @@ void CursorInputMapper::configure(nsecs_t when, } // Update the PointerController if viewports changed. if (mParameters.hasAssociatedDisplay) { if (mParameters.mode == Parameters::MODE_POINTER) { getPolicy()->obtainPointerController(getDeviceId()); } bumpGeneration(); Loading Loading @@ -2919,6 +2955,19 @@ void CursorInputMapper::fadePointer() { } } std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() { 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; } // --- RotaryEncoderInputMapper --- RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) : Loading Loading @@ -6511,9 +6560,7 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 ALOG_ASSERT(false); } } const int32_t displayId = mPointerController != nullptr ? mPointerController->getDisplayId() : mViewport.displayId; const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE); const int32_t deviceId = getDeviceId(); std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId); NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, Loading Loading @@ -6830,6 +6877,16 @@ bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCode return true; } std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() { if (mParameters.hasAssociatedDisplay) { if (mDeviceMode == DEVICE_MODE_POINTER) { return std::make_optional(mPointerController->getDisplayId()); } else { return std::make_optional(mViewport.displayId); } } return std::nullopt; } // --- SingleTouchInputMapper --- Loading services/inputflinger/InputReader.h +7 −2 Original line number Diff line number Diff line Loading @@ -146,6 +146,7 @@ public: ssize_t repeat, int32_t token); virtual void cancelVibrate(int32_t deviceId, int32_t token); virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId); protected: // These members are protected so they can be instrumented by test cases. virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber, Loading Loading @@ -320,6 +321,7 @@ public: return value; } std::optional<int32_t> getAssociatedDisplay(); private: InputReaderContext* mContext; int32_t mId; Loading Loading @@ -778,7 +780,9 @@ public: virtual void updateExternalStylusState(const StylusState& state); virtual void fadePointer(); virtual std::optional<int32_t> getAssociatedDisplay() { return std::nullopt; } protected: InputDevice* mDevice; InputReaderContext* mContext; Loading Loading @@ -932,6 +936,7 @@ public: virtual void fadePointer(); virtual std::optional<int32_t> getAssociatedDisplay(); private: // Amount that trackball needs to move in order to generate a key event. static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6; Loading Loading @@ -1025,7 +1030,7 @@ public: virtual void cancelTouch(nsecs_t when); virtual void timeoutExpired(nsecs_t when); virtual void updateExternalStylusState(const StylusState& state); virtual std::optional<int32_t> getAssociatedDisplay(); protected: CursorButtonAccumulator mCursorButtonAccumulator; CursorScrollAccumulator mCursorScrollAccumulator; Loading services/inputflinger/include/InputReaderBase.h +3 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,9 @@ public: virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token) = 0; virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; /* Return true if the device can send input events to the specified display. */ virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0; }; /* Reads raw events from the event hub and processes them, endlessly. */ Loading services/inputflinger/tests/InputReader_test.cpp +49 −4 Original line number Diff line number Diff line Loading @@ -841,6 +841,7 @@ class FakeInputMapper : public InputMapper { bool mResetWasCalled; bool mProcessWasCalled; std::optional<DisplayViewport> mViewport; public: FakeInputMapper(InputDevice* device, uint32_t sources) : InputMapper(device), Loading Loading @@ -909,8 +910,14 @@ private: } } virtual void configure(nsecs_t, const InputReaderConfiguration*, uint32_t) { virtual void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) { mConfigureWasCalled = true; // Find the associated viewport if exist. const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort(); if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { mViewport = config->getDisplayViewportByPort(*displayPort); } } virtual void reset(nsecs_t) { Loading Loading @@ -957,6 +964,13 @@ private: virtual void fadePointer() { } virtual std::optional<int32_t> getAssociatedDisplay() { if (mViewport) { return std::make_optional(mViewport->displayId); } return std::nullopt; } }; Loading Loading @@ -984,9 +998,10 @@ public: } InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name, uint32_t classes) { uint32_t classes, const std::string& location = "") { InputDeviceIdentifier identifier; identifier.name = name; identifier.location = location; int32_t generation = deviceId + 1; return new InputDevice(&mContext, deviceId, generation, controllerNumber, identifier, classes); Loading Loading @@ -1286,7 +1301,7 @@ TEST_F(InputReaderTest, GetInputDevices) { TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { constexpr int32_t deviceId = 1; constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD; InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass); InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass); // Must add at least one mapper or the device will be ignored! FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); Loading Loading @@ -1470,7 +1485,7 @@ TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { constexpr int32_t deviceId = 1; constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD; InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass); InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass); // Must add at least one mapper or the device will be ignored! FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); Loading Loading @@ -1500,6 +1515,36 @@ TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { prevSequenceNum = resetArgs.sequenceNum; } TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { constexpr int32_t deviceId = 1; constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD; const char* DEVICE_LOCATION = "USB1"; InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass, DEVICE_LOCATION); FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_TOUCHSCREEN); device->addMapper(mapper); mReader->setNextDevice(device); addDevice(deviceId, "fake", deviceClass, nullptr); const uint8_t hdmi1 = 1; // Associated touch screen with second display. mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1); // Add default and second display. mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, "local:0", NO_PORT, ViewportType::VIEWPORT_INTERNAL); mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, "local:1", hdmi1, ViewportType::VIEWPORT_EXTERNAL); mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO); mReader->loopOnce(); // Check device. ASSERT_EQ(deviceId, device->getId()); ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID)); ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID)); } // --- InputDeviceTest --- Loading Loading
services/inputflinger/InputReader.cpp +61 −4 Original line number Diff line number Diff line Loading @@ -805,6 +805,30 @@ bool InputReader::isInputDeviceEnabled(int32_t deviceId) { return false; } bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) { AutoMutex _l(mLock); ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) { ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId); return false; } InputDevice* device = mDevices.valueAt(deviceIndex); std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay(); // No associated display. By default, can dispatch to all displays. if (!associatedDisplayId) { return true; } if (*associatedDisplayId == ADISPLAY_ID_NONE) { ALOGW("Device has associated, but no associated display id."); return true; } return *associatedDisplayId == displayId; } void InputReader::dump(std::string& dump) { AutoMutex _l(mLock); Loading Loading @@ -1275,6 +1299,18 @@ void InputDevice::notifyReset(nsecs_t when) { mContext->getListener()->notifyDeviceReset(&args); } std::optional<int32_t> InputDevice::getAssociatedDisplay() { size_t numMappers = mMappers.size(); for (size_t i = 0; i < numMappers; i++) { InputMapper* mapper = mMappers[i]; std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay(); if (associatedDisplayId) { return associatedDisplayId; } } return std::nullopt; } // --- CursorButtonAccumulator --- Loading Loading @@ -2647,7 +2683,7 @@ void CursorInputMapper::configure(nsecs_t when, } // Update the PointerController if viewports changed. if (mParameters.hasAssociatedDisplay) { if (mParameters.mode == Parameters::MODE_POINTER) { getPolicy()->obtainPointerController(getDeviceId()); } bumpGeneration(); Loading Loading @@ -2919,6 +2955,19 @@ void CursorInputMapper::fadePointer() { } } std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() { 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; } // --- RotaryEncoderInputMapper --- RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) : Loading Loading @@ -6511,9 +6560,7 @@ void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32 ALOG_ASSERT(false); } } const int32_t displayId = mPointerController != nullptr ? mPointerController->getDisplayId() : mViewport.displayId; const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE); const int32_t deviceId = getDeviceId(); std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId); NotifyMotionArgs args(mContext->getNextSequenceNum(), when, deviceId, Loading Loading @@ -6830,6 +6877,16 @@ bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCode return true; } std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() { if (mParameters.hasAssociatedDisplay) { if (mDeviceMode == DEVICE_MODE_POINTER) { return std::make_optional(mPointerController->getDisplayId()); } else { return std::make_optional(mViewport.displayId); } } return std::nullopt; } // --- SingleTouchInputMapper --- Loading
services/inputflinger/InputReader.h +7 −2 Original line number Diff line number Diff line Loading @@ -146,6 +146,7 @@ public: ssize_t repeat, int32_t token); virtual void cancelVibrate(int32_t deviceId, int32_t token); virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId); protected: // These members are protected so they can be instrumented by test cases. virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber, Loading Loading @@ -320,6 +321,7 @@ public: return value; } std::optional<int32_t> getAssociatedDisplay(); private: InputReaderContext* mContext; int32_t mId; Loading Loading @@ -778,7 +780,9 @@ public: virtual void updateExternalStylusState(const StylusState& state); virtual void fadePointer(); virtual std::optional<int32_t> getAssociatedDisplay() { return std::nullopt; } protected: InputDevice* mDevice; InputReaderContext* mContext; Loading Loading @@ -932,6 +936,7 @@ public: virtual void fadePointer(); virtual std::optional<int32_t> getAssociatedDisplay(); private: // Amount that trackball needs to move in order to generate a key event. static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6; Loading Loading @@ -1025,7 +1030,7 @@ public: virtual void cancelTouch(nsecs_t when); virtual void timeoutExpired(nsecs_t when); virtual void updateExternalStylusState(const StylusState& state); virtual std::optional<int32_t> getAssociatedDisplay(); protected: CursorButtonAccumulator mCursorButtonAccumulator; CursorScrollAccumulator mCursorScrollAccumulator; Loading
services/inputflinger/include/InputReaderBase.h +3 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,9 @@ public: virtual void vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize, ssize_t repeat, int32_t token) = 0; virtual void cancelVibrate(int32_t deviceId, int32_t token) = 0; /* Return true if the device can send input events to the specified display. */ virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0; }; /* Reads raw events from the event hub and processes them, endlessly. */ Loading
services/inputflinger/tests/InputReader_test.cpp +49 −4 Original line number Diff line number Diff line Loading @@ -841,6 +841,7 @@ class FakeInputMapper : public InputMapper { bool mResetWasCalled; bool mProcessWasCalled; std::optional<DisplayViewport> mViewport; public: FakeInputMapper(InputDevice* device, uint32_t sources) : InputMapper(device), Loading Loading @@ -909,8 +910,14 @@ private: } } virtual void configure(nsecs_t, const InputReaderConfiguration*, uint32_t) { virtual void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) { mConfigureWasCalled = true; // Find the associated viewport if exist. const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort(); if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) { mViewport = config->getDisplayViewportByPort(*displayPort); } } virtual void reset(nsecs_t) { Loading Loading @@ -957,6 +964,13 @@ private: virtual void fadePointer() { } virtual std::optional<int32_t> getAssociatedDisplay() { if (mViewport) { return std::make_optional(mViewport->displayId); } return std::nullopt; } }; Loading Loading @@ -984,9 +998,10 @@ public: } InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name, uint32_t classes) { uint32_t classes, const std::string& location = "") { InputDeviceIdentifier identifier; identifier.name = name; identifier.location = location; int32_t generation = deviceId + 1; return new InputDevice(&mContext, deviceId, generation, controllerNumber, identifier, classes); Loading Loading @@ -1286,7 +1301,7 @@ TEST_F(InputReaderTest, GetInputDevices) { TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) { constexpr int32_t deviceId = 1; constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD; InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass); InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass); // Must add at least one mapper or the device will be ignored! FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); Loading Loading @@ -1470,7 +1485,7 @@ TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) { TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { constexpr int32_t deviceId = 1; constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD; InputDevice* device = mReader->newDevice(deviceId, 0, "fake", deviceClass); InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass); // Must add at least one mapper or the device will be ignored! FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_KEYBOARD); device->addMapper(mapper); Loading Loading @@ -1500,6 +1515,36 @@ TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) { prevSequenceNum = resetArgs.sequenceNum; } TEST_F(InputReaderTest, Device_CanDispatchToDisplay) { constexpr int32_t deviceId = 1; constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD; const char* DEVICE_LOCATION = "USB1"; InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass, DEVICE_LOCATION); FakeInputMapper* mapper = new FakeInputMapper(device, AINPUT_SOURCE_TOUCHSCREEN); device->addMapper(mapper); mReader->setNextDevice(device); addDevice(deviceId, "fake", deviceClass, nullptr); const uint8_t hdmi1 = 1; // Associated touch screen with second display. mFakePolicy->addInputPortAssociation(DEVICE_LOCATION, hdmi1); // Add default and second display. mFakePolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, "local:0", NO_PORT, ViewportType::VIEWPORT_INTERNAL); mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_ORIENTATION_0, "local:1", hdmi1, ViewportType::VIEWPORT_EXTERNAL); mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_DISPLAY_INFO); mReader->loopOnce(); // Check device. ASSERT_EQ(deviceId, device->getId()); ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, DISPLAY_ID)); ASSERT_TRUE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID)); } // --- InputDeviceTest --- Loading