#include <glib.h>
#include <dlog.h>
#include <string.h>
-#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT)
-#include <syspopup_caller.h>
+#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT
+#include <vconf.h>
#endif
+#include <syspopup_caller.h>
#include "bluetooth-api.h"
#include "bt-internal-types.h"
#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
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;
static gboolean __bt_device_support_uuid(char *remote_address,
bt_audio_type_t type);
+#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)
{
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);
}
- result = BLUETOOTH_ERROR_INTERNAL;
} else {
g_variant_unref(reply);
}
_bt_audio_connect(pdata->req_id,
BT_AUDIO_A2DP,
&device_address,
- pdata->out_param);
+ NULL);
g_free(pdata->address);
g_free(pdata);
}
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);
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;
}
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);
_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 */
#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);
}
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 */
#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];
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
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;
+}
- /* Set disconnection type */
- __bt_set_headset_disconnection_type(connected_address);
+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;
+
+ 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;
}
}
connected_device = g_malloc0(sizeof(bt_connected_headset_data_t));
- /* Fix : NULL_RETURNS */
- if (connected_device == NULL) {
- BT_ERR("No memory allocated");
- return;
- }
connected_device->device_state = status;
if ((status == BT_STATE_CONNECTED) || (status == BT_STATE_CONNECTING))
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);
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);
int size;
int i;
int j;
- bluetooth_device_info_t info;
+ bluetooth_device_info_t *info;
char bond_address[BT_ADDRESS_STRING_SIZE] = { 0 };
gboolean ret = FALSE;
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);
+ 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;
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 };
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);
func_data = g_malloc0(sizeof(bt_audio_function_data_t));
- /* Fix : NULL_RETURNS */
- if (func_data == NULL) {
- result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
- goto fail;
- }
func_data->address = g_strdup(address);
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:
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;
- 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;
+ 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;
}
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);
/* 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 };
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));
- retv_if(func_data == NULL, BLUETOOTH_ERROR_INTERNAL);
-
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) {
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);
}
_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;
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;
GDBusProxy *adapter_proxy;
GDBusConnection *g_conn;
+ gboolean connected = FALSE;
int ret;
char *uuid;
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));
- /* Fix : NULL_RETURNS */
- if (func_data == NULL) {
- result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
+ /* 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);
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_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 };
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));
- /* Fix : NULL_RETURNS */
- if (func_data == NULL) {
- result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
- goto fail;
- }
-
func_data->address = g_strdup(address);
func_data->req_id = request_id;
uuid = g_strdup(HFP_AG_UUID);
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;
BT_DBG("+\n");
- conn = _bt_get_system_gconn();
+ conn = _bt_gdbus_get_system_gconn();
retv_if(conn == NULL, BLUETOOTH_ERROR_INTERNAL);
BT_DBG("Content Protection status = [%d]", status);
BT_DBG("Emit Signal done = [ProtectionRequired]");
return BLUETOOTH_ERROR_NONE;
}
+
+#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;
+
+ reply = g_dbus_proxy_call_finish(proxy, res, &err);
+ g_object_unref(proxy);
+ g_variant_unref(reply);
+
+ 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);
+}
+
+
+// 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;
+
+ 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);
+
+ if (result != BLUETOOTH_ERROR_NONE)
+ return TRUE;
+ else
+ auto_connect_timer.alarm_id = alarm_id;
+
+ return FALSE;
+}
+
+static int __bt_auto_connect_alarm_cb(alarm_id_t alarm_id, void* user_param)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ char *address = NULL;
+ alarm_id_t new_alarm_id;
+
+ BT_INFO("alram id = [%d] , retry_count [%d] ",
+ alarm_id, auto_connect_timer.retry_count);
+
+ if (alarm_id != auto_connect_timer.alarm_id)
+ return 0;
+
+ address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
+
+ if (address == NULL) {
+ BT_ERR("Address vconf is null");
+ auto_connect_timer.alarm_id = 0;
+ return 0;
+ }
+
+ BT_DBG("ADDRESS [%s]", address);
+
+ result = _bt_connect_profile(address, A2DP_SOURCE_UUID,
+ __bt_auto_connect_request_cb, NULL);
+
+ 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;
+ }
+
+ free(address);
+ return 0;
+}
+
+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)
+{
+ int result = BLUETOOTH_ERROR_NONE;
+ char *address = NULL;
+ alarm_id_t alarm_id = 0;
+
+ BT_DBG("");
+
+ address = vconf_get_str(BT_LAST_CONNECTED_DEVICE);
+
+ if (address == NULL) {
+ BT_ERR("No target device");
+ return 0;
+ }
+
+ __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;
+ }
+
+ free(address);
+ return BLUETOOTH_ERROR_NONE;
+}
+
+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 */