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