Fix the prevent issue
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / bt-service-audio.c
index 52856c4..171b96f 100644 (file)
 #include "bt-service-headset-connection.h"
 
 #ifdef TIZEN_SUPPORT_DUAL_HF
-#ifdef TIZEN_PROFILE_WEARABLE
 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
 #endif
-#endif
 
 typedef struct {
        unsigned int type;
@@ -168,7 +166,9 @@ static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
 
        reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
        g_object_unref(proxy);
-       g_variant_unref(reply);
+
+       if (reply)
+               g_variant_unref(reply);
 
        func_data = user_data;
 
@@ -208,12 +208,6 @@ static void __bt_audio_request_cb(GDBusProxy *proxy, GAsyncResult *res,
        }
 
 check_req_info:
-       req_info = _bt_get_request_info(func_data->req_id);
-       if (req_info == NULL) {
-               BT_ERR("req_info == NULL");
-               goto done;
-       }
-
        if (g_error == NULL)
                goto dbus_return;
 
@@ -243,8 +237,12 @@ check_req_info:
 
        /* Event will be sent by the event reciever */
 dbus_return:
-       if (req_info->context == NULL) {
-               BT_DBG("req_info->context is NULL");
+       req_info = _bt_get_request_info(func_data->req_id);
+       if (req_info == NULL) {
+               BT_ERR("req_info == NULL");
+               goto done;
+       } else if (req_info->context == NULL) {
+               BT_ERR("req_info->context is NULL");
                goto done;
        }
 
@@ -311,6 +309,41 @@ static void __bt_set_headset_disconnection_type(const char *address)
        }
 }
 
+#ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
+void _bt_check_already_connected_headset(int type, char *address)
+{
+       GList *node;
+       char connected_address[BT_ADDRESS_STRING_SIZE + 1];
+       bluetooth_device_address_t device_address;
+       int device_count = 0;
+
+       if (address != NULL) {
+               node = g_list_first(g_connected_list);
+               while (node != NULL) {
+                       bt_connected_headset_data_t *connected_device = node->data;
+                       if ((connected_device->type & type) &&
+                               (g_strcmp0(connected_device->device_address, address) != 0)) {
+                               device_count++;
+                               /* Disconnect the earliest(1st) connected headset */
+                               if (device_count == 1) {
+                                       g_strlcpy(connected_address,
+                                               connected_device->device_address,
+                                               BT_ADDRESS_STRING_SIZE + 1);
+                                       BT_DBG("Earliest/First Connected headset %s",
+                                               connected_address);
+                               } else if (device_count == MAX_CONNECTED_HEADSET) {
+                                       _bt_convert_addr_string_to_type(device_address.addr,
+                                               connected_address);
+                                       _bt_audio_disconnect(0, type, &device_address, NULL);
+                                       return;
+                               }
+                       }
+                       node = g_list_next(node);
+               }
+       }
+}
+#endif
+
 gboolean _bt_is_headset_type_connected(int type, char *address)
 {
        GList *node;
@@ -334,27 +367,27 @@ 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_PROFILE_WEARABLE
-       char *host_device_address = NULL;
-       host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
+       if (TIZEN_PROFILE_WEARABLE) {
+               char *host_device_address = NULL;
+               host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
 
-       if (!host_device_address) {
-               BT_INFO("Failed to get a companion device address");
-               return FALSE;
-       }
+               if (!host_device_address) {
+                       BT_INFO("Failed to get a companion device address");
+                       return FALSE;
+               }
+
+               if (g_strcmp0(host_device_address, addr) == 0) {
+                       BT_INFO("Found companion device");
+                       free(host_device_address);
+                       return TRUE;
+               }
 
-       if (g_strcmp0(host_device_address, addr) == 0) {
-               BT_INFO("Found companion device");
                free(host_device_address);
-               return TRUE;
+               return FALSE;
+       } else {
+               /* TODO : Need to add companion device check condition for Phone models */
+               return FALSE;
        }
-
-       free(host_device_address);
-       return FALSE;
-#else
-       /* TODO : Need to add companion device check condition for Phone models */
-       return FALSE;
-#endif
 }
 #endif
 
@@ -376,8 +409,19 @@ static int __bt_is_headset_connected(int type, int req_id,
        while (node != NULL) {
                connected_device = node->data;
                if ((connected_device->type & type)) {
+#ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
+                       device_count++;
+                       /* Disconnect the earliest(1st) connected headset */
+                       if (device_count == 1)
+                               g_strlcpy(connected_address, connected_device->device_address,
+                                       BT_ADDRESS_STRING_SIZE + 1);
+
+                       if (g_strcmp0(connected_device->device_address, address) == 0)
+                               return BLUETOOTH_ERROR_ALREADY_CONNECT;
+#else
                        g_strlcpy(connected_address, connected_device->device_address,
                                        BT_ADDRESS_STRING_SIZE + 1);
+#endif
 #ifdef TIZEN_SUPPORT_DUAL_HF
                        is_companion_device = __bt_is_companion_device(connected_address);
                        BT_INFO(" is_companion_device[%d]", is_companion_device);
@@ -387,15 +431,24 @@ static int __bt_is_headset_connected(int type, int req_id,
                                break;
                        }
 #else
+#ifdef TIZEN_BT_DUAL_HEADSET_CONNECT
+                       if (device_count == MAX_CONNECTED_HEADSET) {
+                               connected = TRUE;
+                               break;
+                       }
+#else
                        connected = TRUE;
                        break;
 #endif
+#endif
                }
                node = g_list_next(node);
        }
 
-       if (!connected)
+       if (!connected) {
+               __bt_free_wait_data();
                return BLUETOOTH_ERROR_NOT_CONNECTED;
+       }
 
        BT_DBG("connected headset %s", connected_address);
 
@@ -463,9 +516,9 @@ int __bt_is_headset_disconnecting(int type)
        node = g_list_first(g_connected_list);
        while (node != NULL) {
                connected_device = node->data;
-               if (connected_device->device_state == BT_STATE_DISCONNECTING) {
+               if (connected_device->device_state == BT_STATE_DISCONNECTING)
                        return BLUETOOTH_ERROR_CONNECTION_BUSY;
-               }
+
                node = g_list_next(node);
        }
 
@@ -513,12 +566,6 @@ 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) || (status == BT_STATE_CONNECTING))
                connected_device->type |= type;
