@@ -1620,41 +1620,43 @@ std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDevi
16201620
16211621 const auto & path = *sysfsRootPathOpt;
16221622
1623- std::shared_ptr<const AssociatedDevice> associatedDevice = std::make_shared<AssociatedDevice>(
1624- AssociatedDevice{.sysfsRootPath = path,
1625- .batteryInfos = readBatteryConfiguration (path),
1626- .lightInfos = readLightsConfiguration (path),
1627- .layoutInfo = readLayoutConfiguration (path)});
1628-
1629- bool associatedDeviceChanged = false ;
1623+ std::shared_ptr<const AssociatedDevice> associatedDevice;
16301624 for (const auto & [id, dev] : mDevices ) {
1631- if (dev->associatedDevice && dev->associatedDevice ->sysfsRootPath = = path) {
1632- if (*associatedDevice != *dev-> associatedDevice ) {
1633- associatedDeviceChanged = true ;
1634- dev-> associatedDevice = associatedDevice;
1635- }
1625+ if (! dev->associatedDevice || dev->associatedDevice ->sysfsRootPath ! = path) {
1626+ continue ;
1627+ }
1628+ if (! associatedDevice) {
1629+ // Found matching associated device for the first time.
16361630 associatedDevice = dev->associatedDevice ;
1631+ // Reload this associated device if needed.
1632+ const auto reloadedDevice = AssociatedDevice (path);
1633+ if (reloadedDevice != *dev->associatedDevice ) {
1634+ ALOGI (" The AssociatedDevice changed for path '%s'. Using new AssociatedDevice: %s" ,
1635+ path.c_str (), associatedDevice->dump ().c_str ());
1636+ associatedDevice = std::make_shared<AssociatedDevice>(std::move (reloadedDevice));
1637+ }
16371638 }
1639+ // Update the associatedDevice.
1640+ dev->associatedDevice = associatedDevice;
1641+ }
1642+
1643+ if (!associatedDevice) {
1644+ // No existing associated device found for this path, so create a new one.
1645+ associatedDevice = std::make_shared<AssociatedDevice>(path);
16381646 }
1639- ALOGI_IF (associatedDeviceChanged,
1640- " The AssociatedDevice changed for path '%s'. Using new AssociatedDevice: %s" ,
1641- path.c_str (), associatedDevice->dump ().c_str ());
16421647
16431648 return associatedDevice;
16441649}
16451650
1646- bool EventHub::AssociatedDevice::isChanged () const {
1647- std::unordered_map<int32_t , RawBatteryInfo> newBatteryInfos =
1648- readBatteryConfiguration (sysfsRootPath);
1649- std::unordered_map<int32_t , RawLightInfo> newLightInfos =
1650- readLightsConfiguration (sysfsRootPath);
1651- std::optional<RawLayoutInfo> newLayoutInfo = readLayoutConfiguration (sysfsRootPath);
1651+ EventHub::AssociatedDevice::AssociatedDevice (const std::filesystem::path& sysfsRootPath)
1652+ : sysfsRootPath(sysfsRootPath),
1653+ batteryInfos (readBatteryConfiguration(sysfsRootPath)),
1654+ lightInfos(readLightsConfiguration(sysfsRootPath)),
1655+ layoutInfo(readLayoutConfiguration(sysfsRootPath)) {}
16521656
1653- if (newBatteryInfos == batteryInfos && newLightInfos == lightInfos &&
1654- newLayoutInfo == layoutInfo) {
1655- return false ;
1656- }
1657- return true ;
1657+ std::string EventHub::AssociatedDevice::dump () const {
1658+ return StringPrintf (" path=%s, numBatteries=%zu, numLight=%zu" , sysfsRootPath.c_str (),
1659+ batteryInfos.size (), lightInfos.size ());
16581660}
16591661
16601662void EventHub::vibrate (int32_t deviceId, const VibrationElement& element) {
@@ -2646,33 +2648,56 @@ status_t EventHub::disableDevice(int32_t deviceId) {
26462648void EventHub::sysfsNodeChanged (const std::string& sysfsNodePath) {
26472649 std::scoped_lock _l (mLock );
26482650
2649- // Check in opening devices
2650- for (auto it = mOpeningDevices .begin (); it != mOpeningDevices .end (); it++) {
2651- std::unique_ptr<Device>& device = *it;
2652- if (device->associatedDevice &&
2653- sysfsNodePath.find (device->associatedDevice ->sysfsRootPath .string ()) !=
2654- std::string::npos &&
2655- device->associatedDevice ->isChanged ()) {
2656- it = mOpeningDevices .erase (it);
2657- openDeviceLocked (device->path );
2651+ // Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid
2652+ // testing the same node multiple times.
2653+ std::map<std::shared_ptr<const AssociatedDevice>, bool /* changed*/ > testedDevices;
2654+ auto isAssociatedDeviceChanged = [&testedDevices, &sysfsNodePath](const Device& dev) {
2655+ if (!dev.associatedDevice ) {
2656+ return false ;
26582657 }
2659- }
2658+ if (auto testedIt = testedDevices.find (dev.associatedDevice );
2659+ testedIt != testedDevices.end ()) {
2660+ return testedIt->second ;
2661+ }
2662+ // Cache miss
2663+ if (sysfsNodePath.find (dev.associatedDevice ->sysfsRootPath .string ()) == std::string::npos) {
2664+ testedDevices.emplace (dev.associatedDevice , false );
2665+ return false ;
2666+ }
2667+ auto reloadedDevice = AssociatedDevice (dev.associatedDevice ->sysfsRootPath );
2668+ const bool changed = *dev.associatedDevice != reloadedDevice;
2669+ testedDevices.emplace (dev.associatedDevice , changed);
2670+ return changed;
2671+ };
26602672
2661- // Check in already added device
2662- std::vector<Device*> devicesToReopen;
2663- for (const auto & [id, device] : mDevices ) {
2664- if (device->associatedDevice &&
2665- sysfsNodePath.find (device->associatedDevice ->sysfsRootPath .string ()) !=
2666- std::string::npos &&
2667- device->associatedDevice ->isChanged ()) {
2668- devicesToReopen.push_back (device.get ());
2673+ std::set<Device*> devicesToClose;
2674+ std::set<std::string /* path*/ > devicesToOpen;
2675+
2676+ // Check in opening devices. If its associated device changed,
2677+ // the device should be removed from mOpeningDevices and needs to be opened again.
2678+ std::erase_if (mOpeningDevices , [&](const auto & dev) {
2679+ if (isAssociatedDeviceChanged (*dev)) {
2680+ devicesToOpen.emplace (dev->path );
2681+ return true ;
2682+ }
2683+ return false ;
2684+ });
2685+
2686+ // Check in already added device. If its associated device changed,
2687+ // the device needs to be re-opened.
2688+ for (const auto & [id, dev] : mDevices ) {
2689+ if (isAssociatedDeviceChanged (*dev)) {
2690+ devicesToOpen.emplace (dev->path );
2691+ devicesToClose.emplace (dev.get ());
26692692 }
26702693 }
2671- for (const auto & device : devicesToReopen) {
2694+
2695+ for (auto * device : devicesToClose) {
26722696 closeDeviceLocked (*device);
2673- openDeviceLocked (device->path );
26742697 }
2675- devicesToReopen.clear ();
2698+ for (const auto & path : devicesToOpen) {
2699+ openDeviceLocked (path);
2700+ }
26762701}
26772702
26782703void EventHub::createVirtualKeyboardLocked () {
@@ -2972,9 +2997,4 @@ void EventHub::monitor() const {
29722997 std::unique_lock<std::mutex> lock (mLock );
29732998}
29742999
2975- std::string EventHub::AssociatedDevice::dump () const {
2976- return StringPrintf (" path=%s, numBatteries=%zu, numLight=%zu" , sysfsRootPath.c_str (),
2977- batteryInfos.size (), lightInfos.size ());
2978- }
2979-
29803000} // namespace android
0 commit comments