Enhance debug message
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-audio.c
old mode 100755 (executable)
new mode 100644 (file)
index b888c3a..7dd091c
@@ -1,11 +1,5 @@
 /*
- * Bluetooth-frwk
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
- *              Girishashok Joshi <girish.joshi@samsung.com>
- *              Chanyeol Park <chanyeol.park@samsung.com>
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  *
  */
 
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus.h>
+#include <gio/gio.h>
 #include <glib.h>
 #include <dlog.h>
 #include <string.h>
+#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
+#include <vconf.h>
+#endif
 #include <syspopup_caller.h>
 
 #include "bluetooth-api.h"
@@ -41,7 +37,7 @@
 #include "bt-service-headset-connection.h"
 
 #ifdef TIZEN_SUPPORT_DUAL_HF
-#ifdef TIZEN_WEARABLE
+#ifdef TIZEN_PROFILE_WEARABLE
 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
 #endif
 #endif
@@ -52,6 +48,15 @@ typedef struct {
        char device_address[BT_ADDRESS_STRING_SIZE + 1];
 } bt_connected_headset_data_t;
 
+#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
+typedef struct {
+       int alarm_id;
+       int retry_count;
+} bt_auto_connect_timer_t;
+
+bt_auto_connect_timer_t auto_connect_timer = {0, };
+#endif
+
 static GList *g_connected_list;
 
 static bt_headset_wait_t *g_wait_data;
@@ -65,18 +70,21 @@ static void __bt_free_wait_data();
 static gboolean __bt_device_support_uuid(char *remote_address,
                                bt_audio_type_t type);
 
-static void __bt_hf_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
+#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
+static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param);
+#endif
+
+static void __bt_hf_request_cb(GDBusProxy *proxy, GAsyncResult *res,
                                    gpointer user_data)
 {
        GError *g_error = NULL;
-       GArray *out_param1 = NULL;
-       GArray *out_param2 = NULL;
+       GVariant *out_param1 = NULL;
+       GVariant *reply = NULL;
        int result = BLUETOOTH_ERROR_NONE;
        bt_function_data_t *func_data;
        request_info_t *req_info;
 
-       dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID);
-
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
        g_object_unref(proxy);
 
        func_data = user_data;
@@ -93,34 +101,29 @@ static void __bt_hf_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
                goto done;
        }
 
-       if (g_error == NULL)
-               goto dbus_return;
-
-       BT_ERR("HFG request Dbus Call Error: %s\n", g_error->message);
-
-       result = BLUETOOTH_ERROR_INTERNAL;
+       if (reply == NULL) {
+               BT_ERR("HF Connect Dbus Call Error");
+               result = _bt_convert_gerror(g_error);
+               if (g_error) {
+                       BT_ERR("Error: %s\n", g_error->message);
+                       g_clear_error(&g_error);
+               }
+       } else {
+               g_variant_unref(reply);
+       }
 
-dbus_return:
        if (req_info->context == NULL)
                goto done;
 
-       out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
-       out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
+       out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
+               func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
 
-       g_array_append_vals(out_param1, func_data->address,
-                               BT_ADDRESS_STR_LEN);
-       g_array_append_vals(out_param2, &result, sizeof(int));
-
-       dbus_g_method_return(req_info->context, out_param1, out_param2);
-
-       g_array_free(out_param1, TRUE);
-       g_array_free(out_param2, TRUE);
+       g_dbus_method_invocation_return_value(req_info->context,
+                       g_variant_new("(iv)", result, out_param1));
 
        _bt_delete_request_list(req_info->req_id);
-done:
-       if (g_error)
-               g_error_free(g_error);
 
+done:
        if (func_data) {
                g_free(func_data->address);
                g_free(func_data);
@@ -139,11 +142,10 @@ void _bt_audio_check_pending_connect()
 
                _bt_convert_addr_string_to_type(device_address.addr,
                                pdata->address);
-
                _bt_audio_connect(pdata->req_id,
                                BT_AUDIO_A2DP,
                                &device_address,
-                               pdata->out_param);
+                               NULL);
 
                g_free(pdata->address);
                g_free(pdata);
@@ -154,21 +156,19 @@ void _bt_audio_check_pending_connect()
        return;
 }
 
-static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
+static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
                                    gpointer user_data)
 {
        GError *g_error = NULL;
-       GArray *out_param1 = NULL;
-       GArray *out_param2 = NULL;
+       GVariant *out_param1 = NULL;
+       GVariant *reply = NULL;
        int result = BLUETOOTH_ERROR_NONE;
-
        bt_audio_function_data_t *func_data;
-
        request_info_t *req_info;
 
-       dbus_g_proxy_end_call(proxy, call, &g_error, G_TYPE_INVALID);
-
+       reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
        g_object_unref(proxy);
+       g_variant_unref(reply);
 
        func_data = user_data;
 
@@ -179,7 +179,6 @@ static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
        }
 
        if (func_data->pending != BT_PENDING_NONE && g_error == NULL) {
-
                bluetooth_device_address_t device_address;
                _bt_convert_addr_string_to_type(device_address.addr,
                                        func_data->address);
@@ -191,20 +190,16 @@ static void __bt_audio_request_cb(DBusGProxy *proxy, DBusGProxyCall *call,
 
                                pdata = g_new0(bt_audio_function_data_t, 1);
                                pdata->req_id = func_data->req_id;
-                               pdata->out_param = func_data->out_param;
                                pdata->address = strdup(func_data->address);
                                pdata->pending = func_data->pending;
                        } else
                                goto check_req_info;
 
                } else {
-
                        if (_bt_is_service_connected(func_data->address
-                                                       , BT_AUDIO_A2DP)) {
+                                                       , BT_AUDIO_HSP)) {
                                _bt_audio_disconnect(func_data->req_id,
-                                       BT_AUDIO_A2DP,
-                                       &device_address,
-                                       func_data->out_param);
+                                       BT_AUDIO_HSP, &device_address, NULL);
                        } else
                                goto check_req_info;
                }