@@ -683,8 +730,8 @@ int _bt_audio_connect(int request_id, int type,
        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;
+       guint hfp_hs_trusted = TRUE; /* set default "allowed" */
+       guint a2dp_trusted = TRUE;
 
        BT_CHECK_PARAMETER(device_address, return);
 
@@ -697,22 +744,16 @@ int _bt_audio_connect(int request_id, int type,
        _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;
 
-       result = _bt_get_restrict_profile(device_address, RESTRICTED_PROFILE_HFP_HS, &hfp_hs_restricted);
+       result = _bt_get_trust_profile(device_address, TRUSTED_PROFILE_HFP_HF, &hfp_hs_trusted);
        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);
+       result = _bt_get_trust_profile(device_address, TRUSTED_PROFILE_A2DP, &a2dp_trusted);
        if (result != BLUETOOTH_ERROR_NONE)
                BT_ERR("Can't get a2dp restriction info");
 
@@ -730,7 +771,7 @@ int _bt_audio_connect(int request_id, int type,
                uuid = A2DP_SOURCE_UUID;
                break;
        case BT_AUDIO_ALL:
-               if ((hfp_hs_restricted == 0x0) && (a2dp_restricted == 0x0)) { /* in case of both profiles are not restricted */
+               if ((hfp_hs_trusted == TRUE) && (a2dp_trusted == TRUE)) { /* 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;
@@ -743,11 +784,11 @@ int _bt_audio_connect(int request_id, int type,
                                result = BLUETOOTH_ERROR_SERVICE_NOT_FOUND;
                                goto fail;
                        }
-               } else if ((hfp_hs_restricted == 0x1) && (a2dp_restricted == 0x1)) { /* in case of both profiles are restricted */
+               } else if ((hfp_hs_trusted == FALSE) && (a2dp_trusted == FALSE)) { /* 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 */
+               } else if (a2dp_trusted == FALSE) { /* 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;
@@ -756,7 +797,7 @@ int _bt_audio_connect(int request_id, int type,
                                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 */
+               } else if (hfp_hs_trusted == FALSE) { /* 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;
@@ -776,17 +817,19 @@ int _bt_audio_connect(int request_id, int type,
                goto fail;
        }
        BT_INFO("Connecting to service %s", uuid);
+       /* First Check if device is in connecting state if it than return error */
+       value = __bt_is_headset_connecting(type);
+       if (value != BLUETOOTH_ERROR_NONE) {
+               result = BLUETOOTH_ERROR_IN_PROGRESS;
+               goto fail;
+       }
 
        value = __bt_is_headset_connected(type, request_id, address);
 
        if (value == BLUETOOTH_ERROR_ALREADY_CONNECT) {
-               return BLUETOOTH_ERROR_ALREADY_CONNECT;
+               result = BLUETOOTH_ERROR_ALREADY_CONNECT;
+               goto fail;
        } 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);
@@ -802,18 +845,19 @@ 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;
+               result = BLUETOOTH_ERROR_IN_PROGRESS;
+               goto fail;
        }
 
-       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,
                                BT_ADDRESS_STR_LEN);
 
+       g_free(func_data->address);
+       g_free(func_data);
+
        return result;
 }
 
