blob: 2083f062d8920539d15cfdab9391bad681f45aac [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
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700309 if ((read = TEMP_FAILURE_RETRY(recv(fd, p, len, MSG_NOSIGNAL))) == -1)
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700310 {
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 */
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700331 if (TEMP_FAILURE_RETRY(poll(&pfd, 1, 500)) == 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800332 return 0;
333
334 ts_log("skt_write", len, NULL);
335
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700336 if ((sent = TEMP_FAILURE_RETRY(send(fd, p, len, MSG_NOSIGNAL))) == -1)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800337 {
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{
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700367 int ret = TEMP_FAILURE_RETRY(recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700368 if (ret < 0)
369 {
370 ERROR("ack failed (%s)", strerror(errno));
371 if (errno == EINTR)
372 {
373 /* retry again */
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700374 ret = TEMP_FAILURE_RETRY(recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700375 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 */
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700401 if (TEMP_FAILURE_RETRY(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");
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700478 TEMP_FAILURE_RETRY(usleep(250000));
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700479 skt_disconnect(common->ctrl_fd);
480 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
481 }
482
483 /* ctrl channel not ready, wait a bit */
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700484 TEMP_FAILURE_RETRY(usleep(250000));
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700485 }
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 {
Christopher R. Palmer7da9d072015-02-13 05:47:20 -0500548 ERROR("audiopath start failed- In call a2dp, stay in state %s",
549 dump_a2dp_hal_state(oldstate));
550 common->state = oldstate;
Rohit Singha9fb00a2013-07-27 14:46:29 +0530551 return -1;
552 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800553
554 /* connect socket if not yet connected */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700555 if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800556 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700557 common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);
558 if (common->audio_fd < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800559 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700560 common->state = oldstate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800561 return -1;
562 }
563
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700564 common->state = AUDIO_A2DP_STATE_STARTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800565 }
566
567 return 0;
568}
569
570
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -0500571static int stop_audio_datapath(struct a2dp_stream_common *common, bool stay_suspended)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800572{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700573 int oldstate = common->state;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800574
rakesh reddy03b63652014-08-14 11:58:45 +0530575 INFO("state %s", dump_a2dp_hal_state(common->state));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800576
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700577 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800578 return -1;
579
580 /* prevent any stray output writes from autostarting the stream
581 while stopping audiopath */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700582 common->state = AUDIO_A2DP_STATE_STOPPING;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800583
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700584 if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800585 {
586 ERROR("audiopath stop failed");
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700587 common->state = oldstate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800588 return -1;
589 }
590
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -0500591 if (!stay_suspended || common->state != AUDIO_A2DP_STATE_SUSPENDED)
592 common->state = AUDIO_A2DP_STATE_STOPPED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800593
594 /* disconnect audio path */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700595 skt_disconnect(common->audio_fd);
596 common->audio_fd = AUDIO_SKT_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800597
598 return 0;
599}
600
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700601static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800602{
rakesh reddy03b63652014-08-14 11:58:45 +0530603 INFO("state %s", dump_a2dp_hal_state(common->state));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800604
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700605 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800606 return -1;
607
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700608 if (common->state == AUDIO_A2DP_STATE_STOPPING)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800609 return -1;
610
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700611 if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800612 return -1;
613
614 if (standby)
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700615 common->state = AUDIO_A2DP_STATE_STANDBY;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800616 else
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700617 common->state = AUDIO_A2DP_STATE_SUSPENDED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800618
619 /* disconnect audio path */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700620 skt_disconnect(common->audio_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800621
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700622 common->audio_fd = AUDIO_SKT_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800623
624 return 0;
625}
626
The Android Open Source Project5738f832012-12-12 16:00:35 -0800627
Rohit Singha9fb00a2013-07-27 14:46:29 +0530628static int check_a2dp_stream_started(struct a2dp_stream_out *out)
629{
630 if (a2dp_command(&out->common, A2DP_CTRL_CMD_CHECK_STREAM_STARTED) < 0)
631 {
rakesh reddy03b63652014-08-14 11:58:45 +0530632 INFO("Btif not in stream state");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530633 return -1;
634 }
635 return 0;
636}
637
638
The Android Open Source Project5738f832012-12-12 16:00:35 -0800639/*****************************************************************************
640**
641** audio output callbacks
642**
643*****************************************************************************/
644
645static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
646 size_t bytes)
647{
648 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
649 int sent;
650
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700651 DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800652
Rohit Singha9fb00a2013-07-27 14:46:29 +0530653 pthread_mutex_lock(&out->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700654 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800655 {
rakesh reddy03b63652014-08-14 11:58:45 +0530656 INFO("stream suspended");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530657 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800658 return -1;
659 }
660
661 /* only allow autostarting if we are in stopped or standby */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700662 if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
663 (out->common.state == AUDIO_A2DP_STATE_STANDBY))
The Android Open Source Project5738f832012-12-12 16:00:35 -0800664 {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800665
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700666 if (start_audio_datapath(&out->common) < 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800667 {
668 /* emulate time this write represents to avoid very fast write
669 failures during transition periods or remote suspend */
670
Ethan Chendec61cd2015-02-13 18:26:44 -0800671 int us_delay = calc_audiotime(out->common.cfg, bytes);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800672
rakesh reddy03b63652014-08-14 11:58:45 +0530673 ERROR("emulate a2dp write delay (%d us)", us_delay);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800674
Sharvil Nanavati405b5c92016-06-17 14:15:46 -0700675 TEMP_FAILURE_RETRY(usleep(us_delay));
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700676 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800677 return -1;
678 }
679
The Android Open Source Project5738f832012-12-12 16:00:35 -0800680 }
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700681 else if (out->common.state != AUDIO_A2DP_STATE_STARTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800682 {
683 ERROR("stream not in stopped or standby");
Rohit Singha9fb00a2013-07-27 14:46:29 +0530684 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800685 return -1;
686 }
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700687
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -0800688 if (audio_sample_log_enabled) {
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -0700689 if (outputpcmsamplefile)
690 {
691 fwrite (buffer,1,bytes,outputpcmsamplefile);
692 }
rakesh reddy03b63652014-08-14 11:58:45 +0530693 }
repo Shareef Ali619b3ed2014-12-29 00:48:01 -0600694#if 0
rakesh reddy03b63652014-08-14 11:58:45 +0530695 ts_error_log("a2dp_out_write", bytes, out->common.buffer_sz, out->common.cfg);
repo Shareef Ali619b3ed2014-12-29 00:48:01 -0600696#endif
Rohit Singha9fb00a2013-07-27 14:46:29 +0530697
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 stop_audio_datapath(&out->common, true);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800715 }
716
Ethan Chenb3fce3e2015-02-19 12:13:00 -0800717 pthread_mutex_unlock(&out->common.lock);
718
Mark Salyzyn40421cb2014-04-17 13:45:20 -0700719 DEBUG("wrote %d bytes out of %zu bytes", sent, bytes);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800720 return sent;
721}
722
Ethan Chendec61cd2015-02-13 18:26:44 -0800723
The Android Open Source Project5738f832012-12-12 16:00:35 -0800724static uint32_t out_get_sample_rate(const struct audio_stream *stream)
725{
726 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
727
Jon Mooneyeb541352015-02-17 21:27:00 -0800728 DEBUG("rate %" PRIu32,out->common.cfg.rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800729
Ethan Chendec61cd2015-02-13 18:26:44 -0800730 return out->common.cfg.rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800731}
732
733static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
734{
735 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
736
Jon Mooneyeb541352015-02-17 21:27:00 -0800737 DEBUG("out_set_sample_rate : %" PRIu32, rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800738
Ethan Chendec61cd2015-02-13 18:26:44 -0800739 if (rate != AUDIO_STREAM_DEFAULT_RATE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800740 {
Ethan Chendec61cd2015-02-13 18:26:44 -0800741 ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800742 return -1;
743 }
744
Ethan Chendec61cd2015-02-13 18:26:44 -0800745 out->common.cfg.rate = rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800746
747 return 0;
748}
749
750static size_t out_get_buffer_size(const struct audio_stream *stream)
751{
752 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
753
Dan Pasanen90e9df12014-12-31 21:13:05 -0600754 DEBUG("buffer_size : %zu", out->common.buffer_sz);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800755
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700756 return out->common.buffer_sz;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800757}
758
759static uint32_t out_get_channels(const struct audio_stream *stream)
760{
761 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
762
Jon Mooneyeb541352015-02-17 21:27:00 -0800763 DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_flags);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800764
Ethan Chendec61cd2015-02-13 18:26:44 -0800765 return out->common.cfg.channel_flags;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800766}
767
768static audio_format_t out_get_format(const struct audio_stream *stream)
769{
770 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
Jon Mooneyeb541352015-02-17 21:27:00 -0800771 DEBUG("format 0x%x", out->common.cfg.format);
Ethan Chendec61cd2015-02-13 18:26:44 -0800772 return out->common.cfg.format;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800773}
774
775static int out_set_format(struct audio_stream *stream, audio_format_t format)
776{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800777 UNUSED(format);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800778 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
Jon Mooneyeb541352015-02-17 21:27:00 -0800779 DEBUG("setting format not yet supported (0x%x)", format);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800780 return -ENOSYS;
781}
782
783static int out_standby(struct audio_stream *stream)
784{
785 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800786 int retVal = 0;
787
788 FNLOG();
789
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700790 pthread_mutex_lock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800791
Rohit Singha9fb00a2013-07-27 14:46:29 +0530792 /*Need not check State here as btif layer does
793 check of btif state , during remote initited suspend
794 DUT need to clear flag else start will not happen but
795 Do nothing in SUSPENDED state. */
796 if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700797 retVal = suspend_audio_datapath(&out->common, true);
Rohit Singha9fb00a2013-07-27 14:46:29 +0530798
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700799 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800800
801 return retVal;
802}
803
804static int out_dump(const struct audio_stream *stream, int fd)
805{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800806 UNUSED(fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800807 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
808 FNLOG();
809 return 0;
810}
811
812static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
813{
814 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
815 struct str_parms *parms;
816 char keyval[16];
xuxy050626765b82015-09-16 10:06:34 +0800817 int retval;
818 int status = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800819
The Android Open Source Project5738f832012-12-12 16:00:35 -0800820 parms = str_parms_create_str(kvpairs);
821
Amit Goel85a35032014-07-31 20:14:27 -0700822 if(!parms)
823 {
824 ERROR("parms is NULL");
825 return retval;
826 }
827
The Android Open Source Project5738f832012-12-12 16:00:35 -0800828 /* dump params */
829 str_parms_dump(parms);
830
Ethan Chenb3fce3e2015-02-19 12:13:00 -0800831 pthread_mutex_lock(&out->common.lock);
832
833 DEBUG("state %d", out->common.state);
834
Christopher R. Palmer93db55f2015-02-18 05:16:32 -0500835 if (str_parms_get_str(parms, "closing", keyval, sizeof(keyval)) >= 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800836 {
837 if (strcmp(keyval, "true") == 0)
838 {
839 DEBUG("stream closing, disallow any writes");
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700840 out->common.state = AUDIO_A2DP_STATE_STOPPING;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800841 }
842 }
843
Christopher R. Palmer93db55f2015-02-18 05:16:32 -0500844 if (str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval)) >= 0)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800845 {
846 if (strcmp(keyval, "true") == 0)
847 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700848 if (out->common.state == AUDIO_A2DP_STATE_STARTED)
Rohit Singha9fb00a2013-07-27 14:46:29 +0530849 {
xuxy050626765b82015-09-16 10:06:34 +0800850 status = suspend_audio_datapath(&out->common, false);
Rohit Singha9fb00a2013-07-27 14:46:29 +0530851 }
852 else
853 {
854 if (check_a2dp_stream_started(out) == 0)
855 /*Btif and A2dp HAL state can be out of sync
856 *check state of btif and suspend audio.
857 *Happens when remote initiates start.*/
xuxy050626765b82015-09-16 10:06:34 +0800858 status = suspend_audio_datapath(&out->common, false);
Rohit Singha9fb00a2013-07-27 14:46:29 +0530859 else
860 out->common.state = AUDIO_A2DP_STATE_SUSPENDED;
861 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800862 }
863 else
864 {
865 /* Do not start the streaming automatically. If the phone was streaming
866 * prior to being suspended, the next out_write shall trigger the
867 * AVDTP start procedure */
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700868 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
869 out->common.state = AUDIO_A2DP_STATE_STANDBY;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800870 /* Irrespective of the state, return 0 */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800871 }
872 }
873
Ethan Chenb3fce3e2015-02-19 12:13:00 -0800874 pthread_mutex_unlock(&out->common.lock);
875
The Android Open Source Project5738f832012-12-12 16:00:35 -0800876 str_parms_destroy(parms);
877
xuxy050626765b82015-09-16 10:06:34 +0800878 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800879}
880
881static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
882{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800883 UNUSED(keys);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800884 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
885
886 FNLOG();
887
888 /* add populating param here */
889
890 return strdup("");
891}
892
893static uint32_t out_get_latency(const struct audio_stream_out *stream)
894{
895 int latency_us;
896
897 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
898
899 FNLOG();
900
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700901 latency_us = ((out->common.buffer_sz * 1000 ) /
Eric Laurent171c23f2014-07-03 16:09:53 -0700902 audio_stream_out_frame_size(&out->stream) /
Ethan Chendec61cd2015-02-13 18:26:44 -0800903 out->common.cfg.rate) * 1000;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800904
905
906 return (latency_us / 1000) + 200;
907}
908
909static int out_set_volume(struct audio_stream_out *stream, float left,
910 float right)
911{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800912 UNUSED(stream);
913 UNUSED(left);
914 UNUSED(right);
915
The Android Open Source Project5738f832012-12-12 16:00:35 -0800916 FNLOG();
917
918 /* volume controlled in audioflinger mixer (digital) */
919
920 return -ENOSYS;
921}
922
923
924
925static int out_get_render_position(const struct audio_stream_out *stream,
926 uint32_t *dsp_frames)
927{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800928 UNUSED(stream);
929 UNUSED(dsp_frames);
930
The Android Open Source Project5738f832012-12-12 16:00:35 -0800931 FNLOG();
932 return -EINVAL;
933}
934
935static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
936{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800937 UNUSED(stream);
938 UNUSED(effect);
939
The Android Open Source Project5738f832012-12-12 16:00:35 -0800940 FNLOG();
941 return 0;
942}
943
944static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
945{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800946 UNUSED(stream);
947 UNUSED(effect);
948
The Android Open Source Project5738f832012-12-12 16:00:35 -0800949 FNLOG();
950 return 0;
951}
952
953/*
954 * AUDIO INPUT STREAM
955 */
956
957static uint32_t in_get_sample_rate(const struct audio_stream *stream)
958{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700959 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800960
The Android Open Source Project5738f832012-12-12 16:00:35 -0800961 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700962 return in->common.cfg.rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800963}
964
965static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
966{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700967 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800968
The Android Open Source Project5738f832012-12-12 16:00:35 -0800969 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700970
971 if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate)
972 return 0;
973 else
974 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800975}
976
977static size_t in_get_buffer_size(const struct audio_stream *stream)
978{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800979 UNUSED(stream);
980
The Android Open Source Project5738f832012-12-12 16:00:35 -0800981 FNLOG();
982 return 320;
983}
984
985static uint32_t in_get_channels(const struct audio_stream *stream)
986{
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700987 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800988
The Android Open Source Project5738f832012-12-12 16:00:35 -0800989 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -0700990 return in->common.cfg.channel_flags;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800991}
992
993static audio_format_t in_get_format(const struct audio_stream *stream)
994{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800995 UNUSED(stream);
996
The Android Open Source Project5738f832012-12-12 16:00:35 -0800997 FNLOG();
998 return AUDIO_FORMAT_PCM_16_BIT;
999}
1000
1001static int in_set_format(struct audio_stream *stream, audio_format_t format)
1002{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001003 UNUSED(stream);
1004 UNUSED(format);
1005
The Android Open Source Project5738f832012-12-12 16:00:35 -08001006 FNLOG();
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001007 if (format == AUDIO_FORMAT_PCM_16_BIT)
1008 return 0;
1009 else
1010 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001011}
1012
1013static int in_standby(struct audio_stream *stream)
1014{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001015 UNUSED(stream);
1016
The Android Open Source Project5738f832012-12-12 16:00:35 -08001017 FNLOG();
1018 return 0;
1019}
1020
1021static int in_dump(const struct audio_stream *stream, int fd)
1022{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001023 UNUSED(stream);
1024 UNUSED(fd);
1025
The Android Open Source Project5738f832012-12-12 16:00:35 -08001026 FNLOG();
1027 return 0;
1028}
1029
1030static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
1031{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001032 UNUSED(stream);
1033 UNUSED(kvpairs);
1034
The Android Open Source Project5738f832012-12-12 16:00:35 -08001035 FNLOG();
1036 return 0;
1037}
1038
1039static char * in_get_parameters(const struct audio_stream *stream,
1040 const char *keys)
1041{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001042 UNUSED(stream);
1043 UNUSED(keys);
1044
The Android Open Source Project5738f832012-12-12 16:00:35 -08001045 FNLOG();
1046 return strdup("");
1047}
1048
1049static int in_set_gain(struct audio_stream_in *stream, float gain)
1050{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001051 UNUSED(stream);
1052 UNUSED(gain);
1053
The Android Open Source Project5738f832012-12-12 16:00:35 -08001054 FNLOG();
1055 return 0;
1056}
1057
1058static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1059 size_t bytes)
1060{
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001061 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
1062 int read;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001063
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001064 DEBUG("read %zu bytes, state: %d", bytes, in->common.state);
1065
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001066 pthread_mutex_lock(&in->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001067 if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED)
1068 {
1069 DEBUG("stream suspended");
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001070 pthread_mutex_unlock(&in->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001071 return -1;
1072 }
1073
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001074 /* only allow autostarting if we are in stopped or standby */
1075 if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
1076 (in->common.state == AUDIO_A2DP_STATE_STANDBY))
1077 {
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001078
1079 if (start_audio_datapath(&in->common) < 0)
1080 {
1081 /* emulate time this write represents to avoid very fast write
1082 failures during transition periods or remote suspend */
1083
Mike Lockwoodb1c8fcc2014-07-11 12:05:04 -07001084 int us_delay = calc_audiotime(in->common.cfg, bytes);
1085
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001086 DEBUG("emulate a2dp read delay (%d us)", us_delay);
1087
Sharvil Nanavati405b5c92016-06-17 14:15:46 -07001088 TEMP_FAILURE_RETRY(usleep(us_delay));
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001089 pthread_mutex_unlock(&in->common.lock);
1090 return -1;
1091 }
1092
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001093 }
1094 else if (in->common.state != AUDIO_A2DP_STATE_STARTED)
1095 {
1096 ERROR("stream not in stopped or standby");
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001097 pthread_mutex_unlock(&in->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001098 return -1;
1099 }
1100
Mike Lockwoodb1c8fcc2014-07-11 12:05:04 -07001101 read = skt_read(in->common.audio_fd, buffer, bytes);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001102
1103 if (read == -1)
1104 {
1105 skt_disconnect(in->common.audio_fd);
1106 in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
1107 in->common.state = AUDIO_A2DP_STATE_STOPPED;
1108 } else if (read == 0) {
1109 DEBUG("read time out - return zeros");
1110 memset(buffer, 0, bytes);
1111 read = bytes;
1112 }
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001113 pthread_mutex_unlock(&in->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001114
1115 DEBUG("read %d bytes out of %zu bytes", read, bytes);
1116 return read;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001117}
1118
1119static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1120{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001121 UNUSED(stream);
1122
The Android Open Source Project5738f832012-12-12 16:00:35 -08001123 FNLOG();
1124 return 0;
1125}
1126
1127static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1128{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001129 UNUSED(stream);
1130 UNUSED(effect);
1131
The Android Open Source Project5738f832012-12-12 16:00:35 -08001132 FNLOG();
1133 return 0;
1134}
1135
1136static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1137{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001138 UNUSED(stream);
1139 UNUSED(effect);
1140
The Android Open Source Project5738f832012-12-12 16:00:35 -08001141 FNLOG();
1142
1143 return 0;
1144}
1145
1146static int adev_open_output_stream(struct audio_hw_device *dev,
1147 audio_io_handle_t handle,
1148 audio_devices_t devices,
1149 audio_output_flags_t flags,
1150 struct audio_config *config,
Eric Laurent70311ac2014-07-27 17:27:35 -07001151 struct audio_stream_out **stream_out,
1152 const char *address __unused)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001153
1154{
1155 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1156 struct a2dp_stream_out *out;
1157 int ret = 0;
1158 int i;
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001159 char local_filename [50];
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001160 UNUSED(handle);
1161 UNUSED(devices);
1162 UNUSED(flags);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001163
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001164 perf_systrace_enabled();
1165 audio_sample_logging_enabled();
1166
The Android Open Source Project5738f832012-12-12 16:00:35 -08001167 INFO("opening output");
1168
1169 out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out));
1170
1171 if (!out)
1172 return -ENOMEM;
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -07001173
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001174 if (audio_sample_log_enabled) {
1175 strncpy(local_filename, btoutputfilename, sizeof(btoutputfilename));
1176 snprintf(local_filename, sizeof(local_filename), "%s%d%s", local_filename, number,".pcm");
1177 outputpcmsamplefile = fopen (local_filename, "ab");
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -07001178 number++;
1179 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001180
1181 out->stream.common.get_sample_rate = out_get_sample_rate;
1182 out->stream.common.set_sample_rate = out_set_sample_rate;
1183 out->stream.common.get_buffer_size = out_get_buffer_size;
1184 out->stream.common.get_channels = out_get_channels;
1185 out->stream.common.get_format = out_get_format;
1186 out->stream.common.set_format = out_set_format;
1187 out->stream.common.standby = out_standby;
1188 out->stream.common.dump = out_dump;
1189 out->stream.common.set_parameters = out_set_parameters;
1190 out->stream.common.get_parameters = out_get_parameters;
1191 out->stream.common.add_audio_effect = out_add_audio_effect;
1192 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1193 out->stream.get_latency = out_get_latency;
1194 out->stream.set_volume = out_set_volume;
1195 out->stream.write = out_write;
1196 out->stream.get_render_position = out_get_render_position;
1197
1198 /* initialize a2dp specifics */
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001199 a2dp_stream_common_init(&out->common);
1200
1201 out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG;
1202 out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
1203 out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001204
Ethan Chendec61cd2015-02-13 18:26:44 -08001205 /* set output config values */
1206 if (config)
1207 {
The Android Open Source Project5738f832012-12-12 16:00:35 -08001208 config->format = out_get_format((const struct audio_stream *)&out->stream);
1209 config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream);
1210 config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream);
1211 }
1212 *stream_out = &out->stream;
1213 a2dp_dev->output = out;
1214
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001215 a2dp_open_ctrl_path(&out->common);
1216 if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001217 {
1218 ERROR("ctrl socket failed to connect (%s)", strerror(errno));
1219 ret = -1;
1220 goto err_open;
1221 }
1222
rakesh reddy03b63652014-08-14 11:58:45 +05301223 INFO("success");
Rohit Singha9fb00a2013-07-27 14:46:29 +05301224 /* Delay to ensure Headset is in proper state when START is initiated
1225 from DUT immediately after the connection due to ongoing music playback. */
1226 usleep(250000);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001227 return 0;
1228
1229err_open:
1230 free(out);
1231 *stream_out = NULL;
Nitin Srivastavae67bf202014-01-31 15:51:24 +05301232 a2dp_dev->output = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001233 ERROR("failed");
1234 return ret;
1235}
1236
1237static void adev_close_output_stream(struct audio_hw_device *dev,
1238 struct audio_stream_out *stream)
1239{
1240 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1241 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
1242
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001243 pthread_mutex_lock(&out->common.lock);
1244
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001245 INFO("closing output (state %d)", out->common.state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001246
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001247 if ((out->common.state == AUDIO_A2DP_STATE_STARTED) || (out->common.state == AUDIO_A2DP_STATE_STOPPING))
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -05001248 stop_audio_datapath(&out->common, false);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001249
Bhakthavatsala Raghavendraa86504f2014-11-24 22:35:55 -08001250 if (audio_sample_log_enabled) {
Bhakthavatsala Raghavendra1903bf62014-09-11 15:38:16 -07001251 ALOGV("close file output");
1252 fclose (outputpcmsamplefile);
1253 }
rakesh reddy03b63652014-08-14 11:58:45 +05301254
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001255 skt_disconnect(out->common.ctrl_fd);
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001256 pthread_mutex_unlock(&out->common.lock);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001257 free(stream);
1258 a2dp_dev->output = NULL;
1259
rakesh reddy03b63652014-08-14 11:58:45 +05301260 INFO("done");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001261}
1262
1263static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1264{
1265 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1266 struct a2dp_stream_out *out = a2dp_dev->output;
1267 int retval = 0;
1268
1269 if (out == NULL)
1270 return retval;
Eric Laurent71ac7a72014-10-29 17:17:31 -07001271
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001272 INFO("state %d", out->common.state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001273
1274 retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
1275
1276 return retval;
1277}
1278
1279static char * adev_get_parameters(const struct audio_hw_device *dev,
1280 const char *keys)
1281{
1282 struct str_parms *parms;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001283 UNUSED(dev);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001284
1285 FNLOG();
1286
1287 parms = str_parms_create_str(keys);
1288
Amit Goel85a35032014-07-31 20:14:27 -07001289 if(!parms)
1290 {
1291 ERROR("parms is NULL");
1292 return strdup("");
1293 }
1294
The Android Open Source Project5738f832012-12-12 16:00:35 -08001295 str_parms_dump(parms);
1296
1297 str_parms_destroy(parms);
1298
1299 return strdup("");
1300}
1301
1302static int adev_init_check(const struct audio_hw_device *dev)
1303{
1304 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev;
1305
1306 FNLOG();
1307
1308 return 0;
1309}
1310
1311static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1312{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001313 UNUSED(dev);
1314 UNUSED(volume);
1315
The Android Open Source Project5738f832012-12-12 16:00:35 -08001316 FNLOG();
1317
1318 return -ENOSYS;
1319}
1320
1321static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1322{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001323 UNUSED(dev);
1324 UNUSED(volume);
1325
The Android Open Source Project5738f832012-12-12 16:00:35 -08001326 FNLOG();
1327
1328 return -ENOSYS;
1329}
1330
1331static int adev_set_mode(struct audio_hw_device *dev, int mode)
1332{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001333 UNUSED(dev);
1334 UNUSED(mode);
1335
The Android Open Source Project5738f832012-12-12 16:00:35 -08001336 FNLOG();
1337
1338 return 0;
1339}
1340
1341static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1342{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001343 UNUSED(dev);
1344 UNUSED(state);
1345
The Android Open Source Project5738f832012-12-12 16:00:35 -08001346 FNLOG();
1347
1348 return -ENOSYS;
1349}
1350
1351static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1352{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001353 UNUSED(dev);
1354 UNUSED(state);
1355
The Android Open Source Project5738f832012-12-12 16:00:35 -08001356 FNLOG();
1357
1358 return -ENOSYS;
1359}
1360
1361static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1362 const struct audio_config *config)
1363{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001364 UNUSED(dev);
1365 UNUSED(config);
1366
The Android Open Source Project5738f832012-12-12 16:00:35 -08001367 FNLOG();
1368
1369 return 320;
1370}
1371
1372static int adev_open_input_stream(struct audio_hw_device *dev,
1373 audio_io_handle_t handle,
1374 audio_devices_t devices,
1375 struct audio_config *config,
Glenn Kasten85f2cd22014-07-17 07:33:51 -07001376 struct audio_stream_in **stream_in,
Eric Laurent70311ac2014-07-27 17:27:35 -07001377 audio_input_flags_t flags __unused,
1378 const char *address __unused,
1379 audio_source_t source __unused)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001380{
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001381 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001382 struct a2dp_stream_in *in;
1383 int ret;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001384 UNUSED(handle);
1385 UNUSED(devices);
1386 UNUSED(config);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001387
1388 FNLOG();
1389
1390 in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in));
1391
1392 if (!in)
1393 return -ENOMEM;
1394
1395 in->stream.common.get_sample_rate = in_get_sample_rate;
1396 in->stream.common.set_sample_rate = in_set_sample_rate;
1397 in->stream.common.get_buffer_size = in_get_buffer_size;
1398 in->stream.common.get_channels = in_get_channels;
1399 in->stream.common.get_format = in_get_format;
1400 in->stream.common.set_format = in_set_format;
1401 in->stream.common.standby = in_standby;
1402 in->stream.common.dump = in_dump;
1403 in->stream.common.set_parameters = in_set_parameters;
1404 in->stream.common.get_parameters = in_get_parameters;
1405 in->stream.common.add_audio_effect = in_add_audio_effect;
1406 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1407 in->stream.set_gain = in_set_gain;
1408 in->stream.read = in_read;
1409 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1410
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001411 /* initialize a2dp specifics */
1412 a2dp_stream_common_init(&in->common);
1413
The Android Open Source Project5738f832012-12-12 16:00:35 -08001414 *stream_in = &in->stream;
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001415 a2dp_dev->input = in;
1416
1417 a2dp_open_ctrl_path(&in->common);
1418 if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
1419 {
1420 ERROR("ctrl socket failed to connect (%s)", strerror(errno));
1421 ret = -1;
1422 goto err_open;
1423 }
1424
1425 if (a2dp_read_audio_config(&in->common) < 0) {
1426 ERROR("a2dp_read_audio_config failed (%s)", strerror(errno));
1427 ret = -1;
1428 goto err_open;
1429 }
1430
1431 DEBUG("success");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001432 return 0;
1433
1434err_open:
1435 free(in);
1436 *stream_in = NULL;
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001437 a2dp_dev->input = NULL;
1438 ERROR("failed");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001439 return ret;
1440}
1441
1442static void adev_close_input_stream(struct audio_hw_device *dev,
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001443 struct audio_stream_in *stream)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001444{
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001445 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1446 struct a2dp_stream_in* in = (struct a2dp_stream_in *)stream;
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001447 a2dp_state_t state;
1448
1449 pthread_mutex_lock(&in->common.lock);
1450
1451 state = in->common.state;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001452
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001453 INFO("closing input (state %d)", state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001454
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001455 if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING))
Christopher R. Palmer2bb2d4a2015-02-13 16:46:17 -05001456 stop_audio_datapath(&in->common, false);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001457
1458 skt_disconnect(in->common.ctrl_fd);
Ethan Chenb3fce3e2015-02-19 12:13:00 -08001459 pthread_mutex_unlock(&in->common.lock);
Mike Lockwood3e8a2422014-05-23 12:42:24 -07001460 free(stream);
1461 a2dp_dev->input = NULL;
1462
1463 DEBUG("done");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001464}
1465
1466static int adev_dump(const audio_hw_device_t *device, int fd)
1467{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001468 UNUSED(device);
1469 UNUSED(fd);
1470
The Android Open Source Project5738f832012-12-12 16:00:35 -08001471 FNLOG();
1472
1473 return 0;
1474}
1475
1476static int adev_close(hw_device_t *device)
1477{
1478 FNLOG();
1479
1480 free(device);
1481 return 0;
1482}
1483
1484static int adev_open(const hw_module_t* module, const char* name,
1485 hw_device_t** device)
1486{
1487 struct a2dp_audio_device *adev;
1488 int ret;
1489
1490 INFO(" adev_open in A2dp_hw module");
1491 FNLOG();
1492
1493 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1494 {
1495 ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
1496 return -EINVAL;
1497 }
1498
1499 adev = calloc(1, sizeof(struct a2dp_audio_device));
1500
1501 if (!adev)
1502 return -ENOMEM;
1503
1504 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Eric Laurent9a445032014-03-20 18:01:09 -07001505 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001506 adev->device.common.module = (struct hw_module_t *) module;
1507 adev->device.common.close = adev_close;
1508
1509 adev->device.init_check = adev_init_check;
1510 adev->device.set_voice_volume = adev_set_voice_volume;
1511 adev->device.set_master_volume = adev_set_master_volume;
1512 adev->device.set_mode = adev_set_mode;
1513 adev->device.set_mic_mute = adev_set_mic_mute;
1514 adev->device.get_mic_mute = adev_get_mic_mute;
1515 adev->device.set_parameters = adev_set_parameters;
1516 adev->device.get_parameters = adev_get_parameters;
1517 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1518 adev->device.open_output_stream = adev_open_output_stream;
1519 adev->device.close_output_stream = adev_close_output_stream;
1520 adev->device.open_input_stream = adev_open_input_stream;
1521 adev->device.close_input_stream = adev_close_input_stream;
1522 adev->device.dump = adev_dump;
1523
1524 adev->output = NULL;
1525
1526
1527 *device = &adev->device.common;
1528
1529 return 0;
1530}
1531
1532static struct hw_module_methods_t hal_module_methods = {
1533 .open = adev_open,
1534};
1535
1536struct audio_module HAL_MODULE_INFO_SYM = {
1537 .common = {
1538 .tag = HARDWARE_MODULE_TAG,
1539 .version_major = 1,
1540 .version_minor = 0,
1541 .id = AUDIO_HARDWARE_MODULE_ID,
1542 .name = "A2DP Audio HW HAL",
1543 .author = "The Android Open Source Project",
1544 .methods = &hal_module_methods,
1545 },
1546};
1547