diff options
author | 2025-02-24 22:07:34 +0000 | |
---|---|---|
committer | 2025-03-18 19:37:13 +0000 | |
commit | 9d63f1cca531b2694b1634827b1e09016c8f3600 (patch) | |
tree | 9f226c1b12fff748e9b467acf475f66db520ef23 | |
parent | 6f9ad7737cb27c4c0ec06d3c6c4c5a1f10c15263 (diff) |
InputReader: Add getter API for the sysfs node path of an InputDevice
Bug: 397208968
Test: Presubmit
Flag: EXEMPT bug fix
Change-Id: I25f41f41ec1f1e47590eef21b982287caea193a6
-rw-r--r-- | services/inputflinger/include/InputReaderBase.h | 3 | ||||
-rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 20 | ||||
-rw-r--r-- | services/inputflinger/reader/InputDevice.cpp | 6 | ||||
-rw-r--r-- | services/inputflinger/reader/InputReader.cpp | 10 | ||||
-rw-r--r-- | services/inputflinger/reader/include/EventHub.h | 5 | ||||
-rw-r--r-- | services/inputflinger/reader/include/InputDevice.h | 6 | ||||
-rw-r--r-- | services/inputflinger/reader/include/InputReader.h | 2 | ||||
-rw-r--r-- | services/inputflinger/tests/FakeEventHub.cpp | 8 | ||||
-rw-r--r-- | services/inputflinger/tests/FakeEventHub.h | 1 | ||||
-rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 16 | ||||
-rw-r--r-- | services/inputflinger/tests/InterfaceMocks.h | 1 | ||||
-rw-r--r-- | services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp | 5 | ||||
-rw-r--r-- | services/inputflinger/tests/fuzzers/MapperHelpers.h | 1 |
13 files changed, 81 insertions, 3 deletions
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 608bec4a0c..c8432005a4 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -443,6 +443,9 @@ public: /* Get the Bluetooth address of an input device, if known. */ virtual std::optional<std::string> getBluetoothAddress(int32_t deviceId) const = 0; + /* Gets the sysfs root path for this device. Returns an empty path if there is none. */ + virtual std::filesystem::path getSysfsRootPath(int32_t deviceId) const = 0; + /* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */ virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0; diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 784baea6f3..a139898ae2 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -246,7 +246,7 @@ static nsecs_t processEventTimestamp(const struct input_event& event) { /** * Returns the sysfs root path of the input device. */ -static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) { +static std::optional<std::filesystem::path> getSysfsRootForEvdevDevicePath(const char* devicePath) { std::error_code errorCode; // Stat the device path to get the major and minor number of the character file @@ -1619,7 +1619,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) { std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked( const std::filesystem::path& devicePath, const std::shared_ptr<PropertyMap>& config) const { const std::optional<std::filesystem::path> sysfsRootPathOpt = - getSysfsRootPath(devicePath.c_str()); + getSysfsRootForEvdevDevicePath(devicePath.c_str()); if (!sysfsRootPathOpt) { return nullptr; } @@ -2666,6 +2666,18 @@ status_t EventHub::disableDevice(int32_t deviceId) { return device->disable(); } +std::filesystem::path EventHub::getSysfsRootPath(int32_t deviceId) const { + std::scoped_lock _l(mLock); + Device* device = getDeviceLocked(deviceId); + if (device == nullptr) { + ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__); + return {}; + } + + return device->associatedDevice ? device->associatedDevice->sysfsRootPath + : std::filesystem::path{}; +} + // TODO(b/274755573): Shift to uevent handling on native side and remove this method // Currently using Java UEventObserver to trigger this which uses UEvent infrastructure that uses a // NETLINK socket to observe UEvents. We can create similar infrastructure on Eventhub side to @@ -2710,6 +2722,10 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() { auto reloadedDevice = AssociatedDevice(dev.associatedDevice->sysfsRootPath, dev.associatedDevice->baseDevConfig); const bool changed = *dev.associatedDevice != reloadedDevice; + if (changed) { + ALOGI("sysfsNodeChanged: Identified change in sysfs nodes for device: %s", + dev.identifier.name.c_str()); + } testedDevices.emplace(dev.associatedDevice, changed); return changed; }; diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 5e42d57f06..594dcba144 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -136,6 +136,8 @@ void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) { } else { dump += "<none>\n"; } + dump += StringPrintf(INDENT2 "SysfsRootPath: %s\n", + mSysfsRootPath.empty() ? "<none>" : mSysfsRootPath.c_str()); dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic)); dump += StringPrintf(INDENT2 "Sources: %s\n", inputEventSourceToString(deviceInfo.getSources()).c_str()); @@ -195,6 +197,10 @@ void InputDevice::addEmptyEventHubDevice(int32_t eventHubId) { DevicePair& devicePair = mDevices[eventHubId]; devicePair.second = createMappers(*devicePair.first, readerConfig); + if (mSysfsRootPath.empty()) { + mSysfsRootPath = devicePair.first->getSysfsRootPath(); + } + // Must change generation to flag this device as changed bumpGeneration(); return out; diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index f2f70c4a10..74ef972848 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -917,6 +917,16 @@ bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId di return *associatedDisplayId == displayId; } +std::filesystem::path InputReader::getSysfsRootPath(int32_t deviceId) const { + std::scoped_lock _l(mLock); + + const InputDevice* device = findInputDeviceLocked(deviceId); + if (!device) { + return {}; + } + return device->getSysfsRootPath(); +} + void InputReader::sysfsNodeChanged(const std::string& sysfsNodePath) { mEventHub->sysfsNodeChanged(sysfsNodePath); mEventHub->wake(); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 913f8f8d1d..3a1f8c6b78 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -399,6 +399,9 @@ public: /* Disable an input device. Closes file descriptor to that device. */ virtual status_t disableDevice(int32_t deviceId) = 0; + /* Gets the sysfs root path for this device. Returns an empty path if there is none. */ + virtual std::filesystem::path getSysfsRootPath(int32_t deviceId) const = 0; + /* Sysfs node changed. Reopen the Eventhub device if any new Peripheral like Light, Battery, * etc. is detected. */ virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0; @@ -614,6 +617,8 @@ public: status_t disableDevice(int32_t deviceId) override final; + std::filesystem::path getSysfsRootPath(int32_t deviceId) const override final; + void sysfsNodeChanged(const std::string& sysfsNodePath) override final; bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override final; diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 4744dd0e4e..a1a8891940 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -81,6 +81,8 @@ public: inline virtual KeyboardType getKeyboardType() const { return mKeyboardType; } + inline std::filesystem::path getSysfsRootPath() const { return mSysfsRootPath; } + bool isEnabled(); void dump(std::string& dump, const std::string& eventHubDevStr); @@ -209,6 +211,7 @@ private: bool mHasMic; bool mDropUntilNextSync; std::optional<bool> mShouldSmoothScroll; + std::filesystem::path mSysfsRootPath; typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code); int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc); @@ -471,6 +474,9 @@ public: inline void setKeyboardType(KeyboardType keyboardType) { return mDevice.setKeyboardType(keyboardType); } + inline std::filesystem::path getSysfsRootPath() const { + return mEventHub->getSysfsRootPath(mId); + } inline bool setKernelWakeEnabled(bool enabled) { return mEventHub->setKernelWakeEnabled(mId, enabled); } diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 6a259373df..9212d37966 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -118,6 +118,8 @@ public: std::optional<std::string> getBluetoothAddress(int32_t deviceId) const override; + std::filesystem::path getSysfsRootPath(int32_t deviceId) const override; + void sysfsNodeChanged(const std::string& sysfsNodePath) override; DeviceId getLastUsedInputDeviceId() override; diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index e72c440480..8987b99525 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -627,6 +627,14 @@ void FakeEventHub::setSysfsRootPath(int32_t deviceId, std::string sysfsRootPath) device->sysfsRootPath = sysfsRootPath; } +std::filesystem::path FakeEventHub::getSysfsRootPath(int32_t deviceId) const { + Device* device = getDevice(deviceId); + if (device == nullptr) { + return {}; + } + return device->sysfsRootPath; +} + void FakeEventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { int32_t foundDeviceId = -1; Device* foundDevice = nullptr; diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index 143b93b245..1cd33c1c98 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -222,6 +222,7 @@ private: std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) const override; std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities( int32_t deviceId, int32_t lightId) const override; + std::filesystem::path getSysfsRootPath(int32_t deviceId) const override; void sysfsNodeChanged(const std::string& sysfsNodePath) override; void dump(std::string&) const override {} void monitor() const override {} diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 43d2378f61..d1d8192395 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -611,8 +611,10 @@ protected: } void addDevice(int32_t eventHubId, const std::string& name, - ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) { + ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration, + std::string sysfsRootPath = "") { mFakeEventHub->addDevice(eventHubId, name, classes); + mFakeEventHub->setSysfsRootPath(eventHubId, sysfsRootPath); if (configuration) { mFakeEventHub->addConfigurationMap(eventHubId, configuration); @@ -664,6 +666,18 @@ TEST_F(InputReaderTest, PolicyGetInputDevices) { ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size()); } +TEST_F(InputReaderTest, GetSysfsRootPath) { + constexpr std::string SYSFS_ROOT = "xyz"; + ASSERT_NO_FATAL_FAILURE( + addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr, SYSFS_ROOT)); + + // Should also have received a notification describing the new input device. + ASSERT_EQ(1U, mFakePolicy->getInputDevices().size()); + InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0]; + + ASSERT_EQ(SYSFS_ROOT, mReader->getSysfsRootPath(inputDevice.getId()).string()); +} + TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) { ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr)); mFakeEventHub->setSysfsRootPath(1, "xyz"); diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index d4e4bb00f7..8eded2e279 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -181,6 +181,7 @@ public: MOCK_METHOD(bool, isDeviceEnabled, (int32_t deviceId), (const, override)); MOCK_METHOD(status_t, enableDevice, (int32_t deviceId), (override)); MOCK_METHOD(status_t, disableDevice, (int32_t deviceId), (override)); + MOCK_METHOD(std::filesystem::path, getSysfsRootPath, (int32_t deviceId), (const, override)); MOCK_METHOD(void, sysfsNodeChanged, (const std::string& sysfsNodePath), (override)); MOCK_METHOD(bool, setKernelWakeEnabled, (int32_t deviceId, bool enabled), (override)); }; diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp index 6be922dfdb..0c8ba50776 100644 --- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -165,6 +165,10 @@ public: return reader->getBluetoothAddress(deviceId); } + std::filesystem::path getSysfsRootPath(int32_t deviceId) const { + return reader->getSysfsRootPath(deviceId); + } + void sysfsNodeChanged(const std::string& sysfsNodePath) { reader->sysfsNodeChanged(sysfsNodePath); } @@ -297,6 +301,7 @@ extern "C" int LLVMFuzzerTestOneInput(uint8_t* data, size_t size) { std::chrono::microseconds(fdp->ConsumeIntegral<size_t>())); }, [&]() -> void { reader->getBluetoothAddress(fdp->ConsumeIntegral<int32_t>()); }, + [&]() -> void { reader->getSysfsRootPath(fdp->ConsumeIntegral<int32_t>()); }, })(); } diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index 9a5903981b..f619c48f3f 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -296,6 +296,7 @@ public: bool isDeviceEnabled(int32_t deviceId) const override { return mFdp->ConsumeBool(); } status_t enableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); } status_t disableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); } + std::filesystem::path getSysfsRootPath(int32_t deviceId) const override { return {}; } void sysfsNodeChanged(const std::string& sysfsNodePath) override {} bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override { return mFdp->ConsumeBool(); |