diff options
| author | 2023-03-30 07:47:21 +0000 | |
|---|---|---|
| committer | 2023-03-30 07:47:21 +0000 | |
| commit | a6e9dd2cb4da7f91f2379b44d3320cdb0f472f7c (patch) | |
| tree | 9f50fef2518c3480f08531c7d004c981a1f176c1 | |
| parent | 2cf827faebace4039cb0c0af0def9efdf454af62 (diff) | |
| parent | 5fc7d853d855b7968ee3b3d020a2362b87001f9f (diff) | |
Merge "Support native API to report sysfs nodes changes" into udc-dev
| -rw-r--r-- | services/inputflinger/include/InputReaderBase.h | 3 | ||||
| -rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 50 | ||||
| -rw-r--r-- | services/inputflinger/reader/InputReader.cpp | 4 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/EventHub.h | 7 | ||||
| -rw-r--r-- | services/inputflinger/reader/include/InputReader.h | 2 | ||||
| -rw-r--r-- | services/inputflinger/tests/FakeEventHub.cpp | 29 | ||||
| -rw-r--r-- | services/inputflinger/tests/FakeEventHub.h | 4 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputReader_test.cpp | 24 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp | 4 | ||||
| -rw-r--r-- | services/inputflinger/tests/fuzzers/MapperHelpers.h | 1 | 
10 files changed, 127 insertions, 1 deletions
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h index 841c914d60..1750c64eca 100644 --- a/services/inputflinger/include/InputReaderBase.h +++ b/services/inputflinger/include/InputReaderBase.h @@ -149,6 +149,9 @@ public:      /* Get the Bluetooth address of an input device, if known. */      virtual std::optional<std::string> getBluetoothAddress(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;  };  // --- InputReaderConfiguration --- diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index e65f3af107..ee8dde1d32 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -1531,6 +1531,20 @@ std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDevi      return associatedDevice;  } +bool EventHub::AssociatedDevice::isChanged() const { +    std::unordered_map<int32_t, RawBatteryInfo> newBatteryInfos = +            readBatteryConfiguration(sysfsRootPath); +    std::unordered_map<int32_t, RawLightInfo> newLightInfos = +            readLightsConfiguration(sysfsRootPath); +    std::optional<RawLayoutInfo> newLayoutInfo = readLayoutConfiguration(sysfsRootPath); + +    if (newBatteryInfos == batteryInfos && newLightInfos == lightInfos && +        newLayoutInfo == layoutInfo) { +        return false; +    } +    return true; +} +  void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {      std::scoped_lock _l(mLock);      Device* device = getDeviceLocked(deviceId); @@ -2536,6 +2550,42 @@ status_t EventHub::disableDevice(int32_t deviceId) {      return device->disable();  } +// 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 +// directly observe UEvents instead of triggering from Java side. +void EventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { +    std::scoped_lock _l(mLock); + +    // Check in opening devices +    for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end(); it++) { +        std::unique_ptr<Device>& device = *it; +        if (device->associatedDevice && +            sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) != +                    std::string::npos && +            device->associatedDevice->isChanged()) { +            it = mOpeningDevices.erase(it); +            openDeviceLocked(device->path); +        } +    } + +    // Check in already added device +    std::vector<Device*> devicesToReopen; +    for (const auto& [id, device] : mDevices) { +        if (device->associatedDevice && +            sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) != +                    std::string::npos && +            device->associatedDevice->isChanged()) { +            devicesToReopen.push_back(device.get()); +        } +    } +    for (const auto& device : devicesToReopen) { +        closeDeviceLocked(*device); +        openDeviceLocked(device->path); +    } +    devicesToReopen.clear(); +} +  void EventHub::createVirtualKeyboardLocked() {      InputDeviceIdentifier identifier;      identifier.name = "Virtual"; diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index 9080cc1d26..81ac03b7b3 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -928,6 +928,10 @@ bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {      return *associatedDisplayId == displayId;  } +void InputReader::sysfsNodeChanged(const std::string& sysfsNodePath) { +    mEventHub->sysfsNodeChanged(sysfsNodePath); +} +  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 0b15efed12..20612c767c 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -388,6 +388,10 @@ public:      /* Disable an input device. Closes file descriptor to that device. */      virtual status_t disableDevice(int32_t deviceId) = 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;  };  template <std::size_t BITS> @@ -567,6 +571,8 @@ public:      status_t disableDevice(int32_t deviceId) override final; +    void sysfsNodeChanged(const std::string& sysfsNodePath) override final; +      ~EventHub() override;  private: @@ -578,6 +584,7 @@ private:          std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos;          std::optional<RawLayoutInfo> layoutInfo; +        bool isChanged() const;          bool operator==(const AssociatedDevice&) const = default;          bool operator!=(const AssociatedDevice&) const = default;          std::string dump() const; diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h index e9c989a224..120e15070c 100644 --- a/services/inputflinger/reader/include/InputReader.h +++ b/services/inputflinger/reader/include/InputReader.h @@ -117,6 +117,8 @@ public:      std::optional<std::string> getBluetoothAddress(int32_t deviceId) const override; +    void sysfsNodeChanged(const std::string& sysfsNodePath) override; +  protected:      // These members are protected so they can be instrumented by test cases.      virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId, diff --git a/services/inputflinger/tests/FakeEventHub.cpp b/services/inputflinger/tests/FakeEventHub.cpp index ff6d584007..4626f5add7 100644 --- a/services/inputflinger/tests/FakeEventHub.cpp +++ b/services/inputflinger/tests/FakeEventHub.cpp @@ -594,4 +594,33 @@ std::optional<std::unordered_map<LightColor, int32_t>> FakeEventHub::getLightInt      return lightIt->second;  }; +void FakeEventHub::setSysfsRootPath(int32_t deviceId, std::string sysfsRootPath) const { +    Device* device = getDevice(deviceId); +    if (device == nullptr) { +        return; +    } +    device->sysfsRootPath = sysfsRootPath; +} + +void FakeEventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { +    int32_t foundDeviceId = -1; +    Device* foundDevice = nullptr; +    for (size_t i = 0; i < mDevices.size(); i++) { +        Device* d = mDevices.valueAt(i); +        if (sysfsNodePath.find(d->sysfsRootPath) != std::string::npos) { +            foundDeviceId = mDevices.keyAt(i); +            foundDevice = d; +        } +    } +    if (foundDevice == nullptr) { +        return; +    } +    // If device sysfs changed -> reopen the device +    if (!mRawLightInfos.empty() && !foundDevice->classes.test(InputDeviceClass::LIGHT)) { +        removeDevice(foundDeviceId); +        addDevice(foundDeviceId, foundDevice->identifier.name, +                  foundDevice->classes | InputDeviceClass::LIGHT, foundDevice->identifier.bus); +    } +} +  } // namespace android diff --git a/services/inputflinger/tests/FakeEventHub.h b/services/inputflinger/tests/FakeEventHub.h index e0a3f9eee1..8e06940aec 100644 --- a/services/inputflinger/tests/FakeEventHub.h +++ b/services/inputflinger/tests/FakeEventHub.h @@ -64,6 +64,7 @@ class FakeEventHub : public EventHubInterface {          std::vector<VirtualKeyDefinition> virtualKeys;          bool enabled;          std::optional<RawLayoutInfo> layoutInfo; +        std::string sysfsRootPath;          status_t enable() {              enabled = true; @@ -152,6 +153,7 @@ public:      void enqueueEvent(nsecs_t when, nsecs_t readTime, int32_t deviceId, int32_t type, int32_t code,                        int32_t value);      void assertQueueIsEmpty(); +    void setSysfsRootPath(int32_t deviceId, std::string sysfsRootPath) const;  private:      Device* getDevice(int32_t deviceId) const; @@ -212,7 +214,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; - +    void sysfsNodeChanged(const std::string& sysfsNodePath) override;      void dump(std::string&) const override {}      void monitor() const override {}      void requestReopenDevices() override {} diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp index 92d5357d8e..3d0fbb4455 100644 --- a/services/inputflinger/tests/InputReader_test.cpp +++ b/services/inputflinger/tests/InputReader_test.cpp @@ -644,6 +644,30 @@ TEST_F(InputReaderTest, PolicyGetInputDevices) {      ASSERT_EQ(0U, inputDevices[0].getMotionRanges().size());  } +TEST_F(InputReaderTest, InputDeviceRecreatedOnSysfsNodeChanged) { +    ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr)); +    mFakeEventHub->setSysfsRootPath(1, "xyz"); + +    // Should also have received a notification describing the new input device. +    ASSERT_EQ(1U, mFakePolicy->getInputDevices().size()); +    InputDeviceInfo inputDevice = mFakePolicy->getInputDevices()[0]; +    ASSERT_EQ(0U, inputDevice.getLights().size()); + +    RawLightInfo infoMonolight = {.id = 123, +                                  .name = "mono_keyboard_backlight", +                                  .maxBrightness = 255, +                                  .flags = InputLightClass::BRIGHTNESS, +                                  .path = ""}; +    mFakeEventHub->addRawLightInfo(/*rawId=*/123, std::move(infoMonolight)); +    mReader->sysfsNodeChanged("xyz"); +    mReader->loopOnce(); + +    // Should also have received a notification describing the new recreated input device. +    ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged()); +    inputDevice = mFakePolicy->getInputDevices()[0]; +    ASSERT_EQ(1U, inputDevice.getLights().size()); +} +  TEST_F(InputReaderTest, GetMergedInputDevices) {      constexpr int32_t deviceId = END_RESERVED_ID + 1000;      constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1}; diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp index 20242b1c15..baece3c110 100644 --- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp +++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp @@ -165,6 +165,10 @@ public:          return reader->getBluetoothAddress(deviceId);      } +    void sysfsNodeChanged(const std::string& sysfsNodePath) { +        reader->sysfsNodeChanged(sysfsNodePath); +    } +  private:      std::unique_ptr<InputReaderInterface> reader;  }; diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h index d9a07b96d5..9f4aa5cd5e 100644 --- a/services/inputflinger/tests/fuzzers/MapperHelpers.h +++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h @@ -225,6 +225,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>(); } +    void sysfsNodeChanged(const std::string& sysfsNodePath) override {}  };  class FuzzPointerController : public PointerControllerInterface {  |