comp-manager: Add new method to store ref count of applications
[platform/core/api/multi-device-group.git] / src / companion-manager / src / comp_gdbus.c
1 /*
2  * Copyright (c) 2018 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
18 #include <comp_gdbus.h>
19 #include <sys/types.h>
20
21 #define DBUS_SERVICE_DBUS               "org.freedesktop.DBus"
22 #define DBUS_INTERFACE_DBUS             "org.freedesktop.DBus"
23
24 static Group *group_skeleton;
25 static Enabler *enabler_skeleton;
26
27 Group *group_dbus_get_object()
28 {
29         return group_skeleton;
30 }
31
32 static bool __group_init(GDBusConnection *connection)
33 {
34         gboolean ret = FALSE;
35         GError *error = NULL;
36
37         GDBusObjectManagerServer *group;
38
39         // Add interface to default object path
40         group_skeleton = group_skeleton_new();
41
42         // Register for method callbacks as signal callbacks
43         g_signal_connect(group_skeleton,
44                 "handle-create",
45                 G_CALLBACK(group_create),
46                 NULL);
47
48         g_signal_connect(group_skeleton,
49                 "handle-find",
50                 G_CALLBACK(group_find),
51                 NULL);
52
53         g_signal_connect(group_skeleton,
54                 "handle-get-found-groups",
55                 G_CALLBACK(group_get_found_groups),
56                 NULL);
57
58         g_signal_connect(group_skeleton,
59                 "handle-join",
60                 G_CALLBACK(group_join),
61                 NULL);
62
63         g_signal_connect(group_skeleton,
64                 "handle-leave",
65                 G_CALLBACK(group_leave),
66                 NULL);
67
68         g_signal_connect(group_skeleton,
69                 "handle-delete",
70                 G_CALLBACK(group_delete),
71                 NULL);
72
73         g_signal_connect(group_skeleton,
74                 "handle-device-find",
75                 G_CALLBACK(group_device_find),
76                 NULL);
77
78         g_signal_connect(group_skeleton,
79                 "handle-invite",
80                 G_CALLBACK(group_invite),
81                 NULL);
82
83         g_signal_connect(group_skeleton,
84                 "handle-eject",
85                 G_CALLBACK(group_eject),
86                 NULL);
87
88         g_signal_connect(group_skeleton,
89                 "handle-device-invite",
90                 G_CALLBACK(group_device_invite),
91                 NULL);
92
93         g_signal_connect(group_skeleton,
94                 "handle-device-eject",
95                 G_CALLBACK(group_device_eject),
96                 NULL);
97
98         g_signal_connect(group_skeleton,
99                 "handle-get-remote-device",
100                 G_CALLBACK(group_get_remote_device),
101                 NULL);
102
103         g_signal_connect(group_skeleton,
104                 "handle-pair-resource",
105                 G_CALLBACK(group_pair_resource),
106                 NULL);
107
108         g_signal_connect(group_skeleton,
109                 "handle-unpair-resource",
110                 G_CALLBACK(group_unpair_resource),
111                 NULL);
112
113         g_signal_connect(group_skeleton,
114                 "handle-send-data",
115                 G_CALLBACK(group_send_data),
116                 NULL);
117
118         g_signal_connect(group_skeleton,
119                 "handle-find-mowned-devices",
120                 G_CALLBACK(group_find_mowned_devices),
121                 NULL);
122
123         g_signal_connect(group_skeleton,
124                 "handle-get-mowned-device",
125                 G_CALLBACK(group_get_mowned_device),
126                 NULL);
127
128         g_signal_connect(group_skeleton,
129                 "handle-get-my-mowned-device",
130                 G_CALLBACK(group_get_my_mowned_device),
131                 NULL);
132
133         g_signal_connect(group_skeleton,
134                 "handle-get-my-uuid",
135                 G_CALLBACK(group_get_my_uuid),
136                 NULL);
137
138         g_signal_connect(group_skeleton,
139                 "handle-request-create-group",
140                 G_CALLBACK(group_request_create_group),
141                 NULL);
142
143         g_signal_connect(group_skeleton,
144                 "handle-request-invite",
145                 G_CALLBACK(group_request_invite),
146                 NULL);
147
148         g_signal_connect(group_skeleton,
149                 "handle-request-eject",
150                 G_CALLBACK(group_request_eject),
151                 NULL);
152
153         g_signal_connect(group_skeleton,
154                 "handle-request-delete-group",
155                 G_CALLBACK(group_request_delete_group),
156                 NULL);
157
158         group = g_dbus_object_manager_server_new(COMP_DBUS_GROUP_PATH);
159
160         // Set connection to 'manager'
161         g_dbus_object_manager_server_set_connection(group, connection);
162
163         // Export 'group' interface on companion-manager DBUS
164         ret = g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(group_skeleton),
165                                 connection, COMP_DBUS_GROUP_PATH, &error);
166
167         if (ret == FALSE) {
168                 LOG_DEBUG("Can not skeleton_export %s", error->message);
169                 g_error_free(error);
170         }
171
172         return ret;
173 }
174
175 static void _app_conn_destroyed_cb(GDBusConnection *conn, const gchar *Name,
176                            const gchar *path, const gchar *interface, const gchar *sig,
177                            GVariant *param, gpointer user_data)
178 {
179         gchar *name = NULL;
180         gchar *old = NULL;
181         gchar *new = NULL;
182         comp_conn_destroy_data *data = user_data;
183         comp_context_t *comp_ctx = comp_context_get_context();
184
185         if (param == NULL)
186                 return;
187
188         g_variant_get(param, "(sss)", &name, &old, &new);
189
190         if (g_strcmp0(name, data->conn_name) == 0 && *new == '\0') {
191                 LOG_DEBUG("App %s Destroyed: name %s id %d", data->conn_name, name,
192                         data->conn_id);
193
194                 comp_ctx->ref_count -= 1;
195
196                 g_dbus_connection_signal_unsubscribe(data->connection, data->conn_id);
197         }
198
199         g_free(name);
200         g_free(old);
201         g_free(new);
202         g_free(data->conn_name);
203         g_free(data);
204
205         if (comp_ctx->ref_count == 0) {
206                 LOG_DEBUG("No app remaining quit comapnion-manager");
207                 g_main_loop_quit(comp_ctx->main_loop);
208         }
209
210         return;
211 }
212
213 static gboolean _register_comp_conn_destroy_signal(Enabler *enabler,
214                                                                    gchar *name)
215 {
216         comp_conn_destroy_data *data;
217         GDBusConnection *connection = NULL;
218
219         connection = g_dbus_interface_skeleton_get_connection(
220                                           (GDBusInterfaceSkeleton *)enabler_skeleton);
221         if (NULL == connection) {
222                 LOG_ERR("Failed to get GDbus connection");
223                 return FALSE;
224         }
225
226         data = g_try_malloc0(sizeof(comp_conn_destroy_data));
227         if (NULL == data) {
228                 LOG_ERR("Failed to Allocate memory");
229                 return FALSE;
230         }
231
232         data->conn_name = g_strdup(name);
233         data->connection = connection;
234
235         data->conn_id = g_dbus_connection_signal_subscribe(connection,
236                                                         DBUS_SERVICE_DBUS, DBUS_INTERFACE_DBUS,
237                                                         "NameOwnerChanged", NULL, name,
238                                                         G_DBUS_SIGNAL_FLAGS_NONE, _app_conn_destroyed_cb,
239                                                         data, NULL);
240
241         return TRUE;
242 }
243
244 gboolean enabler_add_ref(Enabler *enabler, GDBusMethodInvocation *invocation,
245         gchar *name, gpointer user_data)
246 {
247         LOG_DEBUG("Add Reference for %s", name);
248
249         if (TRUE == _register_comp_conn_destroy_signal(enabler, name)) {
250                 comp_context_t *comp_ctx = comp_context_get_context();
251                 comp_ctx->ref_count += 1;
252
253                 enabler_complete_add_ref(enabler, invocation, 0);
254         } else {
255                 LOG_ERR("Failed to register connection destroy signal");
256                 enabler_complete_add_ref(enabler, invocation,
257                                          COMP_ERROR_OPERATION_FAILED);
258         }
259
260         return TRUE;
261 }
262
263 static bool __enabler_init(GDBusConnection *connection)
264 {
265         gboolean ret = FALSE;
266         GError *error = NULL;
267
268         GDBusObjectManagerServer *enabler;
269
270         // Add interface to default object path
271         enabler_skeleton = enabler_skeleton_new();
272
273         // Register for method callbacks as signal callbacks
274         g_signal_connect(enabler_skeleton,
275                 "handle-add-ref",
276                 G_CALLBACK(enabler_add_ref),
277                 NULL);
278
279         enabler = g_dbus_object_manager_server_new(COMP_DBUS_ENABLER_PATH);
280
281         // Set connection to 'enabler'
282         g_dbus_object_manager_server_set_connection(enabler, connection);
283
284         // Export 'enabler' interface on companion DBUS
285         ret = g_dbus_interface_skeleton_export(
286                                 G_DBUS_INTERFACE_SKELETON(enabler_skeleton), connection,
287                                 COMP_DBUS_ENABLER_PATH, &error);
288
289         if (ret == FALSE) {
290                 LOG_DEBUG("Can not skeleton_export %s", error->message);
291                 g_error_free(error);
292         }
293
294         return ret;
295 }
296
297
298 static void on_bus_acquired(GDBusConnection *connection, const gchar *path,
299         gpointer user_data)
300 {
301         if (__group_init(connection) == false)
302                 LOG_DEBUG("Can not signal connect");
303
304         if (__enabler_init(connection) == false)
305                 LOG_ERR("Can't signal connect");
306 }
307
308 static void on_name_acquired(GDBusConnection *connection, const gchar *name,
309         gpointer user_data)
310 {
311         LOG_DEBUG("on_name_acquired : %s", name);
312 }
313
314 static void on_name_lost(GDBusConnection *connnection, const gchar *name,
315         gpointer user_data)
316 {
317         LOG_DEBUG("on_name_lost : %s", name);
318 }
319
320 int comp_gdbus_init()
321 {
322         g_bus_own_name(G_BUS_TYPE_SYSTEM, COMP_DBUS_SERVICE, G_BUS_NAME_OWNER_FLAGS_NONE,
323                 on_bus_acquired, on_name_acquired, on_name_lost, NULL, NULL);
324
325         return 0;
326 }