diff options
| -rw-r--r-- | libs/input/input_flags.aconfig | 7 | ||||
| -rw-r--r-- | services/inputflinger/include/InputReaderBase.h | 10 | ||||
| -rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 29 | ||||
| -rw-r--r-- | services/inputflinger/reader/InputDevice.cpp | 8 | ||||
| -rw-r--r-- | services/inputflinger/reader/InputReader.cpp | 10 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/EventHub.h | 9 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/InputDevice.h | 5 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/InputReader.h | 2 | ||||
| -rw-r--r-- | services/inputflinger/tests/FakeEventHub.cpp | 21 | ||||
| -rw-r--r-- | services/inputflinger/tests/FakeEventHub.h | 4 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 14 | ||||
| -rw-r--r-- | services/inputflinger/tests/InterfaceMocks.h | 1 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp | 4 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/MapperHelpers.h | 3 |
14 files changed, 127 insertions, 0 deletions
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig index 701fb43c1f..e93c04df6d 100644 --- a/libs/input/input_flags.aconfig +++ b/libs/input/input_flags.aconfig @@ -214,3 +214,10 @@ flag { description: "Enable telemetry for rotary input" bug: "370353565" } + +flag { + name: "set_input_device_kernel_wake" + namespace: "input" + description: "Set input device's power/wakeup sysfs node" + bug: "372812925" +} diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 756a29b754..6093c91e34 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -426,6 +426,16 @@ public: /* Notifies that mouse cursor faded due to typing. */ virtual void notifyMouseCursorFadedOnTyping() = 0; + + /* Set whether the given input device can wake up the kernel from sleep + * when it generates input events. By default, usually only internal (built-in) + * input devices can wake the kernel from sleep. For an external input device + * that supports remote wakeup to be able to wake the kernel, this must be called + * after each time the device is connected/added. + * + * Returns true if setting power wakeup was successful. + */ + virtual bool setKernelWakeEnabled(int32_t deviceId, bool enabled) = 0; }; // --- TouchAffineTransformation --- diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index f8cd9733b0..8dec9e5f40 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -2848,6 +2848,35 @@ void EventHub::requestReopenDevices() { mNeedToReopenDevices = true; } +bool EventHub::setKernelWakeEnabled(int32_t deviceId, bool enabled) { + std::scoped_lock _l(mLock); + std::string enabledStr = enabled ? "enabled" : "disabled"; + Device* device = getDeviceLocked(deviceId); + if (device == nullptr) { + ALOGE("Device Id %d does not exist for setting power wakeup", deviceId); + return false; + } + if (device->associatedDevice == nullptr) { + return false; + } + std::filesystem::path currentPath = device->associatedDevice->sysfsRootPath; + while (!currentPath.empty() && currentPath != "/") { + std::string nodePath = currentPath / "power/wakeup"; + if (std::filesystem::exists(nodePath)) { + if (base::WriteStringToFile(enabledStr, nodePath)) { + return true; + + } + // No need to continue searching in parent directories as power/wakeup nodes + // higher up may control other subdevices. + ALOGW("Failed to set power/wakeup node at %s", nodePath.c_str()); + return false; + } + currentPath = currentPath.parent_path(); + } + return false; +} + void EventHub::dump(std::string& dump) const { dump += "Event Hub State:\n"; diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp index 02eeb0a8de..5e42d57f06 100644 --- a/services/inputflinger/reader/InputDevice.cpp +++ b/services/inputflinger/reader/InputDevice.cpp @@ -745,6 +745,14 @@ void InputDevice::setKeyboardType(KeyboardType keyboardType) { } } +bool InputDevice::setKernelWakeEnabled(bool enabled) { + bool success = false; + for_each_subdevice([&enabled, &success](InputDeviceContext& context) { + success |= context.setKernelWakeEnabled(enabled); + }); + return success; +} + InputDeviceContext::InputDeviceContext(InputDevice& device, int32_t eventHubId) : mDevice(device), mContext(device.getContext()), diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index ab2704237f..a2b7e82154 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -901,6 +901,16 @@ void InputReader::notifyMouseCursorFadedOnTyping() { mPreventingTouchpadTaps = true; } +bool InputReader::setKernelWakeEnabled(int32_t deviceId, bool enabled) { + std::scoped_lock _l(mLock); + + InputDevice* device = findInputDeviceLocked(deviceId); + if (device) { + return device->setKernelWakeEnabled(enabled); + } + return false; +} + void InputReader::dump(std::string& dump) { std::scoped_lock _l(mLock); diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index dffd8e3c7a..4336945e96 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -396,6 +396,13 @@ public: /* 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; + + /* Set whether the given input device can wake up the kernel from sleep + * when it generates input events. By default, usually only internal (built-in) + * input devices can wake the kernel from sleep. For an external input device + * that supports remote wakeup to be able to wake the kernel, this must be called + * after each time the device is connected/added. */ + virtual bool setKernelWakeEnabled(int32_t deviceId, bool enabled) = 0; }; template <std::size_t BITS> @@ -603,6 +610,8 @@ public: void sysfsNodeChanged(const std::string& sysfsNodePath) override final; + bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override final; + ~EventHub() override; private: diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h index 8958d9ec0b..abe7a5fa6e 100644 --- a/services/inputflinger/reader/include/InputDevice.h +++ b/services/inputflinger/reader/include/InputDevice.h @@ -139,6 +139,8 @@ public: std::optional<HardwareProperties> getTouchpadHardwareProperties(); + bool setKernelWakeEnabled(bool enabled); + // construct and add a mapper to the input device template <class T, typename... Args> T& addMapper(int32_t eventHubId, Args... args) { @@ -469,6 +471,9 @@ public: inline void setKeyboardType(KeyboardType keyboardType) { return mDevice.setKeyboardType(keyboardType); } + inline bool setKernelWakeEnabled(bool enabled) { + return mEventHub->setKernelWakeEnabled(mId, enabled); + } private: InputDevice& mDevice; diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index 100387195a..7614a05470 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -120,6 +120,8 @@ public: void notifyMouseCursorFadedOnTyping() override; + bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override; + protected: // These members are protected so they can be instrumented by test cases. virtual std::shared_ptr<InputDevice> createDeviceLocked(nsecs_t when, int32_t deviceId, diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index 943de6e3cf..e72c440480 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -650,4 +650,25 @@ void FakeEventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { } } +bool FakeEventHub::setKernelWakeEnabled(int32_t deviceId, bool enabled) { + Device* device = getDevice(deviceId); + if (device == nullptr) { + return false; + } + mKernelWakeup.emplace(deviceId, enabled); + return true; +} + +bool FakeEventHub::fakeReadKernelWakeup(int32_t deviceId) const { + Device* device = getDevice(deviceId); + if (device == nullptr) { + return false; + } + auto it = mKernelWakeup.find(deviceId); + if (it == mKernelWakeup.end()) { + return false; + } + return it->second; +} + } // namespace android diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index 2dfbb2388a..143b93b245 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -94,6 +94,8 @@ class FakeEventHub : public EventHubInterface { // Simulates a device light intensities, from light id to light intensities map. std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>> mLightIntensities; + // fake sysfs node path and value. + std::unordered_map<int32_t /*deviceId*/, bool /* wakeupNode*/> mKernelWakeup; public: static constexpr int32_t DEFAULT_BATTERY = 1; @@ -158,6 +160,8 @@ public: void setMtSlotValues(int32_t deviceId, int32_t axis, const std::vector<int32_t>& values); base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis, size_t slotCount) const override; + bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override; + bool fakeReadKernelWakeup(int32_t deviceId) const; private: Device* getDevice(int32_t deviceId) const; diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 6c8b65c018..19b738ea9d 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -1392,6 +1392,20 @@ TEST_F(InputReaderTest, LightGetColor) { ASSERT_EQ(mReader->getLightColor(deviceId, /*lightId=*/1), LIGHT_BRIGHTNESS); } +TEST_F(InputReaderTest, SetPowerWakeUp) { + ASSERT_NO_FATAL_FAILURE(addDevice(1, "1st", InputDeviceClass::KEYBOARD, nullptr)); + ASSERT_NO_FATAL_FAILURE(addDevice(2, "2nd", InputDeviceClass::KEYBOARD, nullptr)); + ASSERT_NO_FATAL_FAILURE(addDevice(3, "3rd", InputDeviceClass::KEYBOARD, nullptr)); + + ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(1), false); + + ASSERT_TRUE(mFakeEventHub->setKernelWakeEnabled(2, true)); + ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(2), true); + + ASSERT_TRUE(mFakeEventHub->setKernelWakeEnabled(3, false)); + ASSERT_EQ(mFakeEventHub->fakeReadKernelWakeup(3), false); +} + // --- InputReaderIntegrationTest --- // These tests create and interact with the InputReader only through its interface. diff --git a/services/inputflinger/tests/InterfaceMocks.h b/services/inputflinger/tests/InterfaceMocks.h index a43e4e4d80..25e2b4557e 100644 --- a/services/inputflinger/tests/InterfaceMocks.h +++ b/services/inputflinger/tests/InterfaceMocks.h @@ -180,6 +180,7 @@ public: MOCK_METHOD(status_t, enableDevice, (int32_t deviceId), (override)); MOCK_METHOD(status_t, disableDevice, (int32_t deviceId), (override)); MOCK_METHOD(void, sysfsNodeChanged, (const std::string& sysfsNodePath), (override)); + MOCK_METHOD(bool, setKernelWakeEnabled, (int32_t deviceId, bool enabled), (override)); }; class MockPointerChoreographerPolicyInterface : public PointerChoreographerPolicyInterface { diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp index 5442a65f2f..64f3c279a6 100644 --- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -171,6 +171,10 @@ public: void notifyMouseCursorFadedOnTyping() override { reader->notifyMouseCursorFadedOnTyping(); } + bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override { + return reader->setKernelWakeEnabled(deviceId, enabled); + } + private: std::unique_ptr<InputReaderInterface> reader; }; diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index fa8270a3d9..60c676da58 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -269,6 +269,9 @@ public: status_t enableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); } status_t disableDevice(int32_t deviceId) override { return mFdp->ConsumeIntegral<status_t>(); } void sysfsNodeChanged(const std::string& sysfsNodePath) override {} + bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override { + return mFdp->ConsumeBool(); + } }; class FuzzInputReaderPolicy : public InputReaderPolicyInterface { |