Add the exception case for audio initialize
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / bluez_hal / src / bt-hal-a2dp-sink-dbus-handler.c
1 /*
2  * Bluetooth HAL
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Nilesh Trimbake <t.shripati@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 <stdio.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 #include <glib.h>
28 #include <gio/gio.h>
29 #include <dlog.h>
30 #include <vconf.h>
31
32 #include "bt-hal-a2dp-sink-dbus-handler.h"
33 #include "bt-hal-dbus-common-utils.h"
34 #include "bt-hal-internal.h"
35
36
37 static handle_stack_msg event_cb = NULL;
38
39 /* To send stack event to hal-a2dp-sink handler */
40 void _bt_hal_register_a2dp_sink_dbus_handler_cb(handle_stack_msg cb)
41 {
42         event_cb = cb;
43 }
44
45 /* To send stack event to hal-a2dp-sink handler */
46 void _bt_hal_unregister_a2dp_sink_dbus_handler_cb()
47 {
48         event_cb = NULL;
49 }
50
51 static void __bt_a2dp_sink_connect_cb(GDBusProxy *proxy, GAsyncResult *res,
52                 gpointer user_data)
53 {
54         GError *g_error = NULL;
55         struct hal_ev_a2dp_conn_state ev;
56         GVariant *reply = NULL;
57         char *address = user_data;
58         int result = BT_STATUS_SUCCESS;
59
60         DBG("+");
61
62         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
63         g_object_unref(proxy);
64         if (reply == NULL) {
65                 ERR("A2DP Source Connect Dbus Call Error");
66                 if (g_error) {
67                         ERR("Error: %s\n", g_error->message);
68                         g_clear_error(&g_error);
69                 }
70                 result = BT_STATUS_FAIL;
71         }
72         g_variant_unref(reply);
73
74         DBG("Address: %s", address);
75         /*
76          * If result is success, Send connecting event
77          */
78         if (result == BT_STATUS_SUCCESS) {
79                 /* Prepare to send A2DP Source connecting event */
80                 memset(&ev, 0, sizeof(ev));
81                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
82                 ev.state = HAL_EV_A2DP_STATE_CONNECTING;
83                 if (!event_cb)
84                         ERR("A2DP SINK DBUS handler callback not registered");
85                 else
86                         event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
87         } else {
88                 /* Prepare to send A2DP Source disconnected event */
89                 memset(&ev, 0, sizeof(ev));
90                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
91                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
92                 if (!event_cb)
93                         ERR("A2DP SINK DBUS handler callback not registered");
94                 else
95                         event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
96         }
97         g_free(address);
98 }
99
100 bt_status_t _bt_hal_dbus_handler_a2dp_sink_connect(bt_bdaddr_t *bd_addr)
101 {
102         char *address;
103         GDBusConnection *conn;
104
105         int ret;
106
107         if (!bd_addr) {
108                 ERR("bd_addr is NULL, return");
109                 return BT_STATUS_PARM_INVALID;
110         }
111
112         conn = _bt_hal_get_system_gconn();
113         if (!conn) {
114                 ERR("_bt_hal_get_system_gconn returned NULL, return");
115                 return BT_STATUS_FAIL;
116         }
117
118         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
119         if (!address) {
120                 ERR("Memory allocation failed");
121                 return BT_STATUS_NOMEM;
122         }
123         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
124
125         ret = _bt_hal_connect_profile(address, A2DP_SOURCE_UUID,
126                         __bt_a2dp_sink_connect_cb, address);
127
128         if (ret != BT_HAL_ERROR_NONE) {
129                 ERR("_bt_hal_connect_profile(A2DP source) Error");
130                 g_free(address);
131                 return BT_STATUS_FAIL;
132         }
133
134         return BT_STATUS_SUCCESS;
135 }
136
137 static void __bt_a2dp_source_disconnect_cb(GDBusProxy *proxy, GAsyncResult *res,
138                 gpointer user_data)
139 {
140         GError *g_error = NULL;
141         struct hal_ev_a2dp_conn_state ev;
142         GVariant *reply = NULL;
143         char *address = user_data;
144         int result = BT_STATUS_SUCCESS;
145
146         DBG("+");
147
148         reply = g_dbus_proxy_call_finish(proxy, res, &g_error);
149         g_object_unref(proxy);
150         if (reply == NULL) {
151                 ERR("A2DP Source Disconnect Dbus Call Error");
152                 if (g_error) {
153                         ERR("Error: %s\n", g_error->message);
154                         g_clear_error(&g_error);
155                 }
156                 result = BT_STATUS_FAIL;
157         }
158         g_variant_unref(reply);
159
160         if (result != BT_STATUS_FAIL)
161                 DBG("A2DP Source Disconnect successful for Device: %s", address);
162         else
163                 DBG("A2DP Source Disconnect un-successful for Device: %s", address);
164         if (result == BT_STATUS_FAIL) {
165                 /* Prepare to send AV source disconnected state event */
166                 memset(&ev, 0, sizeof(ev));
167                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
168                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTED;
169                 if (!event_cb)
170                         ERR("A2DP SINK DBUS handler callback not registered");
171                 else
172                         event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
173         } else {
174                 /* Prepare to send AV source disconnecting state event */
175                 memset(&ev, 0, sizeof(ev));
176                 _bt_hal_convert_addr_string_to_type(ev.bdaddr, address);
177                 ev.state = HAL_EV_A2DP_STATE_DISCONNECTING;
178                 if (!event_cb)
179                         ERR("A2DP SINK DBUS handler callback not registered");
180                 else
181                         event_cb(HAL_EV_A2DP_SOURCE_CONN_STATE, (void *)&ev, sizeof(ev));
182         }
183         g_free(address);
184         DBG("-");
185 }
186
187 bt_status_t _bt_hal_dbus_handler_a2dp_sink_disconnect(bt_bdaddr_t *bd_addr)
188 {
189         char *address;
190         GDBusConnection *conn;
191
192         int ret;
193
194         if (!bd_addr) {
195                 ERR("bd_addr is NULL, return");
196                 return BT_STATUS_PARM_INVALID;
197         }
198
199         conn = _bt_hal_get_system_gconn();
200         if (!conn) {
201                 ERR("_bt_hal_get_system_gconn returned NULL, return");
202                 return BT_STATUS_FAIL;
203         }
204
205         address = g_malloc0(BT_HAL_ADDRESS_STRING_SIZE * sizeof(char));
206         if (!address) {
207                 ERR("Memory allocation failed");
208                 return BT_STATUS_NOMEM;
209         }
210         _bt_hal_convert_addr_type_to_string(address, bd_addr->address);
211
212         ret = _bt_hal_disconnect_profile(address, A2DP_SOURCE_UUID,
213                         __bt_a2dp_source_disconnect_cb, address);
214
215         if (ret != BT_HAL_ERROR_NONE) {
216                 ERR("_bt_hal_connect_profile(AV) Error");
217                 return BT_STATUS_FAIL;
218         }
219
220         return BT_STATUS_SUCCESS;
221 }
222
223 bt_status_t _bt_hal_dbus_handler_enable_a2dp_sink(void)
224 {
225         GDBusProxy *proxy;
226         GVariant *ret;
227         GError *error = NULL;
228         gchar *adapter_path;
229         GDBusConnection *gconn;
230
231         DBG("+");
232
233         if (_bt_hal_is_service_enabled(A2DP_SINK_UUID)) {
234                 ERR("Audio sink role already enabled, return");
235                 return BT_STATUS_SUCCESS;
236         }
237
238         gconn = _bt_hal_get_system_gconn();
239         if (!gconn) {
240                 ERR("_bt_hal_get_system_gconn returned NULL, return");
241                 return BT_STATUS_FAIL;
242         }
243
244         adapter_path = _bt_hal_get_adapter_path();
245         if (!adapter_path) {
246                 ERR("adapter_path is NULL");
247                 return BT_STATUS_FAIL;
248         }
249
250         proxy = g_dbus_proxy_new_sync(gconn, G_DBUS_PROXY_FLAGS_NONE, NULL,
251                         BT_HAL_BLUEZ_NAME, adapter_path, BT_HAL_MEDIA_INTERFACE, NULL, &error);
252         g_free(adapter_path);
253         if (proxy == NULL) {
254                 ERR("Unable to create proxy");
255
256                 if (error) {
257                         ERR("Error: %s", error->message);
258                         g_clear_error(&error);
259                 }
260                 return BT_STATUS_FAIL;
261         }
262
263         ret = g_dbus_proxy_call_sync(proxy, "SelectRole", g_variant_new("(s)", "sink"),
264                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
265         g_object_unref(proxy);
266         if (ret == NULL) {
267                 ERR("Call SelectRole Failed");
268                 if (error) {
269                         g_dbus_error_strip_remote_error(error);
270
271                         ERR("message[%s]", error->message);
272
273                         /* Add the exception case for Already Exists */
274                         if (g_strrstr(error->message, "Already Exists")) {
275                                 g_clear_error(&error);
276                                 return BT_STATUS_SUCCESS;
277                         }
278
279                         g_clear_error(&error);
280                 }
281                 return BT_STATUS_FAIL;
282         }
283
284         g_variant_unref(ret);
285         DBG("-");
286         return BT_STATUS_SUCCESS;
287 }