@@ -225,6 +220,11 @@ check_req_info:
        BT_ERR("Audio Connect/Disconnect Dbus Call Error: %s\n", g_error->message);
 
        result = BLUETOOTH_ERROR_INTERNAL;
+       /* If there is error then we need to set local initiated connection as false
+         * If don't do this then when headset initiate connection for HFP then we don't
+         * initiate connection for A2dp to headset as this flag was set to true in first
+         * connection failure attempt and not set in error case.*/
+       _bt_headset_set_local_connection(FALSE);
 
        /* Remove the device from the list */
        _bt_remove_headset_from_list(func_data->type, func_data->address);
@@ -238,7 +238,7 @@ check_req_info:
                _bt_convert_addr_string_to_type(device_address.addr,
                                g_wait_data->address);
                _bt_audio_connect(g_wait_data->req_id, g_wait_data->type,
-                               &device_address, g_wait_data->out_param1);
+                               &device_address, NULL);
        }
 
        /* Event will be sent by the event reciever */
@@ -248,22 +248,15 @@ dbus_return:
                goto done;
        }
 
-       out_param1 = g_array_new(FALSE, FALSE, sizeof(gchar));
-       out_param2 = g_array_new(FALSE, FALSE, sizeof(gchar));
-
-       g_array_append_vals(out_param1, func_data->address,
-                       BT_ADDRESS_STR_LEN);
-       g_array_append_vals(out_param2, &result, sizeof(int));
+       out_param1 = g_variant_new_from_data((const GVariantType *)"ay",
+               func_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
 
-       dbus_g_method_return(req_info->context, out_param1, out_param2);
-
-       g_array_free(out_param1, TRUE);
-       g_array_free(out_param2, TRUE);
+       g_dbus_method_invocation_return_value(req_info->context,
+                       g_variant_new("(iv)", result, out_param1));
 
        _bt_delete_request_list(req_info->req_id);
 done:
-       if (g_error)
-               g_error_free(g_error);
+       g_clear_error(&g_error);
 
        if (func_data) {
                g_free(func_data->address);
@@ -271,88 +264,6 @@ done:
        }
 }
 