@@ -842,12 +886,6 @@ int _bt_audio_disconnect(int request_id, int type,
        _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) {
-               BT_ERR("Memory allocation error");
-               result = BLUETOOTH_ERROR_MEMORY_ALLOCATION;
-               goto fail;
-       }
        func_data->address = g_strdup(address);
        func_data->req_id = request_id;
        func_data->pending = BT_PENDING_NONE;
@@ -919,15 +957,15 @@ 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,
                                BT_ADDRESS_STR_LEN);
 
+       g_free(func_data->address);
+       g_free(func_data);
+
        return result;
 }
 
@@ -988,12 +1026,6 @@ int _bt_hf_connect(int request_id,
        }
 
        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);
@@ -1053,12 +1085,6 @@ int _bt_hf_disconnect(int request_id,
        }
 
        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);
@@ -1075,8 +1101,6 @@ 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:
@@ -1241,11 +1265,11 @@ int _bt_audio_start_auto_connect(gboolean 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) {
+               if (result != BLUETOOTH_ERROR_NONE)
                        g_timeout_add(500, (GSourceFunc)__bt_audio_alarm_retry_cb, NULL);
-               } else {
+               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,
@@ -1277,3 +1301,56 @@ void _bt_audio_set_auto_connect_device_addr(const char *address)
        vconf_set_str(BT_LAST_CONNECTED_DEVICE, address);
 }
 #endif /*TIZEN_BT_A2DP_SINK_AUTO_CONNECT */
+
+int _bt_audio_select_role(bluetooth_audio_role_t role)
+{
+
+       GDBusProxy *proxy;
+       GVariant *ret;
+       GError *error = NULL;
+       GDBusConnection *g_conn = _bt_gdbus_get_system_gconn();
+       gchar *adapter_path = _bt_get_adapter_path();
+
+       BT_INFO("_bt_audio_select_role called [%d]", role);
+
+       retv_if(adapter_path == NULL, BLUETOOTH_ERROR_INTERNAL);
+       BT_INFO("Adapter Path = %s", adapter_path);
+
+       proxy = g_dbus_proxy_new_sync(g_conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
+               BT_BLUEZ_NAME, adapter_path, BT_MEDIA_INTERFACE, NULL, &error);
+
+       g_free(adapter_path);
+
+       if (proxy == NULL) {
+               BT_ERR("Unable to create proxy");
+
+               if (error) {
+                       BT_ERR("Error: %s", error->message);
+                       g_clear_error(&error);
+               }
+
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       if (role == BLUETOOTH_A2DP_SOURCE)
+               ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "source"),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+       else
+               ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "sink"),
+                       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+       g_object_unref(proxy);
+
+       if (ret == NULL) {
+               BT_ERR("Call SelectRole Failed");
+               if (error) {
+                       BT_ERR("errCode[%x], message[%s]", error->code, error->message);
+                       g_clear_error(&error);
+               }
+
+               return BLUETOOTH_ERROR_INTERNAL;
+       }
+
+       g_variant_unref(ret);
+       return BLUETOOTH_ERROR_NONE;
+}