bt-api: Fix incorrect macro expansion for service function
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-audio.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 <gio/gio.h>
19 #include <glib.h>
20 #include <dlog.h>
21 #include <string.h>
22 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
23 #include <vconf.h>
24 #endif
25 #include <syspopup_caller.h>
26
27 #include "bluetooth-api.h"
28 #include "bt-internal-types.h"
29
30 #include "bt-service-audio.h"
31 #include "bt-service-adapter.h"
32 #include "bt-service-common.h"
33 #include "bt-service-device.h"
34 #include "bt-service-event.h"
35 #include "bt-service-util.h"
36
37 #include "bt-service-headset-connection.h"
38
39 #ifdef TIZEN_SUPPORT_DUAL_HF
40 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
41 #endif
42
43 typedef struct {
44         unsigned int type;
45         int device_state;
46         char device_address[BT_ADDRESS_STRING_SIZE + 1];
47 } bt_connected_headset_data_t;
48
49 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
50 typedef struct {
51         int alarm_id;
52         int retry_count;
53 } bt_auto_connect_timer_t;
54
55 bt_auto_connect_timer_t auto_connect_timer = {0, };
56 #endif
57
58 static GList *g_connected_list;
59
60 static bt_headset_wait_t *g_wait_data;
61
62 static bt_audio_function_data_t *pdata;
63
64 static void __bt_remove_device_from_wait_list();
65
66 static void __bt_free_wait_data();
67
68 static gboolean __bt_device_support_uuid(char *remote_address,
69                                 bt_audio_type_t type);
70
71 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
72 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param);
73 #endif
74
75 static void __bt_hf_request_cb(GDBusProxy *proxy, GAsyncResult *res,
76                                     gpointer user_data)
77 {
78         GError *g_error = NULL;
79         GVariant *out_param1 = NULL;
80         GVariant *reply = NULL;
81         int result = BLUETOOTH_ERROR_NONE;
82         bt_function_data_t *func_data;
83         request_info_t *req_info;
84
85         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
86         g_object_unref(proxy);
87
88         func_data = user_data;
89
90         if (func_data == NULL) {
91                 /* Send reply */
92                 BT_ERR("func_data == NULL");
93                 goto done;
94         }
95
96         req_info = _bt_get_request_info(func_data->req_id);
97         if (req_info == NULL) {
98                 BT_ERR("req_info == NULL");
99                 goto done;
100         }
101
102         if (reply == NULL) {
103                 BT_ERR("HF Connect Dbus Call Error");
104                 result = _bt_convert_gerror(g_error);
105                 if (g_error) {
106                         BT_ERR("Error: %s\n", g_error->message);
107                         g_clear_error(&g_error);
108                 }
109         } else {
110                 g_variant_unref(reply);
111         }
112
113         if (req_info->context == NULL)
114                 goto done;
115
116         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
117                 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
118
119         g_dbus_method_invocation_return_value(req_info->context,
120                         g_variant_new("(iv)", result, out_param1));
121
122         _bt_delete_request_list(req_info->req_id);
123
124 done:
125         if (func_data) {
126                 g_free(func_data->address);
127                 g_free(func_data);
128         }
129 }
130
131 void _bt_audio_check_pending_connect()
132 {
133         BT_DBG("+");
134         bluetooth_device_address_t device_address;
135
136         if (pdata == NULL)
137                 return;
138
139         if (pdata->pending == BT_PENDING_CONNECT) {
140
141                 _bt_convert_addr_string_to_type(device_address.addr,
142                                 pdata->address);
143                 _bt_audio_connect(pdata->req_id,
144                                 BT_AUDIO_A2DP,
145                                 &device_address,
146                                 NULL);
147
148                 g_free(pdata->address);
149                 g_free(pdata);
150                 pdata = NULL;
151         }
152
153         BT_DBG("-");
154         return;
155 }
156
157 static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
158                                     gpointer user_data)
159 {
160         GError *g_error = NULL;
161         GVariant *out_param1 = NULL;
162         GVariant *reply = NULL;
163         int result = BLUETOOTH_ERROR_NONE;
164         bt_audio_function_data_t *func_data;
165         request_info_t *req_info;
166
167         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
168         g_object_unref(proxy);
169         g_variant_unref(reply);
170
171         func_data = user_data;
172
173         if (func_data == NULL) {
174                 /* Send reply */
175                 BT_ERR("func_data == NULL");
176                 goto done;
177         }
178
179         if (func_data->pending != BT_PENDING_NONE && g_error == NULL) {
180                 bluetooth_device_address_t device_address;
181                 _bt_convert_addr_string_to_type(device_address.addr,
182                                         func_data->address);
183
184                 if (func_data->pending == BT_PENDING_CONNECT) {
185
186                         if (__bt_device_support_uuid(func_data->address,
187                                                         BT_AUDIO_A2DP)) {
188
189                                 pdata = g_new0(bt_audio_function_data_t, 1);
190                                 pdata->req_id = func_data->req_id;
191                                 pdata->address = strdup(func_data->address);
192                                 pdata->pending = func_data->pending;
193                         } else
194                                 goto check_req_info;
195
196                 } else {
197                         if (_bt_is_service_connected(func_data->address
198                                                         , BT_AUDIO_HSP)) {
199                                 _bt_audio_disconnect(func_data->req_id,
200                                         BT_AUDIO_HSP, &device_address, NULL);
201                         } else
202                                 goto check_req_info;
203                 }
204
205                 goto done;
206         }
207
208 check_req_info:
209         req_info = _bt_get_request_info(func_data->req_id);
210         if (req_info == NULL) {
211                 BT_ERR("req_info == NULL");
212                 goto done;
213         }
214
215         if (g_error == NULL)
216                 goto dbus_return;
217
218         BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
219
220         result = BLUETOOTH_ERROR_INTERNAL;
221         /* If there is error then we need to set local initiated connection as false
222           * If don't do this then when headset initiate connection for HFP then we don't
223           * initiate connection for A2dp to headset as this flag was set to true in first
224           * connection failure attempt and not set in error case.*/
225         _bt_headset_set_local_connection(FALSE);
226
227         /* Remove the device from the list */
228         _bt_remove_headset_from_list(func_data->type, func_data->address);
229
230         /* Error, check if any waiting device is there */
231         if (g_wait_data == NULL)
232                 goto dbus_return;
233
234         if (g_strcmp0(g_wait_data->address, func_data->address) != 0) {
235                 bluetooth_device_address_t device_address;
236                 _bt_convert_addr_string_to_type(device_address.addr,
237                                 g_wait_data->address);
238                 _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
239                                 &device_address, NULL);
240         }
241
242         /* Event will be sent by the event reciever */
243 dbus_return:
244         if (req_info->context == NULL) {
245                 BT_DBG("req_info->context is NULL");
246                 goto done;
247         }
248
249         out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
250                 func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
251
252         g_dbus_method_invocation_return_value(req_info->context,
253                         g_variant_new("(iv)", result, out_param1));
254
255         _bt_delete_request_list(req_info->req_id);
256 done:
257         g_clear_error(&g_error);
258
259         if (func_data) {
260                 g_free(func_data->address);
261                 g_free(func_data);
262         }
263 }
264
265 static void __bt_free_wait_data()
266 {
267         if (g_wait_data != NULL) {
268                 g_free(g_wait_data->address);
269                 g_free(g_wait_data);
270                 g_wait_data = NULL;
271         }
272 }
273
274 static void __bt_remove_device_from_wait_list()
275 {
276         /* Before deleting the request update the UI */
277         GVariant *out_param_1 = NULL;
278         int result = BLUETOOTH_ERROR_INTERNAL;
279         request_info_t *req_info;
280
281         req_info = _bt_get_request_info(g_wait_data->req_id);
282         if (req_info == NULL) {
283                 BT_ERR("req_info == NULL");
284                 return;
285         }
286
287         out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
288                 g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
289
290         g_dbus_method_invocation_return_value(req_info->context,
291                         g_variant_new("(iv)", result, out_param_1));
292
293         _bt_delete_request_list(g_wait_data->req_id);
294 }
295
296 static void __bt_set_headset_disconnection_type(const char *address)
297 {
298         bt_connected_headset_data_t *connected_device;
299         GList *node;
300
301         node = g_list_first(g_connected_list);
302         while (node != NULL) {
303                 connected_device = node->data;
304                 if (g_strcmp0(connected_device->device_address, address) == 0) {
305                         g_wait_data->disconnection_type = connected_device->type;
306                         return;
307                 }
308                 node = g_list_next(node);
309         }
310 }
311
312 gboolean _bt_is_headset_type_connected(int type, char *address)
313 {
314         GList *node;
315
316         node = g_list_first(g_connected_list);
317         while (node != NULL) {
318                 bt_connected_headset_data_t *connected_device = node->data;
319
320                 if (connected_device->type & type) {
321                         if (address != NULL)
322                                 g_strlcpy(address, connected_device->device_address,
323                                                 BT_ADDRESS_STRING_SIZE + 1);
324                         return TRUE;
325                 }
326
327                 node = g_list_next(node);
328         }
329         return FALSE;
330 }
331
332 #ifdef TIZEN_SUPPORT_DUAL_HF
333 gboolean __bt_is_companion_device(const char *addr)
334 {
335         if (TIZEN_PROFILE_WEARABLE) {
336                 char *host_device_address = NULL;
337                 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
338
339                 if (!host_device_address) {
340                         BT_INFO("Failed to get a companion device address");
341                         return FALSE;
342                 }
343
344                 if (g_strcmp0(host_device_address, addr) == 0) {
345                         BT_INFO("Found companion device");
346                         free(host_device_address);
347                         return TRUE;
348                 }
349
350                 free(host_device_address);
351                 return FALSE;
352         } else {
353                 /* TODO : Need to add companion device check condition for Phone models */
354                 return FALSE;
355         }
356 }
357 #endif
358
359 static int __bt_is_headset_connected(int type, int req_id,
360                                 const char *address)
361 {
362         gboolean connected = FALSE;
363         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
364         bluetooth_device_address_t device_address;
365         bt_connected_headset_data_t *connected_device = NULL;
366 #ifdef TIZEN_SUPPORT_DUAL_HF
367         gboolean is_companion_device = FALSE;
368 #endif
369
370         /* Check if any other headset is connected */
371         GList *node = NULL;;
372
373         node = g_list_first(g_connected_list);
374         while (node != NULL) {
375                 connected_device = node->data;
376                 if ((connected_device->type & type)) {
377                         g_strlcpy(connected_address, connected_device->device_address,
378                                         BT_ADDRESS_STRING_SIZE + 1);
379 #ifdef TIZEN_SUPPORT_DUAL_HF
380                         is_companion_device = __bt_is_companion_device(connected_address);
381                         BT_INFO(" is_companion_device[%d]", is_companion_device);
382
383                         if (!is_companion_device) {
384                                 connected = TRUE;
385                                 break;
386                         }
387 #else
388                         connected = TRUE;
389                         break;
390 #endif
391                 }
392                 node = g_list_next(node);
393         }
394
395         if (!connected)
396                 return BLUETOOTH_ERROR_NOT_CONNECTED;
397
398         BT_DBG("connected headset %s", connected_address);
399
400         if (g_strcmp0(connected_address, address) == 0)
401                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
402 #ifdef TIZEN_SUPPORT_DUAL_HF
403         else if (TRUE == __bt_is_companion_device(address))
404                 return BLUETOOTH_ERROR_NOT_CONNECTED;
405 #endif
406
407         /* Convert BD adress from string type */
408         _bt_convert_addr_string_to_type(device_address.addr, connected_address);
409         int value = BLUETOOTH_ERROR_NONE;
410         value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
411
412         /* If already one device is waiting, remove current waiting device and add new */
413         if (value == BLUETOOTH_ERROR_NONE) {
414                 if (g_wait_data != NULL) {
415                         if (g_strcmp0(g_wait_data->address, address) != 0) {
416                                 __bt_remove_device_from_wait_list();
417                                 __bt_free_wait_data();
418                         }
419                 }
420
421                 if (g_wait_data == NULL) {
422                         g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
423                         g_wait_data->address = g_strdup(address);
424                         g_wait_data->req_id = req_id;
425                         g_wait_data->type = type;
426                         g_wait_data->ag_flag = FALSE;
427
428                         /* Set disconnection type */
429                         __bt_set_headset_disconnection_type(connected_address);
430                 }
431         }
432
433         return value;
434 }
435
436 static int __bt_is_headset_connecting(int type)
437 {
438         bt_connected_headset_data_t *connected_device = NULL;
439
440         /* Check if any other headset is connected */
441         GList *node = NULL;
442
443         node = g_list_first(g_connected_list);
444         while (node != NULL) {
445                 connected_device = node->data;
446                 if (connected_device->device_state == BT_STATE_CONNECTING)
447                         return BLUETOOTH_ERROR_CONNECTION_BUSY;
448                 node = g_list_next(node);
449         }
450
451         return BLUETOOTH_ERROR_NONE;
452 }
453
454 int __bt_is_headset_disconnecting(int type)
455 {
456         bt_connected_headset_data_t *connected_device = NULL;
457
458         /* Check if any other headset is connected */
459         GList *node = NULL;
460
461         node = g_list_first(g_connected_list);
462         while (node != NULL) {
463                 connected_device = node->data;
464                 if (connected_device->device_state == BT_STATE_DISCONNECTING)
465                         return BLUETOOTH_ERROR_CONNECTION_BUSY;
466
467                 node = g_list_next(node);
468         }
469
470         return BLUETOOTH_ERROR_NONE;
471 }
472
473 void _bt_set_audio_wait_data_flag(gboolean flag)
474 {
475         BT_DBG("_bt_set_audio_wait_data_flag \n");
476         g_wait_data->ag_flag = flag;
477 }
478
479 bt_headset_wait_t *_bt_get_audio_wait_data(void)
480 {
481         BT_DBG("_bt_get_audio_wait_data \n");
482         return g_wait_data;
483 }
484
485 void _bt_rel_wait_data(void)
486 {
487         BT_DBG("_bt_rel_wait_data \n");
488         __bt_free_wait_data();
489 }
490
491 void _bt_add_headset_to_list(int type, int status, const char *address)
492 {
493         bt_connected_headset_data_t *connected_device;
494         bt_connected_headset_data_t *device;
495         GList *node;
496
497         BT_DBG("_bt_add_headset_to_list \n");
498
499         node = g_list_first(g_connected_list);
500         while (node != NULL) {
501                 device = (bt_connected_headset_data_t *)node->data;
502
503                 if (g_strcmp0(device->device_address, address) == 0) {
504                         BT_DBG("Address match, update connection type \n");
505                         if (status == BT_STATE_CONNECTED)
506                                 device->type |= type;
507                         device->device_state = status;
508                         return;
509                 }
510                 node = g_list_next(node);
511         }
512
513         connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
514         connected_device->device_state = status;
515         if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
516                 connected_device->type |= type;
517         g_strlcpy(connected_device->device_address, address,
518                         sizeof(connected_device->device_address));
519         g_connected_list = g_list_append(g_connected_list, connected_device);
520 }
521
522 int _bt_get_device_state_from_list(int type, const char *address)
523 {
524         GList *node;
525         bt_connected_headset_data_t *device;
526
527         BT_DBG("+");
528         node = g_list_first(g_connected_list);
529         while (node != NULL) {
530                 device = (bt_connected_headset_data_t *)node->data;
531                 if (g_strcmp0(device->device_address, address) == 0) {
532                         BT_DBG("Device found");
533                         return device->device_state;
534                 }
535                 node = g_list_next(node);
536         }
537
538         BT_DBG("Device not found");
539         return BLUETOOTH_ERROR_INTERNAL;
540 }
541
542 void _bt_remove_headset_from_list(int type, const char *address)
543 {
544         GList *node;
545
546         BT_DBG("_bt_remove_headset_from_list \n");
547
548         node = g_list_first(g_connected_list);
549         while (node != NULL) {
550                 bt_connected_headset_data_t *connected_device = node->data;
551
552                 if (g_strcmp0(connected_device->device_address, address) != 0) {
553                         node = g_list_next(node);
554                         continue;
555                 }
556
557                 BT_DBG("Address match \n");
558
559                 BT_DBG("Connection type = %x\n", connected_device->type);
560
561                 switch (type) {
562                 case BT_AUDIO_A2DP:
563                         if (connected_device->type & BT_AUDIO_A2DP)
564                                 connected_device->type &= ~(BT_AUDIO_A2DP);
565                         break;
566                 case BT_AUDIO_HSP:
567                         if (connected_device->type & BT_AUDIO_HSP)
568                                 connected_device->type &= ~(BT_AUDIO_HSP);
569                         break;
570                 case BT_AUDIO_ALL:
571                         if (connected_device->type & BT_AUDIO_ALL)
572                                 connected_device->type &= ~(BT_AUDIO_ALL);
573                         break;
574                 case BT_AVRCP:
575                         if (connected_device->type & BT_AVRCP)
576                                 connected_device->type &= ~(BT_AVRCP);
577                         break;
578                 case BT_AUDIO_A2DP_SOURCE:
579                         if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
580                                 connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
581                 }
582
583                 BT_DBG("Connection type = %x\n", connected_device->type);
584
585                 if (connected_device->type == 0x00) {
586                         g_connected_list = g_list_remove(g_connected_list, connected_device);
587                         g_free(connected_device);
588                 } else {
589                         connected_device->device_state = BT_STATE_CONNECTED;
590                 }
591
592                 node = g_list_next(node);
593         }
594 }
595
596 static gboolean __bt_device_support_uuid(char *remote_address,
597                                 bt_audio_type_t type)
598 {
599         GArray *dev_list = NULL;
600         int size;
601         int i;
602         int j;
603         bluetooth_device_info_t info;
604         char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
605         gboolean ret = FALSE;
606
607         BT_DBG("+");
608
609         dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
610
611         _bt_get_bonded_devices(&dev_list);
612         size = (dev_list->len) / sizeof(bluetooth_device_info_t);
613
614         for (i = 0; i < size; i++) {
615                 info = g_array_index(dev_list, bluetooth_device_info_t, i);
616                 _bt_convert_addr_type_to_string(bond_address,
617                                 info.device_address.addr);
618                 if (strcmp(bond_address, remote_address) != 0)
619                         continue;
620
621                 BT_INFO("Device address Matched");
622                 j = 0;
623                 while (j != info.service_index) {
624                         if (type == BT_AUDIO_HSP) {
625                                 if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
626                                         BT_INFO("HFP HS UUID exists");
627                                         ret = TRUE;
628                                         goto end;
629                                 }
630                         } else if (type == BT_AUDIO_A2DP) {
631                                 if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
632                                         BT_INFO("A2DP SINK UUID exists");
633                                         ret = TRUE;
634                                         goto end;
635                                 }
636                         }
637                         j++;
638                 }
639         }
640 end:
641         g_array_free(dev_list, TRUE);
642         BT_DBG("-");
643         return ret;
644 }
645
646 gboolean _bt_is_service_connected(char* address, int type)
647 {
648         GList *node;
649
650         node = g_list_first(g_connected_list);
651         while (node != NULL) {
652                 bt_connected_headset_data_t *conn_device = node->data;
653
654                 if ((g_strcmp0(conn_device->device_address, address) == 0) &&
655                         (conn_device->type & type)) {
656                                 BT_INFO("Service connected");
657                                 return TRUE;
658                 }
659
660                 node = g_list_next(node);
661         }
662         BT_INFO("Service not connected");
663         return FALSE;
664 }
665
666 int _bt_audio_connect(int request_id, int type,
667                 bluetooth_device_address_t *device_address,
668                 GArray *out_param1)
669 {
670         int result = BLUETOOTH_ERROR_NONE;
671         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
672         GDBusProxy *adapter_proxy;
673         GDBusConnection *g_conn;
674         int ret;
675         char *uuid = NULL;
676         int value = BLUETOOTH_ERROR_NONE;
677         bt_audio_function_data_t *func_data;
678         guint hfp_hs_restricted = 0x0; /* set default "allowed" */
679         guint a2dp_restricted = 0x0;
680
681         BT_CHECK_PARAMETER(device_address, return);
682
683         adapter_proxy = _bt_get_adapter_proxy();
684         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
685
686         g_conn = _bt_gdbus_get_system_gconn();
687         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
688
689         _bt_convert_addr_type_to_string(address, device_address->addr);
690
691         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
692         func_data->address = g_strdup(address);
693         func_data->req_id = request_id;
694         func_data->type = type;
695         func_data->pending = BT_PENDING_NONE;
696
697         result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
698         if (result != BLUETOOTH_ERROR_NONE)
699                 BT_ERR("Can't get hfp_hs restriction info");
700
701         result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
702         if (result != BLUETOOTH_ERROR_NONE)
703                 BT_ERR("Can't get a2dp restriction info");
704
705         switch (type) {
706         case BT_AUDIO_HSP:
707                 uuid = HFP_HS_UUID;
708                 break;
709         case BT_AUDIO_A2DP:
710                 uuid = A2DP_SINK_UUID;
711                 break;
712         case BT_AVRCP:
713                 uuid = AVRCP_TARGET_UUID;
714                 break;
715         case BT_AUDIO_A2DP_SOURCE:
716                 uuid = A2DP_SOURCE_UUID;
717                 break;
718         case BT_AUDIO_ALL:
719                 if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
720                         if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
721                                 uuid = HFP_HS_UUID;
722                                 func_data->pending = BT_PENDING_CONNECT;
723                                 type = BT_AUDIO_HSP;
724                         } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
725                                 uuid = A2DP_SINK_UUID;
726                                 type = BT_AUDIO_A2DP;
727                         } else {
728                                 BT_ERR("No audio role supported");
729                                 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
730                                 goto fail;
731                         }
732                 } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
733                         BT_ERR("All profiles are restricted");
734                         result = BLUETOOTH_ERROR_INTERNAL;
735                         goto fail;
736                 } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
737                         if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
738                                 uuid = HFP_HS_UUID;
739                                 type = BT_AUDIO_HSP;
740                         } else {
741                                 BT_ERR("HFP_HS role is not supported");
742                                 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
743                                 goto fail;
744                         }
745                 } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
746                         if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
747                                 uuid = A2DP_SINK_UUID;
748                                 type = BT_AUDIO_A2DP;
749                         } else {
750                                 BT_ERR("A2DP role is not supported");
751                                 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
752                                 goto fail;
753                         }
754                 }
755                 break;
756         case BT_AVRCP_TARGET:
757                 uuid = AVRCP_REMOTE_UUID;
758                 break;
759         default:
760                 BT_ERR("Unknown role");
761                 result = BLUETOOTH_ERROR_INTERNAL;
762                 goto fail;
763         }
764         BT_INFO("Connecting to service %s", uuid);
765
766         value = __bt_is_headset_connected(type, request_id, address);
767
768         if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
769                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
770         } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
771                 value = __bt_is_headset_connecting(type);
772                 if (value != BLUETOOTH_ERROR_NONE) {
773                         result = BLUETOOTH_ERROR_IN_PROGRESS;
774                         goto fail;
775                 }
776                 _bt_headset_set_local_connection(TRUE);
777                 ret = _bt_connect_profile(address, uuid,
778                                 __bt_audio_request_cb, func_data);
779
780                 if (ret != BLUETOOTH_ERROR_NONE) {
781                         BT_ERR("_bt_connect_profile Error");
782                         _bt_headset_set_local_connection(FALSE);
783                         g_free(func_data->address);
784                         g_free(func_data);
785                         return ret;
786                 }
787
788                 /* Add data to the connected list */
789                 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
790         } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
791                 return BLUETOOTH_ERROR_IN_PROGRESS;
792         }
793
794         if (out_param1)
795                 g_array_free(out_param1, TRUE);
796
797         return BLUETOOTH_ERROR_NONE;
798 fail:
799         if (out_param1 != NULL)
800                 g_array_append_vals(out_param1, address,
801                                 BT_ADDRESS_STR_LEN);
802
803         return result;
804 }
805
806 int _bt_audio_disconnect(int request_id, int type,
807                 bluetooth_device_address_t *device_address,
808                 GArray *out_param1)
809 {
810         int result = BLUETOOTH_ERROR_NONE;
811         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
812         bt_audio_function_data_t *func_data;
813         GDBusProxy *adapter_proxy;
814         GDBusConnection *g_conn;
815         GList *node;
816         int ret;
817         char *uuid;
818         int value = BLUETOOTH_ERROR_NONE;
819
820         BT_CHECK_PARAMETER(device_address, return);
821
822         adapter_proxy = _bt_get_adapter_proxy();
823         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
824
825         g_conn = _bt_gdbus_get_system_gconn();
826         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
827
828         _bt_convert_addr_type_to_string(address, device_address->addr);
829
830         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
831         func_data->address = g_strdup(address);
832         func_data->req_id = request_id;
833         func_data->pending = BT_PENDING_NONE;
834         func_data->type = type;
835
836         switch (type) {
837         case BT_AUDIO_HSP:
838                 uuid = HFP_HS_UUID;
839                 break;
840         case BT_AUDIO_A2DP:
841                 uuid = A2DP_SINK_UUID;
842                 break;
843         case BT_AVRCP:
844                 uuid = AVRCP_TARGET_UUID;
845                 break;
846         case BT_AUDIO_A2DP_SOURCE:
847                 uuid = A2DP_SOURCE_UUID;
848                 break;
849         case BT_AUDIO_ALL:
850                 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
851                         uuid = A2DP_SINK_UUID;
852                         func_data->pending = BT_PENDING_DISCONNECT;
853                 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
854                         uuid = HFP_HS_UUID;
855                 } else {
856                         BT_ERR("No audio service connected");
857                         result = BLUETOOTH_ERROR_NOT_CONNECTED;
858                         goto fail;
859                 }
860                 break;
861         case BT_AVRCP_TARGET:
862                 uuid = AVRCP_REMOTE_UUID;
863                 break;
864         default:
865                 BT_ERR("Unknown role");
866                 result = BLUETOOTH_ERROR_INTERNAL;
867                 goto fail;
868         }
869         value = __bt_is_headset_disconnecting(type);
870         if (value != BLUETOOTH_ERROR_NONE) {
871                 BT_INFO("Disconnect in progress");
872                 result = BLUETOOTH_ERROR_IN_PROGRESS;
873                 goto fail;
874         }
875         BT_INFO("Disconnecting service %s", uuid);
876         ret = _bt_disconnect_profile(address, uuid,
877                         __bt_audio_request_cb, func_data);
878
879         if (ret != BLUETOOTH_ERROR_NONE) {
880                 BT_ERR("_bt_disconnect_profile Error");
881                 g_free(func_data->address);
882                 g_free(func_data);
883                 return ret;
884         }
885
886         /*
887          *      This logic is added for dual HF mode issue.
888          */
889         node = g_list_first(g_connected_list);
890         while (node != NULL) {
891                 bt_connected_headset_data_t *connected_device = node->data;
892
893                 if (g_strcmp0(connected_device->device_address, address) == 0) {
894                         BT_DBG("Connection type update");
895                         type = connected_device->type;
896                         break;
897                 }
898                 node = g_list_next(node);
899         }
900         _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
901
902         if (out_param1)
903                 g_array_free(out_param1, TRUE);
904
905         return BLUETOOTH_ERROR_NONE;
906 fail:
907         if (out_param1 != NULL)
908                 g_array_append_vals(out_param1, address,
909                                 BT_ADDRESS_STR_LEN);
910
911         return result;
912 }
913
914 void _bt_remove_from_connected_list(const char *address)
915 {
916         bt_connected_headset_data_t *connected_device;
917         GList *node;
918
919         node = g_list_first(g_connected_list);
920         while (node != NULL) {
921                 connected_device = node->data;
922                 if (connected_device != NULL &&
923                 g_strcmp0(connected_device->device_address, address) == 0) {
924                         BT_ERR("Device is removed from the list");
925                         g_connected_list = g_list_remove(g_connected_list, connected_device);
926                         g_free(connected_device);
927                         return;
928                 }
929                 node = g_list_next(node);
930         }
931 }
932
933 int _bt_hf_connect(int request_id,
934                 bluetooth_device_address_t *device_address,
935                 GArray *out_param1)
936 {
937         int result = BLUETOOTH_ERROR_NONE;
938         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
939         bt_function_data_t *func_data;
940         GDBusProxy *adapter_proxy;
941         GDBusConnection *g_conn;
942         gboolean connected = FALSE;
943         int ret;
944         char *uuid;
945
946         BT_CHECK_PARAMETER(device_address, return);
947
948         _bt_convert_addr_type_to_string(address, device_address->addr);
949
950         adapter_proxy = _bt_get_adapter_proxy();
951         if (adapter_proxy == NULL) {
952                 result = BLUETOOTH_ERROR_INTERNAL;
953                 goto fail;
954         }
955
956         g_conn = _bt_gdbus_get_system_gconn();
957         if (g_conn == NULL) {
958                 result = BLUETOOTH_ERROR_INTERNAL;
959                 goto fail;
960         }
961
962         /* Check if HF is connected or not */
963         result = _bt_is_device_connected(device_address, BT_PROFILE_CONN_HFG, &connected);
964         if (connected == TRUE) {
965                 BT_ERR("HF is already connected");
966                 result = BLUETOOTH_ERROR_ALREADY_CONNECT;
967                 goto fail;
968         }
969
970         func_data = g_malloc0(sizeof(bt_function_data_t));
971         func_data->address = g_strdup(address);
972         func_data->req_id = request_id;
973         uuid = g_strdup(HFP_AG_UUID);
974
975         BT_DBG("Connecting to service %s", uuid);
976
977         ret = _bt_connect_profile(address, uuid,
978                         __bt_hf_request_cb, func_data);
979
980         if (ret != BLUETOOTH_ERROR_NONE) {
981                 BT_ERR("_bt_connect_profile Error");
982                 g_free(func_data->address);
983                 g_free(func_data);
984                 g_free(uuid);
985                 return ret;
986         }
987         g_free(uuid);
988         if (out_param1)
989                 g_array_free(out_param1, TRUE);
990
991         return BLUETOOTH_ERROR_NONE;
992 fail:
993         if (out_param1 != NULL)
994                 g_array_append_vals(out_param1, address,
995                                 BT_ADDRESS_STR_LEN);
996
997         return result;
998 }
999
1000 int _bt_hf_disconnect(int request_id,
1001                 bluetooth_device_address_t *device_address,
1002                 GArray *out_param1)
1003 {
1004         int result = BLUETOOTH_ERROR_NONE;
1005         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1006         bt_function_data_t *func_data;
1007         GDBusProxy *adapter_proxy;
1008         GDBusConnection *g_conn;
1009
1010         int ret;
1011         char *uuid;
1012
1013         BT_CHECK_PARAMETER(device_address, return);
1014
1015         _bt_convert_addr_type_to_string(address, device_address->addr);
1016
1017         adapter_proxy = _bt_get_adapter_proxy();
1018         if (adapter_proxy == NULL) {
1019                 result = BLUETOOTH_ERROR_INTERNAL;
1020                 goto fail;
1021         }
1022
1023         g_conn = _bt_gdbus_get_system_gconn();
1024         if (g_conn == NULL) {
1025                 result = BLUETOOTH_ERROR_INTERNAL;
1026                 goto fail;
1027         }
1028
1029         func_data = g_malloc0(sizeof(bt_function_data_t));
1030         func_data->address = g_strdup(address);
1031         func_data->req_id = request_id;
1032         uuid = g_strdup(HFP_AG_UUID);
1033
1034         BT_DBG("Disconnecting service %s", uuid);
1035         ret = _bt_disconnect_profile(address, uuid,
1036                         __bt_hf_request_cb, func_data);
1037
1038         if (ret != BLUETOOTH_ERROR_NONE) {
1039                 BT_ERR("_bt_disconnect_profile Error");
1040                 g_free(func_data->address);
1041                 g_free(func_data);
1042                 g_free(uuid);
1043                 return ret;
1044         }
1045         g_free(uuid);
1046         if (out_param1)
1047                 g_array_free(out_param1, TRUE);
1048
1049         return BLUETOOTH_ERROR_NONE;
1050 fail:
1051         if (out_param1 != NULL)
1052                 g_array_append_vals(out_param1, address,
1053                                 BT_ADDRESS_STR_LEN);
1054
1055         return result;
1056 }
1057
1058 int _bt_audio_set_content_protect(gboolean status)
1059 {
1060         GDBusConnection *conn;
1061         GError *error = NULL;
1062
1063         BT_DBG("+\n");
1064
1065         conn = _bt_gdbus_get_system_gconn();
1066         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1067
1068         BT_DBG("Content Protection status = [%d]", status);
1069
1070         g_dbus_connection_emit_signal(conn,
1071                         NULL, BT_CONTENT_PROTECTION_PATH,
1072                         BT_CONTENT_PROTECTION_INTERFACE,
1073                         "ProtectionRequired",
1074                         g_variant_new("(b)", status),
1075                         &error);
1076
1077         if (error) {
1078                 /* dBUS gives error cause */
1079                 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1080                         error->code, error->message);
1081                 g_clear_error(&error);
1082                 return BLUETOOTH_ERROR_INTERNAL;
1083         }
1084
1085         BT_DBG("Emit Signal done = [ProtectionRequired]");
1086         return BLUETOOTH_ERROR_NONE;
1087 }
1088
1089 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1090 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1091                                     gpointer user_data)
1092 {
1093         GError *err = NULL;
1094         GVariant *reply = NULL;
1095
1096         reply = g_dbus_proxy_call_finish(proxy, res, &err);
1097         g_object_unref(proxy);
1098         g_variant_unref(reply);
1099
1100         BT_DBG("+");
1101         if (err != NULL) {
1102                 g_dbus_error_strip_remote_error(err);
1103                 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1104
1105                 if (strcmp("Host is down", err->message)) {
1106                         BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1107                         _bt_audio_stop_auto_connect();
1108                         vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1109                 }
1110         }
1111         g_clear_error(&err);
1112 }
1113
1114
1115 // It is the function that retry to create alarm.
1116 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1117 // So, in this case, we have to retry alarmmgr_add_alarm.
1118 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1119 {
1120         int result;
1121         alarm_id_t alarm_id;
1122
1123         BT_DBG("__bt_audio_alarm_retry_cb called.");
1124         result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1125                                                 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1126
1127         if (result != BLUETOOTH_ERROR_NONE)
1128                 return TRUE;
1129         else
1130                 auto_connect_timer.alarm_id = alarm_id;
1131
1132         return FALSE;
1133 }
1134
1135 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1136 {
1137         int result = BLUETOOTH_ERROR_NONE;
1138         char *address = NULL;
1139         alarm_id_t new_alarm_id;
1140
1141         BT_INFO("alram id = [%d] , retry_count [%d] ",
1142                                                 alarm_id, auto_connect_timer.retry_count);
1143
1144         if (alarm_id != auto_connect_timer.alarm_id)
1145                 return 0;
1146
1147         address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1148
1149         if (address == NULL) {
1150                 BT_ERR("Address vconf is null");
1151                 auto_connect_timer.alarm_id = 0;
1152                 return 0;
1153         }
1154
1155         BT_DBG("ADDRESS [%s]", address);
1156
1157         result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1158                         __bt_auto_connect_request_cb, NULL);
1159
1160         auto_connect_timer.retry_count--;
1161
1162         BT_DBG("result [%d]", result);
1163
1164         if (auto_connect_timer.retry_count <= 0) {
1165                 BT_INFO("Stopping Auto connect retry");
1166                 auto_connect_timer.alarm_id = 0;
1167         } else {
1168                 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1169                                                 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1170                 if (result == BLUETOOTH_ERROR_NONE)
1171                         auto_connect_timer.alarm_id = new_alarm_id;
1172         }
1173
1174         free(address);
1175         return 0;
1176 }
1177
1178 static void __bt_auto_connect_alarm_remove()
1179 {
1180         BT_DBG("");
1181         if (auto_connect_timer.alarm_id > 0) {
1182                 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1183                 auto_connect_timer.alarm_id = 0;
1184         }
1185         auto_connect_timer.retry_count = 0;
1186 }
1187
1188 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1189 {
1190         int result = BLUETOOTH_ERROR_NONE;
1191         char *address = NULL;
1192         alarm_id_t alarm_id = 0;
1193
1194         BT_DBG("");
1195
1196         address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1197
1198         if (address == NULL) {
1199                 BT_ERR("No target device");
1200                 return 0;
1201         }
1202
1203         __bt_auto_connect_alarm_remove();
1204
1205         auto_connect_timer.retry_count =  BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1206                                                 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1207
1208         if (linkloss_flag) {
1209                 BT_INFO("Start auto connection after linkloss");
1210                 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1211                                                 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1212                 if (result != BLUETOOTH_ERROR_NONE)
1213                         g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1214                 else
1215                         auto_connect_timer.alarm_id = alarm_id;
1216
1217         } else {
1218                 BT_INFO("Start auto connection after BT activated");
1219                 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1220                                                 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1221                 if (result == BLUETOOTH_ERROR_NONE)
1222                         auto_connect_timer.alarm_id = alarm_id;
1223         }
1224
1225         free(address);
1226         return BLUETOOTH_ERROR_NONE;
1227 }
1228
1229 int _bt_audio_stop_auto_connect(void)
1230 {
1231         BT_DBG("");
1232         __bt_auto_connect_alarm_remove();
1233
1234         return BLUETOOTH_ERROR_NONE;
1235 }
1236
1237 void _bt_audio_set_auto_connect_device_addr(const char *address)
1238 {
1239         if (address == NULL) {
1240                 BT_ERR("address is null");
1241                 return;
1242         }
1243
1244         BT_INFO("Last connected device is [%s]", address);
1245         vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1246 }
1247 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */