2f02c95673f7c75a6e08f2c62f243d61cc26a255
[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         guint hfp_hs_restricted = 0x0; /* set default "allowed" */
697         guint a2dp_restricted = 0x0;
698
699         BT_CHECK_PARAMETER(device_address, return);
700
701         adapter_proxy = _bt_get_adapter_proxy();
702         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
703
704         g_conn = _bt_get_system_gconn();
705         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
706
707         _bt_convert_addr_type_to_string(address, device_address->addr);
708
709         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
710         /* Fix : NULL_RETURNS */
711         if (func_data == NULL) {
712                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
713                 goto fail;
714         }
715
716         func_data->address = g_strdup(address);
717         func_data->req_id = request_id;
718         func_data->type = type;
719         func_data->pending = BT_PENDING_NONE;
720         func_data->out_param = out_param1;
721
722         result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
723         if (result != BLUETOOTH_ERROR_NONE)
724                 BT_ERR("Can't get hfp_hs restriction info");
725
726         result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
727         if (result != BLUETOOTH_ERROR_NONE)
728                 BT_ERR("Can't get a2dp restriction info");
729
730         switch (type) {
731         case BT_AUDIO_HSP:
732                 uuid = HFP_HS_UUID;
733                 break;
734         case BT_AUDIO_A2DP:
735                 uuid = A2DP_SINK_UUID;
736                 break;
737         case BT_AVRCP:
738                 uuid = AVRCP_TARGET_UUID;
739                 break;
740         case BT_AUDIO_A2DP_SOURCE:
741                 uuid = A2DP_SOURCE_UUID;
742                 break;
743         case BT_AUDIO_ALL:
744                 if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
745                         if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
746                                 uuid = HFP_HS_UUID;
747                                 func_data->pending = BT_PENDING_CONNECT;
748                                 type = BT_AUDIO_HSP;
749                         } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
750                                 uuid = A2DP_SINK_UUID;
751                                 type = BT_AUDIO_A2DP;
752                         } else {
753                                 BT_ERR("No audio role supported");
754                                 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
755                                 goto fail;
756                         }
757                 } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
758                         BT_ERR("All profiles are restricted");
759                         result = BLUETOOTH_ERROR_INTERNAL;
760                         goto fail;
761                 } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
762                         if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
763                                 uuid = HFP_HS_UUID;
764                                 type = BT_AUDIO_HSP;
765                         } else {
766                                 BT_ERR("HFP_HS role is not supported");
767                                 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
768                                 goto fail;
769                         }
770                 } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
771                         if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
772                                 uuid = A2DP_SINK_UUID;
773                                 type = BT_AUDIO_A2DP;
774                         } else {
775                                 BT_ERR("A2DP role is not supported");
776                                 result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
777                                 goto fail;
778                         }
779                 }
780                 break;
781         case BT_AVRCP_TARGET:
782                 uuid = AVRCP_REMOTE_UUID;
783                 break;
784         default:
785                 BT_ERR("Unknown role");
786                 result = BLUETOOTH_ERROR_INTERNAL;
787                 goto fail;
788         }
789         BT_INFO("Connecting to service %s", uuid);
790
791         value = __bt_is_headset_connected(type, request_id, address, out_param1);
792
793         if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
794                 return BLUETOOTH_ERROR_ALREADY_CONNECT;
795         } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
796                 value = __bt_is_headset_connecting(type);
797                 if (value != BLUETOOTH_ERROR_NONE) {
798                         result = BLUETOOTH_ERROR_IN_PROGRESS;
799                         goto fail;
800                 }
801                 _bt_headset_set_local_connection(TRUE);
802                 ret = _bt_connect_profile(address, uuid,
803                                 __bt_audio_request_cb, func_data);
804
805                 if (ret != BLUETOOTH_ERROR_NONE) {
806                         BT_ERR("_bt_connect_profile Error");
807                         _bt_headset_set_local_connection(FALSE);
808                         g_free(func_data->address);
809                         g_free(func_data);
810                         return ret;
811                 }
812
813                 /* Add data to the connected list */
814                 _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
815         } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
816                 return BLUETOOTH_ERROR_IN_PROGRESS;
817         }
818
819         return BLUETOOTH_ERROR_NONE;
820 fail:
821         g_array_append_vals(out_param1, address,
822                         BT_ADDRESS_STR_LEN);
823
824         return result;
825 }
826
827 int _bt_audio_disconnect(int request_id, int type,
828                 bluetooth_device_address_t *device_address,
829                 GArray *out_param1)
830 {
831         int result = BLUETOOTH_ERROR_NONE;
832         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
833         bt_audio_function_data_t *func_data;
834         GDBusProxy *adapter_proxy;
835         GDBusConnection *g_conn;
836         GList *node;
837         int ret;
838         char *uuid;
839         int value = BLUETOOTH_ERROR_NONE;
840
841         BT_CHECK_PARAMETER(device_address, return);
842
843         adapter_proxy = _bt_get_adapter_proxy();
844         retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
845
846         g_conn = _bt_get_system_gconn();
847         retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
848
849         _bt_convert_addr_type_to_string(address, device_address->addr);
850
851         func_data = g_malloc0(sizeof(bt_audio_function_data_t));
852         /* Fix : NULL_RETURNS */
853         if (func_data == NULL) {
854                 BT_ERR("Memory allocation error");
855                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
856                 goto fail;
857         }
858         func_data->address = g_strdup(address);
859         func_data->req_id = request_id;
860         func_data->pending = BT_PENDING_NONE;
861         func_data->out_param = out_param1;
862         func_data->type = type;
863
864         switch (type) {
865         case BT_AUDIO_HSP:
866                 uuid = HFP_HS_UUID;
867                 break;
868         case BT_AUDIO_A2DP:
869                 uuid = A2DP_SINK_UUID;
870                 break;
871         case BT_AVRCP:
872                 uuid = AVRCP_TARGET_UUID;
873                 break;
874         case BT_AUDIO_A2DP_SOURCE:
875                 uuid = A2DP_SOURCE_UUID;
876                 break;
877         case BT_AUDIO_ALL:
878                 if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
879                         uuid = A2DP_SINK_UUID;
880                         func_data->pending = BT_PENDING_DISCONNECT;
881                 } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
882                         uuid = HFP_HS_UUID;
883                 } else {
884                         BT_ERR("No audio service connected");
885                         result = BLUETOOTH_ERROR_NOT_CONNECTED;
886                         goto fail;
887                 }
888                 break;
889         case BT_AVRCP_TARGET:
890                 uuid = AVRCP_REMOTE_UUID;
891                 break;
892         default:
893                 BT_ERR("Unknown role");
894                 result = BLUETOOTH_ERROR_INTERNAL;
895                 goto fail;
896         }
897         value = __bt_is_headset_disconnecting(type);
898         if (value != BLUETOOTH_ERROR_NONE) {
899                 BT_INFO("Disconnect in progress");
900                 result = BLUETOOTH_ERROR_IN_PROGRESS;
901                 goto fail;
902         }
903         BT_INFO("Disconnecting service %s", uuid);
904         ret = _bt_disconnect_profile(address, uuid,
905                         __bt_audio_request_cb, func_data);
906
907         if (ret != BLUETOOTH_ERROR_NONE) {
908                 BT_ERR("_bt_disconnect_profile Error");
909                 g_free(func_data->address);
910                 g_free(func_data);
911                 return ret;
912         }
913
914         /*
915          *      This logic is added for dual HF mode issue.
916          */
917         node = g_list_first(g_connected_list);
918         while (node != NULL) {
919                 bt_connected_headset_data_t *connected_device = node->data;
920
921                 if (g_strcmp0(connected_device->device_address, address) == 0) {
922                         BT_DBG("Connection type update");
923                         type = connected_device->type;
924                         break;
925                 }
926                 node = g_list_next(node);
927         }
928         _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
929
930         return BLUETOOTH_ERROR_NONE;
931 fail:
932         if (out_param1 != NULL)
933                 g_array_append_vals(out_param1, address,
934                                 BT_ADDRESS_STR_LEN);
935
936         return result;
937 }
938
939 void _bt_remove_from_connected_list(const char *address)
940 {
941         bt_connected_headset_data_t *connected_device;
942         GList *node;
943
944         node = g_list_first(g_connected_list);
945         while (node != NULL) {
946                 connected_device = node->data;
947                 if (connected_device != NULL &&
948                 g_strcmp0(connected_device->device_address, address) == 0) {
949                         BT_ERR("Device is removed from the list");
950                         g_connected_list = g_list_remove(g_connected_list, connected_device);
951                         g_free(connected_device);
952                         return;
953                 }
954                 node = g_list_next(node);
955         }
956 }
957
958 int _bt_hf_connect(int request_id,
959                 bluetooth_device_address_t *device_address,
960                 GArray *out_param1)
961 {
962         int result = BLUETOOTH_ERROR_NONE;
963         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
964         bt_function_data_t *func_data;
965         GDBusProxy *adapter_proxy;
966         GDBusConnection *g_conn;
967         int ret;
968         char *uuid;
969
970         BT_CHECK_PARAMETER(device_address, return);
971
972         _bt_convert_addr_type_to_string(address, device_address->addr);
973
974         adapter_proxy = _bt_get_adapter_proxy();
975         if (adapter_proxy == NULL) {
976                 result = BLUETOOTH_ERROR_INTERNAL;
977                 goto fail;
978         }
979
980         g_conn = _bt_get_system_gconn();
981         if (g_conn == NULL) {
982                 result = BLUETOOTH_ERROR_INTERNAL;
983                 goto fail;
984         }
985
986         func_data = g_malloc0(sizeof(bt_function_data_t));
987         /* Fix : NULL_RETURNS */
988         if (func_data == NULL) {
989                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
990                 goto fail;
991         }
992
993         func_data->address = g_strdup(address);
994         func_data->req_id = request_id;
995         uuid = g_strdup(HFP_AG_UUID);
996
997         BT_DBG("Connecting to service %s", uuid);
998
999         ret = _bt_connect_profile(address, uuid,
1000                         __bt_hf_request_cb, func_data);
1001
1002         if (ret != BLUETOOTH_ERROR_NONE) {
1003                 BT_ERR("_bt_connect_profile Error");
1004                 g_free(func_data->address);
1005                 g_free(func_data);
1006                 g_free(uuid);
1007                 return ret;
1008         }
1009         g_free(uuid);
1010         return BLUETOOTH_ERROR_NONE;
1011 fail:
1012         if (out_param1 != NULL)
1013                 g_array_append_vals(out_param1, address,
1014                                 BT_ADDRESS_STR_LEN);
1015
1016         return result;
1017 }
1018
1019 int _bt_hf_disconnect(int request_id,
1020                 bluetooth_device_address_t *device_address,
1021                 GArray *out_param1)
1022 {
1023         int result = BLUETOOTH_ERROR_NONE;
1024         char address[BT_ADDRESS_STRING_SIZE] = { 0 };
1025         bt_function_data_t *func_data;
1026         GDBusProxy *adapter_proxy;
1027         GDBusConnection *g_conn;
1028
1029         int ret;
1030         char *uuid;
1031
1032         BT_CHECK_PARAMETER(device_address, return);
1033
1034         _bt_convert_addr_type_to_string(address, device_address->addr);
1035
1036         adapter_proxy = _bt_get_adapter_proxy();
1037         if (adapter_proxy == NULL) {
1038                 result = BLUETOOTH_ERROR_INTERNAL;
1039                 goto fail;
1040         }
1041
1042         g_conn = _bt_get_system_gconn();
1043         if (g_conn == NULL) {
1044                 result = BLUETOOTH_ERROR_INTERNAL;
1045                 goto fail;
1046         }
1047
1048         func_data = g_malloc0(sizeof(bt_function_data_t));
1049         /* Fix : NULL_RETURNS */
1050         if (func_data == NULL) {
1051                 result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
1052                 goto fail;
1053         }
1054
1055         func_data->address = g_strdup(address);
1056         func_data->req_id = request_id;
1057         uuid = g_strdup(HFP_AG_UUID);
1058
1059         BT_DBG("Disconnecting service %s", uuid);
1060         ret = _bt_disconnect_profile(address, uuid,
1061                         __bt_hf_request_cb, func_data);
1062
1063         if (ret != BLUETOOTH_ERROR_NONE) {
1064                 BT_ERR("_bt_disconnect_profile Error");
1065                 g_free(func_data->address);
1066                 g_free(func_data);
1067                 g_free(uuid);
1068                 return ret;
1069         }
1070         g_free(uuid);
1071         return BLUETOOTH_ERROR_NONE;
1072 fail:
1073         if (out_param1 != NULL)
1074                 g_array_append_vals(out_param1, address,
1075                                 BT_ADDRESS_STR_LEN);
1076
1077         return result;
1078 }
1079
1080 int _bt_audio_set_content_protect(gboolean status)
1081 {
1082         GDBusConnection *conn;
1083         GError *error = NULL;
1084
1085         BT_DBG("+\n");
1086
1087         conn = _bt_get_system_gconn();
1088         retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
1089
1090         BT_DBG("Content Protection status = [%d]", status);
1091
1092         g_dbus_connection_emit_signal(conn,
1093                         NULL, BT_CONTENT_PROTECTION_PATH,
1094                         BT_CONTENT_PROTECTION_INTERFACE,
1095                         "ProtectionRequired",
1096                         g_variant_new("(b)", status),
1097                         &error);
1098
1099         if (error) {
1100                 /* dBUS gives error cause */
1101                 ERR("Could not Emit Signal: errCode[%x], message[%s]",
1102                         error->code, error->message);
1103                 g_clear_error(&error);
1104                 return BLUETOOTH_ERROR_INTERNAL;
1105         }
1106
1107         BT_DBG("Emit Signal done = [ProtectionRequired]");
1108         return BLUETOOTH_ERROR_NONE;
1109 }
1110
1111 #ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
1112 static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
1113                                     gpointer user_data)
1114 {
1115         GError *err = NULL;
1116         GVariant *reply = NULL;
1117
1118         reply = g_dbus_proxy_call_finish(proxy, res, &err);
1119         g_object_unref(proxy);
1120         g_variant_unref(reply);
1121
1122         BT_DBG("+");
1123         if (err != NULL) {
1124                 g_dbus_error_strip_remote_error(err);
1125                 BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
1126
1127                 if (strcmp("Host is down", err->message))
1128                 {
1129                         BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
1130                         _bt_audio_stop_auto_connect();
1131                         vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
1132                 }
1133         }
1134         g_clear_error(&err);
1135 }
1136
1137
1138 // It is the function that retry to create alarm.
1139 // Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
1140 // So, in this case, we have to retry alarmmgr_add_alarm.
1141 static gboolean __bt_audio_alarm_retry_cb(gpointer data)
1142 {
1143         int result;
1144         alarm_id_t alarm_id;
1145
1146         BT_DBG("__bt_audio_alarm_retry_cb called.");
1147         result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1148                                                 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1149
1150         if (result != BLUETOOTH_ERROR_NONE)
1151                 return TRUE;
1152         else
1153                 auto_connect_timer.alarm_id = alarm_id;
1154
1155         return FALSE;
1156 }
1157
1158 static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
1159 {
1160         int result = BLUETOOTH_ERROR_NONE;
1161         char *address = NULL;
1162         alarm_id_t new_alarm_id;
1163
1164         BT_INFO("alram id = [%d] , retry_count [%d] ",
1165                                                 alarm_id, auto_connect_timer.retry_count);
1166
1167         if (alarm_id != auto_connect_timer.alarm_id)
1168                 return 0;
1169
1170         address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1171
1172         if (address == NULL) {
1173                 BT_ERR("Address vconf is null");
1174                 auto_connect_timer.alarm_id = 0;
1175                 return 0;
1176         }
1177
1178         BT_DBG("ADDRESS [%s]", address);
1179
1180         result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
1181                         __bt_auto_connect_request_cb, NULL);
1182
1183         auto_connect_timer.retry_count--;
1184
1185         BT_DBG("result [%d]", result);
1186
1187         if (auto_connect_timer.retry_count <= 0) {
1188                 BT_INFO("Stopping Auto connect retry");
1189                 auto_connect_timer.alarm_id = 0;
1190         } else {
1191                 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1192                                                 __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
1193                 if (result == BLUETOOTH_ERROR_NONE)
1194                         auto_connect_timer.alarm_id = new_alarm_id;
1195         }
1196
1197         free(address);
1198         return 0;
1199 }
1200
1201 static void __bt_auto_connect_alarm_remove()
1202 {
1203         BT_DBG("");
1204         if (auto_connect_timer.alarm_id > 0) {
1205                 _bt_service_remove_alarm(auto_connect_timer.alarm_id);
1206                 auto_connect_timer.alarm_id = 0;
1207         }
1208         auto_connect_timer.retry_count = 0;
1209 }
1210
1211 int _bt_audio_start_auto_connect(gboolean linkloss_flag)
1212 {
1213         int result = BLUETOOTH_ERROR_NONE;
1214         char *address = NULL;
1215         alarm_id_t alarm_id = 0;
1216
1217         BT_DBG("");
1218
1219         address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
1220
1221         if (address == NULL) {
1222                 BT_ERR("No target device");
1223                 return 0;
1224         }
1225
1226         __bt_auto_connect_alarm_remove();
1227
1228         auto_connect_timer.retry_count =  BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
1229                                                 BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
1230
1231         if (linkloss_flag) {
1232                 BT_INFO("Start auto connection after linkloss");
1233                 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
1234                                                 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1235                 if (result != BLUETOOTH_ERROR_NONE) {
1236                         g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
1237                 } else {
1238                         auto_connect_timer.alarm_id = alarm_id;
1239                 }
1240         } else {
1241                 BT_INFO("Start auto connection after BT activated");
1242                 result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
1243                                                 __bt_auto_connect_alarm_cb, NULL, &alarm_id);
1244                 if (result == BLUETOOTH_ERROR_NONE)
1245                         auto_connect_timer.alarm_id = alarm_id;
1246         }
1247
1248         free(address);
1249         return BLUETOOTH_ERROR_NONE;
1250 }
1251
1252 int _bt_audio_stop_auto_connect(void)
1253 {
1254         BT_DBG("");
1255         __bt_auto_connect_alarm_remove();
1256
1257         return BLUETOOTH_ERROR_NONE;
1258 }
1259
1260 void _bt_audio_set_auto_connect_device_addr(const char *address)
1261 {
1262         if (address == NULL) {
1263                 BT_ERR("address is null");
1264                 return;
1265         }
1266
1267         BT_INFO("Last connected device is [%s]", address);
1268         vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
1269 }
1270 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */