Adjust coding rule
[platform/core/appfw/librua.git] / src / rua_dbus.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 #include <glib.h>
21 #include <gio/gio.h>
22 #include <dlog.h>
23
24 #include "rua.h"
25 #include "rua_dbus.h"
26 #include "rua_private.h"
27
28 #define RUA_INTERFACE "org.tizen.rua"
29 #define RUA_PATH "/org/tizen/rua"
30 #define RUA_SIGNAL_DATA_UPDATE "dataupdate"
31
32 struct cb_data {
33         int callback_id;
34         rua_history_update_cb callback;
35         void *user_data;
36 };
37
38 static GDBusConnection *conn;
39 static guint s_id;
40
41 static gint atomic_callback_id;
42 static GHashTable *callback_hash_table;
43
44 static void __foreach_callback(gpointer key, gpointer value,
45                 gpointer user_data);
46 static void __signal_handler(GDBusConnection *connection,
47                                         const gchar *sender_name,
48                                         const gchar *object_path,
49                                         const gchar *interface_name,
50                                         const gchar *signal_name,
51                                         GVariant *parameters,
52                                         gpointer user_data);
53 static void __rua_dbus_init(void);
54 static void __rua_dbus_exit(void);
55
56 int rua_dbus_send_update_signal(update_type type)
57 {
58         __rua_dbus_init();
59         GError *err = NULL;
60
61         if (g_dbus_connection_emit_signal(conn,
62                                 NULL,
63                                 RUA_PATH,
64                                 RUA_INTERFACE,
65                                 RUA_SIGNAL_DATA_UPDATE,
66                                 g_variant_new("(i)", type),
67                                 &err) == FALSE) {
68                 LOGE("g_dbus_connection_emit_signal() is failed. %s",
69                                 err->message);
70                 __rua_dbus_exit();
71                 return -1;
72         }
73
74         if (g_dbus_connection_flush_sync(conn, NULL, &err) == FALSE) {
75                 LOGE("g_dbus_connection_flush_sync() is failed. %s",
76                                 err->message);
77                 __rua_dbus_exit();
78                 return -1;
79         }
80
81         g_clear_error(&err);
82
83         __rua_dbus_exit();
84
85         return 0;
86 }
87
88 int rua_dbus_signal_subscribe(rua_history_update_cb callback,
89                 void *user_data, int *callback_id)
90 {
91         struct cb_data *cd = NULL;
92
93         if (s_id == 0) {
94                 __rua_dbus_init();
95
96                 s_id = g_dbus_connection_signal_subscribe(conn,
97                                 NULL,
98                                 RUA_INTERFACE,
99                                 RUA_SIGNAL_DATA_UPDATE,
100                                 RUA_PATH,
101                                 NULL,
102                                 G_DBUS_SIGNAL_FLAGS_NONE,
103                                 __signal_handler,
104                                 NULL,
105                                 NULL);
106
107                 if (s_id == 0) {
108                         LOGE("g_dbus_connection_signal_subscribe() is failed.");
109                         __rua_dbus_exit();
110                         return -1;
111                 }
112
113                 if (!callback_hash_table) {
114                         callback_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
115                                         NULL, free);
116                         if (!callback_hash_table) {
117                                 LOGE("out of memory : g_hash_table_new() is failed");
118                                 __rua_dbus_exit();
119                                 return -1;
120                         }
121                 }
122         }
123
124         cd = (struct cb_data *)malloc(sizeof(struct cb_data));
125         if (!cd) {
126                 LOGE("out of memory : malloc() is failed");
127                 return -1;
128         }
129
130         g_atomic_int_inc(&atomic_callback_id);
131
132         cd->callback = callback;
133         cd->user_data = user_data;
134         cd->callback_id = atomic_callback_id;
135
136         g_hash_table_insert(callback_hash_table,
137                         GINT_TO_POINTER(cd->callback_id), (gpointer)cd);
138
139         *callback_id = cd->callback_id;
140
141         return 0;
142 }
143
144 int rua_dbus_signal_unsubscribe(int callback_id)
145 {
146         gboolean result = FALSE;
147         guint table_size = 0;
148
149         result = g_hash_table_remove(callback_hash_table, GINT_TO_POINTER(callback_id));
150         if (!result) {
151                 LOGE("g_hash_table_remove failed(%d is wrong)", callback_id);
152                 return -1;
153         }
154
155         table_size = g_hash_table_size(callback_hash_table);
156         if (s_id && table_size == 0) {
157                 g_dbus_connection_signal_unsubscribe(conn, s_id);
158                 g_hash_table_destroy(callback_hash_table);
159                 __rua_dbus_exit();
160                 callback_hash_table = NULL;
161                 s_id = 0;
162         }
163
164         return 0;
165 }
166
167 static void __foreach_callback(gpointer key, gpointer value,
168                 gpointer user_data)
169 {
170         char **table = NULL;
171         int nrows = 0;
172         int ncols = 0;
173         int r = 0;
174
175         struct cb_data *cd = (struct cb_data *)value;
176
177         r = rua_history_load_db(&table, &nrows, &ncols);
178         if (r == -1)
179                 return;
180
181         if (cd->callback)
182                 cd->callback(table, nrows, ncols, cd->user_data);
183 }
184
185 static void __signal_handler(GDBusConnection *connection,
186                                         const gchar *sender_name,
187                                         const gchar *object_path,
188                                         const gchar *interface_name,
189                                         const gchar *signal_name,
190                                         GVariant *parameters,
191                                         gpointer user_data)
192 {
193         int update_type;
194
195         LOGI("__signal_handler");
196         if (g_strcmp0(signal_name, RUA_SIGNAL_DATA_UPDATE))
197                 return;
198
199         g_variant_get(parameters, "(i)", &update_type);
200
201         g_hash_table_foreach(callback_hash_table, __foreach_callback, NULL);
202 }
203
204 static void __rua_dbus_init(void)
205 {
206         if (!conn) {
207                 GError *err = NULL;
208                 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
209                 if (!conn) {
210                         LOGE("g_bus_get_sync() is failed. %s", err->message);
211                         g_error_free(err);
212                         return;
213                 }
214         }
215 }
216
217 static void __rua_dbus_exit(void)
218 {
219         if (conn) {
220                 g_object_unref(conn);
221                 conn = NULL;
222         }
223 }