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