1 /******************************************************************************
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 *****************************************************************************/
26
27 #include <errno.h>
28 #include <inttypes.h>
29 #include <pthread.h>
30 #include <stdint.h>
31 #include <sys/time.h>
32 #include <sys/socket.h>
33 #include <sys/un.h>
34 #include <sys/poll.h>
35 #include <sys/errno.h>
36 #include <sys/stat.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <cutils/str_parms.h>
40 #include <cutils/sockets.h>
41
42 #include <system/audio.h>
43 #include <hardware/audio.h>
44
45 #include <hardware/hardware.h>
46 #include "audio_a2dp_hw.h"
47 #include "bt_utils.h"
48
49 #define LOG_TAG "bt_a2dp_hw"
50 #include "osi/include/log.h"
51
52 /*****************************************************************************
53 ** Constants & Macros
54 ******************************************************************************/
55
56 #define CTRL_CHAN_RETRY_COUNT 3
57 #define USEC_PER_SEC 1000000L
58
59 #define CASE_RETURN_STR(const) case const: return #const;
60
61 #define FNLOG() LOG_VERBOSE("%s", __FUNCTION__);
62 #define DEBUG(fmt, ...) LOG_VERBOSE("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
63 #define INFO(fmt, ...) LOG_INFO("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
64 #define ERROR(fmt, ...) LOG_ERROR("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
65
66 #define ASSERTC(cond, msg, val) if (!(cond)) {ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, val);}
67
68 /*****************************************************************************
69 ** Local type definitions
70 ******************************************************************************/
71
72 typedef enum {
73 AUDIO_A2DP_STATE_STARTING,
74 AUDIO_A2DP_STATE_STARTED,
75 AUDIO_A2DP_STATE_STOPPING,
76 AUDIO_A2DP_STATE_STOPPED,
77 AUDIO_A2DP_STATE_SUSPENDED, /* need explicit set param call to resume (suspend=false) */
78 AUDIO_A2DP_STATE_STANDBY /* allows write to autoresume */
79 } a2dp_state_t;
80
81 struct a2dp_stream_in;
82 struct a2dp_stream_out;
83
84 struct a2dp_audio_device {
85 struct audio_hw_device device;
86 struct a2dp_stream_in *input;
87 struct a2dp_stream_out *output;
88 };
89
90 struct a2dp_config {
91 uint32_t rate;
92 uint32_t channel_flags;
93 int format;
94 };
95
96 /* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
97
98 struct a2dp_stream_common {
99 pthread_mutex_t lock;
100 int ctrl_fd;
101 int audio_fd;
102 size_t buffer_sz;
103 struct a2dp_config cfg;
104 a2dp_state_t state;
105 };
106
107 struct a2dp_stream_out {
108 struct audio_stream_out stream;
109 struct a2dp_stream_common common;
110 uint64_t frames_presented; // frames written, never reset
111 uint64_t frames_rendered; // frames written, reset on standby
112 };
113
114 struct a2dp_stream_in {
115 struct audio_stream_in stream;
116 struct a2dp_stream_common common;
117 };
118
119 /*****************************************************************************
120 ** Static variables
121 ******************************************************************************/
122
123 /*****************************************************************************
124 ** Static functions
125 ******************************************************************************/
126
127 static size_t out_get_buffer_size(const struct audio_stream *stream);
128
129 /*****************************************************************************
130 ** Externs
131 ******************************************************************************/
132
133 /*****************************************************************************
134 ** Functions
135 ******************************************************************************/
136
137 /*****************************************************************************
138 ** Miscellaneous helper functions
139 ******************************************************************************/
140
dump_a2dp_ctrl_event(char event)141 static const char* dump_a2dp_ctrl_event(char event)
142 {
143 switch(event)
144 {
145 CASE_RETURN_STR(A2DP_CTRL_CMD_NONE)
146 CASE_RETURN_STR(A2DP_CTRL_CMD_CHECK_READY)
147 CASE_RETURN_STR(A2DP_CTRL_CMD_START)
148 CASE_RETURN_STR(A2DP_CTRL_CMD_STOP)
149 CASE_RETURN_STR(A2DP_CTRL_CMD_SUSPEND)
150 default:
151 return "UNKNOWN MSG ID";
152 }
153 }
154
155 /* logs timestamp with microsec precision
156 pprev is optional in case a dedicated diff is required */
ts_log(char * tag,int val,struct timespec * pprev_opt)157 static void ts_log(char *tag, int val, struct timespec *pprev_opt)
158 {
159 struct timespec now;
160 static struct timespec prev = {0,0};
161 unsigned long long now_us;
162 unsigned long long diff_us;
163 UNUSED(tag);
164 UNUSED(val);
165
166 clock_gettime(CLOCK_MONOTONIC, &now);
167
168 now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
169
170 if (pprev_opt)
171 {
172 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
173 *pprev_opt = now;
174 DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
175 }
176 else
177 {
178 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
179 prev = now;
180 DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
181 }
182 }
183
calc_audiotime(struct a2dp_config cfg,int bytes)184 static int calc_audiotime(struct a2dp_config cfg, int bytes)
185 {
186 int chan_count = popcount(cfg.channel_flags);
187
188 ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT,
189 "unsupported sample sz", cfg.format);
190
191 return bytes*(1000000/(chan_count*2))/cfg.rate;
192 }
193
194 /*****************************************************************************
195 **
196 ** bluedroid stack adaptation
197 **
198 *****************************************************************************/
199
skt_connect(char * path,size_t buffer_sz)200 static int skt_connect(char *path, size_t buffer_sz)
201 {
202 int ret;
203 int skt_fd;
204 struct sockaddr_un remote;
205 int len;
206
207 INFO("connect to %s (sz %zu)", path, buffer_sz);
208
209 skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
210
211 if(socket_local_client_connect(skt_fd, path,
212 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0)
213 {
214 ERROR("failed to connect (%s)", strerror(errno));
215 close(skt_fd);
216 return -1;
217 }
218
219 len = buffer_sz;
220 ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
221
222 /* only issue warning if failed */
223 if (ret < 0)
224 ERROR("setsockopt failed (%s)", strerror(errno));
225
226 ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len));
227
228 /* only issue warning if failed */
229 if (ret < 0)
230 ERROR("setsockopt failed (%s)", strerror(errno));
231
232 INFO("connected to stack fd = %d", skt_fd);
233
234 return skt_fd;
235 }
236
skt_read(int fd,void * p,size_t len)237 static int skt_read(int fd, void *p, size_t len)
238 {
239 int read;
240 struct pollfd pfd;
241 struct timespec ts;
242
243 FNLOG();
244
245 ts_log("skt_read recv", len, NULL);
246
247 if ((read = TEMP_FAILURE_RETRY(recv(fd, p, len, MSG_NOSIGNAL))) == -1)
248 {
249 ERROR("write failed with errno=%d\n", errno);
250 return -1;
251 }
252
253 return read;
254 }
255
skt_write(int fd,const void * p,size_t len)256 static int skt_write(int fd, const void *p, size_t len)
257 {
258 int sent;
259 struct pollfd pfd;
260
261 FNLOG();
262
263 pfd.fd = fd;
264 pfd.events = POLLOUT;
265
266 /* poll for 500 ms */
267
268 /* send time out */
269 if (TEMP_FAILURE_RETRY(poll(&pfd, 1, 500)) == 0)
270 return 0;
271
272 ts_log("skt_write", len, NULL);
273
274 if ((sent = TEMP_FAILURE_RETRY(send(fd, p, len, MSG_NOSIGNAL))) == -1)
275 {
276 ERROR("write failed with errno=%d\n", errno);
277 return -1;
278 }
279
280 return sent;
281 }
282
skt_disconnect(int fd)283 static int skt_disconnect(int fd)
284 {
285 INFO("fd %d", fd);
286
287 if (fd != AUDIO_SKT_DISCONNECTED)
288 {
289 shutdown(fd, SHUT_RDWR);
290 close(fd);
291 }
292 return 0;
293 }
294
295
296
297 /*****************************************************************************
298 **
299 ** AUDIO CONTROL PATH
300 **
301 *****************************************************************************/
302
a2dp_ctrl_receive(struct a2dp_stream_common * common,void * buffer,int length)303 static int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length)
304 {
305 int ret = TEMP_FAILURE_RETRY(recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
306 if (ret < 0)
307 {
308 ERROR("ack failed (%s)", strerror(errno));
309 if (errno == EINTR)
310 {
311 /* retry again */
312 ret = TEMP_FAILURE_RETRY(recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
313 if (ret < 0)
314 {
315 ERROR("ack failed (%s)", strerror(errno));
316 skt_disconnect(common->ctrl_fd);
317 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
318 return -1;
319 }
320 }
321 else
322 {
323 skt_disconnect(common->ctrl_fd);
324 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
325 return -1;
326
327 }
328 }
329 return ret;
330 }
331
a2dp_command(struct a2dp_stream_common * common,char cmd)332 static int a2dp_command(struct a2dp_stream_common *common, char cmd)
333 {
334 char ack;
335
336 DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
337
338 /* send command */
339 if (TEMP_FAILURE_RETRY(send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL)) == -1)
340 {
341 ERROR("cmd failed (%s)", strerror(errno));
342 skt_disconnect(common->ctrl_fd);
343 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
344 return -1;
345 }
346
347 /* wait for ack byte */
348 if (a2dp_ctrl_receive(common, &ack, 1) < 0)
349 return -1;
350
351 DEBUG("A2DP COMMAND %s DONE STATUS %d", dump_a2dp_ctrl_event(cmd), ack);
352
353 if (ack == A2DP_CTRL_ACK_INCALL_FAILURE)
354 return ack;
355 if (ack != A2DP_CTRL_ACK_SUCCESS)
356 return -1;
357
358 return 0;
359 }
360
check_a2dp_ready(struct a2dp_stream_common * common)361 static int check_a2dp_ready(struct a2dp_stream_common *common)
362 {
363 if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0)
364 {
365 ERROR("check a2dp ready failed");
366 return -1;
367 }
368 return 0;
369 }
370
a2dp_read_audio_config(struct a2dp_stream_common * common)371 static int a2dp_read_audio_config(struct a2dp_stream_common *common)
372 {
373 char cmd = A2DP_CTRL_GET_AUDIO_CONFIG;
374 uint32_t sample_rate;
375 uint8_t channel_count;
376
377 if (a2dp_command(common, A2DP_CTRL_GET_AUDIO_CONFIG) < 0)
378 {
379 ERROR("check a2dp ready failed");
380 return -1;
381 }
382
383 if (a2dp_ctrl_receive(common, &sample_rate, 4) < 0)
384 return -1;
385 if (a2dp_ctrl_receive(common, &channel_count, 1) < 0)
386 return -1;
387
388 common->cfg.channel_flags = (channel_count == 1 ? AUDIO_CHANNEL_IN_MONO : AUDIO_CHANNEL_IN_STEREO);
389 common->cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
390 common->cfg.rate = sample_rate;
391
392 INFO("got config %d %d", common->cfg.format, common->cfg.rate);
393
394 return 0;
395 }
396
a2dp_open_ctrl_path(struct a2dp_stream_common * common)397 static void a2dp_open_ctrl_path(struct a2dp_stream_common *common)
398 {
399 int i;
400
401 /* retry logic to catch any timing variations on control channel */
402 for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++)
403 {
404 /* connect control channel if not already connected */
405 if ((common->ctrl_fd = skt_connect(A2DP_CTRL_PATH, common->buffer_sz)) > 0)
406 {
407 /* success, now check if stack is ready */
408 if (check_a2dp_ready(common) == 0)
409 break;
410
411 ERROR("error : a2dp not ready, wait 250 ms and retry");
412 TEMP_FAILURE_RETRY(usleep(250000));
413 skt_disconnect(common->ctrl_fd);
414 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
415 }
416
417 /* ctrl channel not ready, wait a bit */
418 TEMP_FAILURE_RETRY(usleep(250000));
419 }
420 }
421
422 /*****************************************************************************
423 **
424 ** AUDIO DATA PATH
425 **
426 *****************************************************************************/
427
a2dp_stream_common_init(struct a2dp_stream_common * common)428 static void a2dp_stream_common_init(struct a2dp_stream_common *common)
429 {
430 pthread_mutexattr_t lock_attr;
431
432 FNLOG();
433
434 pthread_mutexattr_init(&lock_attr);
435 pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
436 pthread_mutex_init(&common->lock, &lock_attr);
437
438 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
439 common->audio_fd = AUDIO_SKT_DISCONNECTED;
440 common->state = AUDIO_A2DP_STATE_STOPPED;
441
442 /* manages max capacity of socket pipe */
443 common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
444 }
445
start_audio_datapath(struct a2dp_stream_common * common)446 static int start_audio_datapath(struct a2dp_stream_common *common)
447 {
448 INFO("state %d", common->state);
449
450 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
451 INFO("%s AUDIO_SKT_DISCONNECTED", __func__);
452 return -1;
453 }
454
455 int oldstate = common->state;
456 common->state = AUDIO_A2DP_STATE_STARTING;
457
458 int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START);
459 if (a2dp_status < 0)
460 {
461 ERROR("%s Audiopath start failed (status %d)", __func__, a2dp_status);
462
463 common->state = oldstate;
464 return -1;
465 }
466 else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE)
467 {
468 ERROR("%s Audiopath start failed - in call, move to suspended", __func__);
469 common->state = oldstate;
470 return -1;
471 }
472
473 /* connect socket if not yet connected */
474 if (common->audio_fd == AUDIO_SKT_DISCONNECTED)
475 {
476 common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);
477 if (common->audio_fd < 0)
478 {
479 common->state = oldstate;
480 return -1;
481 }
482
483 common->state = AUDIO_A2DP_STATE_STARTED;
484 }
485
486 return 0;
487 }
488
stop_audio_datapath(struct a2dp_stream_common * common)489 static int stop_audio_datapath(struct a2dp_stream_common *common)
490 {
491 int oldstate = common->state;
492
493 INFO("state %d", common->state);
494
495 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
496 return -1;
497
498 /* prevent any stray output writes from autostarting the stream
499 while stopping audiopath */
500 common->state = AUDIO_A2DP_STATE_STOPPING;
501
502 if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0)
503 {
504 ERROR("audiopath stop failed");
505 common->state = oldstate;
506 return -1;
507 }
508
509 common->state = AUDIO_A2DP_STATE_STOPPED;
510
511 /* disconnect audio path */
512 skt_disconnect(common->audio_fd);
513 common->audio_fd = AUDIO_SKT_DISCONNECTED;
514
515 return 0;
516 }
517
suspend_audio_datapath(struct a2dp_stream_common * common,bool standby)518 static int suspend_audio_datapath(struct a2dp_stream_common *common, bool standby)
519 {
520 INFO("state %d", common->state);
521
522 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED)
523 return -1;
524
525 if (common->state == AUDIO_A2DP_STATE_STOPPING)
526 return -1;
527
528 if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0)
529 return -1;
530
531 if (standby)
532 common->state = AUDIO_A2DP_STATE_STANDBY;
533 else
534 common->state = AUDIO_A2DP_STATE_SUSPENDED;
535
536 /* disconnect audio path */
537 skt_disconnect(common->audio_fd);
538
539 common->audio_fd = AUDIO_SKT_DISCONNECTED;
540
541 return 0;
542 }
543
544
545 /*****************************************************************************
546 **
547 ** audio output callbacks
548 **
549 *****************************************************************************/
550
out_write(struct audio_stream_out * stream,const void * buffer,size_t bytes)551 static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
552 size_t bytes)
553 {
554 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
555 int sent;
556
557 DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
558
559 pthread_mutex_lock(&out->common.lock);
560
561 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
562 {
563 DEBUG("stream suspended");
564 pthread_mutex_unlock(&out->common.lock);
565 return -1;
566 }
567
568 /* only allow autostarting if we are in stopped or standby */
569 if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
570 (out->common.state == AUDIO_A2DP_STATE_STANDBY))
571 {
572 if (start_audio_datapath(&out->common) < 0)
573 {
574 /* emulate time this write represents to avoid very fast write
575 failures during transition periods or remote suspend */
576
577 int us_delay = calc_audiotime(out->common.cfg, bytes);
578
579 DEBUG("emulate a2dp write delay (%d us)", us_delay);
580
581 TEMP_FAILURE_RETRY(usleep(us_delay));
582 pthread_mutex_unlock(&out->common.lock);
583 return -1;
584 }
585 }
586 else if (out->common.state != AUDIO_A2DP_STATE_STARTED)
587 {
588 ERROR("stream not in stopped or standby");
589 pthread_mutex_unlock(&out->common.lock);
590 return -1;
591 }
592
593 pthread_mutex_unlock(&out->common.lock);
594 sent = skt_write(out->common.audio_fd, buffer, bytes);
595
596 if (sent == -1) {
597 skt_disconnect(out->common.audio_fd);
598 out->common.audio_fd = AUDIO_SKT_DISCONNECTED;
599 if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
600 out->common.state = AUDIO_A2DP_STATE_STOPPED;
601 else
602 ERROR("write failed : stream suspended, avoid resetting state");
603 } else {
604 const size_t frames = bytes / audio_stream_out_frame_size(stream);
605 out->frames_rendered += frames;
606 out->frames_presented += frames;
607 }
608
609 DEBUG("wrote %d bytes out of %zu bytes", sent, bytes);
610 return sent;
611 }
612
613
out_get_sample_rate(const struct audio_stream * stream)614 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
615 {
616 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
617
618 DEBUG("rate %" PRIu32,out->common.cfg.rate);
619
620 return out->common.cfg.rate;
621 }
622
out_set_sample_rate(struct audio_stream * stream,uint32_t rate)623 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
624 {
625 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
626
627 DEBUG("out_set_sample_rate : %" PRIu32, rate);
628
629 if (rate != AUDIO_STREAM_DEFAULT_RATE)
630 {
631 ERROR("only rate %d supported", AUDIO_STREAM_DEFAULT_RATE);
632 return -1;
633 }
634
635 out->common.cfg.rate = rate;
636
637 return 0;
638 }
639
out_get_buffer_size(const struct audio_stream * stream)640 static size_t out_get_buffer_size(const struct audio_stream *stream)
641 {
642 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
643
644 DEBUG("buffer_size : %zu", out->common.buffer_sz);
645
646 return out->common.buffer_sz;
647 }
648
out_get_channels(const struct audio_stream * stream)649 static uint32_t out_get_channels(const struct audio_stream *stream)
650 {
651 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
652
653 DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_flags);
654
655 return out->common.cfg.channel_flags;
656 }
657
out_get_format(const struct audio_stream * stream)658 static audio_format_t out_get_format(const struct audio_stream *stream)
659 {
660 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
661 DEBUG("format 0x%x", out->common.cfg.format);
662 return out->common.cfg.format;
663 }
664
out_set_format(struct audio_stream * stream,audio_format_t format)665 static int out_set_format(struct audio_stream *stream, audio_format_t format)
666 {
667 UNUSED(format);
668 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
669 DEBUG("setting format not yet supported (0x%x)", format);
670 return -ENOSYS;
671 }
672
out_standby(struct audio_stream * stream)673 static int out_standby(struct audio_stream *stream)
674 {
675 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
676 int retVal = 0;
677
678 FNLOG();
679
680 pthread_mutex_lock(&out->common.lock);
681 // Do nothing in SUSPENDED state.
682 if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
683 retVal = suspend_audio_datapath(&out->common, true);
684 out->frames_rendered = 0; // rendered is reset, presented is not
685 pthread_mutex_unlock (&out->common.lock);
686
687 return retVal;
688 }
689
out_dump(const struct audio_stream * stream,int fd)690 static int out_dump(const struct audio_stream *stream, int fd)
691 {
692 UNUSED(fd);
693 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
694 FNLOG();
695 return 0;
696 }
697
out_set_parameters(struct audio_stream * stream,const char * kvpairs)698 static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
699 {
700 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
701 struct str_parms *parms;
702 char keyval[16];
703 int retval;
704 int status = 0;
705
706 INFO("state %d", out->common.state);
707
708 parms = str_parms_create_str(kvpairs);
709
710 /* dump params */
711 str_parms_dump(parms);
712
713 retval = str_parms_get_str(parms, "closing", keyval, sizeof(keyval));
714
715 if (retval >= 0)
716 {
717 if (strcmp(keyval, "true") == 0)
718 {
719 DEBUG("stream closing, disallow any writes");
720 pthread_mutex_lock(&out->common.lock);
721 out->common.state = AUDIO_A2DP_STATE_STOPPING;
722 pthread_mutex_unlock(&out->common.lock);
723 }
724 }
725
726 retval = str_parms_get_str(parms, "A2dpSuspended", keyval, sizeof(keyval));
727
728 if (retval >= 0)
729 {
730 pthread_mutex_lock(&out->common.lock);
731 if (strcmp(keyval, "true") == 0)
732 {
733 if (out->common.state == AUDIO_A2DP_STATE_STARTED)
734 status = suspend_audio_datapath(&out->common, false);
735 }
736 else
737 {
738 /* Do not start the streaming automatically. If the phone was streaming
739 * prior to being suspended, the next out_write shall trigger the
740 * AVDTP start procedure */
741 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
742 out->common.state = AUDIO_A2DP_STATE_STANDBY;
743 /* Irrespective of the state, return 0 */
744 }
745 pthread_mutex_unlock(&out->common.lock);
746 }
747
748 str_parms_destroy(parms);
749
750 return status;
751 }
752
out_get_parameters(const struct audio_stream * stream,const char * keys)753 static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
754 {
755 UNUSED(keys);
756 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
757
758 FNLOG();
759
760 /* add populating param here */
761
762 return strdup("");
763 }
764
out_get_latency(const struct audio_stream_out * stream)765 static uint32_t out_get_latency(const struct audio_stream_out *stream)
766 {
767 int latency_us;
768
769 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
770
771 FNLOG();
772
773 latency_us = ((out->common.buffer_sz * 1000 ) /
774 audio_stream_out_frame_size(&out->stream) /
775 out->common.cfg.rate) * 1000;
776
777
778 return (latency_us / 1000) + 200;
779 }
780
out_set_volume(struct audio_stream_out * stream,float left,float right)781 static int out_set_volume(struct audio_stream_out *stream, float left,
782 float right)
783 {
784 UNUSED(stream);
785 UNUSED(left);
786 UNUSED(right);
787
788 FNLOG();
789
790 /* volume controlled in audioflinger mixer (digital) */
791
792 return -ENOSYS;
793 }
794
out_get_presentation_position(const struct audio_stream_out * stream,uint64_t * frames,struct timespec * timestamp)795 static int out_get_presentation_position(const struct audio_stream_out *stream,
796 uint64_t *frames, struct timespec *timestamp)
797 {
798 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
799
800 FNLOG();
801 if (stream == NULL || frames == NULL || timestamp == NULL)
802 return -EINVAL;
803
804 int ret = -EWOULDBLOCK;
805 pthread_mutex_lock(&out->common.lock);
806 uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
807 if (out->frames_presented >= latency_frames) {
808 *frames = out->frames_presented - latency_frames;
809 clock_gettime(CLOCK_MONOTONIC, timestamp); // could also be associated with out_write().
810 ret = 0;
811 }
812 pthread_mutex_unlock(&out->common.lock);
813 return ret;
814 }
815
out_get_render_position(const struct audio_stream_out * stream,uint32_t * dsp_frames)816 static int out_get_render_position(const struct audio_stream_out *stream,
817 uint32_t *dsp_frames)
818 {
819 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
820
821 FNLOG();
822 if (stream == NULL || dsp_frames == NULL)
823 return -EINVAL;
824
825 pthread_mutex_lock(&out->common.lock);
826 uint64_t latency_frames = (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
827 if (out->frames_rendered >= latency_frames) {
828 *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames);
829 } else {
830 *dsp_frames = 0;
831 }
832 pthread_mutex_unlock(&out->common.lock);
833 return 0;
834 }
835
out_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)836 static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
837 {
838 UNUSED(stream);
839 UNUSED(effect);
840
841 FNLOG();
842 return 0;
843 }
844
out_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)845 static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
846 {
847 UNUSED(stream);
848 UNUSED(effect);
849
850 FNLOG();
851 return 0;
852 }
853
854 /*
855 * AUDIO INPUT STREAM
856 */
857
in_get_sample_rate(const struct audio_stream * stream)858 static uint32_t in_get_sample_rate(const struct audio_stream *stream)
859 {
860 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
861
862 FNLOG();
863 return in->common.cfg.rate;
864 }
865
in_set_sample_rate(struct audio_stream * stream,uint32_t rate)866 static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
867 {
868 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
869
870 FNLOG();
871
872 if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate)
873 return 0;
874 else
875 return -1;
876 }
877
in_get_buffer_size(const struct audio_stream * stream)878 static size_t in_get_buffer_size(const struct audio_stream *stream)
879 {
880 UNUSED(stream);
881
882 FNLOG();
883 return 320;
884 }
885
in_get_channels(const struct audio_stream * stream)886 static uint32_t in_get_channels(const struct audio_stream *stream)
887 {
888 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
889
890 FNLOG();
891 return in->common.cfg.channel_flags;
892 }
893
in_get_format(const struct audio_stream * stream)894 static audio_format_t in_get_format(const struct audio_stream *stream)
895 {
896 UNUSED(stream);
897
898 FNLOG();
899 return AUDIO_FORMAT_PCM_16_BIT;
900 }
901
in_set_format(struct audio_stream * stream,audio_format_t format)902 static int in_set_format(struct audio_stream *stream, audio_format_t format)
903 {
904 UNUSED(stream);
905 UNUSED(format);
906
907 FNLOG();
908 if (format == AUDIO_FORMAT_PCM_16_BIT)
909 return 0;
910 else
911 return -1;
912 }
913
in_standby(struct audio_stream * stream)914 static int in_standby(struct audio_stream *stream)
915 {
916 UNUSED(stream);
917
918 FNLOG();
919 return 0;
920 }
921
in_dump(const struct audio_stream * stream,int fd)922 static int in_dump(const struct audio_stream *stream, int fd)
923 {
924 UNUSED(stream);
925 UNUSED(fd);
926
927 FNLOG();
928 return 0;
929 }
930
in_set_parameters(struct audio_stream * stream,const char * kvpairs)931 static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
932 {
933 UNUSED(stream);
934 UNUSED(kvpairs);
935
936 FNLOG();
937 return 0;
938 }
939
in_get_parameters(const struct audio_stream * stream,const char * keys)940 static char * in_get_parameters(const struct audio_stream *stream,
941 const char *keys)
942 {
943 UNUSED(stream);
944 UNUSED(keys);
945
946 FNLOG();
947 return strdup("");
948 }
949
in_set_gain(struct audio_stream_in * stream,float gain)950 static int in_set_gain(struct audio_stream_in *stream, float gain)
951 {
952 UNUSED(stream);
953 UNUSED(gain);
954
955 FNLOG();
956 return 0;
957 }
958
in_read(struct audio_stream_in * stream,void * buffer,size_t bytes)959 static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
960 size_t bytes)
961 {
962 struct a2dp_stream_in *in = (struct a2dp_stream_in *)stream;
963 int read;
964
965 DEBUG("read %zu bytes, state: %d", bytes, in->common.state);
966
967 if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED)
968 {
969 DEBUG("stream suspended");
970 return -1;
971 }
972
973 /* only allow autostarting if we are in stopped or standby */
974 if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
975 (in->common.state == AUDIO_A2DP_STATE_STANDBY))
976 {
977 pthread_mutex_lock(&in->common.lock);
978
979 if (start_audio_datapath(&in->common) < 0)
980 {
981 /* emulate time this write represents to avoid very fast write
982 failures during transition periods or remote suspend */
983
984 int us_delay = calc_audiotime(in->common.cfg, bytes);
985
986 DEBUG("emulate a2dp read delay (%d us)", us_delay);
987
988 TEMP_FAILURE_RETRY(usleep(us_delay));
989 pthread_mutex_unlock(&in->common.lock);
990 return -1;
991 }
992
993 pthread_mutex_unlock(&in->common.lock);
994 }
995 else if (in->common.state != AUDIO_A2DP_STATE_STARTED)
996 {
997 ERROR("stream not in stopped or standby");
998 return -1;
999 }
1000
1001 read = skt_read(in->common.audio_fd, buffer, bytes);
1002
1003 if (read == -1)
1004 {
1005 skt_disconnect(in->common.audio_fd);
1006 in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
1007 in->common.state = AUDIO_A2DP_STATE_STOPPED;
1008 } else if (read == 0) {
1009 DEBUG("read time out - return zeros");
1010 memset(buffer, 0, bytes);
1011 read = bytes;
1012 }
1013
1014 DEBUG("read %d bytes out of %zu bytes", read, bytes);
1015 return read;
1016 }
1017
in_get_input_frames_lost(struct audio_stream_in * stream)1018 static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1019 {
1020 UNUSED(stream);
1021
1022 FNLOG();
1023 return 0;
1024 }
1025
in_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)1026 static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1027 {
1028 UNUSED(stream);
1029 UNUSED(effect);
1030
1031 FNLOG();
1032 return 0;
1033 }
1034
in_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)1035 static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1036 {
1037 UNUSED(stream);
1038 UNUSED(effect);
1039
1040 FNLOG();
1041
1042 return 0;
1043 }
1044
adev_open_output_stream(struct audio_hw_device * dev,audio_io_handle_t handle,audio_devices_t devices,audio_output_flags_t flags,struct audio_config * config,struct audio_stream_out ** stream_out,const char * address)1045 static int adev_open_output_stream(struct audio_hw_device *dev,
1046 audio_io_handle_t handle,
1047 audio_devices_t devices,
1048 audio_output_flags_t flags,
1049 struct audio_config *config,
1050 struct audio_stream_out **stream_out,
1051 const char *address)
1052
1053 {
1054 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1055 struct a2dp_stream_out *out;
1056 int ret = 0;
1057 int i;
1058 UNUSED(address);
1059 UNUSED(handle);
1060 UNUSED(devices);
1061 UNUSED(flags);
1062
1063 INFO("opening output");
1064
1065 out = (struct a2dp_stream_out *)calloc(1, sizeof(struct a2dp_stream_out));
1066
1067 if (!out)
1068 return -ENOMEM;
1069
1070 out->stream.common.get_sample_rate = out_get_sample_rate;
1071 out->stream.common.set_sample_rate = out_set_sample_rate;
1072 out->stream.common.get_buffer_size = out_get_buffer_size;
1073 out->stream.common.get_channels = out_get_channels;
1074 out->stream.common.get_format = out_get_format;
1075 out->stream.common.set_format = out_set_format;
1076 out->stream.common.standby = out_standby;
1077 out->stream.common.dump = out_dump;
1078 out->stream.common.set_parameters = out_set_parameters;
1079 out->stream.common.get_parameters = out_get_parameters;
1080 out->stream.common.add_audio_effect = out_add_audio_effect;
1081 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1082 out->stream.get_latency = out_get_latency;
1083 out->stream.set_volume = out_set_volume;
1084 out->stream.write = out_write;
1085 out->stream.get_render_position = out_get_render_position;
1086 out->stream.get_presentation_position = out_get_presentation_position;
1087
1088
1089 /* initialize a2dp specifics */
1090 a2dp_stream_common_init(&out->common);
1091
1092 out->common.cfg.channel_flags = AUDIO_STREAM_DEFAULT_CHANNEL_FLAG;
1093 out->common.cfg.format = AUDIO_STREAM_DEFAULT_FORMAT;
1094 out->common.cfg.rate = AUDIO_STREAM_DEFAULT_RATE;
1095
1096 /* set output config values */
1097 if (config)
1098 {
1099 config->format = out_get_format((const struct audio_stream *)&out->stream);
1100 config->sample_rate = out_get_sample_rate((const struct audio_stream *)&out->stream);
1101 config->channel_mask = out_get_channels((const struct audio_stream *)&out->stream);
1102 }
1103 *stream_out = &out->stream;
1104 a2dp_dev->output = out;
1105
1106 a2dp_open_ctrl_path(&out->common);
1107 if (out->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
1108 {
1109 ERROR("ctrl socket failed to connect (%s)", strerror(errno));
1110 ret = -1;
1111 goto err_open;
1112 }
1113
1114 DEBUG("success");
1115 /* Delay to ensure Headset is in proper state when START is initiated
1116 from DUT immediately after the connection due to ongoing music playback. */
1117 TEMP_FAILURE_RETRY(usleep(250000));
1118 return 0;
1119
1120 err_open:
1121 free(out);
1122 *stream_out = NULL;
1123 a2dp_dev->output = NULL;
1124 ERROR("failed");
1125 return ret;
1126 }
1127
adev_close_output_stream(struct audio_hw_device * dev,struct audio_stream_out * stream)1128 static void adev_close_output_stream(struct audio_hw_device *dev,
1129 struct audio_stream_out *stream)
1130 {
1131 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1132 struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream;
1133
1134 INFO("closing output (state %d)", out->common.state);
1135
1136 pthread_mutex_lock(&out->common.lock);
1137 if ((out->common.state == AUDIO_A2DP_STATE_STARTED) || (out->common.state == AUDIO_A2DP_STATE_STOPPING))
1138 stop_audio_datapath(&out->common);
1139
1140 skt_disconnect(out->common.ctrl_fd);
1141 free(stream);
1142 a2dp_dev->output = NULL;
1143 pthread_mutex_unlock(&out->common.lock);
1144
1145 DEBUG("done");
1146 }
1147
adev_set_parameters(struct audio_hw_device * dev,const char * kvpairs)1148 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1149 {
1150 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1151 struct a2dp_stream_out *out = a2dp_dev->output;
1152 int retval = 0;
1153
1154 if (out == NULL)
1155 return retval;
1156
1157 INFO("state %d", out->common.state);
1158
1159 retval = out->stream.common.set_parameters((struct audio_stream *)out, kvpairs);
1160
1161 return retval;
1162 }
1163
adev_get_parameters(const struct audio_hw_device * dev,const char * keys)1164 static char * adev_get_parameters(const struct audio_hw_device *dev,
1165 const char *keys)
1166 {
1167 struct str_parms *parms;
1168 UNUSED(dev);
1169
1170 FNLOG();
1171
1172 parms = str_parms_create_str(keys);
1173
1174 str_parms_dump(parms);
1175
1176 str_parms_destroy(parms);
1177
1178 return strdup("");
1179 }
1180
adev_init_check(const struct audio_hw_device * dev)1181 static int adev_init_check(const struct audio_hw_device *dev)
1182 {
1183 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device*)dev;
1184
1185 FNLOG();
1186
1187 return 0;
1188 }
1189
adev_set_voice_volume(struct audio_hw_device * dev,float volume)1190 static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1191 {
1192 UNUSED(dev);
1193 UNUSED(volume);
1194
1195 FNLOG();
1196
1197 return -ENOSYS;
1198 }
1199
adev_set_master_volume(struct audio_hw_device * dev,float volume)1200 static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1201 {
1202 UNUSED(dev);
1203 UNUSED(volume);
1204
1205 FNLOG();
1206
1207 return -ENOSYS;
1208 }
1209
adev_set_mode(struct audio_hw_device * dev,int mode)1210 static int adev_set_mode(struct audio_hw_device *dev, int mode)
1211 {
1212 UNUSED(dev);
1213 UNUSED(mode);
1214
1215 FNLOG();
1216
1217 return 0;
1218 }
1219
adev_set_mic_mute(struct audio_hw_device * dev,bool state)1220 static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1221 {
1222 UNUSED(dev);
1223 UNUSED(state);
1224
1225 FNLOG();
1226
1227 return -ENOSYS;
1228 }
1229
adev_get_mic_mute(const struct audio_hw_device * dev,bool * state)1230 static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1231 {
1232 UNUSED(dev);
1233 UNUSED(state);
1234
1235 FNLOG();
1236
1237 return -ENOSYS;
1238 }
1239
adev_get_input_buffer_size(const struct audio_hw_device * dev,const struct audio_config * config)1240 static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
1241 const struct audio_config *config)
1242 {
1243 UNUSED(dev);
1244 UNUSED(config);
1245
1246 FNLOG();
1247
1248 return 320;
1249 }
1250
adev_open_input_stream(struct audio_hw_device * dev,audio_io_handle_t handle,audio_devices_t devices,struct audio_config * config,struct audio_stream_in ** stream_in,audio_input_flags_t flags,const char * address,audio_source_t source)1251 static int adev_open_input_stream(struct audio_hw_device *dev,
1252 audio_io_handle_t handle,
1253 audio_devices_t devices,
1254 struct audio_config *config,
1255 struct audio_stream_in **stream_in,
1256 audio_input_flags_t flags,
1257 const char *address,
1258 audio_source_t source)
1259 {
1260 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1261 struct a2dp_stream_in *in;
1262 int ret;
1263 UNUSED(address);
1264 UNUSED(config);
1265 UNUSED(devices);
1266 UNUSED(flags);
1267 UNUSED(handle);
1268 UNUSED(source);
1269
1270 FNLOG();
1271
1272 in = (struct a2dp_stream_in *)calloc(1, sizeof(struct a2dp_stream_in));
1273
1274 if (!in)
1275 return -ENOMEM;
1276
1277 in->stream.common.get_sample_rate = in_get_sample_rate;
1278 in->stream.common.set_sample_rate = in_set_sample_rate;
1279 in->stream.common.get_buffer_size = in_get_buffer_size;
1280 in->stream.common.get_channels = in_get_channels;
1281 in->stream.common.get_format = in_get_format;
1282 in->stream.common.set_format = in_set_format;
1283 in->stream.common.standby = in_standby;
1284 in->stream.common.dump = in_dump;
1285 in->stream.common.set_parameters = in_set_parameters;
1286 in->stream.common.get_parameters = in_get_parameters;
1287 in->stream.common.add_audio_effect = in_add_audio_effect;
1288 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1289 in->stream.set_gain = in_set_gain;
1290 in->stream.read = in_read;
1291 in->stream.get_input_frames_lost = in_get_input_frames_lost;
1292
1293 /* initialize a2dp specifics */
1294 a2dp_stream_common_init(&in->common);
1295
1296 *stream_in = &in->stream;
1297 a2dp_dev->input = in;
1298
1299 a2dp_open_ctrl_path(&in->common);
1300 if (in->common.ctrl_fd == AUDIO_SKT_DISCONNECTED)
1301 {
1302 ERROR("ctrl socket failed to connect (%s)", strerror(errno));
1303 ret = -1;
1304 goto err_open;
1305 }
1306
1307 if (a2dp_read_audio_config(&in->common) < 0) {
1308 ERROR("a2dp_read_audio_config failed (%s)", strerror(errno));
1309 ret = -1;
1310 goto err_open;
1311 }
1312
1313 DEBUG("success");
1314 return 0;
1315
1316 err_open:
1317 free(in);
1318 *stream_in = NULL;
1319 a2dp_dev->input = NULL;
1320 ERROR("failed");
1321 return ret;
1322 }
1323
adev_close_input_stream(struct audio_hw_device * dev,struct audio_stream_in * stream)1324 static void adev_close_input_stream(struct audio_hw_device *dev,
1325 struct audio_stream_in *stream)
1326 {
1327 struct a2dp_audio_device *a2dp_dev = (struct a2dp_audio_device *)dev;
1328 struct a2dp_stream_in* in = (struct a2dp_stream_in *)stream;
1329 a2dp_state_t state = in->common.state;
1330
1331 INFO("closing input (state %d)", state);
1332
1333 if ((state == AUDIO_A2DP_STATE_STARTED) || (state == AUDIO_A2DP_STATE_STOPPING))
1334 stop_audio_datapath(&in->common);
1335
1336 skt_disconnect(in->common.ctrl_fd);
1337 free(stream);
1338 a2dp_dev->input = NULL;
1339
1340 DEBUG("done");
1341 }
1342
adev_dump(const audio_hw_device_t * device,int fd)1343 static int adev_dump(const audio_hw_device_t *device, int fd)
1344 {
1345 UNUSED(device);
1346 UNUSED(fd);
1347
1348 FNLOG();
1349
1350 return 0;
1351 }
1352
adev_close(hw_device_t * device)1353 static int adev_close(hw_device_t *device)
1354 {
1355 FNLOG();
1356
1357 free(device);
1358 return 0;
1359 }
1360
adev_open(const hw_module_t * module,const char * name,hw_device_t ** device)1361 static int adev_open(const hw_module_t* module, const char* name,
1362 hw_device_t** device)
1363 {
1364 struct a2dp_audio_device *adev;
1365 int ret;
1366
1367 INFO(" adev_open in A2dp_hw module");
1368 FNLOG();
1369
1370 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1371 {
1372 ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
1373 return -EINVAL;
1374 }
1375
1376 adev = calloc(1, sizeof(struct a2dp_audio_device));
1377
1378 if (!adev)
1379 return -ENOMEM;
1380
1381 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1382 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1383 adev->device.common.module = (struct hw_module_t *) module;
1384 adev->device.common.close = adev_close;
1385
1386 adev->device.init_check = adev_init_check;
1387 adev->device.set_voice_volume = adev_set_voice_volume;
1388 adev->device.set_master_volume = adev_set_master_volume;
1389 adev->device.set_mode = adev_set_mode;
1390 adev->device.set_mic_mute = adev_set_mic_mute;
1391 adev->device.get_mic_mute = adev_get_mic_mute;
1392 adev->device.set_parameters = adev_set_parameters;
1393 adev->device.get_parameters = adev_get_parameters;
1394 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1395 adev->device.open_output_stream = adev_open_output_stream;
1396 adev->device.close_output_stream = adev_close_output_stream;
1397 adev->device.open_input_stream = adev_open_input_stream;
1398 adev->device.close_input_stream = adev_close_input_stream;
1399 adev->device.dump = adev_dump;
1400
1401 adev->output = NULL;
1402
1403
1404 *device = &adev->device.common;
1405
1406 return 0;
1407 }
1408
1409 static struct hw_module_methods_t hal_module_methods = {
1410 .open = adev_open,
1411 };
1412
1413 struct audio_module HAL_MODULE_INFO_SYM = {
1414 .common = {
1415 .tag = HARDWARE_MODULE_TAG,
1416 .version_major = 1,
1417 .version_minor = 0,
1418 .id = AUDIO_HARDWARE_MODULE_ID,
1419 .name = "A2DP Audio HW HAL",
1420 .author = "The Android Open Source Project",
1421 .methods = &hal_module_methods,
1422 },
1423 };
1424