Remove old bt-service files
[platform/core/connectivity/bluetooth-frwk.git] / bt-service / services / audio / a2dp_src / bt-service-a2dp-src.c
1 /*
2  * Bluetooth-frwk
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Anupam Roy <anupam.r@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *              http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 #include <sys/socket.h>
23 #include <sys/errno.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <vconf.h>
27
28 #include "oal-hardware.h"
29 #include "oal-device-mgr.h"
30 #include "oal-manager.h"
31 #include "oal-audio-src.h"
32
33 #include "bt-service-a2dp-src.h"
34 #include "bt-service-core-device.h"
35 #include "bt-service-event.h"
36 #include "bt-service-headset-connection.h"
37
38 int _bt_a2dp_connect_remote_sink(bluetooth_device_address_t *device_address)
39 {
40         oal_status_t status = OAL_STATUS_SUCCESS;
41         int result = BLUETOOTH_ERROR_NONE;
42         BT_INFO("+");
43
44         status = audio_connect((bt_address_t*)device_address);
45         if (status != OAL_STATUS_SUCCESS) {
46                 BT_ERR("Connection could not be established, err: [%d]", status);
47                 result = _bt_convert_oal_status_to_bt_error(status);
48         }
49         return result;
50 }
51
52 int _bt_a2dp_disconnect_remote_sink(bluetooth_device_address_t *device_address)
53 {
54         oal_status_t status = OAL_STATUS_SUCCESS;
55         int result = BLUETOOTH_ERROR_NONE;
56         BT_INFO("+");
57
58         status = audio_disconnect((bt_address_t*)device_address);
59         if (status != OAL_STATUS_SUCCESS) {
60                 BT_ERR("DisConnection err: [%d]", status);
61                 result = _bt_convert_oal_status_to_bt_error(status);
62         }
63         return result;
64 }
65
66 static void __bt_handle_av_connected_state(bluetooth_device_address_t *address)
67 {
68         char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
69         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
70         gboolean connected;
71         bt_headset_wait_t *wait_device = NULL;
72         bluetooth_device_address_t device_address;
73         bluetooth_device_address_t wait_device_address;
74         GVariant *param;
75
76         GArray *out_param;
77         invocation_info_t *req_info;
78         bt_pending_audio_conn_t *data = NULL;
79         guint trusted = TRUSTED_PROFILE_ALLOWED;
80
81         int result = BLUETOOTH_ERROR_NONE;
82         ret_if(NULL == address);
83
84         _bt_convert_addr_type_to_string(addr, address->addr);
85         BT_INFO("Address of connected device [%s]", addr + 12);
86
87         /* Set VCONF Key for A2DP Connected status */
88         _bt_set_device_values(TRUE, VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED);
89
90         /* Set readout notification of tts */
91 #ifdef TIZEN_FEATURE_READOUT_NOTIFICATION
92         _bt_set_readout_notification_of_tts();
93 #endif
94
95         /* Send A2DP(SRC Role) connected event to Application */
96         param = g_variant_new("(is)", result, addr);
97         _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_CONNECTED, param);
98         _bt_connection_manager_set_state(addr, BLUETOOTH_EVENT_AV_CONNECTED);
99
100         connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
101         if (connected) {
102                 BT_INFO("connected_address: %s", connected_address + 12);
103                 if (g_strcmp0(connected_address, addr) != 0) {
104                         _bt_convert_addr_string_to_type(
105                                         device_address.addr,
106                                         connected_address);
107                         _bt_audio_disconnect(BT_AUDIO_A2DP, &device_address);
108                 }
109         }
110
111         /* Add data from the connected list */
112         _bt_add_headset_to_list(BT_AUDIO_A2DP, BT_STATE_CONNECTED, addr);
113
114 #ifdef TIZEN_FEATURE_BT_AVC_TARGET
115         /* Send the information to Absolute Volume Controller */
116         _bt_audio_handle_a2dp_state_changed(addr, true);
117 #endif
118
119         /* Delete waiting device data if present */
120         wait_device = _bt_get_audio_wait_data();
121         if (wait_device != NULL &&
122                         (g_strcmp0(wait_device->address, addr) == 0))
123                 _bt_rel_wait_data();
124         else {
125                 if (wait_device != NULL) {
126                         BT_INFO("A2DP Profile connected for device [%s] but another device [%s]is waiting to be connnected type [%d]",
127                                         addr, wait_device->address + 12, wait_device->type);
128                         BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
129                                         wait_device->address + 12, wait_device->type);
130                         _bt_convert_addr_string_to_type(wait_device_address.addr,
131                                         wait_device->address);
132                         _bt_audio_connect(wait_device->type, &wait_device_address);
133                         /* Now free the wait list */
134                         //_bt_rel_wait_data();
135                 }
136         }
137
138         /* DBUS Context return */
139         req_info = _bt_get_request_info_data(BT_AV_CONNECT, addr);
140         if (NULL == req_info) {
141                 BT_INFO("AV Connect request not found or possibly already replied");
142                 req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, addr);
143
144                 if (req_info == NULL) {
145                         BT_INFO("AV Connect request & Audio All connect not found or possibly already replied");
146                         return;
147                 } else {
148                         BT_INFO("Audio All connect request found for address [%s]", addr + 12);
149                         /* TODO Delete the search info if present */
150                         data = _bt_get_pending_audio_conn_info(addr);
151                         if (data) {
152                                 BT_INFO("Audio Connect All request present and pending connect is also present, delete info");
153                                 _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, BLUETOOTH_ERROR_NONE);
154                                 return;
155                         } else {
156                                 BT_ERR("Abnormal: Audio Connect All request present but pending connect absent");
157                         }
158                 }
159         } else {
160                 BT_INFO("AV Connect request found for [%s]", addr);
161         }
162
163         out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
164         g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
165         _bt_service_method_return(req_info->context,
166                         out_param, result);
167         g_array_free(out_param, TRUE);
168         _bt_free_info_from_invocation_list(req_info);
169
170         _bt_get_trust_profile(address, TRUSTED_PROFILE_HFP_HF, &trusted);
171
172         if (_bt_headset_get_local_connection() == FALSE) {
173                 if (trusted == TRUSTED_PROFILE_ALLOWED) /* Trusted */
174                         _bt_start_timer_for_connection(addr, BT_AUDIO_HSP);
175         } else {
176                 /* Connection Started from local device therefore no need to
177                  * intiate connection for pending profile */
178                 _bt_headset_set_local_connection(FALSE);
179         }
180 }
181
182 static void __bt_handle_av_disconnected_state(bluetooth_device_address_t *address)
183 {
184         char addr[BT_ADDRESS_STRING_SIZE] = { 0 };
185         int result = BLUETOOTH_ERROR_NONE;
186         GArray *out_param;
187         bt_headset_wait_t *wait_device;
188         bluetooth_device_address_t device_address;
189         bt_pending_audio_conn_t *data = NULL;
190         GVariant *param;
191         invocation_info_t *req_info = NULL;
192         ret_if(NULL == address);
193
194         _bt_convert_addr_type_to_string(addr, address->addr);
195
196         /* Set VCONF status for A2DP Disconnection */
197         _bt_set_device_values(FALSE, VCONFKEY_BT_DEVICE_A2DP_HEADSET_CONNECTED);
198
199         /* Remove data from the connected list */
200         _bt_remove_headset_from_list(BT_AUDIO_A2DP, addr);
201
202 #ifdef TIZEN_FEATURE_BT_AVC_TARGET
203         /* Send the information to Absolute Volume Controller */
204         _bt_audio_handle_a2dp_state_changed(addr, false);
205 #endif
206
207         _bt_connection_manager_set_state(addr, BLUETOOTH_EVENT_AV_DISCONNECTED);
208
209         req_info = _bt_get_request_info_data(BT_AV_DISCONNECT, addr);
210         BT_DBG("Address  of disconnected device[%s]", addr);
211
212         if (NULL == req_info) {
213                 BT_DBG("AV DisConnect request not found or possibly already replied");
214                 req_info = _bt_get_request_info_data(BT_AV_CONNECT, addr);
215                 if (NULL == req_info) {
216                         /* This means, AV Disconnect request has successfully passed, and real disconnect is completed */
217                         BT_DBG("Neither AV Connect or AV Disconnect request is found..means, AV Profile is disconnected");
218
219                         req_info = _bt_get_request_info_data(BT_AUDIO_CONNECT, addr);
220                         if (req_info == NULL) {
221                                 BT_DBG("Audio Connect All request is also Not found..");
222
223                                 /* Send A2DP(SRC Role) disconnected event to Application */
224                                 param = g_variant_new("(is)", result, addr);
225                                 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_DISCONNECTED, param);
226
227                                 req_info = _bt_get_request_info_data(BT_AUDIO_DISCONNECT, addr);
228                                 if (req_info == NULL) {
229                                         BT_DBG("Audio DisConnect All request is also Not found..");
230                                 } else {
231                                         BT_DBG("Audio DisConnect All request is found..");
232                                         /* Check if HFP profile is also connected, if yes, disconnect it too */
233                                         _bt_audio_check_pending_disconnection(addr, BT_AUDIO_HSP);
234                                 }
235                         } else {
236                                 BT_DBG("Audio Connect All request is found..");
237                                 result = BLUETOOTH_ERROR_INTERNAL;
238                                 data = _bt_get_pending_audio_conn_info(addr);
239                                 if (data) {
240                                         BT_DBG("Pending connect is found, delete it..");
241                                         _bt_cleanup_audio_pending_conn_info_and_reply_pending_req(data, result);
242                                         req_info = NULL;
243                                 } else {
244                                         BT_DBG("Pending connect is Not found..");
245                                 }
246
247                                 /* Delete waiting device data if present for this device */
248                                 wait_device = _bt_get_audio_wait_data();
249                                 if (wait_device && strncasecmp(wait_device->address, addr, BT_ADDRESS_STRING_SIZE) == 0) {
250                                         _bt_rel_wait_data();
251                                         goto dbus_return;
252                                 }
253                         }
254                         goto check_wait_device;
255                 } else {
256                         BT_ERR("AV Connect request has failed.."); /* DBUS return needed */
257                         result = BLUETOOTH_ERROR_INTERNAL;
258                         /* Delete waiting device data if present for this device */
259                         wait_device = _bt_get_audio_wait_data();
260                         if (wait_device && strncasecmp(wait_device->address, addr, BT_ADDRESS_STRING_SIZE) == 0) {
261                                 _bt_rel_wait_data();
262                                 goto dbus_return;
263                         }
264
265                         goto check_wait_device;
266                 }
267         } else {
268                 BT_ERR("AV Disconnect request found for [%s], means disconnect request is successful", addr); /* DBUS return needed */
269                 /* Send A2DP(SRC Role) disconnected event to Application */
270                 param = g_variant_new("(is)", result, addr);
271                 _bt_send_event(BT_HEADSET_EVENT, BLUETOOTH_EVENT_AV_DISCONNECTED, param);
272                 goto check_wait_device;
273         }
274 check_wait_device:
275         wait_device = _bt_get_audio_wait_data();
276
277         if (wait_device == NULL)
278                 goto dbus_return;
279
280         BT_INFO("type: %d, ag_flag: %d, disconnection_type: %d", wait_device->type,
281                         wait_device->ag_flag, wait_device->disconnection_type);
282         if (((wait_device->type == BT_AUDIO_ALL) &&
283                                 (wait_device->ag_flag == TRUE)) ||
284                         (wait_device->type == BT_AUDIO_A2DP) ||
285                         (wait_device->disconnection_type & BT_AUDIO_A2DP)) {
286                 if (g_strcmp0(wait_device->address, addr) != 0) {
287                         BT_INFO("Trigger connect for the waiting device [%s], audio type [%d]",
288                                         wait_device->address, wait_device->type);
289                         _bt_convert_addr_string_to_type(device_address.addr,
290                                         wait_device->address);
291                         _bt_audio_connect(wait_device->type, &device_address);
292                         /* Now free the wait list */
293                         //_bt_rel_wait_data();
294                 }
295         }
296
297 dbus_return:
298         if (req_info) {
299                 out_param = g_array_new(FALSE, FALSE, sizeof(gchar));
300                 g_array_append_vals(out_param, addr, BT_ADDRESS_STRING_SIZE);
301                 _bt_service_method_return(req_info->context,
302                                 out_param, result);
303                 g_array_free(out_param, TRUE);
304                 _bt_free_info_from_invocation_list(req_info);
305         }
306 }
307
308 static void __bt_handle_av_audio_stopped(bluetooth_device_address_t *address)
309 {
310         BT_DBG("Currently not handled..");
311 }
312
313 static void __bt_handle_av_audio_started(bluetooth_device_address_t *address)
314 {
315         BT_DBG("Currently not handled..");
316 }
317
318 void _bt_a2dp_source_event_handler(int oal_event, gpointer event_data)
319 {
320         bluetooth_device_address_t * bd_addr = (bluetooth_device_address_t*)event_data;
321
322         switch (oal_event) {
323         case OAL_EVENT_AUDIO_CONNECTING:
324                 BT_INFO("A2DP Profile connecting..Ignore this event, wait for connected event");
325                 break;
326         case OAL_EVENT_AUDIO_DISCONNECTING:
327                 BT_INFO("A2DP Profile Disconnecting..Ignore this event, wait for Disconnected event");
328                 break;
329         case OAL_EVENT_AUDIO_CONNECTED:
330                 BT_INFO("A2DP Audio Profile connected..");
331                 __bt_handle_av_connected_state(bd_addr);
332                 BT_PERMANENT_LOG("Connected A2DP src");
333                 break;
334         case OAL_EVENT_AUDIO_DISCONNECTED:
335                 BT_INFO("A2DP Audio Profile dissconnected..");
336                 __bt_handle_av_disconnected_state(bd_addr);
337                 BT_PERMANENT_LOG("Disconnected A2DP src");
338                 break;
339         case OAL_EVENT_AUDIO_STOPPED:
340                 BT_INFO("A2DP Audio Stream stopped..");
341                 __bt_handle_av_audio_stopped(bd_addr);
342                 break;
343         case OAL_EVENT_AUDIO_STARTED:
344                 BT_INFO("A2DP Audio Stream started..");
345                 __bt_handle_av_audio_started(bd_addr);
346                 break;
347         default:
348                 BT_INFO("Invalid Event = %d", oal_event);
349                 break;
350         }
351 }
352
353 void _bt_a2dp_src_handle_incoming_authorization(char *address, int service_id)
354 {
355         char connected_address[BT_ADDRESS_STRING_SIZE + 1];
356         gboolean connected;
357         bluetooth_device_address_t device_address;
358         oal_status_t res = OAL_STATUS_SUCCESS;
359
360         _bt_convert_addr_string_to_type(device_address.addr, address);
361
362         switch (service_id) {
363         case A2DP_SERVICE_ID:
364                 connected = _bt_is_headset_type_connected(BT_AUDIO_A2DP, connected_address);
365                 if (connected) {
366                         BT_INFO("A2DP is already connected..check which device..");
367                         if (g_strcmp0(connected_address, address) != 0) {
368                                 BT_INFO("Different device is connected[%s] reject current [%s] device authorization request",
369                                                 connected_address, address);
370                                 res = device_reply_auth_request((bt_address_t*)&device_address, service_id, FALSE, FALSE);
371                                 if (res != OAL_STATUS_SUCCESS)
372                                         BT_ERR("authorize_response: %d", res);
373                                 return;
374                         }
375                 } else {
376                         res = device_reply_auth_request((bt_address_t*)&device_address, service_id, TRUE, FALSE);
377                         if (res != OAL_STATUS_SUCCESS)
378                                 BT_ERR("authorize_response: %d", res);
379                 }
380                 break;
381         default:
382                 BT_ERR("Invalid Audio Service ID..");
383         }
384
385 }