-static char *__bt_get_audio_path(bluetooth_device_address_t *address)
-{
-
-       char *object_path = NULL;
-       char addr_str[BT_ADDRESS_STRING_SIZE + 1] = { 0 };
-       DBusGProxy *audio_proxy;
-       DBusGProxy *adapter_proxy;
-       DBusGConnection *g_conn;
-       GError *error = NULL;
-
-       retv_if(address == NULL, NULL);
-
-       g_conn = _bt_get_system_gconn();
-       retv_if(g_conn == NULL, NULL);
-
-       adapter_proxy = _bt_get_adapter_proxy();
-       retv_if(adapter_proxy == NULL, NULL);
-
-       _bt_convert_addr_type_to_string(addr_str, address->addr);
-
-       dbus_g_proxy_call(adapter_proxy, "FindDevice",
-                       &error, G_TYPE_STRING, addr_str,
-                       G_TYPE_INVALID, DBUS_TYPE_G_OBJECT_PATH,
-                       &object_path, G_TYPE_INVALID);
-
-       if (error != NULL) {
-               BT_ERR("Failed to Find device: %s\n", error->message);
-               g_error_free(error);
-               return NULL;
-       }
-
-       retv_if(object_path == NULL, NULL);
-
-       audio_proxy = dbus_g_proxy_new_for_name(g_conn,
-                       BT_BLUEZ_NAME,
-                       object_path,
-                       BT_HEADSET_INTERFACE);
-
-       retv_if(audio_proxy == NULL, NULL);
-
-       g_object_unref(audio_proxy);
-
-       return object_path;
-}
-
-static char *__bt_get_connected_audio_path(void)
-{
-       int i;
-       guint size;
-       char *audio_path = NULL;
-       GArray *device_list;
-       bluetooth_device_info_t info;
-
-       /* allocate the g_pointer_array */
-       device_list = g_array_new(FALSE, FALSE, sizeof(gchar));
-
-       if (_bt_get_bonded_devices(&device_list)
-                       != BLUETOOTH_ERROR_NONE) {
-               g_array_free(device_list, TRUE);
-               return NULL;
-       }
-
-       size = device_list->len;
-       size = (device_list->len) / sizeof(bluetooth_device_info_t);
-
-       for (i = 0; i < size; i++) {
-
-               info = g_array_index(device_list,
-                               bluetooth_device_info_t, i);
-
-               if (info.connected == TRUE) {
-                       audio_path = __bt_get_audio_path(&info.device_address);
-                       if (audio_path)
-                               break;
-               }
-       }
-
-       g_array_free(device_list, TRUE);
-
-       return audio_path;
-}
-
 static void __bt_free_wait_data()
 {
        if (g_wait_data != NULL) {
@@ -365,8 +276,7 @@ static void __bt_free_wait_data()
 static void __bt_remove_device_from_wait_list()
 {
        /* Before deleting the request update the UI */
-       GArray *out_param_1 = NULL;
-       GArray *out_param_2 = NULL;
+       GVariant *out_param_1 = NULL;
        int result = BLUETOOTH_ERROR_INTERNAL;
        request_info_t *req_info;
 
@@ -376,15 +286,12 @@ static void __bt_remove_device_from_wait_list()
                return;
        }
 
-       out_param_1 = g_array_new(FALSE, FALSE, sizeof(gchar));
-       out_param_2 = g_array_new(FALSE, FALSE, sizeof(gchar));
-       g_array_append_vals(out_param_1, g_wait_data->address,
-                       BT_ADDRESS_STR_LEN);
-       g_array_append_vals(out_param_2, &result, sizeof(int));
-       dbus_g_method_return(req_info->context,
-                       out_param_1, out_param_2);
-       g_array_free(out_param_1, TRUE);
-       g_array_free(out_param_2, TRUE);
+       out_param_1 = g_variant_new_from_data((const GVariantType *)"ay",
+               g_wait_data->address, BT_ADDRESS_STR_LEN, TRUE, NULL, NULL);
+
+       g_dbus_method_invocation_return_value(req_info->context,
+                       g_variant_new("(iv)", result, out_param_1));
+
        _bt_delete_request_list(g_wait_data->req_id);
 }
 
@@ -427,7 +334,7 @@ gboolean _bt_is_headset_type_connected(int type, char *address)
 #ifdef TIZEN_SUPPORT_DUAL_HF
 gboolean __bt_is_companion_device(const char *addr)
 {
-#ifdef TIZEN_WEARABLE
+#ifdef TIZEN_PROFILE_WEARABLE
        char *host_device_address = NULL;
        host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
 
@@ -437,10 +344,12 @@ gboolean __bt_is_companion_device(const char *addr)
        }
 
        if (g_strcmp0(host_device_address, addr) == 0) {
-               BT_INFO("addr[%s] is companion device", addr);
+               BT_INFO("Found companion device");
+               free(host_device_address);
                return TRUE;
        }
 
+       free(host_device_address);
        return FALSE;
 #else
        /* TODO : Need to add companion device check condition for Phone models */
@@ -450,7 +359,7 @@ gboolean __bt_is_companion_device(const char *addr)
 #endif
 
 static int __bt_is_headset_connected(int type, int req_id,
-                               const char *address, GArray **out_param1)
+                               const char *address)
 {
        gboolean connected = FALSE;
        char connected_address[BT_ADDRESS_STRING_SIZE + 1];
@@ -466,7 +375,7 @@ static int __bt_is_headset_connected(int type, int req_id,
        node = g_list_first(g_connected_list);
        while (node != NULL) {
                connected_device = node->data;
-               if ((connected_device->type & type) == type) {
+               if ((connected_device->type & type)) {
                        g_strlcpy(connected_address, connected_device->device_address,
                                        BT_ADDRESS_STRING_SIZE + 1);
 #ifdef TIZEN_SUPPORT_DUAL_HF
@@ -497,29 +406,69 @@ static int __bt_is_headset_connected(int type, int req_id,
                return BLUETOOTH_ERROR_NOT_CONNECTED;
 #endif
 
+       /* Convert BD address from string type */
+       _bt_convert_addr_string_to_type(device_address.addr, connected_address);
+       int value = BLUETOOTH_ERROR_NONE;
+       value = _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
+
        /* If already one device is waiting, remove current waiting device and add new */
-       if (g_wait_data != NULL) {
-               if (g_strcmp0(g_wait_data->address, address) != 0) {
-                       __bt_remove_device_from_wait_list();
-                       __bt_free_wait_data();
+       if (value == BLUETOOTH_ERROR_NONE) {
+               if (g_wait_data != NULL) {
+                       if (g_strcmp0(g_wait_data->address, address) != 0) {
+                               __bt_remove_device_from_wait_list();
+                               __bt_free_wait_data();
+                       }
+               }
+
+               if (g_wait_data == NULL) {
+                       g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
+                       g_wait_data->address = g_strdup(address);
+                       g_wait_data->req_id = req_id;
+                       g_wait_data->type = type;
+                       g_wait_data->ag_flag = FALSE;
+
+                       /* Set disconnection type */
+                       __bt_set_headset_disconnection_type(connected_address);
                }
        }
 
-       if (g_wait_data == NULL) {
-               g_wait_data = g_malloc0(sizeof(bt_headset_wait_t));
-               g_wait_data->address = g_strdup(address);
-               g_wait_data->req_id = req_id;
-               g_wait_data->type = type;
-               g_wait_data->ag_flag = FALSE;
-               g_wait_data->out_param1 = out_param1;
+       return value;
+}
+
+static int __bt_is_headset_connecting(int type)
+{
+       bt_connected_headset_data_t *connected_device = NULL;
+
+       /* Check if any other headset is connected */
+       GList *node = NULL;
 
-               /* Set disconnection type */
-               __bt_set_headset_disconnection_type(connected_address);
+       node = g_list_first(g_connected_list);
+       while (node != NULL) {
+               connected_device = node->data;
+               if (connected_device->device_state == BT_STATE_CONNECTING)
+                       return BLUETOOTH_ERROR_CONNECTION_BUSY;
+               node = g_list_next(node);
+       }
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+int __bt_is_headset_disconnecting(int type)
+{
+       bt_connected_headset_data_t *connected_device = NULL;
+
+       /* Check if any other headset is connected */
+       GList *node = NULL;
+
+       node = g_list_first(g_connected_list);
+       while (node != NULL) {
+               connected_device = node->data;
+               if (connected_device->device_state == BT_STATE_DISCONNECTING)
+                       return BLUETOOTH_ERROR_CONNECTION_BUSY;
+
+               node = g_list_next(node);
        }
 
-       /* Convert BD adress from string type */
-       _bt_convert_addr_string_to_type(device_address.addr, connected_address);
-       _bt_audio_disconnect(0, connected_device->type & type, &device_address, NULL);
        return BLUETOOTH_ERROR_NONE;
 }
 
@@ -564,8 +513,9 @@ void _bt_add_headset_to_list(int type, int status, const char *address)
        }
 
        connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
+
        connected_device->device_state = status;
-       if (status == BT_STATE_CONNECTED)
+       if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
                connected_device->type |= type;
        g_strlcpy(connected_device->device_address, address,
                        sizeof(connected_device->device_address));
@@ -628,6 +578,9 @@ void _bt_remove_headset_from_list(int type, const char *address)
                        if (connected_device->type & BT_AVRCP)
                                connected_device->type &= ~(BT_AVRCP);
                        break;
+               case BT_AUDIO_A2DP_SOURCE:
+                       if (connected_device->type & BT_AUDIO_A2DP_SOURCE)
+                               connected_device->type &= ~(BT_AUDIO_A2DP_SOURCE);
                }
 
                BT_DBG("Connection type = %x\n", connected_device->type);
@@ -635,6 +588,8 @@ void _bt_remove_headset_from_list(int type, const char *address)
                if (connected_device->type == 0x00) {
                        g_connected_list = g_list_remove(g_connected_list, connected_device);
                        g_free(connected_device);
+               } else {
+                       connected_device->device_state = BT_STATE_CONNECTED;
                }
 
                node = g_list_next(node);
@@ -645,36 +600,38 @@ static gboolean __bt_device_support_uuid(char *remote_address,
                                bt_audio_type_t type)
 {
        GArray *dev_list = NULL;
-       int size,i,j;
-       bluetooth_device_info_t info;
+       int size;
+       int i;
+       int j;
+       bluetooth_device_info_t *info;
        char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
        gboolean ret = FALSE;
 
        BT_DBG("+");
 
-       dev_list = g_array_new (FALSE, FALSE, sizeof(gchar));
+       dev_list = g_array_new(FALSE, FALSE, sizeof(gchar));
 
        _bt_get_bonded_devices(&dev_list);
        size = (dev_list->len) / sizeof(bluetooth_device_info_t);
 
-       for (i=0; i < size; i++) {
-               info = g_array_index(dev_list, bluetooth_device_info_t, i);
+       for (i = 0; i < size; i++) {
+               info = &g_array_index(dev_list, bluetooth_device_info_t, i);
                _bt_convert_addr_type_to_string(bond_address,
-                               info.device_address.addr);
+                               info->device_address.addr);
                if (strcmp(bond_address, remote_address) != 0)
                        continue;
 
                BT_INFO("Device address Matched");
                j = 0;
-               while (j != info.service_index) {
+               while (j != info->service_index) {
                        if (type == BT_AUDIO_HSP) {
-                               if (strcmp(info.uuids[j], HFP_HS_UUID) == 0) {
+                               if (strcmp(info->uuids[j], HFP_HS_UUID) == 0) {
                                        BT_INFO("HFP HS UUID exists");
                                        ret = TRUE;
                                        goto end;
                                }
                        } else if (type == BT_AUDIO_A2DP) {
-                               if (strcmp(info.uuids[j], A2DP_SINK_UUID) == 0) {
+                               if (strcmp(info->uuids[j], A2DP_SINK_UUID) == 0) {
                                        BT_INFO("A2DP SINK UUID exists");
                                        ret = TRUE;
                                        goto end;
@@ -711,23 +668,25 @@ gboolean _bt_is_service_connected(char* address, int type)
 
 int _bt_audio_connect(int request_id, int type,
                bluetooth_device_address_t *device_address,
-               GArray **out_param1)
+               GArray *out_param1)
 {
        int result = BLUETOOTH_ERROR_NONE;
        char address[BT_ADDRESS_STRING_SIZE] = { 0 };
-       DBusGProxy *adapter_proxy;
-       DBusGConnection *g_conn;
+       GDBusProxy *adapter_proxy;
+       GDBusConnection *g_conn;
        int ret;
-       char *uuid;
+       char *uuid = NULL;
        int value = BLUETOOTH_ERROR_NONE;
        bt_audio_function_data_t *func_data;
+       guint hfp_hs_restricted = 0x0; /* set default "allowed" */
+       guint a2dp_restricted = 0x0;
 
        BT_CHECK_PARAMETER(device_address, return);
 
        adapter_proxy = _bt_get_adapter_proxy();
        retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       g_conn = _bt_get_system_gconn();
+       g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        _bt_convert_addr_type_to_string(address, device_address->addr);
@@ -738,7 +697,14 @@ int _bt_audio_connect(int request_id, int type,
        func_data->req_id = request_id;
        func_data->type = type;
        func_data->pending = BT_PENDING_NONE;
-       func_data->out_param = out_param1;
+
+       result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
+       if (result != BLUETOOTH_ERROR_NONE)
+               BT_ERR("Can't get hfp_hs restriction info");
+
+       result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_A2DP, &a2dp_restricted);
+       if (result != BLUETOOTH_ERROR_NONE)
+               BT_ERR("Can't get a2dp restriction info");
 
        switch (type) {
        case BT_AUDIO_HSP:
@@ -750,18 +716,50 @@ int _bt_audio_connect(int request_id, int type,
        case BT_AVRCP:
                uuid = AVRCP_TARGET_UUID;
                break;
+       case BT_AUDIO_A2DP_SOURCE:
+               uuid = A2DP_SOURCE_UUID;
+               break;
        case BT_AUDIO_ALL:
-               if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
-                       uuid = HFP_HS_UUID;
-                       func_data->pending = BT_PENDING_CONNECT;
-               } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
-                       uuid = A2DP_SINK_UUID;
-               } else {
-                       BT_ERR("No audio role supported");
-                       result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
+               if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
+                       if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
+                               uuid = HFP_HS_UUID;
+                               func_data->pending = BT_PENDING_CONNECT;
+                               type = BT_AUDIO_HSP;
+                       } else if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
+                               uuid = A2DP_SINK_UUID;
+                               type = BT_AUDIO_A2DP;
+                       } else {
+                               BT_ERR("No audio role supported");
+                               result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
+                               goto fail;
+                       }
+               } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
+                       BT_ERR("All profiles are restricted");
+                       result = BLUETOOTH_ERROR_INTERNAL;
                        goto fail;
+               } else if (a2dp_restricted == 0x01) { /* in case of a2dp is restricted, only connection for hfp_hs */
+                       if (__bt_device_support_uuid(address, BT_AUDIO_HSP)) {
+                               uuid = HFP_HS_UUID;
+                               type = BT_AUDIO_HSP;
+                       } else {
+                               BT_ERR("HFP_HS role is not supported");
+                               result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
+                               goto fail;
+                       }
+               } else if (hfp_hs_restricted == 0x01) { /* in case of hfp_hs is restricted, only connection for a2dp */
+                       if (__bt_device_support_uuid(address, BT_AUDIO_A2DP)) {
+                               uuid = A2DP_SINK_UUID;
+                               type = BT_AUDIO_A2DP;
+                       } else {
+                               BT_ERR("A2DP role is not supported");
+                               result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
+                               goto fail;
+                       }
                }
                break;
+       case BT_AVRCP_TARGET:
+               uuid = AVRCP_REMOTE_UUID;
+               break;
        default:
                BT_ERR("Unknown role");
                result = BLUETOOTH_ERROR_INTERNAL;
@@ -769,11 +767,16 @@ int _bt_audio_connect(int request_id, int type,
        }
        BT_INFO("Connecting to service %s", uuid);
 
-       value = __bt_is_headset_connected(type, request_id, address, out_param1);
+       value = __bt_is_headset_connected(type, request_id, address);
 
        if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
                return BLUETOOTH_ERROR_ALREADY_CONNECT;
        } else if (value == BLUETOOTH_ERROR_NOT_CONNECTED) {
+               value = __bt_is_headset_connecting(type);
+               if (value != BLUETOOTH_ERROR_NONE) {
+                       result = BLUETOOTH_ERROR_IN_PROGRESS;
+                       goto fail;
+               }
                _bt_headset_set_local_connection(TRUE);
                ret = _bt_connect_profile(address, uuid,
                                __bt_audio_request_cb, func_data);
@@ -788,45 +791,50 @@ int _bt_audio_connect(int request_id, int type,
 
                /* Add data to the connected list */
                _bt_add_headset_to_list(type, BT_STATE_CONNECTING, address);
+       } else if (value == BLUETOOTH_ERROR_IN_PROGRESS) {
+               return BLUETOOTH_ERROR_IN_PROGRESS;
        }
 
+       if (out_param1)
+               g_array_free(out_param1, TRUE);
+
        return BLUETOOTH_ERROR_NONE;
 fail:
-       g_array_append_vals(*out_param1, address,
-                       BT_ADDRESS_STR_LEN);
+       if (out_param1 != NULL)
+               g_array_append_vals(out_param1, address,
+                               BT_ADDRESS_STR_LEN);
 
        return result;
 }
 
 int _bt_audio_disconnect(int request_id, int type,
                bluetooth_device_address_t *device_address,
-               GArray **out_param1)
+               GArray *out_param1)
 {
        int result = BLUETOOTH_ERROR_NONE;
        char address[BT_ADDRESS_STRING_SIZE] = { 0 };
        bt_audio_function_data_t *func_data;
-       DBusGProxy *adapter_proxy;
-       DBusGConnection *g_conn;
+       GDBusProxy *adapter_proxy;
+       GDBusConnection *g_conn;
        GList *node;
        int ret;
        char *uuid;
+       int value = BLUETOOTH_ERROR_NONE;
 
        BT_CHECK_PARAMETER(device_address, return);
 
        adapter_proxy = _bt_get_adapter_proxy();
        retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       g_conn = _bt_get_system_gconn();
+       g_conn = _bt_gdbus_get_system_gconn();
        retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
 
        _bt_convert_addr_type_to_string(address, device_address->addr);
 
        func_data = g_malloc0(sizeof(bt_audio_function_data_t));
-
        func_data->address = g_strdup(address);
        func_data->req_id = request_id;
        func_data->pending = BT_PENDING_NONE;
-       func_data->out_param = out_param1;
        func_data->type = type;
 
        switch (type) {
@@ -839,24 +847,35 @@ int _bt_audio_disconnect(int request_id, int type,
        case BT_AVRCP:
                uuid = AVRCP_TARGET_UUID;
                break;
+       case BT_AUDIO_A2DP_SOURCE:
+               uuid = A2DP_SOURCE_UUID;
+               break;
        case BT_AUDIO_ALL:
-               if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
-                       uuid = HFP_HS_UUID;
-                       func_data->pending = BT_PENDING_DISCONNECT;
-               } else if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
+               if (_bt_is_service_connected(address, BT_AUDIO_A2DP)) {
                        uuid = A2DP_SINK_UUID;
+                       func_data->pending = BT_PENDING_DISCONNECT;
+               } else if (_bt_is_service_connected(address, BT_AUDIO_HSP)) {
+                       uuid = HFP_HS_UUID;
                } else {
                        BT_ERR("No audio service connected");
                        result = BLUETOOTH_ERROR_NOT_CONNECTED;
                        goto fail;
                }
                break;
+       case BT_AVRCP_TARGET:
+               uuid = AVRCP_REMOTE_UUID;
+               break;
        default:
                BT_ERR("Unknown role");
                result = BLUETOOTH_ERROR_INTERNAL;
                goto fail;
        }
-
+       value = __bt_is_headset_disconnecting(type);
+       if (value != BLUETOOTH_ERROR_NONE) {
+               BT_INFO("Disconnect in progress");
+               result = BLUETOOTH_ERROR_IN_PROGRESS;
+               goto fail;
+       }
        BT_INFO("Disconnecting service %s", uuid);
        ret = _bt_disconnect_profile(address, uuid,
                        __bt_audio_request_cb, func_data);
@@ -884,10 +903,13 @@ int _bt_audio_disconnect(int request_id, int type,
        }
        _bt_add_headset_to_list(type, BT_STATE_DISCONNECTING, address);
 
+       if (out_param1)
+               g_array_free(out_param1, TRUE);
+
        return BLUETOOTH_ERROR_NONE;
 fail:
        if (out_param1 != NULL)
-               g_array_append_vals(*out_param1, address,
+               g_array_append_vals(out_param1, address,
                                BT_ADDRESS_STR_LEN);
 
        return result;
@@ -914,18 +936,17 @@ void _bt_remove_from_connected_list(const char *address)
 
 int _bt_hf_connect(int request_id,
                bluetooth_device_address_t *device_address,
-               GArray **out_param1)
+               GArray *out_param1)
 {
        int result = BLUETOOTH_ERROR_NONE;
        char address[BT_ADDRESS_STRING_SIZE] = { 0 };
        bt_function_data_t *func_data;
-       DBusGProxy *adapter_proxy;
-       DBusGConnection *g_conn;
-
+       GDBusProxy *adapter_proxy;
+       GDBusConnection *g_conn;
+       gboolean connected = FALSE;
        int ret;
        char *uuid;
 
-
        BT_CHECK_PARAMETER(device_address, return);
 
        _bt_convert_addr_type_to_string(address, device_address->addr);
@@ -936,14 +957,21 @@ int _bt_hf_connect(int request_id,
                goto fail;
        }
 
-       g_conn = _bt_get_system_gconn();
+       g_conn = _bt_gdbus_get_system_gconn();
        if (g_conn == NULL) {
                result = BLUETOOTH_ERROR_INTERNAL;
                goto fail;
        }
 
-       func_data = g_malloc0(sizeof(bt_function_data_t));
+       /* Check if HF is connected or not */
+       result = _bt_is_device_connected(device_address, BT_PROFILE_CONN_HFG, &connected);
+       if (connected == TRUE) {
+               BT_ERR("HF is already connected");
+               result = BLUETOOTH_ERROR_ALREADY_CONNECT;
+               goto fail;
+       }
 
+       func_data = g_malloc0(sizeof(bt_function_data_t));
        func_data->address = g_strdup(address);
        func_data->req_id = request_id;
        uuid = g_strdup(HFP_AG_UUID);
@@ -961,10 +989,13 @@ int _bt_hf_connect(int request_id,
                return ret;
        }
        g_free(uuid);
+       if (out_param1)
+               g_array_free(out_param1, TRUE);
+
        return BLUETOOTH_ERROR_NONE;
 fail:
        if (out_param1 != NULL)
-               g_array_append_vals(*out_param1, address,
+               g_array_append_vals(out_param1, address,
                                BT_ADDRESS_STR_LEN);
 
        return result;
@@ -972,13 +1003,13 @@ fail:
 
 int _bt_hf_disconnect(int request_id,
                bluetooth_device_address_t *device_address,
-               GArray **out_param1)
+               GArray *out_param1)
 {
        int result = BLUETOOTH_ERROR_NONE;
        char address[BT_ADDRESS_STRING_SIZE] = { 0 };
        bt_function_data_t *func_data;
-       DBusGProxy *adapter_proxy;
-       DBusGConnection *g_conn;
+       GDBusProxy *adapter_proxy;
+       GDBusConnection *g_conn;
 
        int ret;
        char *uuid;
@@ -993,14 +1024,13 @@ int _bt_hf_disconnect(int request_id,
                goto fail;
        }
 
-       g_conn = _bt_get_system_gconn();
+       g_conn = _bt_gdbus_get_system_gconn();
        if (g_conn == NULL) {
                result = BLUETOOTH_ERROR_INTERNAL;
                goto fail;
        }
 
        func_data = g_malloc0(sizeof(bt_function_data_t));
-
        func_data->address = g_strdup(address);
        func_data->req_id = request_id;
        uuid = g_strdup(HFP_AG_UUID);
@@ -1017,135 +1047,205 @@ int _bt_hf_disconnect(int request_id,
                return ret;
        }
        g_free(uuid);
+       if (out_param1)
+               g_array_free(out_param1, TRUE);
+
        return BLUETOOTH_ERROR_NONE;
 fail:
        if (out_param1 != NULL)
-               g_array_append_vals(*out_param1, address,
+               g_array_append_vals(out_param1, address,
                                BT_ADDRESS_STR_LEN);
 
        return result;
 }
 
-int _bt_audio_get_speaker_gain(unsigned int *gain)
+int _bt_audio_set_content_protect(gboolean status)
 {
-       char *device_path = NULL;
-       DBusGProxy *adapter_proxy;
-       DBusGProxy *profile_proxy;
-       DBusGConnection *g_conn;
-       GHashTable *hash = NULL;
-       GValue *value;
+       GDBusConnection *conn;
+       GError *error = NULL;
 
-       adapter_proxy = _bt_get_adapter_proxy();
-       retv_if(adapter_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
+       BT_DBG("+\n");
 
-       g_conn = _bt_get_system_gconn();
-       retv_if(g_conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+       conn = _bt_gdbus_get_system_gconn();
+       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+
+       BT_DBG("Content Protection status = [%d]", status);
+
+       g_dbus_connection_emit_signal(conn,
+                       NULL, BT_CONTENT_PROTECTION_PATH,
+                       BT_CONTENT_PROTECTION_INTERFACE,
+                       "ProtectionRequired",
+                       g_variant_new("(b)", status),
+                       &error);
+
+       if (error) {
+               /* dBUS gives error cause */
+               ERR("Could not Emit Signal: errCode[%x], message[%s]",
+                       error->code, error->message);
+               g_clear_error(&error);
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       BT_DBG("Emit Signal done = [ProtectionRequired]");
+       return BLUETOOTH_ERROR_NONE;
+}
 
-       device_path = __bt_get_connected_audio_path();
-       retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
+#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
+static void __bt_auto_connect_request_cb(GDBusProxy *proxy, GAsyncResult *res,
+                                   gpointer user_data)
+{
+       GError *err = NULL;
+       GVariant *reply = NULL;
 
-       profile_proxy = dbus_g_proxy_new_for_name(g_conn, BT_BLUEZ_NAME,
-                                     device_path, BT_HEADSET_INTERFACE);
+       reply = g_dbus_proxy_call_finish(proxy, res, &err);
+       g_object_unref(proxy);
+       g_variant_unref(reply);
 
-       g_free(device_path);
+       BT_DBG("+");
+       if (err != NULL) {
+               g_dbus_error_strip_remote_error(err);
+               BT_INFO("Auto_connect_request Dbus Call Error: %s", err->message);
+
+               if (strcmp("Host is down", err->message)) {
+                       BT_INFO("Fail reason is not 'Host Down'. Terminate auto connect");
+                       _bt_audio_stop_auto_connect();
+                       vconf_set_str(BT_LAST_CONNECTED_DEVICE, "");
+               }
+       }
+       g_clear_error(&err);
+}
 
-       retv_if(profile_proxy == NULL, BLUETOOTH_ERROR_INTERNAL);
 
-       dbus_g_proxy_call(profile_proxy, "GetProperties", NULL,
-                       G_TYPE_INVALID,
-                       dbus_g_type_get_map("GHashTable",
-                       G_TYPE_STRING, G_TYPE_VALUE),
-                       &hash, G_TYPE_INVALID);
+// It is the function that retry to create alarm.
+// Sometimes alarm mgr service is created later than bluetooth-frwk service in booting time.
+// So, in this case, we have to retry alarmmgr_add_alarm.
+static gboolean __bt_audio_alarm_retry_cb(gpointer data)
+{
+       int result;
+       alarm_id_t alarm_id;
 
-       g_object_unref(profile_proxy);
+       BT_DBG("__bt_audio_alarm_retry_cb called.");
+       result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
+                                               __bt_auto_connect_alarm_cb, NULL, &alarm_id);
 
-       retv_if(hash == NULL, BLUETOOTH_ERROR_INTERNAL);
+       if (result != BLUETOOTH_ERROR_NONE)
+               return TRUE;
+       else
+               auto_connect_timer.alarm_id = alarm_id;
 
-       value = g_hash_table_lookup(hash, "SpeakerGain");
-       *gain = value ? g_value_get_uint(value) : 0;
-       g_hash_table_destroy(hash);
-       return BLUETOOTH_ERROR_NONE;
+       return FALSE;
 }
 
-int _bt_audio_set_speaker_gain(unsigned int gain)
+static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
 {
-       char *device_path = NULL;
-       char *gain_str = "SpeakerGain";
-       char sig[2] = {DBUS_TYPE_UINT16, '\0'};
-       int ret = BLUETOOTH_ERROR_NONE;
-       DBusMessage *msg;
-       DBusMessageIter iter;
-       DBusMessageIter value;
-       DBusConnection *conn;
-
-       conn = _bt_get_system_conn();
-       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+       int result = BLUETOOTH_ERROR_NONE;
+       char *address = NULL;
+       alarm_id_t new_alarm_id;
 
-       device_path = __bt_get_connected_audio_path();
-       retv_if(device_path == NULL, BLUETOOTH_ERROR_NOT_CONNECTED);
+       BT_INFO("alram id = [%d] , retry_count [%d] ",
+                                               alarm_id, auto_connect_timer.retry_count);
 
-       msg = dbus_message_new_method_call(BT_BLUEZ_NAME,
-                       device_path, BT_HEADSET_INTERFACE,
-                       "SetProperty");
+       if (alarm_id != auto_connect_timer.alarm_id)
+               return 0;
 
-       g_free(device_path);
+       address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
 
-       retv_if(msg == NULL, BLUETOOTH_ERROR_INTERNAL);
+       if (address == NULL) {
+               BT_ERR("Address vconf is null");
+               auto_connect_timer.alarm_id = 0;
+               return 0;
+       }
 
-       dbus_message_iter_init_append(msg, &iter);
-       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
-                       &gain_str);
-       dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
-                       sig, &value);
-       dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT16,
-                       &gain);
-       dbus_message_iter_close_container(&iter, &value);
+       BT_DBG("ADDRESS [%s]", address);
 
-       if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
-               dbus_message_set_no_reply(msg, TRUE);
+       result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
+                       __bt_auto_connect_request_cb, NULL);
 
-       if (!dbus_connection_send(conn, msg, NULL)) {
-               BT_ERR("Dbus sending failed\n");
-               ret = BLUETOOTH_ERROR_INTERNAL;
+       auto_connect_timer.retry_count--;
+
+       BT_DBG("result [%d]", result);
+
+       if (auto_connect_timer.retry_count <= 0) {
+               BT_INFO(" ### Stopping Auto connect retry");
+               auto_connect_timer.alarm_id = 0;
+       } else {
+               result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
+                                               __bt_auto_connect_alarm_cb, NULL, &new_alarm_id);
+               if (result == BLUETOOTH_ERROR_NONE)
+                       auto_connect_timer.alarm_id = new_alarm_id;
        }
-       dbus_message_unref(msg);
 
-       return ret;
+       free(address);
+       return 0;
 }
 
-int _bt_audio_set_content_protect(gboolean status)
+static void __bt_auto_connect_alarm_remove()
+{
+       BT_DBG("");
+       if (auto_connect_timer.alarm_id > 0) {
+               _bt_service_remove_alarm(auto_connect_timer.alarm_id);
+               auto_connect_timer.alarm_id = 0;
+       }
+       auto_connect_timer.retry_count = 0;
+}
+
+int _bt_audio_start_auto_connect(gboolean linkloss_flag)
 {
-       DBusConnection *conn;
-       DBusMessage *signal;
+       int result = BLUETOOTH_ERROR_NONE;
+       char *address = NULL;
+       alarm_id_t alarm_id = 0;
 
-       BT_DBG("+\n");
+       BT_DBG("");
 
-       conn = _bt_get_system_conn();
-       retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
+       address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
 
-       BT_DBG("Content Protection status = [%d] \n", status);
-
-       /*Emit Content protection Status change signal with value*/
-       signal = dbus_message_new_signal(BT_CONTENT_PROTECTION_PATH,
-                                       BT_CONTENT_PROTECTION_INTERFACE,
-                                       "ProtectionRequired");
-       if (!signal)
-               goto err;
-
-       if (!dbus_message_append_args(signal,
-                               DBUS_TYPE_BOOLEAN, &status,
-                               DBUS_TYPE_INVALID)) {
-               BT_ERR("Signal appending failed\n");
-               dbus_message_unref(signal);
-               goto err;
+       if (address == NULL) {
+               BT_ERR("No target device");
+               return 0;
        }
 
-       dbus_connection_send(conn, signal, NULL);
-       dbus_message_unref(signal);
+       __bt_auto_connect_alarm_remove();
+
+       auto_connect_timer.retry_count =  BT_AUTO_CONNECT_TIMEOUT_RETRY_TIME /
+                                               BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS;
+
+       if (linkloss_flag) {
+               BT_INFO(" ### Start auto connection after linkloss");
+               result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_LINKLOSS,
+                                               __bt_auto_connect_alarm_cb, NULL, &alarm_id);
+               if (result != BLUETOOTH_ERROR_NONE)
+                       g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
+               else
+                       auto_connect_timer.alarm_id = alarm_id;
+
+       } else {
+               BT_INFO(" ### Start auto connection after BT activated");
+               result = _bt_service_set_alarm(BT_AUTO_CONNECT_TIMEOUT_AFTER_BT_ACTIVATED,
+                                               __bt_auto_connect_alarm_cb, NULL, &alarm_id);
+               if (result == BLUETOOTH_ERROR_NONE)
+                       auto_connect_timer.alarm_id = alarm_id;
+       }
 
-       BT_DBG("-\n");
+       free(address);
        return BLUETOOTH_ERROR_NONE;
+}
 
-err:
-       return BLUETOOTH_ERROR_INTERNAL;
+int _bt_audio_stop_auto_connect(void)
+{
+       BT_DBG("");
+       __bt_auto_connect_alarm_remove();
+
+       return BLUETOOTH_ERROR_NONE;
+}
+
+void _bt_audio_set_auto_connect_device_addr(const char *address)
+{
+       if (address == NULL) {
+               BT_ERR("address is null");
+               return;
+       }
+
+       BT_INFO("Last connected device is [%s]", address);
+       vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
 }
+#endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */