• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2008-2011 The Android Open Source Project
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Lesser General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2.1 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Lesser General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Lesser General Public
15  *  License along with this library; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19 
20 #define LOG_TAG "a2dp_audio_hw"
21 //#define LOG_NDEBUG 0
22 
23 #include <errno.h>
24 #include <pthread.h>
25 #include <stdint.h>
26 #include <sys/time.h>
27 
28 #include <cutils/log.h>
29 #include <cutils/str_parms.h>
30 
31 #include <hardware/hardware.h>
32 #include <system/audio.h>
33 #include <hardware/audio.h>
34 
35 #include <hardware_legacy/power.h>
36 
37 #include "liba2dp.h"
38 
39 #define A2DP_WAKE_LOCK_NAME            "A2dpOutputStream"
40 #define MAX_WRITE_RETRIES              5
41 
42 #define A2DP_SUSPENDED_PARM            "A2dpSuspended"
43 #define BLUETOOOTH_ENABLED_PARM        "bluetooth_enabled"
44 
45 #define OUT_SINK_ADDR_PARM             "a2dp_sink_address"
46 
47 /* NOTE: If you need to hold the adev_a2dp->lock AND the astream_out->lock,
48    you MUST take adev_a2dp lock first!!
49  */
50 
51 struct astream_out;
52 struct adev_a2dp {
53     struct audio_hw_device  device;
54 
55     audio_mode_t            mode;
56     bool                    bt_enabled;
57     bool                    suspended;
58 
59     pthread_mutex_t         lock;
60 
61     struct astream_out      *output;
62 };
63 
64 struct astream_out {
65     struct audio_stream_out stream;
66 
67     uint32_t                sample_rate;
68     size_t                  buffer_size;
69     uint32_t                channels;
70     int                     format;
71 
72     int                     fd;
73     bool                    standby;
74     int                     start_count;
75     int                     retry_count;
76     void*                   data;
77 
78     pthread_mutex_t         lock;
79 
80     audio_devices_t         device;
81     uint64_t                 last_write_time;
82     uint32_t                buffer_duration_us;
83 
84     bool                    bt_enabled;
85     bool                    suspended;
86     char                    a2dp_addr[20];
87 };
88 
system_time(void)89 static uint64_t system_time(void)
90 {
91     struct timespec t;
92 
93     t.tv_sec = t.tv_nsec = 0;
94     clock_gettime(CLOCK_MONOTONIC, &t);
95 
96     return t.tv_sec*1000000000LL + t.tv_nsec;
97 }
98 
99 /** audio_stream_out implementation **/
out_get_sample_rate(const struct audio_stream * stream)100 static uint32_t out_get_sample_rate(const struct audio_stream *stream)
101 {
102     const struct astream_out *out = (const struct astream_out *)stream;
103     return out->sample_rate;
104 }
105 
out_set_sample_rate(struct audio_stream * stream,uint32_t rate)106 static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
107 {
108     struct astream_out *out = (struct astream_out *)stream;
109 
110     LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
111     return 0;
112 }
113 
out_get_buffer_size(const struct audio_stream * stream)114 static size_t out_get_buffer_size(const struct audio_stream *stream)
115 {
116     const struct astream_out *out = (const struct astream_out *)stream;
117     return out->buffer_size;
118 }
119 
out_get_channels(const struct audio_stream * stream)120 static uint32_t out_get_channels(const struct audio_stream *stream)
121 {
122     const struct astream_out *out = (const struct astream_out *)stream;
123     return out->channels;
124 }
125 
out_get_format(const struct audio_stream * stream)126 static int out_get_format(const struct audio_stream *stream)
127 {
128     const struct astream_out *out = (const struct astream_out *)stream;
129     return out->format;
130 }
131 
out_set_format(struct audio_stream * stream,int format)132 static int out_set_format(struct audio_stream *stream, int format)
133 {
134     struct astream_out *out = (struct astream_out *)stream;
135     LOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
136     return 0;
137 }
138 
out_dump(const struct audio_stream * stream,int fd)139 static int out_dump(const struct audio_stream *stream, int fd)
140 {
141     return 0;
142 }
143 
out_get_latency(const struct audio_stream_out * stream)144 static uint32_t out_get_latency(const struct audio_stream_out *stream)
145 {
146     const struct astream_out *out = (const struct astream_out *)stream;
147 
148     return (out->buffer_duration_us / 1000) + 200;
149 }
150 
out_set_volume(struct audio_stream_out * stream,float left,float right)151 static int out_set_volume(struct audio_stream_out *stream, float left,
152                           float right)
153 {
154     return -ENOSYS;
155 }
156 
out_get_render_position(const struct audio_stream_out * stream,uint32_t * dsp_frames)157 static int out_get_render_position(const struct audio_stream_out *stream,
158                                    uint32_t *dsp_frames)
159 {
160     return -ENOSYS;
161 }
162 
_out_init_locked(struct astream_out * out,const char * addr)163 static int _out_init_locked(struct astream_out *out, const char *addr)
164 {
165     int ret;
166 
167     if (out->data)
168         return 0;
169 
170     /* XXX: shouldn't this use the sample_rate/channel_count from 'out'? */
171     ret = a2dp_init(44100, 2, &out->data);
172     if (ret < 0) {
173         LOGE("a2dp_init failed err: %d\n", ret);
174         out->data = NULL;
175         return ret;
176     }
177 
178     /* XXX: is this even necessary? */
179     if (addr)
180         strlcpy(out->a2dp_addr, addr, sizeof(out->a2dp_addr));
181     a2dp_set_sink(out->data, out->a2dp_addr);
182 
183     return 0;
184 }
185 
_out_validate_parms(struct astream_out * out,int format,uint32_t chans,uint32_t rate)186 static bool _out_validate_parms(struct astream_out *out, int format,
187                                 uint32_t chans, uint32_t rate)
188 {
189     if ((format && (format != out->format)) ||
190         (chans && (chans != out->channels)) ||
191         (rate && (rate != out->sample_rate)))
192         return false;
193     return true;
194 }
195 
out_standby_stream_locked(struct astream_out * out)196 static int out_standby_stream_locked(struct astream_out *out)
197 {
198     int ret = 0;
199 
200     if (out->standby || !out->data)
201         return 0;
202 
203     LOGV_IF(!out->bt_enabled, "Standby skip stop: enabled %d", out->bt_enabled);
204     if (out->bt_enabled)
205         ret = a2dp_stop(out->data);
206     release_wake_lock(A2DP_WAKE_LOCK_NAME);
207     out->standby = true;
208 
209     return ret;
210 }
211 
out_close_stream_locked(struct astream_out * out)212 static int out_close_stream_locked(struct astream_out *out)
213 {
214     out_standby_stream_locked(out);
215 
216     if (out->data) {
217         LOGV("%s: calling a2dp_cleanup()", __func__);
218         a2dp_cleanup(out->data);
219         out->data = NULL;
220     }
221 
222     return 0;
223 }
224 
out_standby(struct audio_stream * stream)225 static int out_standby(struct audio_stream *stream)
226 {
227     struct astream_out *out = (struct astream_out *)stream;
228 
229     pthread_mutex_lock(&out->lock);
230     out_standby_stream_locked(out);
231     pthread_mutex_unlock(&out->lock);
232 
233     return 0;
234 }
235 
out_set_parameters(struct audio_stream * stream,const char * kvpairs)236 static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
237 {
238     struct astream_out *out = (struct astream_out *)stream;
239     struct str_parms *parms;
240     char *str;
241     char value[32];
242     int ret;
243 
244     parms = str_parms_create_str(kvpairs);
245 
246     pthread_mutex_lock(&out->lock);
247 
248     ret = str_parms_get_str(parms, OUT_SINK_ADDR_PARM, value, sizeof(value));
249     if (ret >= 0) {
250         /* strlen(00:00:00:00:00:00) == 17 */
251         if (strlen(value) == 17) {
252             strlcpy(out->a2dp_addr, value, sizeof(out->a2dp_addr));
253             if (out->data)
254                 a2dp_set_sink(out->data, out->a2dp_addr);
255         } else
256             ret = -EINVAL;
257     }
258 
259     pthread_mutex_unlock(&out->lock);
260     str_parms_destroy(parms);
261     return ret;
262 }
263 
out_get_device(const struct audio_stream * stream)264 static audio_devices_t out_get_device(const struct audio_stream *stream)
265 {
266     const struct astream_out *out = (const struct astream_out *)stream;
267     return out->device;
268 }
269 
270 
out_set_device(struct audio_stream * stream,audio_devices_t device)271 static int out_set_device(struct audio_stream *stream, audio_devices_t device)
272 {
273     struct astream_out *out = (struct astream_out *)stream;
274 
275     if (!audio_is_a2dp_device(device))
276         return -EINVAL;
277 
278     /* XXX: if out->device ever starts getting used for anything, need to
279      * grab the out->lock */
280     out->device = device;
281     return 0;
282 }
283 
out_get_parameters(const struct audio_stream * stream,const char * keys)284 static char * out_get_parameters(const struct audio_stream *stream,
285                                  const char *keys)
286 {
287     struct astream_out *out = (struct astream_out *)stream;
288     struct str_parms *parms;
289     struct str_parms *out_parms;
290     char *str;
291     char value[20];
292     int ret;
293 
294     parms = str_parms_create_str(keys);
295     out_parms = str_parms_create();
296 
297     pthread_mutex_lock(&out->lock);
298 
299     ret = str_parms_get_str(parms, OUT_SINK_ADDR_PARM, value, sizeof(value));
300     if (ret >= 0)
301         str_parms_add_str(out_parms, OUT_SINK_ADDR_PARM, out->a2dp_addr);
302 
303     pthread_mutex_unlock(&out->lock);
304 
305     str = str_parms_to_str(out_parms);
306     str_parms_destroy(out_parms);
307     str_parms_destroy(parms);
308 
309     return str;
310 }
311 
out_write(struct audio_stream_out * stream,const void * buffer,size_t bytes)312 static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
313                          size_t bytes)
314 {
315     struct astream_out *out = (struct astream_out *)stream;
316     int ret;
317     int cnt = bytes;
318     int retries = MAX_WRITE_RETRIES;
319     uint64_t now;
320     uint32_t elapsed_us;
321     const uint8_t *buf = buffer;
322 
323     pthread_mutex_lock(&out->lock);
324     if (!out->bt_enabled || out->suspended) {
325         LOGV("a2dp %s: bluetooth disabled bt_en %d, suspended %d",
326              out->bt_enabled, out->suspended);
327         ret = -1;
328         goto err_bt_disabled;
329     }
330 
331     if (out->standby) {
332         acquire_wake_lock(PARTIAL_WAKE_LOCK, A2DP_WAKE_LOCK_NAME);
333         out->standby = false;
334         out->last_write_time = system_time();
335     }
336 
337     ret = _out_init_locked(out, NULL);
338     if (ret < 0)
339         goto err_init;
340 
341     while (cnt > 0 && retries > 0) {
342         ret = a2dp_write(out->data, buf, cnt);
343         if (ret < 0) {
344             LOGE("%s: a2dp_write failed (%d)\n", __func__, ret);
345             goto err_write;
346         } else if (ret == 0) {
347             retries--;
348             continue;
349         }
350 
351         cnt -= ret;
352         buf += ret;
353     }
354 
355     /* XXX: PLEASE FIX ME!!!! */
356 
357     /* if A2DP sink runs abnormally fast, sleep a little so that
358      * audioflinger mixer thread does no spin and starve other threads. */
359     /* NOTE: It is likely that the A2DP headset is being disconnected */
360     now = system_time();
361     elapsed_us = (now - out->last_write_time) / 1000UL;
362     if (elapsed_us < (out->buffer_duration_us / 4)) {
363         LOGV("A2DP sink runs too fast");
364         usleep(out->buffer_duration_us - elapsed_us);
365     }
366     out->last_write_time = now;
367 
368     pthread_mutex_unlock(&out->lock);
369 
370     return bytes;
371 
372 err_write:
373 err_init:
374 err_bt_disabled:
375     out_standby_stream_locked(out);
376     pthread_mutex_unlock(&out->lock);
377 
378     /* XXX: simulate audio output timing in case of error?!?! */
379     usleep(out->buffer_duration_us);
380     return ret;
381 }
382 
out_add_audio_effect(const struct audio_stream * stream,effect_handle_t effect)383 static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
384 {
385     return 0;
386 }
387 
out_remove_audio_effect(const struct audio_stream * stream,effect_handle_t effect)388 static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
389 {
390     return 0;
391 }
392 
_out_bt_enable(struct astream_out * out,bool enable)393 static int _out_bt_enable(struct astream_out *out, bool enable)
394 {
395     int ret = 0;
396 
397     pthread_mutex_lock(&out->lock);
398     out->bt_enabled = enable;
399     if (!enable)
400         ret = out_close_stream_locked(out);
401     pthread_mutex_unlock(&out->lock);
402 
403     return ret;
404 }
405 
_out_a2dp_suspend(struct astream_out * out,bool suspend)406 static int _out_a2dp_suspend(struct astream_out *out, bool suspend)
407 {
408     pthread_mutex_lock(&out->lock);
409     out->suspended = suspend;
410     out_standby_stream_locked(out);
411     pthread_mutex_unlock(&out->lock);
412 
413     return 0;
414 }
415 
adev_open_output_stream(struct audio_hw_device * dev,uint32_t devices,int * format,uint32_t * channels,uint32_t * sample_rate,struct audio_stream_out ** stream_out)416 static int adev_open_output_stream(struct audio_hw_device *dev,
417                                    uint32_t devices, int *format,
418                                    uint32_t *channels, uint32_t *sample_rate,
419                                    struct audio_stream_out **stream_out)
420 {
421     struct adev_a2dp *adev = (struct adev_a2dp *)dev;
422     struct astream_out *out;
423     int ret;
424 
425     pthread_mutex_lock(&adev->lock);
426 
427     /* one output stream at a time */
428     if (adev->output) {
429         LOGV("output exists");
430         ret = -EBUSY;
431         goto err_output_exists;
432     }
433 
434     out = calloc(1, sizeof(struct astream_out));
435     if (!out) {
436         ret = -ENOMEM;
437         goto err_alloc;
438     }
439 
440     pthread_mutex_init(&out->lock, NULL);
441 
442     out->stream.common.get_sample_rate = out_get_sample_rate;
443     out->stream.common.set_sample_rate = out_set_sample_rate;
444     out->stream.common.get_buffer_size = out_get_buffer_size;
445     out->stream.common.get_channels = out_get_channels;
446     out->stream.common.get_format = out_get_format;
447     out->stream.common.set_format = out_set_format;
448     out->stream.common.standby = out_standby;
449     out->stream.common.dump = out_dump;
450     out->stream.common.set_parameters = out_set_parameters;
451     out->stream.common.get_parameters = out_get_parameters;
452     out->stream.common.set_device = out_set_device;
453     out->stream.common.get_device = out_get_device;
454     out->stream.common.add_audio_effect = out_add_audio_effect;
455     out->stream.common.remove_audio_effect = out_remove_audio_effect;
456     out->stream.get_latency = out_get_latency;
457     out->stream.set_volume = out_set_volume;
458     out->stream.write = out_write;
459     out->stream.get_render_position = out_get_render_position;
460 
461     out->sample_rate = 44100;
462     out->buffer_size = 512 * 20;
463     out->channels = AUDIO_CHANNEL_OUT_STEREO;
464     out->format = AUDIO_FORMAT_PCM_16_BIT;
465 
466     out->fd = -1;
467     out->device = devices;
468     out->bt_enabled = adev->bt_enabled;
469     out->suspended = adev->suspended;
470 
471     /* for now, buffer_duration_us is precalculated and never changed.
472      * if the sample rate or the format ever changes on the fly, we'd have
473      * to recalculate this */
474     out->buffer_duration_us = ((out->buffer_size * 1000 ) /
475                                audio_stream_frame_size(&out->stream.common) /
476                                out->sample_rate) * 1000;
477     if (!_out_validate_parms(out, format ? *format : 0,
478                              channels ? *channels : 0,
479                              sample_rate ? *sample_rate : 0)) {
480         LOGV("invalid parameters");
481         ret = -EINVAL;
482         goto err_validate_parms;
483     }
484 
485     /* XXX: check return code? */
486     if (adev->bt_enabled)
487         _out_init_locked(out, "00:00:00:00:00:00");
488 
489     adev->output = out;
490 
491     if (format)
492         *format = out->format;
493     if (channels)
494         *channels = out->channels;
495     if (sample_rate)
496         *sample_rate = out->sample_rate;
497 
498     pthread_mutex_unlock(&adev->lock);
499 
500     *stream_out = &out->stream;
501 
502     return 0;
503 
504 err_validate_parms:
505     free(out);
506 err_alloc:
507 err_output_exists:
508     pthread_mutex_unlock(&adev->lock);
509     *stream_out = NULL;
510     return ret;
511 }
512 
513 /* needs the adev->lock held */
adev_close_output_stream_locked(struct adev_a2dp * dev,struct astream_out * stream)514 static void adev_close_output_stream_locked(struct adev_a2dp *dev,
515                                             struct astream_out *stream)
516 {
517     struct adev_a2dp *adev = (struct adev_a2dp *)dev;
518     struct astream_out *out = (struct astream_out *)stream;
519 
520     /* invalid stream? */
521     if (!adev->output || adev->output != out) {
522         LOGE("%s: unknown stream %p (ours is %p)", __func__, out, adev->output);
523         return;
524     }
525 
526     pthread_mutex_lock(&out->lock);
527     out_close_stream_locked(out);
528     pthread_mutex_unlock(&out->lock);
529 
530     adev->output = NULL;
531     free(out);
532 }
533 
adev_close_output_stream(struct audio_hw_device * dev,struct audio_stream_out * stream)534 static void adev_close_output_stream(struct audio_hw_device *dev,
535                                      struct audio_stream_out *stream)
536 {
537     struct adev_a2dp *adev = (struct adev_a2dp *)dev;
538     struct astream_out *out = (struct astream_out *)stream;
539 
540     pthread_mutex_lock(&adev->lock);
541     adev_close_output_stream_locked(adev, out);
542     pthread_mutex_unlock(&adev->lock);
543 }
544 
adev_set_parameters(struct audio_hw_device * dev,const char * kvpairs)545 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
546 {
547     struct adev_a2dp *adev = (struct adev_a2dp *)dev;
548     struct str_parms *parms;
549     char *str;
550     char value[8];
551     int ret;
552 
553     parms = str_parms_create_str(kvpairs);
554 
555     pthread_mutex_lock(&adev->lock);
556 
557     ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value,
558                             sizeof(value));
559     if (ret >= 0) {
560         adev->bt_enabled = !strcmp(value, "true");
561         if (adev->output)
562             _out_bt_enable(adev->output, adev->bt_enabled);
563     }
564 
565     ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value));
566     if (ret >= 0) {
567         adev->suspended = !strcmp(value, "true");
568         if (adev->output)
569             _out_a2dp_suspend(adev->output, adev->suspended);
570     }
571 
572     pthread_mutex_unlock(&adev->lock);
573 
574     str_parms_destroy(parms);
575 
576     return ret;
577 }
578 
adev_get_parameters(const struct audio_hw_device * dev,const char * keys)579 static char * adev_get_parameters(const struct audio_hw_device *dev,
580                                   const char *keys)
581 {
582     struct adev_a2dp *adev = (struct adev_a2dp *)dev;
583     struct str_parms *parms;
584     struct str_parms *out_parms;
585     char *str;
586     char value[8];
587     int ret;
588 
589     parms = str_parms_create_str(keys);
590     out_parms = str_parms_create();
591 
592     pthread_mutex_lock(&adev->lock);
593 
594     ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value,
595                             sizeof(value));
596     if (ret >= 0)
597         str_parms_add_str(out_parms, BLUETOOOTH_ENABLED_PARM,
598                           adev->bt_enabled ? "true" : "false");
599 
600     ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value));
601     if (ret >= 0)
602         str_parms_add_str(out_parms, A2DP_SUSPENDED_PARM,
603                           adev->suspended ? "true" : "false");
604 
605     pthread_mutex_unlock(&adev->lock);
606 
607     str = str_parms_to_str(out_parms);
608     str_parms_destroy(out_parms);
609     str_parms_destroy(parms);
610 
611     return str;
612 }
613 
adev_init_check(const struct audio_hw_device * dev)614 static int adev_init_check(const struct audio_hw_device *dev)
615 {
616     return 0;
617 }
618 
adev_set_voice_volume(struct audio_hw_device * dev,float volume)619 static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
620 {
621     return -ENOSYS;
622 }
623 
adev_set_master_volume(struct audio_hw_device * dev,float volume)624 static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
625 {
626     return -ENOSYS;
627 }
628 
adev_set_mode(struct audio_hw_device * dev,int mode)629 static int adev_set_mode(struct audio_hw_device *dev, int mode)
630 {
631     /* TODO: do we care for the mode? */
632     return 0;
633 }
634 
adev_set_mic_mute(struct audio_hw_device * dev,bool state)635 static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
636 {
637     return -ENOSYS;
638 }
639 
adev_get_mic_mute(const struct audio_hw_device * dev,bool * state)640 static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
641 {
642     return -ENOSYS;
643 }
644 
adev_get_input_buffer_size(const struct audio_hw_device * dev,uint32_t sample_rate,int format,int channel_count)645 static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
646                                          uint32_t sample_rate, int format,
647                                          int channel_count)
648 {
649     /* no input */
650     return 0;
651 }
652 
adev_open_input_stream(struct audio_hw_device * dev,uint32_t devices,int * format,uint32_t * channels,uint32_t * sample_rate,audio_in_acoustics_t acoustics,struct audio_stream_in ** stream_in)653 static int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
654                                   int *format, uint32_t *channels,
655                                   uint32_t *sample_rate,
656                                   audio_in_acoustics_t acoustics,
657                                   struct audio_stream_in **stream_in)
658 {
659     return -ENOSYS;
660 }
661 
adev_close_input_stream(struct audio_hw_device * dev,struct audio_stream_in * in)662 static void adev_close_input_stream(struct audio_hw_device *dev,
663                                    struct audio_stream_in *in)
664 {
665     return;
666 }
667 
adev_dump(const audio_hw_device_t * device,int fd)668 static int adev_dump(const audio_hw_device_t *device, int fd)
669 {
670     return 0;
671 }
672 
adev_close(hw_device_t * device)673 static int adev_close(hw_device_t *device)
674 {
675     struct adev_a2dp *adev = (struct adev_a2dp *)device;
676 
677     pthread_mutex_lock(&adev->lock);
678     if (adev->output)
679         adev_close_output_stream_locked(adev, adev->output);
680     pthread_mutex_unlock(&adev->lock);
681     free(adev);
682 
683     return 0;
684 }
685 
adev_get_supported_devices(const struct audio_hw_device * dev)686 static uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
687 {
688     return AUDIO_DEVICE_OUT_ALL_A2DP;
689 }
690 
adev_open(const hw_module_t * module,const char * name,hw_device_t ** device)691 static int adev_open(const hw_module_t* module, const char* name,
692                      hw_device_t** device)
693 {
694     struct adev_a2dp *adev;
695     int ret;
696 
697     if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
698         return -EINVAL;
699 
700     adev = calloc(1, sizeof(struct adev_a2dp));
701     if (!adev)
702         return -ENOMEM;
703 
704     adev->bt_enabled = true;
705     adev->suspended = false;
706     pthread_mutex_init(&adev->lock, NULL);
707     adev->output = NULL;
708 
709     adev->device.common.tag = HARDWARE_DEVICE_TAG;
710     adev->device.common.version = 0;
711     adev->device.common.module = (struct hw_module_t *) module;
712     adev->device.common.close = adev_close;
713 
714     adev->device.get_supported_devices = adev_get_supported_devices;
715     adev->device.init_check = adev_init_check;
716     adev->device.set_voice_volume = adev_set_voice_volume;
717     adev->device.set_master_volume = adev_set_master_volume;
718     adev->device.set_mode = adev_set_mode;
719     adev->device.set_mic_mute = adev_set_mic_mute;
720     adev->device.get_mic_mute = adev_get_mic_mute;
721     adev->device.set_parameters = adev_set_parameters;
722     adev->device.get_parameters = adev_get_parameters;
723     adev->device.get_input_buffer_size = adev_get_input_buffer_size;
724     adev->device.open_output_stream = adev_open_output_stream;
725     adev->device.close_output_stream = adev_close_output_stream;
726     adev->device.open_input_stream = adev_open_input_stream;
727     adev->device.close_input_stream = adev_close_input_stream;
728     adev->device.dump = adev_dump;
729 
730     *device = &adev->device.common;
731 
732     return 0;
733 
734 err_str_parms_create:
735     free(adev);
736     return ret;
737 }
738 
739 static struct hw_module_methods_t hal_module_methods = {
740     .open = adev_open,
741 };
742 
743 struct audio_module HAL_MODULE_INFO_SYM = {
744     .common = {
745         .tag = HARDWARE_MODULE_TAG,
746         .version_major = 1,
747         .version_minor = 0,
748         .id = AUDIO_HARDWARE_MODULE_ID,
749         .name = "A2DP Audio HW HAL",
750         .author = "The Android Open Source Project",
751         .methods = &hal_module_methods,
752     },
753 };
754 
755 
756