blob: 8b7b6bfd3aaa85fa02b956d6a993bf307c2e9a0a [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
3 * Copyright (C) 2009-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/*****************************************************************************
20 *
21 * Filename: audio_a2dp_hw.c
22 *
23 * Description: Implements hal for bluedroid a2dp audio device
24 *
25 *****************************************************************************/
rakesh reddy03b63652014-08-14 11:58:45 +053026#define ATRACE_TAG ATRACE_TAG_ALWAYS
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -070027
The Android Open Source Project5738f832012-12-12 16:00:35 -080028#include <errno.h>
Mark Salyzyn40421cb2014-04-17 13:45:20 -070029#include <inttypes.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080030#include <pthread.h>
31#include <stdint.h>
32#include <sys/time.h>
33#include <sys/socket.h>
34#include <sys/un.h>
35#include <sys/poll.h>
36#include <sys/errno.h>
37#include <sys/stat.h>
38#include <unistd.h>
39#include <fcntl.h>
40#include <cutils/str_parms.h>
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -070041#include <cutils/properties.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080042#include <cutils/sockets.h>
43
44#include <system/audio.h>
45#include <hardware/audio.h>
46
47#include <hardware/hardware.h>
48#include "audio_a2dp_hw.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080049#include "bt_utils.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080050
rakesh reddy03b63652014-08-14 11:58:45 +053051
52
The Android Open Source Project5738f832012-12-12 16:00:35 -080053#define LOG_TAG "audio_a2dp_hw"
54/* #define LOG_NDEBUG 0 */
Mark Salyzyn40421cb2014-04-17 13:45:20 -070055#include <log/log.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080056
rakesh reddy03b63652014-08-14 11:58:45 +053057#include <cutils/trace.h>
rakesh reddy03b63652014-08-14 11:58:45 +053058
rakesh reddy03b63652014-08-14 11:58:45 +053059
rakesh reddy03b63652014-08-14 11:58:45 +053060FILE *outputpcmsamplefile;
61char btoutputfilename [50] = "/data/audio/output_sample";
62static int number =0;
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -080063static int perf_systrace_log_enabled=0;
64static int audio_sample_log_enabled=0;
rakesh reddy03b63652014-08-14 11:58:45 +053065
The Android Open Source Project5738f832012-12-12 16:00:35 -080066/*****************************************************************************
67** Constants & Macros
68******************************************************************************/
69
70#define CTRL_CHAN_RETRY_COUNT 3
71#define USEC_PER_SEC 1000000L
72
73#define CASE_RETURN_STR(const) case const: return #const;
74
75#define FNLOG() ALOGV("%s", __FUNCTION__);
76#define DEBUG(fmt, ...) ALOGV("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
77#define INFO(fmt, ...) ALOGI("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
78#define ERROR(fmt, ...) ALOGE("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
79
80#define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
81
82/*****************************************************************************
83** Local type definitions
84******************************************************************************/
85
86typedef enum {
87 AUDIO_A2DP_STATE_STARTING,
88 AUDIO_A2DP_STATE_STARTED,
89 AUDIO_A2DP_STATE_STOPPING,
90 AUDIO_A2DP_STATE_STOPPED,
91 AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */
92 AUDIO_A2DP_STATE_STANDBY /* allows write to autoresume */
93} a2dp_state_t;
94
Mike Lockwood3e8a2422014-05-23 12:42:24 -070095struct a2dp_stream_in;
The Android Open Source Project5738f832012-12-12 16:00:35 -080096struct a2dp_stream_out;
97
98struct a2dp_audio_device {
99 struct audio_hw_device device;
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700100 struct a2dp_stream_in *input;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800101 struct a2dp_stream_out *output;
102};
103
104struct a2dp_config {
105 uint32_t rate;
106 uint32_t channel_flags;
107 int format;
108};
109
110/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
111
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700112struct a2dp_stream_common {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800113 pthread_mutex_t lock;
114 int ctrl_fd;
115 int audio_fd;
116 size_t buffer_sz;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800117 struct a2dp_config cfg;
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700118 a2dp_state_t state;
119};
120
121struct a2dp_stream_out {
122 struct audio_stream_out stream;
123 struct a2dp_stream_common common;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800124};
125
126struct a2dp_stream_in {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700127 struct audio_stream_in stream;
128 struct a2dp_stream_common common;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800129};
130
131/*****************************************************************************
132** Static variables
133******************************************************************************/
134
135/*****************************************************************************
136** Static functions
137******************************************************************************/
138
139static size_t out_get_buffer_size(const struct audio_stream *stream);
140
141/*****************************************************************************
142** Externs
143******************************************************************************/
144
145/*****************************************************************************
146** Functions
147******************************************************************************/
148
149/*****************************************************************************
150** Miscellaneous helper functions
151******************************************************************************/
152
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700153int perf_systrace_enabled() {
154 char value[PROPERTY_VALUE_MAX] = {'\0'};
155 property_get("bt_audio_systrace_log", value, "false");
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800156 perf_systrace_log_enabled = (strcmp(value, "true") == 0);
157 return perf_systrace_log_enabled;
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700158}
159
160int audio_sample_logging_enabled() {
161 char value[PROPERTY_VALUE_MAX] = {'\0'};
162 property_get("bt_audio_sample_log", value, "false");
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800163 audio_sample_log_enabled = (strcmp(value, "true") == 0);
164 return audio_sample_log_enabled;
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700165}
166
167
The Android Open Source Project5738f832012-12-12 16:00:35 -0800168static const char* dump_a2dp_ctrl_event(char event)
169{
170 switch(event)
171 {
172 CASE_RETURN_STR(A2DP_CTRL_CMD_NONE)
173 CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY)
174 CASE_RETURN_STR(A2DP_CTRL_CMD_START)
175 CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
176 CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
Rohit Singha9fb00a2013-07-27 14:46:29 +0530177 CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_STREAM_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800178 default:
179 return "UNKNOWN MSG ID";
180 }
181}
182
rakesh reddy03b63652014-08-14 11:58:45 +0530183static int calc_audiotime(struct a2dp_config cfg, int bytes)
184{
185 int chan_count = popcount(cfg.channel_flags);
186
187 ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT,
188 "unsupported sample sz", cfg.format);
189
190 return bytes*(1000000/(chan_count*2))/cfg.rate;
191}
192
193static void ts_error_log(char *tag, int val, int buff_size, struct a2dp_config cfg)
194{
195 struct timespec now;
196 static struct timespec prev = {0,0};
197 unsigned long long now_us;
198 unsigned long long diff_us;
199
200 clock_gettime(CLOCK_MONOTONIC, &now);
201
202 now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
203
204 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
205 prev = now;
206 if(diff_us > (calc_audiotime (cfg, buff_size) + 10000L))
207 {
208 ERROR("[%s] ts %08lld, diff %08lld, val %d %d", tag, now_us, diff_us, val, buff_size);
209 }
210}
211
The Android Open Source Project5738f832012-12-12 16:00:35 -0800212/* logs timestamp with microsec precision
213 pprev is optional in case a dedicated diff is required */
214static void ts_log(char *tag, int val, struct timespec *pprev_opt)
215{
216 struct timespec now;
217 static struct timespec prev = {0,0};
218 unsigned long long now_us;
219 unsigned long long diff_us;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800220 UNUSED(tag);
221 UNUSED(val);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800222
223 clock_gettime(CLOCK_MONOTONIC, &now);
224
225 now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
226
227 if (pprev_opt)
228 {
229 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
230 *pprev_opt = now;
231 DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
232 }
233 else
234 {
235 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
236 prev = now;
237 DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
238 }
239}
240
rakesh reddy03b63652014-08-14 11:58:45 +0530241
242static const char* dump_a2dp_hal_state(int event)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800243{
rakesh reddy03b63652014-08-14 11:58:45 +0530244 switch(event)
245 {
246 CASE_RETURN_STR(AUDIO_A2DP_STATE_STARTING)
247 CASE_RETURN_STR(AUDIO_A2DP_STATE_STARTED)
248 CASE_RETURN_STR(AUDIO_A2DP_STATE_STOPPING)
249 CASE_RETURN_STR(AUDIO_A2DP_STATE_STOPPED)
250 CASE_RETURN_STR(AUDIO_A2DP_STATE_SUSPENDED)
251 CASE_RETURN_STR(AUDIO_A2DP_STATE_STANDBY)
252 default:
253 return "UNKNOWN STATE ID";
254 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800255}
The Android Open Source Project5738f832012-12-12 16:00:35 -0800256/*****************************************************************************
257**
258** bluedroid stack adaptation
259**
260*****************************************************************************/
261
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700262static int skt_connect(char *path, size_t buffer_sz)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800263{
264 int ret;
265 int skt_fd;
266 struct sockaddr_un remote;
267 int len;
268
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700269 INFO("connect to %s (sz %zu)", path, buffer_sz);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800270
271 skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
272
273 if(socket_local_client_connect(skt_fd, path,
274 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
275 {
276 ERROR("failed to connect (%s)", strerror(errno));
277 close(skt_fd);
278 return -1;
279 }
280
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700281 len = buffer_sz;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800282 ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
283
284 /* only issue warning if failed */
285 if (ret < 0)
286 ERROR("setsockopt failed (%s)", strerror(errno));
287
Mike Lockwoodb1c8fcc2014-07-11 12:05:04 -0700288 ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len));
289
290 /* only issue warning if failed */
291 if (ret < 0)
292 ERROR("setsockopt failed (%s)", strerror(errno));
293
The Android Open Source Project5738f832012-12-12 16:00:35 -0800294 INFO("connected to stack fd = %d", skt_fd);
295
296 return skt_fd;
297}
298
Mike Lockwoodb1c8fcc2014-07-11 12:05:04 -0700299static int skt_read(int fd, void *p, size_t len)
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700300{
301 int read;
302 struct pollfd pfd;
303 struct timespec ts;
304
305 FNLOG();
306
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700307 ts_log("skt_read recv", len, NULL);
308
309 if ((read = recv(fd, p, len, MSG_NOSIGNAL)) == -1)
310 {
311 ERROR("write failed with errno=%d\n", errno);
312 return -1;
313 }
314
315 return read;
316}
317
The Android Open Source Project5738f832012-12-12 16:00:35 -0800318static int skt_write(int fd, const void *p, size_t len)
319{
320 int sent;
321 struct pollfd pfd;
322
323 FNLOG();
324
325 pfd.fd = fd;
326 pfd.events = POLLOUT;
327
328 /* poll for 500 ms */
329
330 /* send time out */
331 if (poll(&pfd, 1, 500) == 0)
332 return 0;
333
334 ts_log("skt_write", len, NULL);
335
336 if ((sent = send(fd, p, len, MSG_NOSIGNAL)) == -1)
337 {
338 ERROR("write failed with errno=%d\n", errno);
339 return -1;
340 }
341
342 return sent;
343}
344
345static int skt_disconnect(int fd)
346{
347 INFO("fd %d", fd);
348
349 if (fd != AUDIO_SKT_DISCONNECTED)
350 {
351 shutdown(fd, SHUT_RDWR);
352 close(fd);
353 }
354 return 0;
355}
356
357
358
359/*****************************************************************************
360**
361** AUDIO CONTROL PATH
362**
363*****************************************************************************/
364
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700365static int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length)
366{
367 int ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL);
368 if (ret < 0)
369 {
370 ERROR("ack failed (%s)", strerror(errno));
371 if (errno == EINTR)
372 {
373 /* retry again */
374 ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL);
375 if (ret < 0)
376 {
377 ERROR("ack failed (%s)", strerror(errno));
378 skt_disconnect(common->ctrl_fd);
379 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
380 return -1;
381 }
382 }
383 else
384 {
385 skt_disconnect(common->ctrl_fd);
386 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
387 return -1;
388
389 }
390 }
391 return ret;
392}
393
Ethan Chendec61cd2015-02-13 18:26:44 -0800394static int a2dp_command(struct a2dp_stream_common *common, char cmd)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800395{
396 char ack;
397
rakesh reddy03b63652014-08-14 11:58:45 +0530398 INFO("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800399
400 /* send command */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700401 if (send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800402 {
403 ERROR("cmd failed (%s)", strerror(errno));
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700404 skt_disconnect(common->ctrl_fd);
405 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800406 return -1;
407 }
408
409 /* wait for ack byte */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700410 if (a2dp_ctrl_receive(common, &ack, 1) < 0)
411 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800412
rakesh reddy03b63652014-08-14 11:58:45 +0530413 INFO("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800414
Rohit Singha9fb00a2013-07-27 14:46:29 +0530415 if (ack == A2DP_CTRL_ACK_INCALL_FAILURE)
416 {
417 return ack;
418 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800419 if (ack != A2DP_CTRL_ACK_SUCCESS)
420 return -1;
421
422 return 0;
423}
424
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700425static int check_a2dp_ready(struct a2dp_stream_common *common)
426{
rakesh reddy03b63652014-08-14 11:58:45 +0530427 INFO("state %s", dump_a2dp_hal_state(common->state));
428
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700429 if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0)
430 {
431 ERROR("check a2dp ready failed");
432 return -1;
433 }
434 return 0;
435}
436
437static int a2dp_read_audio_config(struct a2dp_stream_common *common)
438{
439 char cmd = A2DP_CTRL_GET_AUDIO_CONFIG;
440 uint32_t sample_rate;
441 uint8_t channel_count;
442
443 if (a2dp_command(common, A2DP_CTRL_GET_AUDIO_CONFIG) < 0)
444 {
445 ERROR("check a2dp ready failed");
446 return -1;
447 }
448
449 if (a2dp_ctrl_receive(common, &sample_rate, 4) < 0)
450 return -1;
451 if (a2dp_ctrl_receive(common, &channel_count, 1) < 0)
452 return -1;
453
454 common->cfg.channel_flags = (channel_count == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO);
455 common->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
456 common->cfg.rate = sample_rate;
457
458 INFO("got config %d %d", common->cfg.format, common->cfg.rate);
459
460 return 0;
461}
462
463static void a2dp_open_ctrl_path(struct a2dp_stream_common *common)
464{
465 int i;
466
467 /* retry logic to catch any timing variations on control channel */
468 for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++)
469 {
470 /* connect control channel if not already connected */
471 if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0)
472 {
473 /* success, now check if stack is ready */
474 if (check_a2dp_ready(common) == 0)
475 break;
476
477 ERROR("error : a2dp not ready, wait 250 ms and retry");
478 usleep(250000);
479 skt_disconnect(common->ctrl_fd);
480 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
481 }
482
483 /* ctrl channel not ready, wait a bit */
484 usleep(250000);
485 }
486}
487
The Android Open Source Project5738f832012-12-12 16:00:35 -0800488/*****************************************************************************
489**
490** AUDIO DATA PATH
491**
492*****************************************************************************/
493
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700494static void a2dp_stream_common_init(struct a2dp_stream_common *common)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800495{
496 pthread_mutexattr_t lock_attr;
497
498 FNLOG();
499
500 pthread_mutexattr_init(&lock_attr);
501 pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700502 pthread_mutex_init(&common->lock, &lock_attr);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800503
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700504 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
505 common->audio_fd = AUDIO_SKT_DISCONNECTED;
506 common->state = AUDIO_A2DP_STATE_STOPPED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800507
508 /* manages max capacity of socket pipe */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700509 common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800510}
511
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700512static int start_audio_datapath(struct a2dp_stream_common *common)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800513{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700514 int oldstate = common->state;
Rohit Singha9fb00a2013-07-27 14:46:29 +0530515 int a2dp_status;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800516
rakesh reddy03b63652014-08-14 11:58:45 +0530517 INFO("state %s", dump_a2dp_hal_state(common->state));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800518
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700519 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
520 INFO("AUDIO_SKT_DISCONNECTED");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800521 return -1;
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700522 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800523
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800524 if (perf_systrace_log_enabled)
rakesh reddy03b63652014-08-14 11:58:45 +0530525 {
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700526 char trace_buf[512];
527 snprintf(trace_buf, 32, "start_audio_data_path:");
rakesh reddy03b63652014-08-14 11:58:45 +0530528 ATRACE_BEGIN(trace_buf);
529 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800530
rakesh reddy03b63652014-08-14 11:58:45 +0530531 common->state = AUDIO_A2DP_STATE_STARTING;
Rohit Singha9fb00a2013-07-27 14:46:29 +0530532 a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START);
rakesh reddy03b63652014-08-14 11:58:45 +0530533
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800534 if (perf_systrace_log_enabled)
rakesh reddy03b63652014-08-14 11:58:45 +0530535 {
536 ATRACE_END();
537 }
rakesh reddy03b63652014-08-14 11:58:45 +0530538
Rohit Singha9fb00a2013-07-27 14:46:29 +0530539 if (a2dp_status < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800540 {
541 ERROR("audiopath start failed");
542
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700543 common->state = oldstate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800544 return -1;
545 }
Rohit Singha9fb00a2013-07-27 14:46:29 +0530546 else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE)
547 {
548 ERROR("audiopath start failed- In call a2dp, move to suspended");
549 common->state = AUDIO_A2DP_STATE_SUSPENDED;
550 return -1;
551 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800552
553 /* connect socket if not yet connected */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700554 if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800555 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700556 common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);
557 if (common->audio_fd < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800558 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700559 common->state = oldstate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800560 return -1;
561 }
562
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700563 common->state = AUDIO_A2DP_STATE_STARTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800564 }
565
566 return 0;
567}
568
569
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -0500570static int stop_audio_datapath(struct a2dp_stream_common *common, bool stay_suspended)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800571{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700572 int oldstate = common->state;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800573
rakesh reddy03b63652014-08-14 11:58:45 +0530574 INFO("state %s", dump_a2dp_hal_state(common->state));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800575
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700576 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800577 return -1;
578
579 /* prevent any stray output writes from autostarting the stream
580 while stopping audiopath */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700581 common->state = AUDIO_A2DP_STATE_STOPPING;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800582
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700583 if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800584 {
585 ERROR("audiopath stop failed");
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700586 common->state = oldstate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800587 return -1;
588 }
589
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -0500590 if (!stay_suspended || common->state != AUDIO_A2DP_STATE_SUSPENDED)
591 common->state = AUDIO_A2DP_STATE_STOPPED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800592
593 /* disconnect audio path */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700594 skt_disconnect(common->audio_fd);
595 common->audio_fd = AUDIO_SKT_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800596
597 return 0;
598}
599
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700600static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800601{
rakesh reddy03b63652014-08-14 11:58:45 +0530602 INFO("state %s", dump_a2dp_hal_state(common->state));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800603
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700604 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800605 return -1;
606
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700607 if (common->state == AUDIO_A2DP_STATE_STOPPING)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800608 return -1;
609
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700610 if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800611 return -1;
612
613 if (standby)
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700614 common->state = AUDIO_A2DP_STATE_STANDBY;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800615 else
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700616 common->state = AUDIO_A2DP_STATE_SUSPENDED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800617
618 /* disconnect audio path */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700619 skt_disconnect(common->audio_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800620
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700621 common->audio_fd = AUDIO_SKT_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800622
623 return 0;
624}
625
The Android Open Source Project5738f832012-12-12 16:00:35 -0800626
Rohit Singha9fb00a2013-07-27 14:46:29 +0530627static int check_a2dp_stream_started(struct a2dp_stream_out *out)
628{
629 if (a2dp_command(&out->common, A2DP_CTRL_CMD_CHECK_STREAM_STARTED) < 0)
630 {
rakesh reddy03b63652014-08-14 11:58:45 +0530631 INFO("Btif not in stream state");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530632 return -1;
633 }
634 return 0;
635}
636
637
The Android Open Source Project5738f832012-12-12 16:00:35 -0800638/*****************************************************************************
639**
640** audio output callbacks
641**
642*****************************************************************************/
643
644static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
645 size_t bytes)
646{
647 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
648 int sent;
649
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700650 DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800651
Rohit Singha9fb00a2013-07-27 14:46:29 +0530652 pthread_mutex_lock(&out->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700653 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800654 {
rakesh reddy03b63652014-08-14 11:58:45 +0530655 INFO("stream suspended");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530656 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800657 return -1;
658 }
659
660 /* only allow autostarting if we are in stopped or standby */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700661 if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
662 (out->common.state == AUDIO_A2DP_STATE_STANDBY))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800663 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800664
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700665 if (start_audio_datapath(&out->common) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800666 {
667 /* emulate time this write represents to avoid very fast write
668 failures during transition periods or remote suspend */
669
Ethan Chendec61cd2015-02-13 18:26:44 -0800670 int us_delay = calc_audiotime(out->common.cfg, bytes);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800671
rakesh reddy03b63652014-08-14 11:58:45 +0530672 ERROR("emulate a2dp write delay (%d us)", us_delay);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800673
674 usleep(us_delay);
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700675 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800676 return -1;
677 }
678
The Android Open Source Project5738f832012-12-12 16:00:35 -0800679 }
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700680 else if (out->common.state != AUDIO_A2DP_STATE_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800681 {
682 ERROR("stream not in stopped or standby");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530683 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800684 return -1;
685 }
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700686
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800687 if (audio_sample_log_enabled) {
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700688 if (outputpcmsamplefile)
689 {
690 fwrite (buffer,1,bytes,outputpcmsamplefile);
691 }
rakesh reddy03b63652014-08-14 11:58:45 +0530692 }
repo Shareef Ali619b3ed2014-12-29 00:48:01 -0600693#if 0
rakesh reddy03b63652014-08-14 11:58:45 +0530694 ts_error_log("a2dp_out_write", bytes, out->common.buffer_sz, out->common.cfg);
repo Shareef Ali619b3ed2014-12-29 00:48:01 -0600695#endif
Rohit Singha9fb00a2013-07-27 14:46:29 +0530696 pthread_mutex_unlock(&out->common.lock);
697
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800698 if (perf_systrace_log_enabled)
rakesh reddy03b63652014-08-14 11:58:45 +0530699 {
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700700 char trace_buf[512];
701 snprintf(trace_buf, 32, "out_write:");
rakesh reddy03b63652014-08-14 11:58:45 +0530702 ATRACE_BEGIN(trace_buf);
703 }
rakesh reddy03b63652014-08-14 11:58:45 +0530704
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700705 sent = skt_write(out->common.audio_fd, buffer, bytes);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800706
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800707 if (perf_systrace_log_enabled)
rakesh reddy03b63652014-08-14 11:58:45 +0530708 {
709 ATRACE_END();
710 }
rakesh reddy03b63652014-08-14 11:58:45 +0530711
The Android Open Source Project5738f832012-12-12 16:00:35 -0800712 if (sent == -1)
713 {
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -0500714 pthread_mutex_lock(&out->common.lock);
715
716 stop_audio_datapath(&out->common, true);
717
718 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800719 }
720
Mark Salyzyn40421cb2014-04-17 13:45:20 -0700721 DEBUG("wrote %d bytes out of %zu bytes", sent, bytes);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800722 return sent;
723}
724
Ethan Chendec61cd2015-02-13 18:26:44 -0800725
The Android Open Source Project5738f832012-12-12 16:00:35 -0800726static uint32_t out_get_sample_rate(const struct audio_stream *stream)
727{
728 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
729
Ethan Chendec61cd2015-02-13 18:26:44 -0800730 INFO("rate %" PRIu32,out->common.cfg.rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800731
Ethan Chendec61cd2015-02-13 18:26:44 -0800732 return out->common.cfg.rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800733}
734
735static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
736{
737 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
738
rakesh reddy03b63652014-08-14 11:58:45 +0530739 INFO("out_set_sample_rate : %" PRIu32, rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800740
Ethan Chendec61cd2015-02-13 18:26:44 -0800741 if (rate != AUDIO_STREAM_DEFAULT_RATE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800742 {
Ethan Chendec61cd2015-02-13 18:26:44 -0800743 ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800744 return -1;
745 }
746
Ethan Chendec61cd2015-02-13 18:26:44 -0800747 out->common.cfg.rate = rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800748
749 return 0;
750}
751
752static size_t out_get_buffer_size(const struct audio_stream *stream)
753{
754 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
755
Dan Pasanen90e9df12014-12-31 21:13:05 -0600756 DEBUG("buffer_size : %zu", out->common.buffer_sz);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800757
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700758 return out->common.buffer_sz;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800759}
760
761static uint32_t out_get_channels(const struct audio_stream *stream)
762{
763 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
764
Ethan Chendec61cd2015-02-13 18:26:44 -0800765 INFO("channels 0x%" PRIx32, out->common.cfg.channel_flags);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800766
Ethan Chendec61cd2015-02-13 18:26:44 -0800767 return out->common.cfg.channel_flags;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800768}
769
770static audio_format_t out_get_format(const struct audio_stream *stream)
771{
772 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
Ethan Chendec61cd2015-02-13 18:26:44 -0800773 INFO("format 0x%x", out->common.cfg.format);
774 return out->common.cfg.format;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800775}
776
777static int out_set_format(struct audio_stream *stream, audio_format_t format)
778{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800779 UNUSED(format);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800780 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
rakesh reddy03b63652014-08-14 11:58:45 +0530781 INFO("setting format not yet supported (0x%x)", format);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800782 return -ENOSYS;
783}
784
785static int out_standby(struct audio_stream *stream)
786{
787 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800788 int retVal = 0;
789
790 FNLOG();
791
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700792 pthread_mutex_lock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800793
Rohit Singha9fb00a2013-07-27 14:46:29 +0530794 /*Need not check State here as btif layer does
795 check of btif state , during remote initited suspend
796 DUT need to clear flag else start will not happen but
797 Do nothing in SUSPENDED state. */
798 if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700799 retVal = suspend_audio_datapath(&out->common, true);
Rohit Singha9fb00a2013-07-27 14:46:29 +0530800
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700801 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800802
803 return retVal;
804}
805
806static int out_dump(const struct audio_stream *stream, int fd)
807{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800808 UNUSED(fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800809 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
810 FNLOG();
811 return 0;
812}
813
814static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
815{
816 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
817 struct str_parms *parms;
818 char keyval[16];
xuxy050626765b82015-09-16 10:06:34 +0800819 int retval;
820 int status = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800821
Ethan Chendec61cd2015-02-13 18:26:44 -0800822 INFO("state %d", out->common.state);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800823
The Android Open Source Project5738f832012-12-12 16:00:35 -0800824 parms = str_parms_create_str(kvpairs);
825
Amit Goel85a35032014-07-31 20:14:27 -0700826 if(!parms)
827 {
828 ERROR("parms is NULL");
829 return retval;
830 }
831
The Android Open Source Project5738f832012-12-12 16:00:35 -0800832 /* dump params */
833 str_parms_dump(parms);
834
835 retval = str_parms_get_str(parms, "closing", keyval, sizeof(keyval));
836
837 if (retval >= 0)
838 {
839 if (strcmp(keyval, "true") == 0)
840 {
841 DEBUG("stream closing, disallow any writes");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530842 pthread_mutex_lock(&out->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700843 out->common.state = AUDIO_A2DP_STATE_STOPPING;
Rohit Singha9fb00a2013-07-27 14:46:29 +0530844 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800845 }
846 }
847
848 retval = str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval));
849
850 if (retval >= 0)
851 {
Rohit Singha9fb00a2013-07-27 14:46:29 +0530852 pthread_mutex_lock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800853 if (strcmp(keyval, "true") == 0)
854 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700855 if (out->common.state == AUDIO_A2DP_STATE_STARTED)
Rohit Singha9fb00a2013-07-27 14:46:29 +0530856 {
xuxy050626765b82015-09-16 10:06:34 +0800857 status = suspend_audio_datapath(&out->common, false);
Rohit Singha9fb00a2013-07-27 14:46:29 +0530858 }
859 else
860 {
861 if (check_a2dp_stream_started(out) == 0)
862 /*Btif and A2dp HAL state can be out of sync
863 *check state of btif and suspend audio.
864 *Happens when remote initiates start.*/
xuxy050626765b82015-09-16 10:06:34 +0800865 status = suspend_audio_datapath(&out->common, false);
Rohit Singha9fb00a2013-07-27 14:46:29 +0530866 else
867 out->common.state = AUDIO_A2DP_STATE_SUSPENDED;
868 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800869 }
870 else
871 {
872 /* Do not start the streaming automatically. If the phone was streaming
873 * prior to being suspended, the next out_write shall trigger the
874 * AVDTP start procedure */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700875 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
876 out->common.state = AUDIO_A2DP_STATE_STANDBY;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800877 /* Irrespective of the state, return 0 */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800878 }
Rohit Singha9fb00a2013-07-27 14:46:29 +0530879 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800880 }
881
The Android Open Source Project5738f832012-12-12 16:00:35 -0800882 str_parms_destroy(parms);
883
xuxy050626765b82015-09-16 10:06:34 +0800884 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800885}
886
887static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
888{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800889 UNUSED(keys);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800890 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
891
892 FNLOG();
893
894 /* add populating param here */
895
896 return strdup("");
897}
898
899static uint32_t out_get_latency(const struct audio_stream_out *stream)
900{
901 int latency_us;
902
903 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
904
905 FNLOG();
906
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700907 latency_us = ((out->common.buffer_sz * 1000 ) /
Eric Laurent171c23f2014-07-03 16:09:53 -0700908 audio_stream_out_frame_size(&out->stream) /
Ethan Chendec61cd2015-02-13 18:26:44 -0800909 out->common.cfg.rate) * 1000;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800910
911
912 return (latency_us / 1000) + 200;
913}
914
915static int out_set_volume(struct audio_stream_out *stream, float left,
916 float right)
917{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800918 UNUSED(stream);
919 UNUSED(left);
920 UNUSED(right);
921
The Android Open Source Project5738f832012-12-12 16:00:35 -0800922 FNLOG();
923
924 /* volume controlled in audioflinger mixer (digital) */
925
926 return -ENOSYS;
927}
928
929
930
931static int out_get_render_position(const struct audio_stream_out *stream,
932 uint32_t *dsp_frames)
933{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800934 UNUSED(stream);
935 UNUSED(dsp_frames);
936
The Android Open Source Project5738f832012-12-12 16:00:35 -0800937 FNLOG();
938 return -EINVAL;
939}
940
941static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
942{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800943 UNUSED(stream);
944 UNUSED(effect);
945
The Android Open Source Project5738f832012-12-12 16:00:35 -0800946 FNLOG();
947 return 0;
948}
949
950static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
951{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800952 UNUSED(stream);
953 UNUSED(effect);
954
The Android Open Source Project5738f832012-12-12 16:00:35 -0800955 FNLOG();
956 return 0;
957}
958
959/*
960 * AUDIO INPUT STREAM
961 */
962
963static uint32_t in_get_sample_rate(const struct audio_stream *stream)
964{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700965 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800966
The Android Open Source Project5738f832012-12-12 16:00:35 -0800967 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700968 return in->common.cfg.rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800969}
970
971static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
972{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700973 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800974
The Android Open Source Project5738f832012-12-12 16:00:35 -0800975 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700976
977 if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate)
978 return 0;
979 else
980 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800981}
982
983static size_t in_get_buffer_size(const struct audio_stream *stream)
984{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800985 UNUSED(stream);
986
The Android Open Source Project5738f832012-12-12 16:00:35 -0800987 FNLOG();
988 return 320;
989}
990
991static uint32_t in_get_channels(const struct audio_stream *stream)
992{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700993 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800994
The Android Open Source Project5738f832012-12-12 16:00:35 -0800995 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700996 return in->common.cfg.channel_flags;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800997}
998
999static audio_format_t in_get_format(const struct audio_stream *stream)
1000{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001001 UNUSED(stream);
1002
The Android Open Source Project5738f832012-12-12 16:00:35 -08001003 FNLOG();
1004 return AUDIO_FORMAT_PCM_16_BIT;
1005}
1006
1007static int in_set_format(struct audio_stream *stream, audio_format_t format)
1008{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001009 UNUSED(stream);
1010 UNUSED(format);
1011
The Android Open Source Project5738f832012-12-12 16:00:35 -08001012 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001013 if (format == AUDIO_FORMAT_PCM_16_BIT)
1014 return 0;
1015 else
1016 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001017}
1018
1019static int in_standby(struct audio_stream *stream)
1020{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001021 UNUSED(stream);
1022
The Android Open Source Project5738f832012-12-12 16:00:35 -08001023 FNLOG();
1024 return 0;
1025}
1026
1027static int in_dump(const struct audio_stream *stream, int fd)
1028{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001029 UNUSED(stream);
1030 UNUSED(fd);
1031
The Android Open Source Project5738f832012-12-12 16:00:35 -08001032 FNLOG();
1033 return 0;
1034}
1035
1036static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1037{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001038 UNUSED(stream);
1039 UNUSED(kvpairs);
1040
The Android Open Source Project5738f832012-12-12 16:00:35 -08001041 FNLOG();
1042 return 0;
1043}
1044
1045static char * in_get_parameters(const struct audio_stream *stream,
1046 const char *keys)
1047{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001048 UNUSED(stream);
1049 UNUSED(keys);
1050
The Android Open Source Project5738f832012-12-12 16:00:35 -08001051 FNLOG();
1052 return strdup("");
1053}
1054
1055static int in_set_gain(struct audio_stream_in *stream, float gain)
1056{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001057 UNUSED(stream);
1058 UNUSED(gain);
1059
The Android Open Source Project5738f832012-12-12 16:00:35 -08001060 FNLOG();
1061 return 0;
1062}
1063
1064static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1065 size_t bytes)
1066{
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001067 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
1068 int read;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001069
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001070 DEBUG("read %zu bytes, state: %d", bytes, in->common.state);
1071
1072 if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED)
1073 {
1074 DEBUG("stream suspended");
1075 return -1;
1076 }
1077
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001078 /* only allow autostarting if we are in stopped or standby */
1079 if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
1080 (in->common.state == AUDIO_A2DP_STATE_STANDBY))
1081 {
1082 pthread_mutex_lock(&in->common.lock);
1083
1084 if (start_audio_datapath(&in->common) < 0)
1085 {
1086 /* emulate time this write represents to avoid very fast write
1087 failures during transition periods or remote suspend */
1088
Mike Lockwoodb1c8fcc2014-07-11 12:05:04 -07001089 int us_delay = calc_audiotime(in->common.cfg, bytes);
1090
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001091 DEBUG("emulate a2dp read delay (%d us)", us_delay);
1092
1093 usleep(us_delay);
1094 pthread_mutex_unlock(&in->common.lock);
1095 return -1;
1096 }
1097
1098 pthread_mutex_unlock(&in->common.lock);
1099 }
1100 else if (in->common.state != AUDIO_A2DP_STATE_STARTED)
1101 {
1102 ERROR("stream not in stopped or standby");
1103 return -1;
1104 }
1105
Mike Lockwoodb1c8fcc2014-07-11 12:05:04 -07001106 read = skt_read(in->common.audio_fd, buffer, bytes);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001107
1108 if (read == -1)
1109 {
1110 skt_disconnect(in->common.audio_fd);
1111 in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
1112 in->common.state = AUDIO_A2DP_STATE_STOPPED;
1113 } else if (read == 0) {
1114 DEBUG("read time out - return zeros");
1115 memset(buffer, 0, bytes);
1116 read = bytes;
1117 }
1118
1119 DEBUG("read %d bytes out of %zu bytes", read, bytes);
1120 return read;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001121}
1122
1123static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1124{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001125 UNUSED(stream);
1126
The Android Open Source Project5738f832012-12-12 16:00:35 -08001127 FNLOG();
1128 return 0;
1129}
1130
1131static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1132{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001133 UNUSED(stream);
1134 UNUSED(effect);
1135
The Android Open Source Project5738f832012-12-12 16:00:35 -08001136 FNLOG();
1137 return 0;
1138}
1139
1140static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1141{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001142 UNUSED(stream);
1143 UNUSED(effect);
1144
The Android Open Source Project5738f832012-12-12 16:00:35 -08001145 FNLOG();
1146
1147 return 0;
1148}
1149
1150static int adev_open_output_stream(struct audio_hw_device *dev,
1151 audio_io_handle_t handle,
1152 audio_devices_t devices,
1153 audio_output_flags_t flags,
1154 struct audio_config *config,
Eric Laurent70311ac2014-07-27 17:27:35 -07001155 struct audio_stream_out **stream_out,
1156 const char *address __unused)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001157
1158{
1159 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1160 struct a2dp_stream_out *out;
1161 int ret = 0;
1162 int i;
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001163 char local_filename [50];
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001164 UNUSED(handle);
1165 UNUSED(devices);
1166 UNUSED(flags);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001167
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001168 perf_systrace_enabled();
1169 audio_sample_logging_enabled();
1170
The Android Open Source Project5738f832012-12-12 16:00:35 -08001171 INFO("opening output");
1172
1173 out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out));
1174
1175 if (!out)
1176 return -ENOMEM;
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -07001177
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001178 if (audio_sample_log_enabled) {
1179 strncpy(local_filename, btoutputfilename, sizeof(btoutputfilename));
1180 snprintf(local_filename, sizeof(local_filename), "%s%d%s", local_filename, number,".pcm");
1181 outputpcmsamplefile = fopen (local_filename, "ab");
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -07001182 number++;
1183 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001184
1185 out->stream.common.get_sample_rate = out_get_sample_rate;
1186 out->stream.common.set_sample_rate = out_set_sample_rate;
1187 out->stream.common.get_buffer_size = out_get_buffer_size;
1188 out->stream.common.get_channels = out_get_channels;
1189 out->stream.common.get_format = out_get_format;
1190 out->stream.common.set_format = out_set_format;
1191 out->stream.common.standby = out_standby;
1192 out->stream.common.dump = out_dump;
1193 out->stream.common.set_parameters = out_set_parameters;
1194 out->stream.common.get_parameters = out_get_parameters;
1195 out->stream.common.add_audio_effect = out_add_audio_effect;
1196 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1197 out->stream.get_latency = out_get_latency;
1198 out->stream.set_volume = out_set_volume;
1199 out->stream.write = out_write;
1200 out->stream.get_render_position = out_get_render_position;
1201
1202 /* initialize a2dp specifics */
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001203 a2dp_stream_common_init(&out->common);
1204
1205 out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG;
1206 out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
1207 out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001208
Ethan Chendec61cd2015-02-13 18:26:44 -08001209 /* set output config values */
1210 if (config)
1211 {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001212 config->format = out_get_format((const struct audio_stream *)&out->stream);
1213 config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream);
1214 config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream);
1215 }
1216 *stream_out = &out->stream;
1217 a2dp_dev->output = out;
1218
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001219 a2dp_open_ctrl_path(&out->common);
1220 if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001221 {
1222 ERROR("ctrl socket failed to connect (%s)", strerror(errno));
1223 ret = -1;
1224 goto err_open;
1225 }
1226
rakesh reddy03b63652014-08-14 11:58:45 +05301227 INFO("success");
Rohit Singha9fb00a2013-07-27 14:46:29 +05301228 /* Delay to ensure Headset is in proper state when START is initiated
1229 from DUT immediately after the connection due to ongoing music playback. */
1230 usleep(250000);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001231 return 0;
1232
1233err_open:
1234 free(out);
1235 *stream_out = NULL;
Nitin Srivastavae67bf202014-01-31 15:51:24 +05301236 a2dp_dev->output = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001237 ERROR("failed");
1238 return ret;
1239}
1240
1241static void adev_close_output_stream(struct audio_hw_device *dev,
1242 struct audio_stream_out *stream)
1243{
1244 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1245 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
1246
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001247 INFO("closing output (state %d)", out->common.state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001248
Ayan Ghoshb77efd02014-12-22 19:54:09 +05301249 pthread_mutex_lock(&out->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001250 if ((out->common.state == AUDIO_A2DP_STATE_STARTED) || (out->common.state == AUDIO_A2DP_STATE_STOPPING))
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -05001251 stop_audio_datapath(&out->common, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001252
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001253 if (audio_sample_log_enabled) {
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -07001254 ALOGV("close file output");
1255 fclose (outputpcmsamplefile);
1256 }
rakesh reddy03b63652014-08-14 11:58:45 +05301257
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001258 skt_disconnect(out->common.ctrl_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001259 free(stream);
1260 a2dp_dev->output = NULL;
Ayan Ghoshb77efd02014-12-22 19:54:09 +05301261 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001262
rakesh reddy03b63652014-08-14 11:58:45 +05301263 INFO("done");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001264}
1265
1266static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1267{
1268 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1269 struct a2dp_stream_out *out = a2dp_dev->output;
1270 int retval = 0;
1271
1272 if (out == NULL)
1273 return retval;
Eric Laurent71ac7a72014-10-29 17:17:31 -07001274
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001275 INFO("state %d", out->common.state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001276
1277 retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
1278
1279 return retval;
1280}
1281
1282static char * adev_get_parameters(const struct audio_hw_device *dev,
1283 const char *keys)
1284{
1285 struct str_parms *parms;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001286 UNUSED(dev);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001287
1288 FNLOG();
1289
1290 parms = str_parms_create_str(keys);
1291
Amit Goel85a35032014-07-31 20:14:27 -07001292 if(!parms)
1293 {
1294 ERROR("parms is NULL");
1295 return strdup("");
1296 }
1297
The Android Open Source Project5738f832012-12-12 16:00:35 -08001298 str_parms_dump(parms);
1299
1300 str_parms_destroy(parms);
1301
1302 return strdup("");
1303}
1304
1305static int adev_init_check(const struct audio_hw_device *dev)
1306{
1307 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev;
1308
1309 FNLOG();
1310
1311 return 0;
1312}
1313
1314static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1315{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001316 UNUSED(dev);
1317 UNUSED(volume);
1318
The Android Open Source Project5738f832012-12-12 16:00:35 -08001319 FNLOG();
1320
1321 return -ENOSYS;
1322}
1323
1324static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1325{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001326 UNUSED(dev);
1327 UNUSED(volume);
1328
The Android Open Source Project5738f832012-12-12 16:00:35 -08001329 FNLOG();
1330
1331 return -ENOSYS;
1332}
1333
1334static int adev_set_mode(struct audio_hw_device *dev, int mode)
1335{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001336 UNUSED(dev);
1337 UNUSED(mode);
1338
The Android Open Source Project5738f832012-12-12 16:00:35 -08001339 FNLOG();
1340
1341 return 0;
1342}
1343
1344static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1345{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001346 UNUSED(dev);
1347 UNUSED(state);
1348
The Android Open Source Project5738f832012-12-12 16:00:35 -08001349 FNLOG();
1350
1351 return -ENOSYS;
1352}
1353
1354static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1355{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001356 UNUSED(dev);
1357 UNUSED(state);
1358
The Android Open Source Project5738f832012-12-12 16:00:35 -08001359 FNLOG();
1360
1361 return -ENOSYS;
1362}
1363
1364static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1365 const struct audio_config *config)
1366{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001367 UNUSED(dev);
1368 UNUSED(config);
1369
The Android Open Source Project5738f832012-12-12 16:00:35 -08001370 FNLOG();
1371
1372 return 320;
1373}
1374
1375static int adev_open_input_stream(struct audio_hw_device *dev,
1376 audio_io_handle_t handle,
1377 audio_devices_t devices,
1378 struct audio_config *config,
Glenn Kasten85f2cd22014-07-17 07:33:51 -07001379 struct audio_stream_in **stream_in,
Eric Laurent70311ac2014-07-27 17:27:35 -07001380 audio_input_flags_t flags __unused,
1381 const char *address __unused,
1382 audio_source_t source __unused)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001383{
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001384 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001385 struct a2dp_stream_in *in;
1386 int ret;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001387 UNUSED(handle);
1388 UNUSED(devices);
1389 UNUSED(config);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001390
1391 FNLOG();
1392
1393 in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in));
1394
1395 if (!in)
1396 return -ENOMEM;
1397
1398 in->stream.common.get_sample_rate = in_get_sample_rate;
1399 in->stream.common.set_sample_rate = in_set_sample_rate;
1400 in->stream.common.get_buffer_size = in_get_buffer_size;
1401 in->stream.common.get_channels = in_get_channels;
1402 in->stream.common.get_format = in_get_format;
1403 in->stream.common.set_format = in_set_format;
1404 in->stream.common.standby = in_standby;
1405 in->stream.common.dump = in_dump;
1406 in->stream.common.set_parameters = in_set_parameters;
1407 in->stream.common.get_parameters = in_get_parameters;
1408 in->stream.common.add_audio_effect = in_add_audio_effect;
1409 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1410 in->stream.set_gain = in_set_gain;
1411 in->stream.read = in_read;
1412 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1413
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001414 /* initialize a2dp specifics */
1415 a2dp_stream_common_init(&in->common);
1416
The Android Open Source Project5738f832012-12-12 16:00:35 -08001417 *stream_in = &in->stream;
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001418 a2dp_dev->input = in;
1419
1420 a2dp_open_ctrl_path(&in->common);
1421 if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
1422 {
1423 ERROR("ctrl socket failed to connect (%s)", strerror(errno));
1424 ret = -1;
1425 goto err_open;
1426 }
1427
1428 if (a2dp_read_audio_config(&in->common) < 0) {
1429 ERROR("a2dp_read_audio_config failed (%s)", strerror(errno));
1430 ret = -1;
1431 goto err_open;
1432 }
1433
1434 DEBUG("success");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001435 return 0;
1436
1437err_open:
1438 free(in);
1439 *stream_in = NULL;
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001440 a2dp_dev->input = NULL;
1441 ERROR("failed");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001442 return ret;
1443}
1444
1445static void adev_close_input_stream(struct audio_hw_device *dev,
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001446 struct audio_stream_in *stream)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001447{
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001448 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1449 struct a2dp_stream_in* in = (struct a2dp_stream_in *)stream;
1450 a2dp_state_t state = in->common.state;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001451
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001452 INFO("closing input (state %d)", state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001453
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001454 if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING))
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -05001455 stop_audio_datapath(&in->common, false);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001456
1457 skt_disconnect(in->common.ctrl_fd);
1458 free(stream);
1459 a2dp_dev->input = NULL;
1460
1461 DEBUG("done");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001462}
1463
1464static int adev_dump(const audio_hw_device_t *device, int fd)
1465{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001466 UNUSED(device);
1467 UNUSED(fd);
1468
The Android Open Source Project5738f832012-12-12 16:00:35 -08001469 FNLOG();
1470
1471 return 0;
1472}
1473
1474static int adev_close(hw_device_t *device)
1475{
1476 FNLOG();
1477
1478 free(device);
1479 return 0;
1480}
1481
1482static int adev_open(const hw_module_t* module, const char* name,
1483 hw_device_t** device)
1484{
1485 struct a2dp_audio_device *adev;
1486 int ret;
1487
1488 INFO(" adev_open in A2dp_hw module");
1489 FNLOG();
1490
1491 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1492 {
1493 ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
1494 return -EINVAL;
1495 }
1496
1497 adev = calloc(1, sizeof(struct a2dp_audio_device));
1498
1499 if (!adev)
1500 return -ENOMEM;
1501
1502 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent9a445032014-03-20 18:01:09 -07001503 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001504 adev->device.common.module = (struct hw_module_t *) module;
1505 adev->device.common.close = adev_close;
1506
1507 adev->device.init_check = adev_init_check;
1508 adev->device.set_voice_volume = adev_set_voice_volume;
1509 adev->device.set_master_volume = adev_set_master_volume;
1510 adev->device.set_mode = adev_set_mode;
1511 adev->device.set_mic_mute = adev_set_mic_mute;
1512 adev->device.get_mic_mute = adev_get_mic_mute;
1513 adev->device.set_parameters = adev_set_parameters;
1514 adev->device.get_parameters = adev_get_parameters;
1515 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1516 adev->device.open_output_stream = adev_open_output_stream;
1517 adev->device.close_output_stream = adev_close_output_stream;
1518 adev->device.open_input_stream = adev_open_input_stream;
1519 adev->device.close_input_stream = adev_close_input_stream;
1520 adev->device.dump = adev_dump;
1521
1522 adev->output = NULL;
1523
1524
1525 *device = &adev->device.common;
1526
1527 return 0;
1528}
1529
1530static struct hw_module_methods_t hal_module_methods = {
1531 .open = adev_open,
1532};
1533
1534struct audio_module HAL_MODULE_INFO_SYM = {
1535 .common = {
1536 .tag = HARDWARE_MODULE_TAG,
1537 .version_major = 1,
1538 .version_minor = 0,
1539 .id = AUDIO_HARDWARE_MODULE_ID,
1540 .name = "A2DP Audio HW HAL",
1541 .author = "The Android Open Source Project",
1542 .methods = &hal_module_methods,
1543 },
1544};
1545