Once again support Technology PropertyChanged signal reporting. devel
authorOssama Othman <ossama.othman@intel.com>
Tue, 3 Dec 2013 20:48:33 +0000 (12:48 -0800)
committerOssama Othman <ossama.othman@intel.com>
Tue, 3 Dec 2013 20:48:33 +0000 (12:48 -0800)
Signed-off-by: Ossama Othman <ossama.othman@intel.com>
plugins/connman/connman_manager.cpp
plugins/connman/connman_manager.hpp
plugins/connman/subscription_manager.cpp

index 1f7a2ee..79a70eb 100644 (file)
@@ -31,7 +31,6 @@
 #include <settingsd/glib_traits.hpp>
 #include <settingsd/unique_ptr.hpp>
 
-
 #include <cstring>
 
 // ----------------------------------------------------------------------
 namespace
 {
   std::string const manager_name("connman::manager");
+
+  void
+  on_technology_added(GDBusConnection * connection,
+                      char const * sender_name,
+                      char const * object_path,
+                      char const * interface_name,
+                      char const * signal_name,
+                      GVariant   * parameters,
+                      gpointer     user_data)
+  {
+    // The technology's object path is found in the first argument.
+    ivi::settings::unique_ptr<GVariant> const tech_path(
+      g_variant_get_child_value(parameters, 0));
+
+    // Subscribe to the technology's PropertyChanged signal.
+    typedef ivi::settings::connman_manager::signal_data signal_data;
+    signal_data * const data = static_cast<signal_data *>(user_data);
+
+    data->subscriptions.subscribe("net.connman.Technology",
+                                  "PropertyChanged",
+                                  g_variant_get_string(tech_path.get(),
+                                                       nullptr));
+
+    ivi::settings::on_dbus_signal(connection,
+                                  sender_name,
+                                  object_path,
+                                  interface_name,
+                                  signal_name,
+                                  parameters,
+                                  &data->callback);
+  }
+
+  void
+  on_technology_removed(GDBusConnection * connection,
+                        char const * sender_name,
+                        char const * object_path,
+                        char const * interface_name,
+                        char const * signal_name,
+                        GVariant   * parameters,
+                        gpointer     user_data)
+  {
+    // The technology's object path is found in the first argument.
+    ivi::settings::unique_ptr<GVariant> const tech_path(
+      g_variant_get_child_value(parameters, 0));
+
+    // Unubscribe from the technology's PropertyChanged signal.
+    typedef ivi::settings::connman_manager::signal_data signal_data;
+    signal_data * const data = static_cast<signal_data *>(user_data);
+
+    data->subscriptions.unsubscribe(
+      g_variant_get_string(tech_path.get(), nullptr));
+
+    ivi::settings::on_dbus_signal(connection,
+                                  sender_name,
+                                  object_path,
+                                  interface_name,
+                                  signal_name,
+                                  parameters,
+                                  &data->callback);
+  }
 }
 
 // ----------------------------------------------------------------------
@@ -50,14 +109,19 @@ ivi::settings::connman_manager::connman_manager(
              "/",                       // Object path
              connection,
              e)
