2 * @file connman_manager.cpp
4 * @brief Connman_Manager-based settings plugin.
6 * @author Ossama Othman @<ossama.othman@@intel.com@>
9 * Copyright 2013 Intel Corporation All Rights Reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation;
14 * version 2.1 of the License.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301 USA
27 #include "connman_manager.hpp"
29 #include <settingsd/json_glib_traits.hpp>
30 #include <settingsd/reverse_lock.hpp>
38 on_services_changed(GDBusConnection * /* connection */,
39 char const * /* sender_name */,
40 char const * /* object_path */,
41 char const * /* interface_name */,
42 char const * /* signal_name */,
43 GVariant * parameters,
46 gsize const num_params = g_variant_n_children(parameters);
47 if (num_params != 2) {
48 // We should never get here!
49 g_printerr("Number of ServicesChanged signal parameters "
50 "is not 2: %" G_GSIZE_FORMAT "\n",
56 using namespace ivi::settings;
58 // Changed services are found in the first ServicesChanged
60 smart_ptr<GVariant> const changed_services(
61 g_variant_get_child_value(parameters, 0));
63 // Serialize the changed services into a JSON tree. This will be
64 // an array of [object, dict], where "object" is the D-Bus object
65 // path, and "dict" is a dictionary of object-specific
67 smart_ptr<JsonNode> services(
68 json_gvariant_serialize(changed_services.get()));
70 // Notify callers about the scan results.
71 typedef connman_manager::user_data user_data_type;
73 user_data_type * const p = static_cast<user_data_type *>(user_data);
74 connman_manager::promise_list_type & promises = p->promises;
76 // Synchronize access to the promises list.
77 std::lock_guard<std::mutex> lock(p->mutex);
79 // Note that the end() iterator must be retrieved during each loop
80 // iteration in case another thread caused another promise to be
81 // added to the list when the lock was temporarily unlocked during
82 // the promise::set_value() call below.
83 for (auto i = promises.begin(); i != promises.end(); ) {
87 // Release the mutex during the promise::set_value()
88 // call/notification so that we don't unnecessarily block
89 // threads attempting to get a services_changed promise.
90 typedef ivi::settings::reverse_lock<std::mutex> reverse_lock;
91 reverse_lock reverse(p->mutex);
93 std::lock_guard<reverse_lock> kcol(reverse);
95 // Thread that owns the corresponding future must transfer
96 // ownership of the JsonNode to something that will release
97 // the underlying JsonNode, e.g. a JsonBuilder via
98 // json_builder_add_value() or another smart_ptr<JsonNode>.
99 promise->set_value(std::move(services));
102 // Done with the pointer to the promise. Remove it from the
103 // list now since we already have an iterator to it.
104 i = promises.erase(i);
110 // ---------------------------------------------------------------
112 ivi::settings::connman_manager::connman_manager()
113 : connman_("net.connman.Manager", // Interface
117 , data_(mutex_, promises_)
119 g_dbus_connection_signal_subscribe(
120 g_dbus_proxy_get_connection(G_DBUS_PROXY(connman_.proxy())),
122 connman_.interface_name(),
124 connman_.object_path(),
126 G_DBUS_SIGNAL_FLAGS_NONE,
133 ivi::settings::connman_manager::~connman_manager()
135 g_dbus_connection_signal_unsubscribe(
136 g_dbus_proxy_get_connection(G_DBUS_PROXY(connman_.proxy())),
141 ivi::settings::connman_manager::get_properties(
142 std::string const & technology,
143 GError *& error) const
145 constexpr gint const timeout = 5000; // milliseconds
147 smart_ptr<GVariant> const dictionary(
148 g_dbus_proxy_call_sync(connman_.proxy(),
150 nullptr, // No parameters
151 G_DBUS_CALL_FLAGS_NONE,
153 nullptr, // Not cancellable
156 if (dictionary != nullptr) {
157 GVariantIter * i = nullptr;
158 g_variant_get(dictionary.get(), "(a(oa{sv}))", &i);
159 smart_ptr<GVariantIter> const safe_i(i);
161 for (smart_ptr<GVariant> child(g_variant_iter_next_value(i));
163 child.reset(g_variant_iter_next_value(i))) {
165 // The object path is the first tuple element.
166 smart_ptr<GVariant> const tmp(
167 g_variant_get_child_value(child.get(), 0));
169 char const * object =
170 g_variant_get_string(tmp.get(), nullptr);
172 // The technology is found at end the object path,
173 // e.g. "/net/connman/technology/wifi" for the wifi.
174 char const * tech = strrchr(object, '/');
176 if (tech != nullptr) {
177 ++tech; // Skip the found '/'.
179 if (technology == tech) {
180 // The property dictionary is the second tuple element.
181 return g_variant_get_child_value(child.get(), 1);
191 ivi::settings::connman_manager::get_services(GError *& error) const
193 constexpr gint const timeout = 5000; // milliseconds
195 return g_dbus_proxy_call_sync(connman_.proxy(),
197 nullptr, // No parameters
198 G_DBUS_CALL_FLAGS_NONE,
200 nullptr, // Not cancellable
204 ivi::settings::connman_manager::shared_promise_type
205 ivi::settings::connman_manager::get_services_changed_promise()
207 // This promise must exist long enough for the value to retrieved
208 // from the future. Use a shared_ptr<> to make that possible.
209 shared_promise_type p = std::make_shared<promise_type>();
212 std::lock_guard<std::mutex> lock(mutex_);
214 // Add a new std::promise to the promises list. The promise will
215 // only be used once, and will be removed once its value has been
217 promises_.push_back(p);
227 // indent-tabs-mode: nil