power: Add a Udev wrapper around udev_device_get_devlinks_list_entry
Proximity sensors are given devlinks that correspond to what kind of device
they are a source of proximity info for (e.g. proximity-lte,
proximity-wifi-left).
This helper function allows powerd to discover the devlinks that udev has
assigned to a given device.
TEST=manual
BUG=b:74586744
Change-Id: Ie99b209d7cc40d928d0ca013f1aa3c4b9a540211
Signed-off-by: Enrico Granata <egranata@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1148957
Reviewed-by: Dan Erat <derat@chromium.org>
(cherry picked from commit 73786143269064238e159c2804a767a4a8415cdf)
Reviewed-on: https://chromium-review.googlesource.com/1154709
Commit-Queue: Jongpil Jung <jongpil19.jung@samsung.corp-partner.google.com>
Tested-by: Jongpil Jung <jongpil19.jung@samsung.corp-partner.google.com>
diff --git a/power_manager/powerd/system/input_watcher_unittest.cc b/power_manager/powerd/system/input_watcher_unittest.cc
index a86d542..27e730d 100644
--- a/power_manager/powerd/system/input_watcher_unittest.cc
+++ b/power_manager/powerd/system/input_watcher_unittest.cc
@@ -171,7 +171,7 @@
input_device_info.sysname = name;
input_device_info.syspath = syspath;
udev_.AddSubsystemDevice(InputWatcher::kInputUdevSubsystem,
- input_device_info);
+ input_device_info, {});
event_device_factory_->RegisterDevice(path, device);
}
diff --git a/power_manager/powerd/system/udev.cc b/power_manager/powerd/system/udev.cc
index 080a362..50b9fea 100644
--- a/power_manager/powerd/system/udev.cc
+++ b/power_manager/powerd/system/udev.cc
@@ -15,6 +15,7 @@
#include "power_manager/powerd/system/tagged_device.h"
#include "power_manager/powerd/system/udev_subsystem_observer.h"
#include "power_manager/powerd/system/udev_tagged_device_observer.h"
+#include "power_manager/powerd/system/udev_util.h"
namespace power_manager {
namespace system {
@@ -65,6 +66,13 @@
return true;
}
+struct UdevDeviceDeleter {
+ void operator()(udev_device* dev) {
+ if (dev)
+ udev_device_unref(dev);
+ }
+};
+
}; // namespace
Udev::Udev() : udev_(NULL), udev_monitor_(NULL) {}
@@ -274,6 +282,34 @@
return parent != NULL;
}
+bool Udev::GetDevlinks(const std::string& syspath,
+ std::vector<std::string>* out) {
+ DCHECK(udev_);
+ DCHECK(out);
+
+ std::unique_ptr<udev_device, UdevDeviceDeleter> device(
+ udev_device_new_from_syspath(udev_, syspath.c_str()));
+ if (!device) {
+ PLOG(WARNING) << "Failed to open udev device: " << syspath;
+ return false;
+ }
+
+ out->clear();
+
+ // TODO(egranata): maybe write a wrapper around udev_list to support
+ // for(entry : list) {...}
+ struct udev_list_entry* devlink =
+ udev_device_get_devlinks_list_entry(device.get());
+ while (devlink) {
+ const char* name = udev_list_entry_get_name(devlink);
+ if (name)
+ out->push_back(name);
+ devlink = udev_list_entry_get_next(devlink);
+ }
+
+ return true;
+}
+
void Udev::OnFileCanReadWithoutBlocking(int fd) {
struct udev_device* dev = udev_monitor_receive_device(udev_monitor_);
if (!dev)
diff --git a/power_manager/powerd/system/udev.h b/power_manager/powerd/system/udev.h
index 6564285..748a3d4 100644
--- a/power_manager/powerd/system/udev.h
+++ b/power_manager/powerd/system/udev.h
@@ -96,6 +96,11 @@
const std::string& sysattr,
const std::string& stop_at_devtype,
std::string* parent_syspath) = 0;
+
+ // For the device specified by |syspath|, finds all the devlinks that
+ // udev configured, and stores their paths in |out|.
+ virtual bool GetDevlinks(const std::string& syspath,
+ std::vector<std::string>* out) = 0;
};
// Actual implementation of UdevInterface.
@@ -127,6 +132,8 @@
const std::string& sysattr,
const std::string& stopat_devtype,
std::string* parent_syspath) override;
+ bool GetDevlinks(const std::string& syspath,
+ std::vector<std::string>* out) override;
// base::MessageLoopForIO::Watcher implementation:
void OnFileCanReadWithoutBlocking(int fd) override;
diff --git a/power_manager/powerd/system/udev_stub.cc b/power_manager/powerd/system/udev_stub.cc
index 9a93cc8..6db54c0 100644
--- a/power_manager/powerd/system/udev_stub.cc
+++ b/power_manager/powerd/system/udev_stub.cc
@@ -50,8 +50,10 @@
}
void UdevStub::AddSubsystemDevice(const std::string& subsystem,
- const UdevDeviceInfo& udev_device) {
+ const UdevDeviceInfo& udev_device,
+ std::initializer_list<std::string> dlinks) {
subsystem_devices_[subsystem].push_back(udev_device);
+ devlinks_.emplace(udev_device.syspath, dlinks);
}
void UdevStub::AddSubsystemObserver(const std::string& subsystem,
@@ -131,5 +133,15 @@
return true;
}
+bool UdevStub::GetDevlinks(const std::string& syspath,
+ std::vector<std::string>* out) {
+ auto iter = devlinks_.find(syspath);
+ if (iter == devlinks_.end())
+ return false;
+
+ *out = iter->second;
+ return true;
+}
+
} // namespace system
} // namespace power_manager
diff --git a/power_manager/powerd/system/udev_stub.h b/power_manager/powerd/system/udev_stub.h
index 16a909a..8f56b53 100644
--- a/power_manager/powerd/system/udev_stub.h
+++ b/power_manager/powerd/system/udev_stub.h
@@ -43,7 +43,8 @@
// Adds a device to be returned by GetSubsystemDevices.
void AddSubsystemDevice(const std::string& subsystem,
- const UdevDeviceInfo& udev_device);
+ const UdevDeviceInfo& udev_device,
+ std::initializer_list<std::string> devlinks);
// UdevInterface implementation:
void AddSubsystemObserver(const std::string& subsystem,
@@ -65,6 +66,8 @@
const std::string& sysattr,
const std::string& stop_at_devtype,
std::string* parent_syspath) override;
+ bool GetDevlinks(const std::string& syspath,
+ std::vector<std::string>* out) override;
private:
// List of subsystem devices returned when GetSubsystemDevices is called.
@@ -82,6 +85,9 @@
// Maps a syspath to the corresponding TaggedDevice.
std::map<std::string, TaggedDevice> tagged_devices_;
+ // Maps a syspath to the corresponding devlinks.
+ std::map<std::string, std::vector<std::string>> devlinks_;
+
// Maps a pair (device syspath, sysattr name) to the corresponding sysattr
// value.
typedef std::map<std::pair<std::string, std::string>, std::string> SysattrMap;