ueventd: Break devices.cpp into discrete classes
devices.cpp handles too many things for creating one class. This
change breaks it up into various files and classes.
* Parsing is moved to ueventd_parser.cpp
* Reading from the uevent socket and Cold booting is moved to a
UeventListener class, in uevent_listener.cpp
* Firmware handling is moved to firmware_handler.cpp
* The remaining contents form a DeviceHandler class within devices.cpp
Bug: 33785894
Test: boot bullhead x40, observe no major differences in /dev and /sys
Test: boot sailfish x40, observe no major differences in /dev and /sys
Test: init unit tests
Change-Id: I846a2e5995fbb344c7a8e349065c18a934fa6aba
diff --git a/init/devices.h b/init/devices.h
index 647b4c4..50f49fc 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -20,35 +20,14 @@
#include <sys/stat.h>
#include <sys/types.h>
-#include <functional>
+#include <algorithm>
#include <string>
#include <vector>
-#include "init_parser.h"
+#include <android-base/file.h>
+#include <selinux/label.h>
-enum coldboot_action_t {
- // coldboot continues without creating the device for the uevent
- COLDBOOT_CONTINUE = 0,
- // coldboot continues after creating the device for the uevent
- COLDBOOT_CREATE,
- // coldboot stops after creating the device for uevent but doesn't
- // create the COLDBOOT_DONE file
- COLDBOOT_STOP,
- // same as COLDBOOT_STOP, but creates the COLDBOOT_DONE file
- COLDBOOT_FINISH
-};
-
-struct uevent {
- std::string action;
- std::string path;
- std::string subsystem;
- std::string firmware;
- std::string partition_name;
- std::string device_name;
- int partition_num;
- int major;
- int minor;
-};
+#include "uevent.h"
class Permissions {
public:
@@ -93,9 +72,15 @@
// 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(uevent* uevent) const;
+ std::string ParseDevPath(const Uevent& uevent) const {
+ std::string devname = devname_source_ == DevnameSource::DEVNAME_UEVENT_DEVNAME
+ ? uevent.device_name
+ : android::base::Basename(uevent.path);
- bool operator==(const std::string& string_name) { return name_ == string_name; }
+ return dir_name_ + "/" + devname;
+ }
+
+ bool operator==(const std::string& string_name) const { return name_ == string_name; }
private:
enum class DevnameSource {
@@ -108,34 +93,54 @@
DevnameSource devname_source_;
};
-class SubsystemParser : public SectionParser {
+class PlatformDeviceList {
public:
- SubsystemParser() {}
- bool ParseSection(std::vector<std::string>&& args, const std::string& filename, int line,
- std::string* err) override;
- bool ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) override;
- void EndSection() override;
+ void Add(const std::string& path) { platform_devices_.emplace_back(path); }
+ void Remove(const std::string& path) {
+ auto it = std::find(platform_devices_.begin(), platform_devices_.end(), path);
+ if (it != platform_devices_.end()) platform_devices_.erase(it);
+ }
+ bool Find(const std::string& path, std::string* out_path) const;
+ auto size() const { return platform_devices_.size(); }
private:
- bool ParseDevName(std::vector<std::string>&& args, std::string* err);
- bool ParseDirName(std::vector<std::string>&& args, std::string* err);
-
- Subsystem subsystem_;
+ std::vector<std::string> platform_devices_;
};
-bool ParsePermissionsLine(std::vector<std::string>&& args, std::string* err, bool is_sysfs);
-typedef std::function<coldboot_action_t(struct uevent* uevent)> coldboot_callback;
-extern coldboot_action_t handle_device_fd(coldboot_callback fn = nullptr);
-extern void device_init(const char* path = nullptr, coldboot_callback fn = nullptr);
-extern void device_close();
-int get_device_fd();
+class DeviceHandler {
+ public:
+ friend class DeviceHandlerTester;
+
+ DeviceHandler();
+ DeviceHandler(std::vector<Permissions> dev_permissions,
+ std::vector<SysfsPermissions> sysfs_permissions,
+ std::vector<Subsystem> subsystems);
+ ~DeviceHandler(){};
+
+ void HandleDeviceEvent(const Uevent& uevent);
+ std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
+
+ private:
+ void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
+ std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
+ const std::string& path, const std::vector<std::string>& links) const;
+ void MakeDevice(const std::string& path, int block, int major, int minor,
+ const std::vector<std::string>& links) const;
+ std::vector<std::string> GetCharacterDeviceSymlinks(const Uevent& uevent) const;
+ void HandleDevice(const std::string& action, const std::string& devpath, int block, int major,
+ int minor, const std::vector<std::string>& links) const;
+ void HandlePlatformDeviceEvent(const Uevent& uevent);
+ void HandleBlockDeviceEvent(const Uevent& uevent) const;
+ void HandleGenericDeviceEvent(const Uevent& uevent) const;
+
+ std::vector<Permissions> dev_permissions_;
+ std::vector<SysfsPermissions> sysfs_permissions_;
+ std::vector<Subsystem> subsystems_;
+ PlatformDeviceList platform_devices_;
+ selabel_handle* sehandle_;
+};
// Exposed for testing
-extern std::vector<std::string> platform_devices;
-bool find_platform_device(const std::string& path, std::string* out_path);
-std::vector<std::string> get_character_device_symlinks(uevent* uevent);
-std::vector<std::string> get_block_device_symlinks(uevent* uevent);
-void sanitize_partition_name(std::string* string);
-void handle_platform_device_event(uevent* uevent);
+void SanitizePartitionName(std::string* string);
-#endif /* _INIT_DEVICES_H */
+#endif