Merge "ueventd: Add `devname sys_name` to `subsystem`, pulling device names from sysfs" into main
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index 3c7107a..7d00195 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -59,9 +59,10 @@
 
 `subsystem_name` is used to match uevent `SUBSYSTEM` value
 
-`devname` takes one of two options
+`devname` takes one of three options
   1. `uevent_devname` specifies that the name of the node will be the uevent `DEVNAME`
-  2. `uevent_devpath` specified that the name of the node will be basename uevent `DEVPATH`
+  2. `uevent_devpath` specifies that the name of the node will be basename uevent `DEVPATH`
+  3. `sys_name` specifies that the name of the node will be the contents of `/sys/DEVPATH/name`
 
 `dirname` is an optional parameter that specifies a directory within `/dev` where the node will be
 created.
diff --git a/init/devices.h b/init/devices.h
index f9f4d79..44ce2a9 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -82,6 +82,7 @@
     enum DevnameSource {
         DEVNAME_UEVENT_DEVNAME,
         DEVNAME_UEVENT_DEVPATH,
+        DEVNAME_SYS_NAME,
     };
 
     Subsystem() {}
@@ -92,10 +93,18 @@
     // Returns the full path for a uevent of a device that is a member of this subsystem,
     // according to the rules parsed from ueventd.rc
     std::string ParseDevPath(const Uevent& uevent) const {
-        std::string devname = devname_source_ == DEVNAME_UEVENT_DEVNAME
-                                      ? uevent.device_name
-                                      : android::base::Basename(uevent.path);
-
+        std::string devname;
+        if (devname_source_ == DEVNAME_UEVENT_DEVNAME) {
+            devname = uevent.device_name;
+        } else if (devname_source_ == DEVNAME_UEVENT_DEVPATH) {
+            devname = android::base::Basename(uevent.path);
+        } else if (devname_source_ == DEVNAME_SYS_NAME) {
+            if (android::base::ReadFileToString("/sys/" + uevent.path + "/name", &devname)) {
+                devname.pop_back();  // Remove terminating newline
+            } else {
+                devname = uevent.device_name;
+            }
+        }
         return dir_name_ + "/" + devname;
     }
 
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp
index d34672e..4395d88 100644
--- a/init/ueventd_parser.cpp
+++ b/init/ueventd_parser.cpp
@@ -218,6 +218,10 @@
         subsystem_.devname_source_ = Subsystem::DEVNAME_UEVENT_DEVPATH;
         return {};
     }
+    if (args[1] == "sys_name") {
+        subsystem_.devname_source_ = Subsystem::DEVNAME_SYS_NAME;
+        return {};
+    }
 
     return Error() << "invalid devname '" << args[1] << "'";
 }