Consolidate disk-related udev handling in cros-disks.
BUG=chromium-os:15740
TEST=Tested inserting/removing USB/SD devices on a Cr48.
Change-Id: I40c6bf43057ba04944c720821d0b5a6b71066957
Reviewed-on: http://gerrit.chromium.org/gerrit/2484
Tested-by: Ben Chan <benchan@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
diff --git a/SConstruct.chromiumos b/SConstruct.chromiumos
index c17387a..55f475c 100644
--- a/SConstruct.chromiumos
+++ b/SConstruct.chromiumos
@@ -116,10 +116,10 @@
''')
env = base_env.Clone()
-env.Append(LIBS=['chromeos', 'base', 'rt', 'rootdev'])
+env.Append(LIBS=['chromeos', 'base', 'rt'])
# glib, dbus, and ibus environment
-env.ParseConfig('%s --cflags --libs dbus-1 glib-2.0 gudev-1.0 dbus-glib-1 '
+env.ParseConfig('%s --cflags --libs dbus-1 glib-2.0 dbus-glib-1 '
'ibus-1.0 libpcrecpp x11' % env['ENV']['PKG_CONFIG'])
env.GlibMarshal('marshal.glibmarshal.c', 'marshal.list')
diff --git a/chromeos_mount.cc b/chromeos_mount.cc
index 2b7e784..8dbd3ca 100644
--- a/chromeos_mount.cc
+++ b/chromeos_mount.cc
@@ -5,6 +5,7 @@
#include "chromeos_mount.h" // NOLINT
#include <base/logging.h>
+#include <base/memory/scoped_vector.h>
#include <algorithm>
#include <cstdlib>
@@ -17,9 +18,6 @@
#include "chromeos/dbus/dbus.h"
#include "chromeos/glib/object.h"
#include "chromeos/string.h"
-#define G_UDEV_API_IS_SUBJECT_TO_CHANGE
-#include <gudev/gudev.h>
-#include <rootdev/rootdev.h>
namespace chromeos { // NOLINT
@@ -222,6 +220,16 @@
delete cb_data;
}
+struct MountEventCallbackData {
+ MountEventCallbackData(MountEventConnection connection,
+ MountEventType type)
+ : event_connection(connection),
+ event_type(type) {}
+
+ MountEventConnection event_connection;
+ MountEventType event_type;
+};
+
void MountRequestNotify(DBusGProxy* gproxy,
DBusGProxyCall* call_id,
void* user_data) {
@@ -491,98 +499,79 @@
class OpaqueMountEventConnection {
public:
- typedef dbus::MonitorConnection<void (const char*)>* ConnectionType;
+ typedef dbus::MonitorConnection<void (const char*)> ConnectionType;
OpaqueMountEventConnection(const MountEventMonitor& monitor,
const dbus::Proxy& mount,
void* object)
- : gudev_client(NULL),
- monitor_(monitor),
+ : monitor_(monitor),
object_(object),
- mount_(mount),
- addconnection_(NULL),
- removeconnection_(NULL) {
+ mount_(mount) {
+ }
+
+ ~OpaqueMountEventConnection() {
+ TearDownConnections();
+ }
+
+ void SetUpConnections() {
+ static const struct {
+ const char *signal_name;
+ MountEventType event_type;
+ } kSignalEventTuples[] = {
+ { "DeviceAdded", DEVICE_ADDED },
+ { "DeviceScanned", DEVICE_SCANNED },
+ { "DeviceRemoved", DEVICE_REMOVED },
+ { "DiskAdded", DISK_ADDED },
+ { "DiskChanged", DISK_CHANGED },
+ { "DiskRemoved", DISK_REMOVED },
+ };
+ static const size_t kNumSignalEventTuples =
+ sizeof(kSignalEventTuples) / sizeof(kSignalEventTuples[0]);
+
+ callback_data_.reserve(kNumSignalEventTuples);
+ connections_.reserve(kNumSignalEventTuples);
+
+ for (size_t i = 0; i < kNumSignalEventTuples; ++i) {
+ MountEventCallbackData* cb_data = new MountEventCallbackData(this,
+ kSignalEventTuples[i].event_type);
+ callback_data_.push_back(cb_data);
+
+ ConnectionType* connection = dbus::Monitor(mount_,
+ kSignalEventTuples[i].signal_name,
+ &OpaqueMountEventConnection::MountEventCallback,
+ cb_data);
+ connections_.push_back(connection);
+ }
+ }
+
+ void TearDownConnections() {
+ for (std::vector<ConnectionType*>::const_iterator
+ connection_iter = connections_.begin();
+ connection_iter != connections_.end();
+ ++connection_iter) {
+ // dbus::Disconnect also deletes the connection object.
+ dbus::Disconnect(*connection_iter);
+ }
+ connections_.clear();
+ callback_data_.reset();
}
void FireEvent(MountEventType evt, const char* path) {
monitor_(object_, evt, path);
}
- static void Added(void* object, const char* device) {
- MountEventConnection self =
- reinterpret_cast<MountEventConnection>(object);
- self->FireEvent(DISK_ADDED, device);
+ static void MountEventCallback(void* data, const char* device) {
+ MountEventCallbackData* cb_data =
+ reinterpret_cast<MountEventCallbackData*>(data);
+ cb_data->event_connection->FireEvent(cb_data->event_type, device);
}
- static void Removed(void* object, const char* device) {
- MountEventConnection self =
- reinterpret_cast<MountEventConnection>(object);
- self->FireEvent(DISK_REMOVED, device);
- }
-
- static void Changed(void* object, const char* device) {
- MountEventConnection self =
- reinterpret_cast<MountEventConnection>(object);
- self->FireEvent(DISK_CHANGED, device);
- }
-
- static void OnUDevEvent(GUdevClient* client,
- const char* action,
- GUdevDevice* device,
- gpointer object) {
- MountEventConnection self = reinterpret_cast<MountEventConnection>(object);
- std::set<std::string>::iterator iter;
- // can be scsi or block
- const char* subsystem = g_udev_device_get_subsystem(device);
- if (subsystem == NULL || strcmp(subsystem, "scsi") != 0) {
- return;
- }
- if (strcmp(action, "add") == 0) {
- const char* device_path = g_udev_device_get_sysfs_path(device);
- if (device_path == NULL)
- return;
- std::string device_string(device_path);
- iter = self->paths_.find(device_string);
- if (iter != self->paths_.end()) {
- self->FireEvent(DEVICE_SCANNED, device_path);
- } else {
- self->paths_.insert(device_string);
- self->FireEvent(DEVICE_ADDED, device_path);
- }
- } else if (strcmp(action, "remove") == 0) {
- const char* device_path = g_udev_device_get_sysfs_path(device);
- if (device_path == NULL)
- return;
- std::string device_string(device_path);
- iter = self->paths_.find(device_string);
- if (iter != self->paths_.end()) {
- self->paths_.erase(iter);
- self->FireEvent(DEVICE_REMOVED, device_path);
- }
- }
- }
- ConnectionType& addedconnection() {
- return addconnection_;
- }
-
- ConnectionType& removedconnection() {
- return removeconnection_;
- }
-
- ConnectionType& changedconnection() {
- return changedconnection_;
- }
-
- GUdevClient* gudev_client;
-
private:
MountEventMonitor monitor_;
void* object_;
- std::set<std::string> paths_;
dbus::Proxy mount_;
- ConnectionType addconnection_;
- ConnectionType removeconnection_;
- ConnectionType changedconnection_;
+ ScopedVector<MountEventCallbackData> callback_data_;
+ std::vector<ConnectionType*> connections_;
};
extern "C"
@@ -593,58 +582,10 @@
kCrosDisksInterface,
kCrosDisksPath,
kCrosDisksInterface);
- MountEventConnection result =
- new OpaqueMountEventConnection(monitor, mount, object);
- ::dbus_g_proxy_add_signal(mount.gproxy(),
- "DeviceAdded",
- G_TYPE_STRING,
- G_TYPE_INVALID);
- ::dbus_g_proxy_add_signal(mount.gproxy(),
- "DeviceRemoved",
- G_TYPE_STRING,
- G_TYPE_INVALID);
- ::dbus_g_proxy_add_signal(mount.gproxy(),
- "DeviceChanged",
- G_TYPE_STRING,
- G_TYPE_INVALID);
- typedef dbus::MonitorConnection<void (const char*)> ConnectionType;
-
- ConnectionType* added = new ConnectionType(mount, "DeviceAdded",
- &OpaqueMountEventConnection::Added, result);
-
- ::dbus_g_proxy_connect_signal(mount.gproxy(), "DeviceAdded",
- G_CALLBACK(&ConnectionType::Run),
- added, NULL);
- result->addedconnection() = added;
-
-
- ConnectionType* removed = new ConnectionType(mount, "DeviceRemoved",
- &OpaqueMountEventConnection::Removed, result);
-
- ::dbus_g_proxy_connect_signal(mount.gproxy(), "DeviceRemoved",
- G_CALLBACK(&ConnectionType::Run),
- removed, NULL);
- result->removedconnection() = removed;
-
-
- ConnectionType* changed = new ConnectionType(mount, "DeviceChanged",
- &OpaqueMountEventConnection::Changed, result);
-
- ::dbus_g_proxy_connect_signal(mount.gproxy(), "DeviceChanged",
- G_CALLBACK(&ConnectionType::Run),
- changed, NULL);
- result->changedconnection() = changed;
-
- // Listen to udev events
-
- const char *subsystems[] = {"scsi", "block", NULL};
- result->gudev_client = g_udev_client_new(subsystems);
- g_signal_connect(result->gudev_client,
- "uevent",
- G_CALLBACK(&OpaqueMountEventConnection::OnUDevEvent),
- result);
-
- return result;
+ MountEventConnection connection =
+ new OpaqueMountEventConnection(monitor, mount, object);
+ connection->SetUpConnections();
+ return connection;
}
extern "C"
@@ -676,9 +617,6 @@
extern "C"
void ChromeOSDisconnectMountEventMonitor(MountEventConnection connection) {
- dbus::Disconnect(connection->addedconnection());
- dbus::Disconnect(connection->removedconnection());
- dbus::Disconnect(connection->changedconnection());
delete connection;
}