Add support for default service changed notifier
[platform/upstream/connman.git] / src / notifier.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gdbus.h>
27
28 #include "connman.h"
29
30 static DBusConnection *connection = NULL;
31
32 static GSList *notifier_list = NULL;
33
34 static gint compare_priority(gconstpointer a, gconstpointer b)
35 {
36         const struct connman_notifier *notifier1 = a;
37         const struct connman_notifier *notifier2 = b;
38
39         return notifier2->priority - notifier1->priority;
40 }
41
42 /**
43  * connman_notifier_register:
44  * @notifier: notifier module
45  *
46  * Register a new notifier module
47  *
48  * Returns: %0 on success
49  */
50 int connman_notifier_register(struct connman_notifier *notifier)
51 {
52         DBG("notifier %p name %s", notifier, notifier->name);
53
54         notifier_list = g_slist_insert_sorted(notifier_list, notifier,
55                                                         compare_priority);
56
57         return 0;
58 }
59
60 /**
61  * connman_notifier_unregister:
62  * @notifier: notifier module
63  *
64  * Remove a previously registered notifier module
65  */
66 void connman_notifier_unregister(struct connman_notifier *notifier)
67 {
68         DBG("notifier %p name %s", notifier, notifier->name);
69
70         notifier_list = g_slist_remove(notifier_list, notifier);
71 }
72
73 #define MAX_TECHNOLOGIES 10
74
75 static volatile gint registered[MAX_TECHNOLOGIES];
76 static volatile gint enabled[MAX_TECHNOLOGIES];
77 static volatile gint connected[MAX_TECHNOLOGIES];
78
79 void __connman_notifier_list_registered(DBusMessageIter *iter)
80 {
81         int i;
82
83         for (i = 0; i < 10; i++) {
84                 const char *type = __connman_service_type2string(i);
85
86                 if (type == NULL)
87                         continue;
88
89                 if (g_atomic_int_get(&registered[i]) > 0)
90                         dbus_message_iter_append_basic(iter,
91                                                 DBUS_TYPE_STRING, &type);
92         }
93 }
94
95 void __connman_notifier_list_enabled(DBusMessageIter *iter)
96 {
97         int i;
98
99         for (i = 0; i < 10; i++) {
100                 const char *type = __connman_service_type2string(i);
101
102                 if (type == NULL)
103                         continue;
104
105                 if (g_atomic_int_get(&enabled[i]) > 0)
106                         dbus_message_iter_append_basic(iter,
107                                                 DBUS_TYPE_STRING, &type);
108         }
109 }
110
111 void __connman_notifier_list_connected(DBusMessageIter *iter)
112 {
113         int i;
114
115         for (i = 0; i < 10; i++) {
116                 const char *type = __connman_service_type2string(i);
117
118                 if (type == NULL)
119                         continue;
120
121                 if (g_atomic_int_get(&connected[i]) > 0)
122                         dbus_message_iter_append_basic(iter,
123                                                 DBUS_TYPE_STRING, &type);
124         }
125 }
126
127 static void technology_registered(enum connman_service_type type,
128                                                 connman_bool_t registered)
129 {
130         DBusMessage *signal;
131         DBusMessageIter entry, value, iter;
132         const char *key = "AvailableTechnologies";
133
134         DBG("type %d registered %d", type, registered);
135
136         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
137                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
138         if (signal == NULL)
139                 return;
140
141         dbus_message_iter_init_append(signal, &entry);
142
143         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
144
145         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
146                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
147                                                                 &value);
148
149         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
150                                         DBUS_TYPE_STRING_AS_STRING, &iter);
151         __connman_notifier_list_registered(&iter);
152         dbus_message_iter_close_container(&value, &iter);
153
154         dbus_message_iter_close_container(&entry, &value);
155
156         g_dbus_send_message(connection, signal);
157 }
158
159 static void technology_enabled(enum connman_service_type type,
160                                                 connman_bool_t enabled)
161 {
162         GSList *list;
163         DBusMessage *signal;
164         DBusMessageIter entry, value, iter;
165         const char *key = "EnabledTechnologies";
166
167         DBG("type %d enabled %d", type, enabled);
168
169         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
170                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
171         if (signal == NULL)
172                 goto done;
173
174         dbus_message_iter_init_append(signal, &entry);
175
176         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
177
178         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
179                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
180                                                                 &value);
181
182         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
183                                         DBUS_TYPE_STRING_AS_STRING, &iter);
184         __connman_notifier_list_enabled(&iter);
185         dbus_message_iter_close_container(&value, &iter);
186
187         dbus_message_iter_close_container(&entry, &value);
188
189         g_dbus_send_message(connection, signal);
190
191 done:
192         for (list = notifier_list; list; list = list->next) {
193                 struct connman_notifier *notifier = list->data;
194
195                 if (notifier->service_enabled)
196                         notifier->service_enabled(type, enabled);
197         }
198 }
199
200 static void technology_connected(enum connman_service_type type,
201                                                 connman_bool_t connected)
202 {
203         DBusMessage *signal;
204         DBusMessageIter entry, value, iter;
205         const char *key = "ConnectedTechnologies";
206
207         DBG("type %d connected %d", type, connected);
208
209         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
210                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
211         if (signal == NULL)
212                 return;
213
214         dbus_message_iter_init_append(signal, &entry);
215
216         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
217
218         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
219                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
220                                                                 &value);
221
222         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
223                                         DBUS_TYPE_STRING_AS_STRING, &iter);
224         __connman_notifier_list_connected(&iter);
225         dbus_message_iter_close_container(&value, &iter);
226
227         dbus_message_iter_close_container(&entry, &value);
228
229         g_dbus_send_message(connection, signal);
230 }
231
232 void __connman_notifier_register(enum connman_service_type type)
233 {
234         DBG("type %d", type);
235
236         switch (type) {
237         case CONNMAN_SERVICE_TYPE_UNKNOWN:
238                 return;
239         case CONNMAN_SERVICE_TYPE_ETHERNET:
240         case CONNMAN_SERVICE_TYPE_WIFI:
241         case CONNMAN_SERVICE_TYPE_WIMAX:
242         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
243         case CONNMAN_SERVICE_TYPE_CELLULAR:
244                 break;
245         }
246
247         if (g_atomic_int_exchange_and_add(&registered[type], 1) == 0)
248                 technology_registered(type, TRUE);
249 }
250
251 void __connman_notifier_unregister(enum connman_service_type type)
252 {
253         DBG("type %d", type);
254
255         switch (type) {
256         case CONNMAN_SERVICE_TYPE_UNKNOWN:
257                 return;
258         case CONNMAN_SERVICE_TYPE_ETHERNET:
259         case CONNMAN_SERVICE_TYPE_WIFI:
260         case CONNMAN_SERVICE_TYPE_WIMAX:
261         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
262         case CONNMAN_SERVICE_TYPE_CELLULAR:
263                 break;
264         }
265
266         if (g_atomic_int_dec_and_test(&registered[type]) == TRUE)
267                 technology_registered(type, FALSE);
268 }
269
270 void __connman_notifier_enable(enum connman_service_type type)
271 {
272         DBG("type %d", type);
273
274         switch (type) {
275         case CONNMAN_SERVICE_TYPE_UNKNOWN:
276                 return;
277         case CONNMAN_SERVICE_TYPE_ETHERNET:
278         case CONNMAN_SERVICE_TYPE_WIFI:
279         case CONNMAN_SERVICE_TYPE_WIMAX:
280         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
281         case CONNMAN_SERVICE_TYPE_CELLULAR:
282                 break;
283         }
284
285         if (g_atomic_int_exchange_and_add(&enabled[type], 1) == 0)
286                 technology_enabled(type, TRUE);
287 }
288
289 void __connman_notifier_disable(enum connman_service_type type)
290 {
291         DBG("type %d", type);
292
293         switch (type) {
294         case CONNMAN_SERVICE_TYPE_UNKNOWN:
295                 return;
296         case CONNMAN_SERVICE_TYPE_ETHERNET:
297         case CONNMAN_SERVICE_TYPE_WIFI:
298         case CONNMAN_SERVICE_TYPE_WIMAX:
299         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
300         case CONNMAN_SERVICE_TYPE_CELLULAR:
301                 break;
302         }
303
304         if (g_atomic_int_dec_and_test(&enabled[type]) == TRUE)
305                 technology_enabled(type, FALSE);
306 }
307
308 void __connman_notifier_connect(enum connman_service_type type)
309 {
310         DBG("type %d", type);
311
312         switch (type) {
313         case CONNMAN_SERVICE_TYPE_UNKNOWN:
314                 return;
315         case CONNMAN_SERVICE_TYPE_ETHERNET:
316         case CONNMAN_SERVICE_TYPE_WIFI:
317         case CONNMAN_SERVICE_TYPE_WIMAX:
318         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
319         case CONNMAN_SERVICE_TYPE_CELLULAR:
320                 break;
321         }
322
323         if (g_atomic_int_exchange_and_add(&connected[type], 1) == 0)
324                 technology_connected(type, TRUE);
325 }
326
327 void __connman_notifier_disconnect(enum connman_service_type type)
328 {
329         DBG("type %d", type);
330
331         switch (type) {
332         case CONNMAN_SERVICE_TYPE_UNKNOWN:
333                 return;
334         case CONNMAN_SERVICE_TYPE_ETHERNET:
335         case CONNMAN_SERVICE_TYPE_WIFI:
336         case CONNMAN_SERVICE_TYPE_WIMAX:
337         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
338         case CONNMAN_SERVICE_TYPE_CELLULAR:
339                 break;
340         }
341
342         if (g_atomic_int_dec_and_test(&connected[type]) == TRUE)
343                 technology_connected(type, FALSE);
344 }
345
346 static void technology_default(enum connman_service_type type)
347 {
348         DBusMessage *signal;
349         DBusMessageIter entry, value;
350         const char *str, *key = "DefaultTechnology";
351
352         str = __connman_service_type2string(type);
353         if (str == NULL)
354                 return;
355
356         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
357                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
358         if (signal == NULL)
359                 return;
360
361         dbus_message_iter_init_append(signal, &entry);
362
363         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
364
365         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
366                                         DBUS_TYPE_STRING_AS_STRING, &value);
367         dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
368         dbus_message_iter_close_container(&entry, &value);
369
370         g_dbus_send_message(connection, signal);
371 }
372
373 void __connman_notifier_default_changed(struct connman_service *service)
374 {
375         enum connman_service_type type = connman_service_get_type(service);
376         GSList *list;
377
378         technology_default(type);
379
380         for (list = notifier_list; list; list = list->next) {
381                 struct connman_notifier *notifier = list->data;
382
383                 if (notifier->default_changed)
384                         notifier->default_changed(service);
385         }
386 }
387
388 static void offlinemode_changed(dbus_bool_t enabled)
389 {
390         DBusMessage *signal;
391         DBusMessageIter entry, value;
392         const char *key = "OfflineMode";
393
394         DBG("enabled %d", enabled);
395
396         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
397                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
398         if (signal == NULL)
399                 return;
400
401         dbus_message_iter_init_append(signal, &entry);
402
403         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
404
405         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
406                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
407         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &enabled);
408         dbus_message_iter_close_container(&entry, &value);
409
410         g_dbus_send_message(connection, signal);
411 }
412
413 void __connman_notifier_offlinemode(connman_bool_t enabled)
414 {
415         GSList *list;
416
417         DBG("enabled %d", enabled);
418
419         __connman_profile_changed(FALSE);
420
421         offlinemode_changed(enabled);
422
423         for (list = notifier_list; list; list = list->next) {
424                 struct connman_notifier *notifier = list->data;
425
426                 if (notifier->offline_mode)
427                         notifier->offline_mode(enabled);
428         }
429 }
430
431 connman_bool_t __connman_notifier_is_enabled(enum connman_service_type type)
432 {
433         DBG("type %d", type);
434
435         switch (type) {
436         case CONNMAN_SERVICE_TYPE_UNKNOWN:
437                 return FALSE;
438         case CONNMAN_SERVICE_TYPE_ETHERNET:
439         case CONNMAN_SERVICE_TYPE_WIFI:
440         case CONNMAN_SERVICE_TYPE_WIMAX:
441         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
442         case CONNMAN_SERVICE_TYPE_CELLULAR:
443                 break;
444         }
445
446         if (g_atomic_int_get(&enabled[type]) > 0)
447                 return TRUE;
448
449         return FALSE;
450 }
451
452 int __connman_notifier_init(void)
453 {
454         DBG("");
455
456         connection = connman_dbus_get_connection();
457
458         return 0;
459 }
460
461 void __connman_notifier_cleanup(void)
462 {
463         DBG("");
464
465         dbus_connection_unref(connection);
466 }