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