-  , event_callback_(e)
+  , data_(connection, e)
   , technology_added_id_(subscribe_to_signal(connection,
-                                             "TechnologyAdded"))
+                                             "TechnologyAdded",
+                                             on_technology_added,
+                                             &data_))
   , technology_removed_id_(subscribe_to_signal(connection,
-                                               "TechnologyRemoved"))
+                                               "TechnologyRemoved",
+                                               on_technology_removed,
+                                               &data_))
   , services_changed_id_(subscribe_to_signal(connection,
-                                             "ServicesChanged"))
-  , subscriptions_(connection, event_callback_)
+                                             "ServicesChanged",
+                                             on_dbus_signal,
+                                             &data_.callback))
 {
   // The ServicesChanged signal parameters are:
   //
@@ -68,7 +132,45 @@ ivi::settings::connman_manager::connman_manager(
   // list of changed services.  The second is a list of removed
   // services.
 
+  /**
+   * @todo Refactor duplicate code found here an in get_properties()
+   *       method.
+   */
   // Subscribe to PropertyChanged signal for all technologies.
+  constexpr gint const timeout = 5000;  // milliseconds
+  GError * error = nullptr;
+
+  unique_ptr<GVariant> const dictionary(
+    g_dbus_proxy_call_sync(connman_.proxy(),
+                           "GetTechnologies",
+                           nullptr,  // No parameters
+                           G_DBUS_CALL_FLAGS_NONE,
+                           timeout,
+                           nullptr,  // Not cancellable
+                           &error));
+  unique_ptr<GError> safe_error(error);
+
+  if (dictionary != nullptr) {
+    GVariantIter * i = nullptr;
+    g_variant_get(dictionary.get(), "(a(oa{sv}))", &i);
+    unique_ptr<GVariantIter> const safe_i(i);
+
+    for (unique_ptr<GVariant> child(g_variant_iter_next_value(i));
+         child != nullptr;
+         child.reset(g_variant_iter_next_value(i))) {
+
+      // The object path is the first tuple element.
+      unique_ptr<GVariant> const tmp(
+        g_variant_get_child_value(child.get(), 0));
+
+      char const * const tech_path =
+        g_variant_get_string(tmp.get(), nullptr);
+
+      data_.subscriptions.subscribe("net.connman.Technology",
+                                    "PropertyChanged",
+                                    tech_path);
+    }
+  }
 }
 
 ivi::settings::connman_manager::~connman_manager()
@@ -231,7 +333,9 @@ ivi::settings::connman_manager::call_method(
 guint
 ivi::settings::connman_manager::subscribe_to_signal(
   GDBusConnection * connection,
-  char const* name)
+  char const* name,
+  ivi_signal_callback callback,
+  void * user_data)
 {
   return
     g_dbus_connection_signal_subscribe(connection,
@@ -241,8 +345,8 @@ ivi::settings::connman_manager::subscribe_to_signal(
                                        connman_.object_path(),
                                        nullptr,
                                        G_DBUS_SIGNAL_FLAGS_NONE,
-                                       on_dbus_signal,
-                                       &event_callback_,
+                                       callback,
+                                       user_data,
                                        nullptr);
 }
 
index b174950..e96542d 100644 (file)
@@ -98,6 +98,22 @@ namespace ivi
        */
       void get_services(response_callback & response) const;
 
+      struct signal_data
+      {
+        signal_data(GDBusConnection * connection,
+                    event_callback const & e)
+          : callback(e)
+          , subscriptions(connection, callback)
+        {
+        }
+
+        /// Callback through which events will be sent to clients.
+        event_callback callback;
+
+        /// Signal subscription manager.
+        subscription_manager subscriptions;
+      };
+
     private:
 
       /**
@@ -121,17 +137,27 @@ namespace ivi
       void call_method(char const * name,
                        response_callback & response) const;
 
+      typedef void (*ivi_signal_callback)(GDBusConnection * connection,
+                                          char const * sender_name,
+                                          char const * object_path,
+                                          char const * interface_name,
+                                          char const * signal_name,
+                                          GVariant   * parameters,
+                                          gpointer     user_data);
+
       /// Subscribe to Connman Manager signal @a name.
       guint subscribe_to_signal(GDBusConnection * connection,
-                                char const * name);
+                                char const * name,
+                                ivi_signal_callback callback,
+                                void * user_data);
 
     private:
 
       /// The proxy used to access the connman Manager D-Bus API.
       connman connman_;
 
-      /// Callback through which events will be sent to clients.
-      event_callback event_callback_;
+      /// Data passed to signal handlers.
+      signal_data data_;
 
       /// TechnologyAdded signal subscription ID.
       guint const technology_added_id_;
@@ -142,9 +168,6 @@ namespace ivi
       /// ServicesChanged signal subscription ID.
       guint const services_changed_id_;
 
-      /// Signal subscription manager.
-      subscription_manager subscriptions_;
-
     };
 
   }
index 233fe65..8f6751f 100644 (file)
@@ -61,7 +61,7 @@ ivi::settings::subscription_manager::subscribe(
 
   {
     std::lock_guard<std::mutex> guard(mutex_);
-    result = subscriptions_.emplace(std::make_pair(object_path, 0));
+    result = subscriptions_.insert(std::make_pair(object_path, 0));
   }
 
   if (result.second) {