b0db797a2b3897d05b6a62395a34ed9257423e8b
[platform/core/connectivity/bluetooth-frwk.git] / bt-service-adaptation / services / obex / bt-service-obex-event-receiver.c
1 /*
2  * Copyright (c) 2011 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 <glib.h>
19 #include <string.h>
20 #include <dlog.h>
21 #include <vconf.h>
22 #include <vconf-internal-bt-keys.h>
23
24 #include "bluetooth-api.h"
25 #include "bt-internal-types.h"
26
27 #include "bt-service-common.h"
28 #include "bt-service-event.h"
29 #include "bt-service-main.h"
30 #include "bt-service-core-device.h"
31 #include "bt-service-obex-server.h"
32 #include "bt-service-obex-agent.h"
33 #include "bt-service-pbap.h"
34 #include "bt-service-opp-client.h"
35 #include "bt-service-map-client.h"
36 #include "bt-service-core-adapter.h"
37
38 #ifdef TIZEN_FEATURE_BT_DPM
39 #include "bt-service-dpm.h"
40 #endif
41
42 #define DBUS_TIMEOUT 20 * 1000 /* 20 Sec */
43 static GDBusConnection *manager_conn;
44 static GDBusConnection *obexd_conn;
45 static GDBusConnection *opc_obexd_conn;
46 static GDBusConnection *map_obexd_conn;
47
48 static guint event_id;
49
50 static guint session_reinit_timer;
51
52 /**
53  * obexd connection type
54  */
55 typedef enum {
56         OBEX_OPP = (1 << 1),
57         OBEX_FTP = (1 << 2),
58         OBEX_BIP = (1 << 3),
59         OBEX_PBAP = (1 << 4),
60         OBEX_IRMC = (1 << 5),
61         OBEX_PCSUITE = (1 << 6),
62         OBEX_SYNCEVOLUTION = (1 << 7),
63         OBEX_MAS = (1 << 8),
64         OBEX_MAP = (1 << 9),
65 } bluetooth_obex_connection_type_t;
66
67
68 void _bt_handle_property_changed_event(GVariant *msg, const char *object_path);
69 void _bt_opc_property_changed_event(GVariant *msg, char *path);
70 void _bt_map_property_changed_event(GVariant *msg, const char *path);
71 int _bt_register_service_event(GDBusConnection *g_conn, int event_type);
72 void _bt_unregister_service_event(GDBusConnection *g_conn, int event_type);
73 void _bt_opp_client_event_deinit(void);
74 void _bt_map_client_event_deinit(void);
75 void _bt_map_on_transfer_finished(const char *transfer_object_path, const int error);
76
77 /* Temp Adapter changes required to make OBEX work for handling device events here ,
78    This code will be removed and moved to OAL Event Handling part .
79 */
80
81 #if 0
82 static void __bt_get_uuids(GVariant *value, bt_remote_dev_info_t *info)
83 {
84         ret_if(value == NULL);
85         ret_if(info == NULL);
86
87         gsize uuid_count = 0;
88
89         info->uuids = g_variant_dup_strv(value, &uuid_count);
90         info->uuid_count = (unsigned int)uuid_count;
91
92         BT_DBG("uuid count : %d", uuid_count);
93 }
94 #endif
95
96 void _bt_convert_addr_string_to_secure_string(char *addr,
97                                         const char *address)
98 {
99         int len;
100
101         ret_if(address == NULL);
102         ret_if(addr == NULL);
103
104         len = strlen(address);
105         ret_if(len != BT_ADDRESS_STRING_SIZE - 1);
106
107         g_strlcpy(addr, address, BT_ADDRESS_STRING_SIZE);
108
109         addr[len-1] = 'X';
110         addr[len-2] = 'X';
111
112         return;
113 }
114
115 bt_status_t _bt_adapter_get_status_for_Obex(void)
116 {
117         int value = VCONFKEY_BT_STATUS_OFF;
118
119         /* check VCONFKEY_BT_STATUS */
120         if (vconf_get_int(VCONFKEY_BT_STATUS, &value) != 0) {
121                 BT_ERR("fail to get vconf key!");
122                 return BLUETOOTH_ADAPTER_DISABLED;
123         }
124
125         return value;
126 }
127
128 static int __bt_get_owner_info(GVariant *msg, char **name,
129                                 char **previous, char **current)
130 {
131         g_variant_get(msg, "(sss)", name, previous, current);
132         return BLUETOOTH_ERROR_NONE;
133 }
134
135 static int __bt_get_agent_signal_info(GVariant *msg, char **address,
136                                 char **name, char **uuid)
137 {
138         g_variant_get(msg, "(sss)", address, name, uuid);
139         return BLUETOOTH_ERROR_NONE;
140 }
141
142 gboolean __bt_handle_is_flight_mode_enabled(void)
143 {
144         if (TIZEN_FEATURE_FLIGHTMODE_ENABLED) {
145                 int is_flight_mode = 0;
146                 int ret = -1;
147                 ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &is_flight_mode);
148                 if (ret != 0)
149                         BT_ERR("vconf_get_bool failed");
150
151                 return (is_flight_mode == 0) ? FALSE : TRUE;
152         } else {
153                 return FALSE;
154         }
155 }
156
157 void _bt_handle_adapter_event(GVariant *msg, const char *member)
158 {
159         BT_DBG("+");
160         ret_if(member == NULL);
161
162         if (strcasecmp(member, "DeviceCreated") == 0) {
163                 char *object_path = NULL;
164                 char *address;
165                 ret_if(_bt_is_device_creating() == FALSE);
166
167                 /* Bonding from remote device */
168                 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
169
170                 g_variant_get(msg, "(&o)", &object_path);
171                 _bt_convert_device_path_to_address((const char*)object_path, address);
172
173                 g_free(address);
174         } else if (strcasecmp(member, BT_HARDWARE_ERROR) == 0) {
175                 BT_ERR_C("### Hardware error received from BLUEZ");
176         } else if (strcasecmp(member, BT_TX_TIMEOUT_ERROR) == 0) {
177                 BT_ERR_C("### Tx timeout error received from BLUEZ");
178         }
179         BT_DBG("-");
180 }
181
182 static void __bt_obex_property_changed_event(GVariant *msg, const char *path)
183 {
184         BT_DBG("+");
185
186         GVariantIter value_iter;
187         GVariant *child = NULL, *val = NULL;
188         char *property = NULL;
189         g_variant_iter_init(&value_iter, msg);
190         while ((child = g_variant_iter_next_value(&value_iter))) {
191                 g_variant_get(child, "{sv}", &property, &val);
192
193                 ret_if(property == NULL);
194
195                 BT_DBG("property :%s", property);
196
197                 if (strcasecmp(property, "Status") == 0) {
198                         char  *status;
199                         g_variant_get(val, "s", &status);
200
201                         if (strcasecmp(status, "active") == 0) {
202                                 _bt_obex_transfer_started(path);
203                         } else if (strcasecmp(status, "complete") == 0) {
204                                 _bt_obex_transfer_completed(path, TRUE);
205                                 _bt_pbap_obex_transfer_completed(path, TRUE);
206                         } else if (strcasecmp(status, "error") == 0) {
207                                 _bt_obex_transfer_completed(path, FALSE);
208                                 _bt_pbap_obex_transfer_completed(path, FALSE);
209                         }
210                         g_free(status);
211                 } else if (strcasecmp(property, "Transferred") == 0) {
212                         guint64 transferred  = 0;
213                         /* As Transferred is expected guint64 so change int to guint64 and
214                          * eariler transferred is static because of it can overwrite data
215                          * on present on opc_obex_conn or obexd_conn as these are
216                          * static memory are in sequential */
217                         g_variant_get(val, "t", &transferred);
218
219                         _bt_obex_transfer_progress(path, transferred);
220                 }
221                 /* TODO: MAP, "Complete"? see above */
222                 g_free(property);
223                 g_variant_unref(val);
224                 g_variant_unref(child);
225         }
226         BT_DBG("-");
227 }
228
229 void _bt_handle_property_changed_event(GVariant *msg, const char *object_path)
230 {
231         char *interface_name = NULL;
232         GVariant *val = NULL;
233
234         g_variant_get(msg, "(&s@a{sv}@as)", &interface_name, &val, NULL);
235         BT_DBG("_bt_handle_property_changed_event");
236
237         if (strcasecmp(interface_name, BT_ADAPTER_INTERFACE) == 0) {
238                 gboolean ret = FALSE;
239                 gboolean powered = FALSE;
240
241                 /* Check if Adapter is disabled, cancle queued transfers if any */
242                 ret = g_variant_lookup(msg, "Powered", "b", &powered);
243                 if (ret && !powered)
244                         _bt_cancel_queued_transfers();
245         } else if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) {
246                 BT_DBG("BT_OBEX_TRANSFER_INTERFACE");
247                 __bt_obex_property_changed_event(val,
248                                         object_path);
249         }
250         g_variant_unref(val);
251 }
252
253 void __bt_opc_property_changed_event(GVariant *msg,
254                                                 const char *path)
255 {
256         GVariantIter value_iter;
257         char *property = NULL;
258         GVariant *val = NULL;
259         GVariant *child = NULL;
260
261         g_variant_iter_init(&value_iter, msg);
262         if ((child = g_variant_iter_next_value(&value_iter))) {
263                 g_variant_get(child, "{sv}", &property, &val);
264                 ret_if(property == NULL);
265
266                 if (strcasecmp(property, "Status") == 0) {
267                         char *status = NULL;
268                         g_variant_get(val, "s", &status);
269                         BT_DBG("Status is %s", status);
270
271                         if (strcasecmp(status, "active") == 0)
272                                 _bt_obex_client_started(path);
273                         else if (strcasecmp(status, "complete") == 0)
274                                 _bt_obex_client_completed(path, TRUE);
275                         else if (strcasecmp(status, "error") == 0)
276                                 _bt_obex_client_completed(path, FALSE);
277
278                         g_free(status);
279                 } else if (strcasecmp(property, "Transferred") == 0) {
280                         guint64 transferred  = 0;
281                         g_variant_get(val, "t", &transferred);
282
283                         _bt_obex_client_progress(path, transferred);
284                 } else {
285                         BT_DBG("property : [%s]", property);
286                 }
287                 g_free(property);
288                 g_variant_unref(child);
289                 g_variant_unref(val);
290         }
291 }
292
293 void _bt_opc_property_changed_event(GVariant *msg, char *path)
294 {
295         char *interface_name = NULL;
296         GVariant *value = NULL;
297         g_variant_get(msg, "(&s@a{sv}@as)", &interface_name, &value, NULL);
298         BT_INFO("interface_name = %s", interface_name);
299         if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) {
300                 __bt_opc_property_changed_event(value,
301                                         path);
302         } else {
303                 BT_DBG("interface_name : [%s]", interface_name);
304         }
305         g_variant_unref(value);
306 }
307
308
309 void __bt_map_property_changed_event(GVariant *msg,
310                                                 const char *path)
311 {
312         BT_DBG("Entered");
313         GVariantIter value_iter;
314         char *property = NULL;
315         GVariant *val = NULL;
316         GVariant *child = NULL;
317
318         g_variant_iter_init(&value_iter, msg);
319         while ((child = g_variant_iter_next_value(&value_iter))) {
320                 g_variant_get(child, "{sv}", &property, &val);
321                 ret_if(property == NULL);
322
323                 if (strcasecmp(property, "Status") == 0) {
324                         char *status = NULL;
325                         g_variant_get(val, "s", &status);
326                         BT_DBG("Status is %s", status);
327
328                         if (strcasecmp(status, "active") == 0) {
329                                 BT_DBG("EVENT : STARTED");
330                                 // currently doing nothing
331                         } else if (strcasecmp(status, "complete") == 0) {
332                                 BT_DBG("EVENT : COMPLETED");
333                                 _bt_map_on_transfer_finished(path, BLUETOOTH_ERROR_NONE);
334                         } else if (strcasecmp(status, "error") == 0) {
335                                 BT_DBG("EVENT : FAILED");
336                                 _bt_map_on_transfer_finished(path, BLUETOOTH_ERROR_INTERNAL);
337                         }
338                         g_free(status);
339                 } else if (strcasecmp(property, "Transferred") == 0) {
340                         guint64 transferred  = 0;
341                         g_variant_get(val, "t", &transferred);
342
343                         BT_DBG("EVENT : PROGRESS CALLBACK");
344                         // currently doing nothing - progress callback type is not used
345                 } else {
346                         BT_DBG("OTHER EVENT : property : [%s]", property);
347                 }
348                 g_free(property);
349                 g_variant_unref(child);
350                 g_variant_unref(val);
351         }
352 }
353
354 void _bt_map_property_changed_event(GVariant *msg, const char *path)
355 {
356         BT_DBG("Entered _bt_map_property_changed_event");
357         char *interface_name = NULL;
358         GVariant *value = NULL;
359         g_variant_get(msg, "(&s@a{sv}@as)", &interface_name, &value, NULL);
360         BT_INFO("interface_name = %s", interface_name);
361         if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) {
362                 __bt_map_property_changed_event(value,
363                                 path);
364         } else {
365                 BT_DBG("interface_name : [%s]", interface_name);
366         }
367         g_variant_unref(value);
368 }
369
370
371 void _bt_handle_agent_event(GVariant *msg, const char *member)
372 {
373         int result = BLUETOOTH_ERROR_NONE;
374         char *address = NULL;
375         char *name = NULL;
376         char *uuid = NULL;
377         GVariant *param = NULL;
378         ret_if(member == NULL);
379
380         if (strcasecmp(member, "ObexAuthorize") == 0) {
381                 __bt_get_agent_signal_info(msg, &address, &name, &uuid);
382                 param = g_variant_new("(iss)", result, address, name);
383                 _bt_send_event(BT_OPP_SERVER_EVENT,
384                         BLUETOOTH_EVENT_OBEX_SERVER_CONNECTION_AUTHORIZE,
385                         param);
386                 /* TODO: MAP? see above */
387                 g_free(address);
388                 g_free(name);
389         }
390 }
391
392 static int __bt_get_object_path(GVariant *msg, char **path)
393 {
394         g_variant_get(msg, "(o*)", path, NULL);
395         if (*path == NULL)
396                 return BLUETOOTH_ERROR_INTERNAL;
397
398         return BLUETOOTH_ERROR_NONE;
399 }
400
401 char *_bt_get_bonded_device_name(char *address)
402 {
403         bt_remote_dev_info_t *dev_info;
404
405         retv_if(address == NULL, strdup(""));
406
407         dev_info = _bt_service_get_remote_dev_info(address);
408         retv_if(dev_info == NULL, strdup(""));
409         retv_if(dev_info->name == NULL, strdup(""));
410
411         return g_strdup(dev_info->name);
412 }
413 /* Temp Adapter Util changes to make OBEX work.
414 */
415
416 void _bt_handle_device_event(GVariant *msg, const char *member, const char *path)
417 {
418         char *address;
419         char secure_address[BT_ADDRESS_STRING_SIZE] = { 0 };
420         ret_if(path == NULL);
421
422         if (strcasecmp(member, "Disconnected") == 0) {
423                 unsigned char disc_reason = 0;
424                 unsigned char addr_type = 0;
425                 char *dev_name = NULL;
426                 gboolean sending = FALSE;
427
428                 g_variant_get(msg, "(yys)", &addr_type, &disc_reason, &dev_name);
429
430                 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
431
432                 _bt_convert_device_path_to_address(path, address);
433
434                 /* 0x00 BDADDR_BRDER
435                       0x01 BDADDR_LE_PUBLIC
436                       0x02 BDADDR_LE_RANDOM */
437                 _bt_convert_addr_string_to_secure_string(secure_address, address);
438                 BT_INFO("Address : %s Type : %d", secure_address, addr_type);
439                 BT_ERR_C("### Disconnected [%s] [%d : %s] [%s]", !addr_type ? "BREDR" : "LE",
440                                 disc_reason, _bt_convert_disc_reason_to_string(disc_reason),
441                                 !addr_type ? dev_name : secure_address);
442                 g_free(dev_name);
443
444                 if (!addr_type) {
445                         /*Check for any OPP transfer on the device and cancel
446                          * the transfer
447                          */
448                         _bt_obex_check_pending_transfer(address);
449                         _bt_opp_client_is_sending(&sending);
450                         if (sending == TRUE)
451                                 _bt_opp_client_check_pending_transfer(address);
452                         /* TODO: MAP? see above */
453                 }
454                 g_free(address);
455         } else if (strcasecmp(member, "ProfileStateChanged") == 0) {
456                 int state = 0;
457                 char *profile_uuid = NULL;
458                 bluetooth_device_address_t bd_addr;
459
460                 g_variant_get(msg, "(si)", &profile_uuid, &state);
461
462                 address = g_malloc0(BT_ADDRESS_STRING_SIZE);
463
464                 _bt_convert_device_path_to_address(path, address);
465                 _bt_convert_addr_string_to_type(bd_addr.addr, address);
466
467                 _bt_convert_addr_string_to_secure_string(secure_address, address);
468                 BT_DBG("Address: %s", secure_address);
469                 BT_DBG("Profile UUID: %s", profile_uuid);
470                 BT_DBG("State: %d", state);
471                 g_free(address);
472         }
473 }
474
475 static  void __bt_manager_event_filter(GDBusConnection *connection,
476                                         const gchar *sender_name,
477                                         const gchar *object_path,
478                                         const gchar *interface_name,
479                                         const gchar *signal_name,
480                                         GVariant *parameters,
481                                         gpointer user_data)
482 {
483
484         GVariant *value;
485         char *obj_path = NULL;
486
487         if (signal_name == NULL)
488                 return;
489
490         if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
491                 g_variant_get(parameters, "(&o@a{sa{sv}})", &obj_path, &value);
492
493                 if (strcasecmp(obj_path, BT_BLUEZ_HCI_PATH) == 0)
494                         if (!TIZEN_FEATURE_BT_USB_DONGLE) {
495                                 if (_bt_register_obex_server() != BLUETOOTH_ERROR_NONE)
496                                         BT_ERR("Fail to init obex server");
497                         }
498                 g_variant_unref(value);
499         } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
500                         if (TIZEN_FEATURE_BT_USB_DONGLE) {
501                                 if (_bt_unregister_obex_server() != BLUETOOTH_ERROR_NONE)
502                                         BT_ERR("Fail to unregister obex server");
503                         }
504         } else if (strcasecmp(signal_name, "NameOwnerChanged") == 0) {
505                 gboolean value;
506                 char *name = NULL;
507                 char *previous = NULL;
508                 char *current = NULL;
509
510                 if (__bt_get_owner_info(parameters, &name, &previous, &current)) {
511                         BT_ERR("Fail to get the owner info");
512                         return;
513                 }
514
515                 if (*current != '\0') {
516                         g_free(current);
517                         if (name)
518                                 g_free(name);
519                         if (previous)
520                                 g_free(previous);
521                         return;
522                 }
523
524                 if (strcasecmp(name, BT_BLUEZ_NAME) == 0) {
525                         BT_INFO_C("### Bluetoothd is terminated");
526
527                         if (_bt_unregister_obex_server() != BLUETOOTH_ERROR_NONE)
528                                 BT_ERR("Fail to unregister obex server");
529
530                 }
531
532                 _bt_obex_server_check_allocation(&value);
533
534                 if (value == TRUE) {
535                         /* Check if the obex server was terminated abnormally */
536                         _bt_obex_server_check_termination(name);
537                 }
538
539                 g_free(name);
540                 g_free(previous);
541                 g_free(current);
542         } else if (g_strcmp0(interface_name, BT_AGENT_INTERFACE) == 0) {
543                 _bt_handle_agent_event(parameters, signal_name);
544         } else if (g_strcmp0(interface_name, BT_DEVICE_INTERFACE) == 0) {
545                 _bt_handle_device_event(parameters, signal_name, object_path);
546         }
547
548         return;
549 }
550
551 static gboolean __bt_is_obexd_event(GVariant *msg, const char *interface)
552 {
553
554         if (g_strcmp0(interface, BT_PROPERTIES_INTERFACE) == 0) {
555                 char *interface_name = NULL;
556
557                 g_variant_get(msg, "(&s@a{sv}@as)", &interface_name, NULL, NULL);
558                 retv_if(interface_name == NULL, FALSE);
559
560                 if (strcasecmp(interface_name, BT_OBEX_TRANSFER_INTERFACE) == 0) {
561                         BT_DBG("BT_OBEX_TRANSFER_INTERFACE");
562                         return TRUE;
563                 }
564         }
565
566         return FALSE;
567 }
568
569 static  void __bt_obexd_event_filter(GDBusConnection *connection,
570                                         const gchar *sender_name,
571                                         const gchar *object_path,
572                                         const gchar *interface_name,
573                                         const gchar *signal_name,
574                                         GVariant *parameters,
575                                         gpointer user_data)
576 {
577         const char *member = signal_name;
578         char *obj_path = NULL;
579         ret_if(member == NULL);
580
581         if (strcasecmp(member, "InterfacesAdded") == 0) {
582                 if (__bt_get_object_path(parameters, &obj_path)) {
583                         BT_ERR("Fail to get the path");
584                         return;
585                 }
586                 BT_INFO("object_path = [%s]", obj_path);
587
588                 /*Handle OPP_SERVER_CONNECTED_EVENT here */
589                 /* TODO: MAP? see above */
590                 if (strncmp(obj_path, BT_SESSION_BASEPATH_SERVER,
591                                 strlen(BT_SESSION_BASEPATH_SERVER)) != 0) {
592                         g_free(obj_path);
593                         return;
594                 }
595
596                 if (g_strrstr(obj_path, "session") && g_strrstr(obj_path, "transfer")) {
597                         BT_DBG("Obex_Server_Session_Transfer connected");
598                         _bt_obex_transfer_connected(obj_path);
599                 }
600                 g_free(obj_path);
601         } else if (strcasecmp(member, "InterfacesRemoved") == 0) {
602                 /*Handle OPP_SERVER_DISCONNECTED_EVENT here */
603                 /* TODO: MAP? see above */
604                 if (__bt_get_object_path(parameters, &obj_path)) {
605                         BT_ERR("Fail to get the path");
606                         return;
607                 }
608                 BT_INFO("object_path = [%s]", obj_path);
609
610                 if (strncmp(obj_path, BT_SESSION_BASEPATH_CLIENT,
611                                 strlen(BT_SESSION_BASEPATH_CLIENT)) == 0) {
612                         BT_DBG("Call PBAP Disconnected");
613                         _bt_obex_pbap_client_disconnect(obj_path);
614                 }
615
616                 if (strncmp(obj_path, BT_SESSION_BASEPATH_SERVER,
617                                 strlen(BT_SESSION_BASEPATH_SERVER)) != 0) {
618                         g_free(obj_path);
619                         return;
620                 }
621
622                 if (g_strrstr(obj_path, "session") && g_strrstr(obj_path, "transfer")) {
623                         BT_DBG("Obex_Server_Session_Transfer disconnected %s",
624                                                                 obj_path);
625
626                         _bt_obex_transfer_disconnected(obj_path);
627                 }
628                 g_free(obj_path);
629         } else if (__bt_is_obexd_event(parameters, interface_name) == TRUE) {
630                 const char *path = object_path;
631
632                 if (strncmp(path, BT_SESSION_BASEPATH_SERVER,
633                                 strlen(BT_SESSION_BASEPATH_SERVER)) != 0 &&
634                         strncmp(path, BT_SESSION_BASEPATH_CLIENT,
635                                 strlen(BT_SESSION_BASEPATH_CLIENT)) != 0) {
636                         BT_DBG("DBUS_HANDLER_RESULT_NOT_YET_HANDLED");
637                         return;
638                 }
639
640                 _bt_handle_property_changed_event(parameters, path);
641         }
642         return;
643 }
644
645 static gboolean __bt_is_obexd_client_event(GVariant *msg, const char *interface)
646 {
647         BT_DBG("+");
648
649         if (g_strcmp0(interface, BT_PROPERTIES_INTERFACE) == 0) {
650                 char *interface_name = NULL;
651
652                 g_variant_get(msg, "(&s@a{sv}@as)", &interface_name, NULL, NULL);
653
654                 retv_if(interface_name == NULL, FALSE);
655
656                 if (strcasecmp(interface_name,
657                                         BT_OBEX_TRANSFER_INTERFACE) == 0) {
658                         BT_DBG("-");
659                         return TRUE;
660                 }
661         }
662
663         BT_DBG("-");
664
665         return FALSE;
666 }
667
668 static  void __bt_opc_event_filter(GDBusConnection *connection,
669                                         const gchar *sender_name,
670                                         const gchar *object_path,
671                                         const gchar *interface_name,
672                                         const gchar *signal_name,
673                                         GVariant *parameters,
674                                         gpointer user_data)
675 {
676         const char *member = signal_name;
677         char *obj_path = NULL;
678         if (strcasecmp(member, "InterfacesAdded") == 0) {
679                 BT_DBG("InterfacesAdded");
680         } else if (strcasecmp(member, "InterfacesRemoved") == 0) {
681
682                 if (__bt_get_object_path(parameters, &obj_path)) {
683                         BT_ERR("Fail to get the path");
684                         return;
685                 }
686
687                 BT_DBG("object_path = %s", obj_path);
688
689                 if (strncmp(obj_path, BT_SESSION_BASEPATH_CLIENT,
690                                 strlen(BT_SESSION_BASEPATH_CLIENT)) != 0
691                                 || strstr(obj_path, "transfer") == NULL) {
692                         g_free(obj_path);
693                         return;
694                 } else if (strncmp(obj_path, BT_SESSION_BASEPATH_CLIENT,
695                                 strlen(BT_SESSION_BASEPATH_CLIENT)) == 0) {
696                         BT_DBG("Going to call opc disconnected");
697                         _bt_opc_disconnected(obj_path);
698                 }
699
700                 _bt_sending_files();
701                 g_free(obj_path);
702         } else if (__bt_is_obexd_client_event(parameters, interface_name) == TRUE) {
703                 char *path = (char *)object_path;
704                 BT_INFO("object_path %s", path);
705                 if (strncmp(path, BT_SESSION_BASEPATH_CLIENT,
706                         strlen(BT_SESSION_BASEPATH_CLIENT)) != 0) {
707                         BT_DBG("NOT BT_SESSION_BASEPATH_CLIENT");
708                         return;
709                 }
710
711                 _bt_opc_property_changed_event(parameters, path);
712         }
713
714         return;
715 }
716
717 int _bt_opp_client_event_init(void)
718 {
719         GError *error = NULL;
720
721         if (opc_obexd_conn == NULL) {
722                 opc_obexd_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
723
724                 if (!opc_obexd_conn) {
725                         if (error) {
726                                 BT_ERR("Unable to connect to dbus: %s", error->message);
727                                 g_clear_error(&error);
728                         }
729                 return BLUETOOTH_ERROR_INTERNAL;
730                 }
731         }
732
733         if (_bt_register_service_event(opc_obexd_conn,
734                         BT_OPP_CLIENT_EVENT) != BLUETOOTH_ERROR_NONE) {
735                         g_object_unref(opc_obexd_conn);
736                         opc_obexd_conn = NULL;
737                         return BLUETOOTH_ERROR_INTERNAL;
738         }
739
740         return BLUETOOTH_ERROR_NONE;
741 }
742
743 void _bt_opp_client_event_deinit(void)
744 {
745         if (opc_obexd_conn) {
746                 _bt_unregister_service_event(opc_obexd_conn,
747                                                 BT_OPP_CLIENT_EVENT);
748                  g_object_unref(opc_obexd_conn);
749                  opc_obexd_conn = NULL;
750         }
751 }
752
753 static  void __bt_map_event_filter(GDBusConnection *connection,
754                                         const gchar *sender_name,
755                                         const gchar *object_path,
756                                         const gchar *interface_name,
757                                         const gchar *signal_name,
758                                         GVariant *parameters,
759                                         gpointer user_data)
760 {
761         BT_DBG("Entered __bt_map_event_filter");
762         const char *member = signal_name;
763
764         if (strcasecmp(member, "InterfacesAdded") == 0) {
765                 BT_DBG("------------------------------------ADDED------------------------------------");
766                 // currently doing nothing
767         } else if (strcasecmp(member, "InterfacesRemoved") == 0) {
768                 BT_DBG("------------------------------------REMOVED------------------------------------");
769                 // TODO check if something should be called here?
770                 //_bt_map_on_transfer_finished(object_path, error);
771         } else if (__bt_is_obexd_client_event(parameters, interface_name) == TRUE) {
772                 BT_DBG("------------------------------------CLIENT EVENT------------------------------------");
773                 _bt_map_property_changed_event(parameters, object_path);
774         }
775
776         return;
777 }
778
779 int _bt_map_client_event_init(void)
780 {
781         GError *error = NULL;
782
783         if (map_obexd_conn == NULL) {
784                 map_obexd_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
785
786                 if (!map_obexd_conn) {
787                         if (error) {
788                                 BT_ERR("Unable to connect to dbus: %s", error->message);
789                                 g_clear_error(&error);
790                         }
791                 return BLUETOOTH_ERROR_INTERNAL;
792                 }
793         }
794
795         if (_bt_register_service_event(map_obexd_conn,
796                         BT_MAP_CLIENT_EVENT) != BLUETOOTH_ERROR_NONE) {
797                         g_object_unref(map_obexd_conn);
798                         map_obexd_conn = NULL;
799                         return BLUETOOTH_ERROR_INTERNAL;
800         }
801
802         return BLUETOOTH_ERROR_NONE;
803 }
804
805 void _bt_map_client_event_deinit(void)
806 {
807         if (map_obexd_conn) {
808                 _bt_unregister_service_event(map_obexd_conn,
809                                                 BT_MAP_CLIENT_EVENT);
810                  g_object_unref(map_obexd_conn);
811                  map_obexd_conn = NULL;
812         }
813 }
814
815 int _bt_register_manager_subscribe_signal(GDBusConnection *conn,
816                 int subscribe)
817 {
818         if (conn == NULL)
819                 return -1;
820
821         static int subs_interface_added_id = -1;
822         static int subs_interface_removed_id = -1;
823         static int subs_name_owner_changed = -1;
824
825         if (subscribe) {
826                 if (subs_interface_added_id == -1) {
827                         subs_interface_added_id = g_dbus_connection_signal_subscribe(conn,
828                                 NULL, BT_MANAGER_INTERFACE,
829                                 BT_INTERFACES_ADDED, NULL, NULL, 0,
830                                 __bt_manager_event_filter,
831                                 NULL, NULL);
832                 }
833                 if (subs_interface_removed_id == -1) {
834                         subs_interface_removed_id = g_dbus_connection_signal_subscribe(conn,
835                                 NULL, BT_MANAGER_INTERFACE,
836                                 BT_INTERFACES_REMOVED, NULL, NULL, 0,
837                                 __bt_manager_event_filter,
838                                 NULL, NULL);
839                 }
840                 if (subs_name_owner_changed == -1) {
841                         subs_name_owner_changed = g_dbus_connection_signal_subscribe(conn,
842                                 NULL, BT_EVENT_FREEDESKTOP,
843                                 BT_NAME_OWNER_CHANGED, NULL, NULL, 0,
844                                 __bt_manager_event_filter, NULL, NULL);
845                 }
846
847         } else {
848                 if (subs_interface_added_id != -1) {
849                         g_dbus_connection_signal_unsubscribe(conn,
850                                         subs_interface_added_id);
851                         subs_interface_added_id = -1;
852                 }
853                 if (subs_interface_removed_id != -1) {
854                         g_dbus_connection_signal_unsubscribe(conn,
855                                         subs_interface_removed_id);
856                         subs_interface_removed_id = -1;
857                 }
858                 if (subs_name_owner_changed != -1) {
859                         g_dbus_connection_signal_unsubscribe(conn,
860                                         subs_name_owner_changed);
861                         subs_name_owner_changed = -1;
862                 }
863
864         }
865         return 0;
866 }
867
868 int _bt_register_device_subscribe_signal(GDBusConnection *conn,
869                 int subscribe)
870 {
871         if (conn == NULL)
872                 return -1;
873
874         static int subs_device_id = -1;
875
876         if (subscribe) {
877                 if (subs_device_id == -1) {
878                         subs_device_id = g_dbus_connection_signal_subscribe(conn,
879                                 NULL, BT_DEVICE_INTERFACE,
880                                 NULL, NULL, NULL, 0,
881                                 __bt_manager_event_filter,
882                                 NULL, NULL);
883                 }
884         } else {
885                 if (subs_device_id != -1) {
886                         g_dbus_connection_signal_unsubscribe(conn,
887                                         subs_device_id);
888                         subs_device_id = -1;
889                 }
890         }
891         return 0;
892 }
893
894 int _bt_register_input_subscribe_signal(GDBusConnection *conn,
895                 int subscribe)
896 {
897         if (conn == NULL)
898                 return -1;
899
900         static int subs_input_id = -1;
901
902         if (subscribe) {
903                 if (subs_input_id == -1) {
904                         subs_input_id = g_dbus_connection_signal_subscribe(conn,
905                                 NULL, BT_INPUT_INTERFACE,
906                                 NULL, NULL, NULL, 0,
907                                 __bt_manager_event_filter,
908                                 NULL, NULL);
909                 }
910         } else {
911                 if (subs_input_id != -1) {
912                         g_dbus_connection_signal_unsubscribe(conn,
913                                         subs_input_id);
914                         subs_input_id = -1;
915                 }
916         }
917         return 0;
918 }
919
920
921
922 int _bt_register_opp_server_subscribe_signal(GDBusConnection *conn,
923                 int subscribe)
924 {
925         if (conn == NULL)
926                 return -1;
927
928         static int subs_opp_server_interface_added_id = -1;
929         static int subs_opp_server_interface_removed_id = -1;
930         static int subs_opp_server_property_id = -1;
931
932
933         if (subscribe) {
934                 if (subs_opp_server_interface_added_id == -1) {
935                         subs_opp_server_interface_added_id = g_dbus_connection_signal_subscribe(conn,
936                                 NULL, BT_MANAGER_INTERFACE,
937                                 BT_INTERFACES_ADDED, NULL, NULL, 0,
938                                 __bt_obexd_event_filter,
939                                 NULL, NULL);
940                 }
941                 if (subs_opp_server_interface_removed_id == -1) {
942                         subs_opp_server_interface_removed_id = g_dbus_connection_signal_subscribe(conn,
943                                 NULL, BT_MANAGER_INTERFACE,
944                                 BT_INTERFACES_REMOVED, NULL, NULL, 0,
945                                 __bt_obexd_event_filter,
946                                 NULL, NULL);
947                 }
948                 if (subs_opp_server_property_id == -1) {
949                         subs_opp_server_property_id = g_dbus_connection_signal_subscribe(conn,
950                                 NULL, BT_PROPERTIES_INTERFACE,
951                                 BT_PROPERTIES_CHANGED, NULL, NULL, 0,
952                                 __bt_obexd_event_filter,
953                                 NULL, NULL);
954                 }
955         } else {
956                 if (subs_opp_server_interface_added_id != -1) {
957                         g_dbus_connection_signal_unsubscribe(conn,
958                                         subs_opp_server_interface_added_id);
959                         subs_opp_server_interface_added_id = -1;
960                 }
961                 if (subs_opp_server_interface_removed_id != -1) {
962                         g_dbus_connection_signal_unsubscribe(conn,
963                                         subs_opp_server_interface_removed_id);
964                         subs_opp_server_interface_removed_id = -1;
965                 }
966                 if (subs_opp_server_property_id != -1) {
967                         g_dbus_connection_signal_unsubscribe(conn,
968                                         subs_opp_server_property_id);
969                         subs_opp_server_property_id = -1;
970                 }
971         }
972         return 0;
973 }
974
975 int _bt_register_opp_client_subscribe_signal(GDBusConnection *conn,
976                 int subscribe)
977 {
978         if (conn == NULL)
979                 return -1;
980
981         static int subs_opp_client_interface_added_id = -1;
982         static int subs_opp_client_interface_removed_id = -1;
983         static int subs_opp_client_property_id = -1;
984
985
986         if (subscribe) {
987                 if (subs_opp_client_interface_added_id == -1) {
988                         subs_opp_client_interface_added_id = g_dbus_connection_signal_subscribe(conn,
989                                 NULL, BT_MANAGER_INTERFACE,
990                                 BT_INTERFACES_ADDED, NULL, NULL, 0,
991                                 __bt_opc_event_filter,
992                                 NULL, NULL);
993                 }
994                 if (subs_opp_client_interface_removed_id == -1) {
995                         subs_opp_client_interface_removed_id = g_dbus_connection_signal_subscribe(conn,
996                                 NULL, BT_MANAGER_INTERFACE,
997                                 BT_INTERFACES_REMOVED, NULL, NULL, 0,
998                                 __bt_opc_event_filter,
999                                 NULL, NULL);
1000                 }
1001                 if (subs_opp_client_property_id == -1) {
1002                         subs_opp_client_property_id = g_dbus_connection_signal_subscribe(conn,
1003                                 NULL, BT_PROPERTIES_INTERFACE,
1004                                 BT_PROPERTIES_CHANGED, NULL, NULL, 0,
1005                                 __bt_opc_event_filter,
1006                                 NULL, NULL);
1007                 }
1008         } else {
1009                 if (subs_opp_client_interface_added_id != -1) {
1010                         g_dbus_connection_signal_unsubscribe(conn,
1011                                         subs_opp_client_interface_added_id);
1012                         subs_opp_client_interface_added_id = -1;
1013                 }
1014                 if (subs_opp_client_interface_removed_id != -1) {
1015                         g_dbus_connection_signal_unsubscribe(conn,
1016                                         subs_opp_client_interface_removed_id);
1017                         subs_opp_client_interface_removed_id = -1;
1018                 }
1019                 if (subs_opp_client_property_id != -1) {
1020                         g_dbus_connection_signal_unsubscribe(conn,
1021                                         subs_opp_client_property_id);
1022                         subs_opp_client_property_id = -1;
1023                 }
1024         }
1025         return 0;
1026 }
1027
1028 int _bt_register_map_client_subscribe_signal(GDBusConnection *conn,
1029                 int subscribe)
1030 {
1031         if (conn == NULL)
1032                 return -1;
1033
1034         static int subs_map_client_interface_added_id = -1;
1035         static int subs_map_client_interface_removed_id = -1;
1036         static int subs_map_client_property_id = -1;
1037
1038
1039         if (subscribe) {
1040                 if (subs_map_client_interface_added_id == -1) {
1041                         subs_map_client_interface_added_id = g_dbus_connection_signal_subscribe(conn,
1042                                 NULL, BT_MANAGER_INTERFACE,
1043                                 BT_INTERFACES_ADDED, NULL, NULL, 0,
1044                                 __bt_map_event_filter,
1045                                 NULL, NULL);
1046                 }
1047                 if (subs_map_client_interface_removed_id == -1) {
1048                         subs_map_client_interface_removed_id = g_dbus_connection_signal_subscribe(conn,
1049                                 NULL, BT_MANAGER_INTERFACE,
1050                                 BT_INTERFACES_REMOVED, NULL, NULL, 0,
1051                                 __bt_map_event_filter,
1052                                 NULL, NULL);
1053                 }
1054                 if (subs_map_client_property_id == -1) {
1055                         subs_map_client_property_id = g_dbus_connection_signal_subscribe(conn,
1056                                 NULL, BT_PROPERTIES_INTERFACE,
1057                                 BT_PROPERTIES_CHANGED, NULL, NULL, 0,
1058                                 __bt_map_event_filter,
1059                                 NULL, NULL);
1060                 }
1061         } else {
1062                 if (subs_map_client_interface_added_id != -1) {
1063                         g_dbus_connection_signal_unsubscribe(conn,
1064                                         subs_map_client_interface_added_id);
1065                         subs_map_client_interface_added_id = -1;
1066                 }
1067                 if (subs_map_client_interface_removed_id != -1) {
1068                         g_dbus_connection_signal_unsubscribe(conn,
1069                                         subs_map_client_interface_removed_id);
1070                         subs_map_client_interface_removed_id = -1;
1071                 }
1072                 if (subs_map_client_property_id != -1) {
1073                         g_dbus_connection_signal_unsubscribe(conn,
1074                                         subs_map_client_property_id);
1075                         subs_map_client_property_id = -1;
1076                 }
1077         }
1078         return 0;
1079 }
1080
1081
1082 int _bt_register_service_event(GDBusConnection *g_conn, int event_type)
1083 {
1084         BT_DBG("+");
1085
1086         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1087
1088         switch (event_type) {
1089         case BT_MANAGER_EVENT:
1090                 BT_DBG("BT_MANAGER_EVENT: register service event");
1091                 _bt_register_manager_subscribe_signal(g_conn, TRUE);
1092                 break;
1093         case BT_DEVICE_EVENT:
1094                 BT_DBG("BT_DEVICE_EVENT: register service event");
1095                 _bt_register_device_subscribe_signal(g_conn, TRUE);
1096                 break;
1097         case BT_OPP_SERVER_EVENT:
1098                 BT_DBG("BT_OPP_SERVER_EVENT: register service event");
1099                 _bt_register_opp_server_subscribe_signal(g_conn, TRUE);
1100                 break;
1101         case BT_OPP_CLIENT_EVENT:
1102                 BT_DBG("BT_OPP_CLIENT_EVENT: register service event");
1103                 _bt_register_opp_client_subscribe_signal(g_conn, TRUE);
1104                 break;
1105         case BT_MAP_CLIENT_EVENT:
1106                 BT_DBG("BT_MAP_CLIENT_EVENT: register service event");
1107                 _bt_register_map_client_subscribe_signal(g_conn, TRUE);
1108                 break;
1109         default:
1110                 BT_ERR("Unknown event");
1111                 return BLUETOOTH_ERROR_INTERNAL;
1112         }
1113
1114         return BLUETOOTH_ERROR_NONE;
1115 }
1116
1117 void _bt_unregister_service_event(GDBusConnection *g_conn, int event_type)
1118 {
1119         BT_DBG("+");
1120
1121         ret_if(g_conn == NULL);
1122
1123         switch (event_type) {
1124         case BT_MANAGER_EVENT:
1125                 _bt_register_manager_subscribe_signal(g_conn, FALSE);
1126                 _bt_register_device_subscribe_signal(g_conn, FALSE);
1127                 _bt_register_input_subscribe_signal(g_conn, FALSE);
1128                 break;
1129         case BT_OPP_SERVER_EVENT:
1130                 _bt_register_opp_server_subscribe_signal(g_conn, FALSE);
1131                 break;
1132         case BT_OPP_CLIENT_EVENT:
1133                 _bt_register_opp_client_subscribe_signal(g_conn, FALSE);
1134                 break;
1135         case BT_MAP_CLIENT_EVENT:
1136                 _bt_register_map_client_subscribe_signal(g_conn, FALSE);
1137                 break;
1138         default:
1139                 BT_ERR("Unknown event");
1140                 return;
1141         }
1142
1143         BT_DBG("-");
1144 }
1145
1146 static int __bt_init_manager_receiver(void)
1147 {
1148         BT_DBG("+");
1149
1150         GError *error = NULL;
1151
1152         if (manager_conn == NULL) {
1153                 manager_conn =  g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1154                 if (error != NULL) {
1155                         BT_ERR("ERROR: Can't get on system bus [%s]", error->message);
1156                         g_clear_error(&error);
1157                 }
1158                 retv_if(manager_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1159         }
1160
1161         if (_bt_register_service_event(manager_conn,
1162                                 BT_MANAGER_EVENT) != BLUETOOTH_ERROR_NONE)
1163                 goto fail;
1164
1165         if (_bt_register_service_event(manager_conn,
1166                                 BT_DEVICE_EVENT) != BLUETOOTH_ERROR_NONE)
1167                 goto fail;
1168
1169         return BLUETOOTH_ERROR_NONE;
1170 fail:
1171         if (manager_conn) {
1172                 g_object_unref(manager_conn);
1173                 manager_conn = NULL;
1174         }
1175
1176         BT_DBG("-");
1177
1178         return BLUETOOTH_ERROR_INTERNAL;
1179 }
1180
1181 static int __bt_init_obexd_receiver(void)
1182 {
1183         BT_DBG("+");
1184         if (!TIZEN_PROFILE_TV) { /* TODO: obexd doesn't work in TV profile. It should be resolved later. */
1185                 GError *error = NULL;
1186
1187                 if (obexd_conn == NULL) {
1188                         obexd_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1189                         if (error != NULL) {
1190                                 BT_ERR("ERROR: Can't get on session bus [%s]", error->message);
1191                                 g_clear_error(&error);
1192                         }
1193                         retv_if(obexd_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1194                 }
1195
1196                 if (_bt_register_service_event(obexd_conn,
1197                                         BT_OPP_SERVER_EVENT) != BLUETOOTH_ERROR_NONE) {
1198                         BT_ERR("Error while registering service event");
1199                         g_object_unref(obexd_conn);
1200                         obexd_conn = NULL;
1201                         return BLUETOOTH_ERROR_INTERNAL;
1202                 }
1203         }
1204
1205         BT_DBG("-");
1206
1207         return BLUETOOTH_ERROR_NONE;
1208 }
1209
1210 gboolean __bt_reinit_obexd_receiver(gpointer user_data)
1211 {
1212         static int retry_cnt = 0;
1213         int result = BLUETOOTH_ERROR_NONE;
1214
1215         BT_DBG("+");
1216
1217         result = __bt_init_obexd_receiver();
1218         if (result != BLUETOOTH_ERROR_NONE) {
1219                 /* 20 ms * 50 = 10 seconds. During 10 seconds fail to initialize,
1220                    then it is not the timing issue. Just can't use the session bus connection */
1221                 if (retry_cnt > 100) {
1222                         BT_ERR("Fail to init obexd receiver by 50 times.");
1223                         retry_cnt = 0;
1224                         session_reinit_timer = 0;
1225                         return FALSE;
1226                 }
1227                 retry_cnt++;
1228                 BT_DBG("Retry to initialize the obexd receiver");
1229                 return TRUE;
1230         }
1231
1232         retry_cnt = 0;
1233         session_reinit_timer = 0;
1234
1235         BT_DBG("-");
1236
1237         return FALSE;
1238 }
1239
1240 /* To receive the event from bluez */
1241 int _bt_init_obex_event_receiver(void)
1242 {
1243         BT_DBG("+");
1244
1245         int result;
1246
1247         result = __bt_init_manager_receiver();
1248         retv_if(result != BLUETOOTH_ERROR_NONE, result);
1249
1250         result = __bt_init_obexd_receiver();
1251         if (result != BLUETOOTH_ERROR_NONE) {
1252                 BT_ERR("Fail to init obexd receiver");
1253
1254                 /* Try to re-initialize obexd receiver in the timer */
1255                 if (session_reinit_timer > 0)
1256                         g_source_remove(session_reinit_timer);
1257
1258                 session_reinit_timer = g_timeout_add(200,
1259                                                         (GSourceFunc)__bt_reinit_obexd_receiver, NULL);
1260         }
1261
1262         BT_DBG("-");
1263
1264         return BLUETOOTH_ERROR_NONE;
1265 }
1266
1267 void _bt_deinit_obex_event_receiver(void)
1268 {
1269         BT_DBG("+");
1270
1271         _bt_unregister_service_event(manager_conn, BT_MANAGER_EVENT);
1272
1273         _bt_unregister_service_event(obexd_conn, BT_OPP_SERVER_EVENT);
1274
1275         if (manager_conn) {
1276                 g_object_unref(manager_conn);
1277                 manager_conn = NULL;
1278         }
1279
1280         if (obexd_conn) {
1281                 g_object_unref(obexd_conn);
1282                 obexd_conn = NULL;
1283         }
1284
1285         if (event_id > 0)
1286                 g_source_remove(event_id);
1287         event_id = 0;
1288
1289         BT_DBG("-");
1290 }
1291