X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bt-service%2Fbt-service-audio.c;h=7dd091c6c86f88450155ef01935805a515a7b63a;hb=1fa07edcd0e77a445700975773db3300f556caf5;hp=ec9e9ab02ab8467d1e398f098eb0cb69b6fb39c8;hpb=41bfe957df119c7d3693451fe94b950bccf70904;p=platform%2Fcore%2Fconnectivity%2Fbluetooth-frwk.git diff --git a/bt-service/bt-service-audio.c b/bt-service/bt-service-audio.c index ec9e9ab..7dd091c 100644 --- a/bt-service/bt-service-audio.c +++ b/bt-service/bt-service-audio.c @@ -1,11 +1,5 @@ /* - * Bluetooth-frwk - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Hocheol Seo - * Girishashok Joshi - * Chanyeol Park + * 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. @@ -25,9 +19,10 @@ #include #include #include -#if !defined(LIBNOTIFY_SUPPORT) && !defined(LIBNOTIFICATION_SUPPORT) -#include +#ifdef TIZEN_BT_A2DP_SINK_AUTO_CONNECT +#include #endif +#include #include "bluetooth-api.h" #include "bt-internal-types.h" @@ -42,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 @@ -53,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; @@ -66,6 +70,10 @@ static void __bt_free_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) { @@ -95,11 +103,11 @@ static void __bt_hf_request_cb(GDBusProxy *proxy, GAsyncResult *res, 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); } @@ -137,7 +145,7 @@ void _bt_audio_check_pending_connect() _bt_audio_connect(pdata->req_id, BT_AUDIO_A2DP, &device_address, - pdata->out_param); + NULL); g_free(pdata->address); g_free(pdata); @@ -171,7 +179,6 @@ static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res, } 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); @@ -183,20 +190,16 @@ static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res, 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; } @@ -217,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); @@ -230,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 */ @@ -326,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); @@ -336,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 */ @@ -349,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]; @@ -365,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 @@ -396,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; } @@ -463,14 +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)); - /* Fix : NULL_RETURNS */ - if (connected_device == NULL) { - BT_ERR("No memory allocated"); - return; - } 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)); @@ -533,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); @@ -540,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); @@ -550,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; @@ -616,39 +668,43 @@ 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 }; 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: @@ -664,17 +720,46 @@ int _bt_audio_connect(int request_id, int type, 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; @@ -682,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); @@ -701,19 +791,25 @@ 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 }; @@ -723,24 +819,22 @@ int _bt_audio_disconnect(int request_id, int type, 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) { @@ -757,23 +851,31 @@ int _bt_audio_disconnect(int request_id, int 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); @@ -801,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; @@ -831,13 +936,14 @@ 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; GDBusProxy *adapter_proxy; GDBusConnection *g_conn; + gboolean connected = FALSE; int ret; char *uuid; @@ -851,19 +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)); - /* 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); @@ -881,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; @@ -892,7 +1003,7 @@ 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 }; @@ -913,19 +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)); - /* 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); @@ -942,10 +1047,13 @@ 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; @@ -958,7 +1066,7 @@ int _bt_audio_set_content_protect(gboolean status) 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); @@ -981,3 +1089,163 @@ int _bt_audio_set_content_protect(gboolean 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 */