summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOssama Othman <ossama.othman@intel.com>2013-12-03 12:51:05 -0800
committerOssama Othman <ossama.othman@intel.com>2013-12-03 12:51:32 -0800
commit76786f7f381cc02fefec41a40b4c10a293f7c73d (patch)
treeba2f23de7c1eb526c911d921941f568a6fc03400
parentcc55a073c51f01e3e7caa91f6a6d60e658337857 (diff)
downloadsettings-daemon-76786f7f381cc02fefec41a40b4c10a293f7c73d.tar.gz
settings-daemon-76786f7f381cc02fefec41a40b4c10a293f7c73d.tar.bz2
settings-daemon-76786f7f381cc02fefec41a40b4c10a293f7c73d.zip
Support technology PropertyChanged signal reporting again.
Change-Id: I6a68046a324b603388a20a084950bfc1f4baa73e Signed-off-by: Ossama Othman <ossama.othman@intel.com>
-rw-r--r--configure.ac2
-rw-r--r--plugins/connman/Makefile.am4
-rw-r--r--plugins/connman/connman_manager.cpp124
-rw-r--r--plugins/connman/connman_manager.hpp33
-rw-r--r--plugins/connman/subscription_manager.cpp117
-rw-r--r--plugins/connman/subscription_manager.hpp110
6 files changed, 376 insertions, 14 deletions
diff --git a/configure.ac b/configure.ac
index 59a97b6..aa0d1e3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -24,7 +24,7 @@ Boston, MA 02110-1301 USA
])
AC_INIT([settingsd], [0.2], [ossama.othman@intel.com])
-AM_INIT_AUTOMAKE([1.11.1 foreign -Wall -Werror silent-rules])
+AM_INIT_AUTOMAKE([1.11.1 foreign -Wall -Werror -Wno-portability silent-rules])
LT_INIT([disable-static dlopen])
AC_CONFIG_SRCDIR([src/daemon.cpp])
diff --git a/plugins/connman/Makefile.am b/plugins/connman/Makefile.am
index f6683fc..d452e63 100644
--- a/plugins/connman/Makefile.am
+++ b/plugins/connman/Makefile.am
@@ -42,6 +42,7 @@ connman_la_SOURCES = \
technology.cpp \
clock.cpp \
registration.cpp \
+ subscription_manager.cpp
$(BUILT_SOURCES)
connman_la_CXXFLAGS = \
$(IVI_SETTINGS_PLUGIN_CXXFLAGS) \
@@ -68,7 +69,8 @@ noinst_HEADERS = \
connman_technology.hpp \
service.hpp \
technology.hpp \
- clock.hpp
+ clock.hpp \
+ subscription_manager.hpp
dbus_codegen_verbose = $(dbus_codegen_verbose_$(V))
dbus_codegen_verbose_ = $(dbus_codegen_verbose_$(AM_DEFAULT_VERBOSITY))
diff --git a/plugins/connman/connman_manager.cpp b/plugins/connman/connman_manager.cpp
index 9285144..79a70eb 100644
--- a/plugins/connman/connman_manager.cpp
+++ b/plugins/connman/connman_manager.cpp
@@ -25,14 +25,12 @@
*/
#include "connman_manager.hpp"
-#include "dbus_connection.hpp"
#include <settingsd/response_callback.hpp>
#include <settingsd/dbus_signal_callback.hpp>
#include <settingsd/glib_traits.hpp>
#include <settingsd/unique_ptr.hpp>
-
#include <cstring>
// ----------------------------------------------------------------------
@@ -40,6 +38,66 @@
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);
+ }
}
// ----------------------------------------------------------------------
@@ -51,13 +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"))
+ "ServicesChanged",
+ on_dbus_signal,
+ &data_.callback))
{
// The ServicesChanged signal parameters are:
//
@@ -67,6 +131,46 @@ ivi::settings::connman_manager::connman_manager(
// dictionary of object-specific properties. The first parameter is
// 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()
@@ -229,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,
@@ -239,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);
}
diff --git a/plugins/connman/connman_manager.hpp b/plugins/connman/connman_manager.hpp
index 23ef262..e96542d 100644
--- a/plugins/connman/connman_manager.hpp
+++ b/plugins/connman/connman_manager.hpp
@@ -28,6 +28,7 @@
#define IVI_SETTINGS_CONNMAN_MANAGER_HPP
#include "connman.hpp"
+#include "subscription_manager.hpp"
#include <settingsd/plugin.hpp>
#include <settingsd/event_callback.hpp>
@@ -97,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:
/**
@@ -120,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_;
diff --git a/plugins/connman/subscription_manager.cpp b/plugins/connman/subscription_manager.cpp
new file mode 100644
index 0000000..8f6751f
--- /dev/null
+++ b/plugins/connman/subscription_manager.cpp
@@ -0,0 +1,117 @@
+/**
+ * @file subscription_manager.cpp
+ *
+ * @brief Signal subscription manager.
+ *
+ * @author Ossama Othman @<ossama.othman@@intel.com@>
+ *
+ * @copyright @par
+ * Copyright 2013 Intel Corporation All Rights Reserved.
+ * @par
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ * @par
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * @par
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "subscription_manager.hpp"
+
+#include <settingsd/dbus_signal_callback.hpp>
+
+
+ivi::settings::subscription_manager::subscription_manager(
+ GDBusConnection * connection,
+ event_callback & e)
+ : connection_(connection)
+ , event_callback_(e)
+ , mutex_()
+ , subscriptions_()
+{
+}
+
+ivi::settings::subscription_manager::~subscription_manager()
+{
+ // No need to grab the lock here since no other threads should be
+ // accessing this object by the time this destructor is called.
+
+ for (auto const & i : subscriptions_) {
+ // The signal ID is the second pair member.
+ g_dbus_connection_signal_unsubscribe(connection_,
+ i.second);
+ }
+}
+
+bool
+ivi::settings::subscription_manager::subscribe(
+ char const * interface_name,
+ char const * signal_name,
+ char const * object_path)
+{
+ std::pair<map_type::iterator, bool> result;
+
+ {
+ std::lock_guard<std::mutex> guard(mutex_);
+ result = subscriptions_.insert(std::make_pair(object_path, 0));
+ }
+
+ if (result.second) {
+ // Insertion succeeded, meaning no previous subscription for the
+ // given object path exists.
+ guint const id =
+ g_dbus_connection_signal_subscribe(connection_,
+ nullptr,
+ interface_name,
+ signal_name,
+ object_path,
+ nullptr,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_dbus_signal,
+ &event_callback_,
+ nullptr);
+
+ auto & pos = result.first; // The iterator.
+
+ pos->second = id; // Dereference the iterator to get
+ // access to the second pair member,
+ // i.e. the signal subscription ID.
+ }
+
+ return result.second;
+}
+
+bool
+ivi::settings::subscription_manager::unsubscribe(
+ char const * object_path)
+{
+ bool result = false;
+
+ std::lock_guard<std::mutex> guard(mutex_);
+ map_type::iterator pos = subscriptions_.find(object_path);
+
+ if (pos != subscriptions_.end()) {
+ // The signal ID is the second pair member.
+ g_dbus_connection_signal_unsubscribe(connection_,
+ pos->second);
+
+ result = true;
+ }
+
+ return result;
+}
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End:
diff --git a/plugins/connman/subscription_manager.hpp b/plugins/connman/subscription_manager.hpp
new file mode 100644
index 0000000..b3d3687
--- /dev/null
+++ b/plugins/connman/subscription_manager.hpp
@@ -0,0 +1,110 @@
+/**
+ * @file subscription_manager.hpp
+ *
+ * @brief Connman signal subscription manager header.
+ *
+ * @author Ossama Othman @<ossama.othman@@intel.com@>
+ *
+ * @copyright @par
+ * Copyright 2013 Intel Corporation All Rights Reserved.
+ * @par
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ * @par
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ * @par
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef IVI_SETTINGS_CONNMAN_SUBSCRIPTION_MANAGER_HPP
+#define IVI_SETTINGS_CONNMAN_SUBSCRIPTION_MANAGER_HPP
+
+#include <gio/gio.h>
+
+#include <mutex>
+#include <map>
+#include <string>
+
+
+namespace ivi
+{
+ namespace settings
+ {
+ class event_callback;
+
+ /**
+ * @class subscription_manager
+ *
+ * @brief Connman signal subscription manager.
+ *
+ * This class manages all Connman signal subscriptions.
+ */
+ class subscription_manager
+ {
+ public:
+
+ /// Constructor.
+ subscription_manager(GDBusConnection * connection,
+ event_callback & e);
+
+ /// Destructor.
+ ~subscription_manager();
+
+ /**
+ * Subscribe to signal @a signal_name exposed by
+ * @a interface_name at @a object_path.
+ */
+ bool subscribe(char const * interface_name,
+ char const * signal_name,
+ char const * object_path);
+
+ /**
+ * Unsubscribe from signal corresponding to given @a
+ * object_path. This @a object_path corresponds to path passed
+ * to Connman signals like @c TechnologyRemoved.
+ *
+ * @note An assumption is made that the object path will be
+ * unique accross interfaces. If that's not reasonable
+ * we'll have to take into account the interface name as
+ * well.
+ */
+ bool unsubscribe(char const * object_path);
+
+ private:
+
+ typedef std::map<std::string, guint> map_type;
+
+ /// Underlying D-Bus connection.
+ GDBusConnection * const connection_;
+
+ /// Callback through which events will be sent to clients.
+ event_callback & event_callback_;
+
+ /// Mutex used to synchronize access to the underlying map.
+ std::mutex mutex_;
+
+ /// Map of D-Bus object path to signal subscription ID.
+ map_type subscriptions_;
+
+ };
+
+ }
+}
+
+
+#endif /* IVI_SETTINGS_CONNMAN_SUBSCRIPTION_MANAGER_HPP */
+
+
+// Local Variables:
+// mode:c++
+// c-basic-offset:2
+// indent-tabs-mode: nil
+// End: