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