android_audio_hw.c revision 6934b76075fabbd7a1f542b3000b250f4a589492
1be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/*
2be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  Copyright (C) 2008-2011 The Android Open Source Project
3be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *
4be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  This library is free software; you can redistribute it and/or
5be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  modify it under the terms of the GNU Lesser General Public
6be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  License as published by the Free Software Foundation; either
7be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  version 2.1 of the License, or (at your option) any later version.
8be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *
9be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  This library is distributed in the hope that it will be useful,
10be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  Lesser General Public License for more details.
13be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *
14be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  You should have received a copy of the GNU Lesser General Public
15be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  License along with this library; if not, write to the Free Software
16be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin *
18be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin */
19be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
20be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define LOG_TAG "a2dp_audio_hw"
21be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin//#define LOG_NDEBUG 0
22be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
23be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <errno.h>
24be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <pthread.h>
25be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <stdint.h>
26be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <sys/time.h>
27be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
28be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <cutils/log.h>
29be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <cutils/str_parms.h>
30be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
31be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <hardware/hardware.h>
325ca3dfce0e1c35f913f569049bd3f89204bddf92Dima Zavin#include <system/audio.h>
338126b3eb0ce7d77577aa364c1a0066c0d2334d19Dima Zavin#include <hardware/audio.h>
34be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
35be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include <hardware_legacy/power.h>
36be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
37be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#include "liba2dp.h"
38be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
39be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define A2DP_WAKE_LOCK_NAME            "A2dpOutputStream"
40be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define MAX_WRITE_RETRIES              5
41be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
42be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define A2DP_SUSPENDED_PARM            "A2dpSuspended"
43be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define BLUETOOOTH_ENABLED_PARM        "bluetooth_enabled"
44be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
45be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin#define OUT_SINK_ADDR_PARM             "a2dp_sink_address"
46be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
47355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* number of periods in pcm buffer (one period corresponds to buffer size reported to audio flinger
48355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * by out_get_buffer_size() */
49355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define BUF_NUM_PERIODS 6
50355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum time allowed by out_standby_stream_locked() for 2dp_write() to complete */
51355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define BUF_WRITE_COMPLETION_TIMEOUT_MS 5000
52355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum time allowed by out_write() for frames to be available in in write thread buffer */
5305675015d13729f7da5bf32c88264c68e02d6028Eric Laurent#define BUF_WRITE_AVAILABILITY_TIMEOUT_MS 5000
54355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* maximum number of attempts to wait for a write completion in out_standby_stream_locked() */
55355afe9a49d429650c955894220caebc1db3b1cfEric Laurent#define MAX_WRITE_COMPLETION_ATTEMPTS 5
56355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
57355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* NOTE: there are 2 mutexes used by the a2dp output stream.
58355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *  - lock: protects all calls to a2dp lib functions (a2dp_stop(), a2dp_cleanup()...).
59355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *    One exception is a2dp_write() which is also protected by the flag write_busy. This is because
60355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *    out_write() cannot block waiting for a2dp_write() to complete because this function
61355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *    can sleep to throttle the A2DP bit rate.
62355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *    This flag is always set/reset and tested with "lock" mutex held.
63355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *  - buf_lock: protects access to pcm buffer read and write indexes.
64355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *
65355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *  The locking order is always as follows:
66355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *      buf_lock -> lock
67355afe9a49d429650c955894220caebc1db3b1cfEric Laurent *
68355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * If you need to hold the adev_a2dp->lock AND the astream_out->lock or astream_out->buf_lock,
69355afe9a49d429650c955894220caebc1db3b1cfEric Laurent * you MUST take adev_a2dp lock first!!
70be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin */
71be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
72be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct astream_out;
73be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct adev_a2dp {
74be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct audio_hw_device  device;
75be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
76be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    audio_mode_t            mode;
77be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    bool                    bt_enabled;
78be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    bool                    suspended;
79be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
80be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_t         lock;
81be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
82be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out      *output;
83be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin};
84be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
85be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct astream_out {
86be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct audio_stream_out stream;
87be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
88be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    uint32_t                sample_rate;
89be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    size_t                  buffer_size;
90be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    uint32_t                channels;
91be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int                     format;
92be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
93be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int                     fd;
94be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    bool                    standby;
95be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int                     start_count;
96be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int                     retry_count;
97be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    void*                   data;
98be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
99355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_t         lock;   /* see NOTE on mutex locking order above */
100be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
101be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    audio_devices_t         device;
102be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    uint64_t                 last_write_time;
103be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    uint32_t                buffer_duration_us;
104be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
105be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    bool                    bt_enabled;
106be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    bool                    suspended;
107be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char                    a2dp_addr[20];
108355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
109355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    uint32_t *buf;              /* pcm buffer between audioflinger thread and write thread*/
110355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t buf_size;            /* size of pcm buffer in frames */
111355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t buf_rd_idx;          /* read index in pcm buffer, in frames*/
112355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t buf_wr_idx;          /* write index in pcm buffer, in frames */
113355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t buf_frames_ready;    /* number of frames ready for writing to a2dp sink */
114355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_t buf_lock;   /* mutex protecting read and write indexes */
115355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                                /* see NOTE on mutex locking order above */
116355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_cond_t buf_cond;    /* condition signaling data write/read to/from pcm buffer */
117355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_t buf_thread;       /* thread reading data from buffer and writing to a2dp sink*/
118355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    bool buf_thread_exit;       /* flag requesting write thread exit */
119355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    bool write_busy;            /* indicates that a write to a2dp sink is in progress and that
120355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                                   standby must wait for this flag to be cleared by write thread */
121355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_cond_t write_cond;  /* condition associated with write_busy flag */
122be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin};
123be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
124be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint64_t system_time(void)
125be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
126be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct timespec t;
127be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
128be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    t.tv_sec = t.tv_nsec = 0;
129be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    clock_gettime(CLOCK_MONOTONIC, &t);
130be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
131be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return t.tv_sec*1000000000LL + t.tv_nsec;
132be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
133be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
134be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/** audio_stream_out implementation **/
135be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_sample_rate(const struct audio_stream *stream)
136be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
137be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    const struct astream_out *out = (const struct astream_out *)stream;
138be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return out->sample_rate;
139be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
140be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
141be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
142be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
143be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
144be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
1456934b76075fabbd7a1f542b3000b250f4a589492Steve Block    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
146be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
147be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
148be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
149be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic size_t out_get_buffer_size(const struct audio_stream *stream)
150be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
151be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    const struct astream_out *out = (const struct astream_out *)stream;
152be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return out->buffer_size;
153be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
154be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
155be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_channels(const struct audio_stream *stream)
156be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
157be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    const struct astream_out *out = (const struct astream_out *)stream;
158be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return out->channels;
159be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
160be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
161be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_get_format(const struct audio_stream *stream)
162be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
163be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    const struct astream_out *out = (const struct astream_out *)stream;
164be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return out->format;
165be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
166be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
167be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_format(struct audio_stream *stream, int format)
168be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
169be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
1706934b76075fabbd7a1f542b3000b250f4a589492Steve Block    ALOGE("(%s:%d) %s: Implement me!", __FILE__, __LINE__, __func__);
171be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
172be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
173be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
174be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_dump(const struct audio_stream *stream, int fd)
175be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
176be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
177be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
178be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
179be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t out_get_latency(const struct audio_stream_out *stream)
180be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
181be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    const struct astream_out *out = (const struct astream_out *)stream;
182be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
183be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return (out->buffer_duration_us / 1000) + 200;
184be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
185be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
186be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_volume(struct audio_stream_out *stream, float left,
187be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                          float right)
188be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
189be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
190be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
191be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
192be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_get_render_position(const struct audio_stream_out *stream,
193be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                   uint32_t *dsp_frames)
194be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
195be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
196be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
197be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
198be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_init_locked(struct astream_out *out, const char *addr)
199be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
200be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
201be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
202be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (out->data)
203be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return 0;
204be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
205be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* XXX: shouldn't this use the sample_rate/channel_count from 'out'? */
206be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = a2dp_init(44100, 2, &out->data);
207be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret < 0) {
2086934b76075fabbd7a1f542b3000b250f4a589492Steve Block        ALOGE("a2dp_init failed err: %d\n", ret);
209be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        out->data = NULL;
210be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return ret;
211be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
212be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
213be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* XXX: is this even necessary? */
214be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (addr)
215be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        strlcpy(out->a2dp_addr, addr, sizeof(out->a2dp_addr));
216be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    a2dp_set_sink(out->data, out->a2dp_addr);
217be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
218be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
219be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
220be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
221be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic bool _out_validate_parms(struct astream_out *out, int format,
222be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                uint32_t chans, uint32_t rate)
223be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
224be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if ((format && (format != out->format)) ||
225be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        (chans && (chans != out->channels)) ||
226be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        (rate && (rate != out->sample_rate)))
227be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return false;
228be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return true;
229be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
230be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
231be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_standby_stream_locked(struct astream_out *out)
232be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
233be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret = 0;
234355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    int attempts = MAX_WRITE_COMPLETION_ATTEMPTS;
235be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
236be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (out->standby || !out->data)
237be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return 0;
238be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
239355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->standby = true;
240355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    /* wait for write completion if needed */
241355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    while (out->write_busy && attempts--) {
242355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        ret = pthread_cond_timeout_np(&out->write_cond,
243355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                                &out->lock,
244355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                                BUF_WRITE_COMPLETION_TIMEOUT_MS);
2456934b76075fabbd7a1f542b3000b250f4a589492Steve Block        ALOGE_IF(ret != 0, "out_standby_stream_locked() wait cond error %d", ret);
246355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
2476934b76075fabbd7a1f542b3000b250f4a589492Steve Block    ALOGE_IF(attempts == 0, "out_standby_stream_locked() a2dp_write() would not stop!!!");
248355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
249999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block    ALOGV_IF(!out->bt_enabled, "Standby skip stop: enabled %d", out->bt_enabled);
250355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (out->bt_enabled) {
251be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        ret = a2dp_stop(out->data);
252355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
253be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    release_wake_lock(A2DP_WAKE_LOCK_NAME);
254be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
255be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
256be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
257be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
258be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_close_stream_locked(struct astream_out *out)
259be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
260be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_standby_stream_locked(out);
261be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
262be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (out->data) {
263999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block        ALOGV("%s: calling a2dp_cleanup()", __func__);
264be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        a2dp_cleanup(out->data);
265be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        out->data = NULL;
266be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
267be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
268be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
269be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
270be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
271be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_standby(struct audio_stream *stream)
272be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
273be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
274be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
275be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
276be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_standby_stream_locked(out);
277be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
278be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
279be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
280be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
281be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
282be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
283be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
284be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
285be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct str_parms *parms;
286be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char *str;
287be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char value[32];
288be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
289be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
290be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    parms = str_parms_create_str(kvpairs);
291be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
292be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
293be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
294be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = str_parms_get_str(parms, OUT_SINK_ADDR_PARM, value, sizeof(value));
295be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret >= 0) {
296be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        /* strlen(00:00:00:00:00:00) == 17 */
297be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        if (strlen(value) == 17) {
298be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin            strlcpy(out->a2dp_addr, value, sizeof(out->a2dp_addr));
299be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin            if (out->data)
300be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                a2dp_set_sink(out->data, out->a2dp_addr);
301be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        } else
302be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin            ret = -EINVAL;
303be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
304be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
305be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
306be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str_parms_destroy(parms);
307be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
308be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
309be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
310be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic audio_devices_t out_get_device(const struct audio_stream *stream)
311be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
312be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    const struct astream_out *out = (const struct astream_out *)stream;
313be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return out->device;
314be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
315be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
316be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
317be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int out_set_device(struct audio_stream *stream, audio_devices_t device)
318be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
319be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
320be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
321be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!audio_is_a2dp_device(device))
322be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return -EINVAL;
323be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
324be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* XXX: if out->device ever starts getting used for anything, need to
325be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin     * grab the out->lock */
326be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->device = device;
327be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
328be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
329be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
330be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic char * out_get_parameters(const struct audio_stream *stream,
331be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                 const char *keys)
332be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
333be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
334be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct str_parms *parms;
335be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct str_parms *out_parms;
336be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char *str;
337be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char value[20];
338be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
339be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
340be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    parms = str_parms_create_str(keys);
341be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_parms = str_parms_create();
342be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
343be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
344be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
345be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = str_parms_get_str(parms, OUT_SINK_ADDR_PARM, value, sizeof(value));
346be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret >= 0)
347be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        str_parms_add_str(out_parms, OUT_SINK_ADDR_PARM, out->a2dp_addr);
348be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
349be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
350be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
351be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str = str_parms_to_str(out_parms);
352be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str_parms_destroy(out_parms);
353be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str_parms_destroy(parms);
354be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
355be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return str;
356be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
357be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
358355afe9a49d429650c955894220caebc1db3b1cfEric Laurentsize_t _out_frames_available_locked(struct astream_out *out)
359355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{
360355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
361355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t frames = out->buf_size - out->buf_frames_ready;
362355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (frames > out->buf_size - out->buf_wr_idx) {
363355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        frames = out->buf_size - out->buf_wr_idx;
364355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
365355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    return frames;
366355afe9a49d429650c955894220caebc1db3b1cfEric Laurent}
367355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
368355afe9a49d429650c955894220caebc1db3b1cfEric Laurentsize_t _out_frames_ready_locked(struct astream_out *out)
369355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{
370355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t frames = out->buf_frames_ready;
371355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
372355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (frames > out->buf_size - out->buf_rd_idx) {
373355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        frames = out->buf_size - out->buf_rd_idx;
374355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
375355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    return frames;
376355afe9a49d429650c955894220caebc1db3b1cfEric Laurent}
377355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
378355afe9a49d429650c955894220caebc1db3b1cfEric Laurentvoid _out_inc_wr_idx_locked(struct astream_out *out, size_t frames)
379355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{
380355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->buf_wr_idx += frames;
381355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->buf_frames_ready += frames;
382355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (out->buf_wr_idx == out->buf_size) {
383355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        out->buf_wr_idx = 0;
384355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
385355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_cond_signal(&out->buf_cond);
386355afe9a49d429650c955894220caebc1db3b1cfEric Laurent}
387355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
388355afe9a49d429650c955894220caebc1db3b1cfEric Laurentvoid _out_inc_rd_idx_locked(struct astream_out *out, size_t frames)
389355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{
390355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->buf_rd_idx += frames;
391355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->buf_frames_ready -= frames;
392355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (out->buf_rd_idx == out->buf_size) {
393355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        out->buf_rd_idx = 0;
394355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
395355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_cond_signal(&out->buf_cond);
396355afe9a49d429650c955894220caebc1db3b1cfEric Laurent}
397355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
398be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
399be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                         size_t bytes)
400be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
401be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
402be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
403355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t frames_total = bytes / sizeof(uint32_t); // always stereo 16 bit
404355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    uint32_t *buf = (uint32_t *)buffer;
405355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    size_t frames_written = 0;
406be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
407355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_lock(&out->buf_lock);
408be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
409be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!out->bt_enabled || out->suspended) {
410999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block        ALOGV("a2dp %s: bluetooth disabled bt_en %d, suspended %d",
411be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin             out->bt_enabled, out->suspended);
412be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        ret = -1;
413be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        goto err_bt_disabled;
414be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
415be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
416be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (out->standby) {
417be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        acquire_wake_lock(PARTIAL_WAKE_LOCK, A2DP_WAKE_LOCK_NAME);
418be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        out->standby = false;
419be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        out->last_write_time = system_time();
420355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        out->buf_rd_idx = 0;
421355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        out->buf_wr_idx = 0;
422355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        out->buf_frames_ready = 0;
423be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
424be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
425be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = _out_init_locked(out, NULL);
426355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (ret < 0) {
427be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        goto err_init;
428be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
429be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
430355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_unlock(&out->lock);
431be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
432355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    while (frames_written < frames_total) {
433355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        size_t frames = _out_frames_available_locked(out);
434355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        if (frames == 0) {
435355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            int ret = pthread_cond_timeout_np(&out->buf_cond,
436355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                                              &out->buf_lock,
437355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                                              BUF_WRITE_AVAILABILITY_TIMEOUT_MS);
438355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            if (ret != 0) {
439355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_lock(&out->lock);
440355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                goto err_write;
441355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            }
442355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            frames  = _out_frames_available_locked(out);
443355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        }
444355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        if (frames > frames_total - frames_written) {
445355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            frames = frames_total - frames_written;
446355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        }
447355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        memcpy(out->buf + out->buf_wr_idx, buf + frames_written, frames * sizeof(uint32_t));
448355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        frames_written += frames;
449355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        _out_inc_wr_idx_locked(out, frames);
450355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_mutex_lock(&out->lock);
451355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        if (out->standby) {
452355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            goto err_write;
453355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        }
454355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_mutex_unlock(&out->lock);
455be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
456355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_unlock(&out->buf_lock);
457be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
458be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return bytes;
459be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
460355afe9a49d429650c955894220caebc1db3b1cfEric Laurent/* out->lock must be locked and out->buf_lock unlocked when jumping here */
461be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_write:
462be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_init:
463be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_bt_disabled:
464355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_unlock(&out->buf_lock);
4657169d82f3c06e91f42226478302150693c5dd56aEric Laurent    ALOGV("!!!! write error");
466be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_standby_stream_locked(out);
467be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
468be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
469be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* XXX: simulate audio output timing in case of error?!?! */
470be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    usleep(out->buffer_duration_us);
471be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
472be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
473be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
474355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
475355afe9a49d429650c955894220caebc1db3b1cfEric Laurentstatic void *_out_buf_thread_func(void *context)
476355afe9a49d429650c955894220caebc1db3b1cfEric Laurent{
477355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    struct astream_out *out = (struct astream_out *)context;
478355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
479355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_lock(&out->buf_lock);
480355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
481355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    while(!out->buf_thread_exit) {
482355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        size_t frames;
483355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
484355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        frames = _out_frames_ready_locked(out);
485355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        while (frames && !out->buf_thread_exit) {
486355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            int retries = MAX_WRITE_RETRIES;
487355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            uint64_t now;
488355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            uint32_t elapsed_us;
489355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
490355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            while (frames > 0 && !out->buf_thread_exit) {
491355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                int ret;
492355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                uint32_t buffer_duration_us;
493355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                /* PCM format is always 16bit stereo */
494355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                size_t bytes = frames * sizeof(uint32_t);
495355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                if (bytes > out->buffer_size) {
496355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    bytes = out->buffer_size;
497355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                }
498355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
499355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_lock(&out->lock);
500355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                if (out->standby) {
501355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    /* abort and clear all pending frames if standby requested */
502355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    pthread_mutex_unlock(&out->lock);
503355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    frames = _out_frames_ready_locked(out);
504355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    _out_inc_rd_idx_locked(out, frames);
505355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    goto wait;
506355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                }
507355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                /* indicate to out_standby_stream_locked() that a2dp_write() is active */
508355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                out->write_busy = true;
509355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_unlock(&out->lock);
510355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_unlock(&out->buf_lock);
511355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
512355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                ret = a2dp_write(out->data, out->buf + out->buf_rd_idx, bytes);
513355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
514355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                /* clear write_busy condition */
515355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_lock(&out->buf_lock);
516355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_lock(&out->lock);
517355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                out->write_busy = false;
518355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_cond_signal(&out->write_cond);
519355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                pthread_mutex_unlock(&out->lock);
520355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
521355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                if (ret < 0) {
5226934b76075fabbd7a1f542b3000b250f4a589492Steve Block                    ALOGE("%s: a2dp_write failed (%d)\n", __func__, ret);
523355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    /* skip pending frames in case of write error */
524355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    _out_inc_rd_idx_locked(out, frames);
525355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    break;
526355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                } else if (ret == 0) {
527355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    if (retries-- == 0) {
528355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                        /* skip pending frames in case of multiple time out */
529355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                        _out_inc_rd_idx_locked(out, frames);
530355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                        break;
531355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    }
532355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    continue;
533355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                }
534355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                ret /= sizeof(uint32_t);
535355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                _out_inc_rd_idx_locked(out, ret);
536355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                frames -= ret;
537355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
538355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                /* XXX: PLEASE FIX ME!!!! */
539355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
540355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                /* if A2DP sink runs abnormally fast, sleep a little so that
541355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                 * audioflinger mixer thread does no spin and starve other threads. */
542355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                /* NOTE: It is likely that the A2DP headset is being disconnected */
543355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                now = system_time();
544355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                elapsed_us = (now - out->last_write_time) / 1000UL;
545355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                buffer_duration_us = ((ret * 1000) / out->sample_rate) * 1000;
546355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
547355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                if (elapsed_us < (buffer_duration_us / 4)) {
5487169d82f3c06e91f42226478302150693c5dd56aEric Laurent                    ALOGV("A2DP sink runs too fast");
549355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                    usleep(buffer_duration_us - elapsed_us);
550355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                }
551355afe9a49d429650c955894220caebc1db3b1cfEric Laurent                out->last_write_time = now;
552355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
553355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            }
554355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            frames = _out_frames_ready_locked(out);
555355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        }
556355afe9a49d429650c955894220caebc1db3b1cfEric Laurentwait:
557355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        if (!out->buf_thread_exit) {
558355afe9a49d429650c955894220caebc1db3b1cfEric Laurent            pthread_cond_wait(&out->buf_cond, &out->buf_lock);
559355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        }
560355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
561355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    pthread_mutex_unlock(&out->buf_lock);
562355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    return NULL;
563355afe9a49d429650c955894220caebc1db3b1cfEric Laurent}
564355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
565355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
566355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
56721defc264075dd8953e7e491a06820e54c964635Eric Laurentstatic int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
56821defc264075dd8953e7e491a06820e54c964635Eric Laurent{
56921defc264075dd8953e7e491a06820e54c964635Eric Laurent    return 0;
57021defc264075dd8953e7e491a06820e54c964635Eric Laurent}
57121defc264075dd8953e7e491a06820e54c964635Eric Laurent
57221defc264075dd8953e7e491a06820e54c964635Eric Laurentstatic int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
57321defc264075dd8953e7e491a06820e54c964635Eric Laurent{
57421defc264075dd8953e7e491a06820e54c964635Eric Laurent    return 0;
57521defc264075dd8953e7e491a06820e54c964635Eric Laurent}
57621defc264075dd8953e7e491a06820e54c964635Eric Laurent
577be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_bt_enable(struct astream_out *out, bool enable)
578be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
579be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret = 0;
580be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
581be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
582be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->bt_enabled = enable;
583be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!enable)
584be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        ret = out_close_stream_locked(out);
585be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
586be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
587be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
588be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
589be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
590be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int _out_a2dp_suspend(struct astream_out *out, bool suspend)
591be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
592be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
593be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->suspended = suspend;
594be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_standby_stream_locked(out);
595be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
596be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
597be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
598be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
599be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
600be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open_output_stream(struct audio_hw_device *dev,
601be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                   uint32_t devices, int *format,
602be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                   uint32_t *channels, uint32_t *sample_rate,
603be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                   struct audio_stream_out **stream_out)
604be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
605be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev = (struct adev_a2dp *)dev;
606be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out;
607be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
608be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
609be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&adev->lock);
610be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
611be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* one output stream at a time */
612be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (adev->output) {
613999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block        ALOGV("output exists");
614be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        ret = -EBUSY;
615be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        goto err_output_exists;
616be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
617be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
618be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out = calloc(1, sizeof(struct astream_out));
619be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!out) {
620be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        ret = -ENOMEM;
621be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        goto err_alloc;
622be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
623be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
624be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_init(&out->lock, NULL);
625be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
626be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.get_sample_rate = out_get_sample_rate;
627be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.set_sample_rate = out_set_sample_rate;
628be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.get_buffer_size = out_get_buffer_size;
629be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.get_channels = out_get_channels;
630be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.get_format = out_get_format;
631be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.set_format = out_set_format;
632be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.standby = out_standby;
633be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.dump = out_dump;
634be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.set_parameters = out_set_parameters;
635be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.get_parameters = out_get_parameters;
636be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.set_device = out_set_device;
637be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.common.get_device = out_get_device;
63821defc264075dd8953e7e491a06820e54c964635Eric Laurent    out->stream.common.add_audio_effect = out_add_audio_effect;
63921defc264075dd8953e7e491a06820e54c964635Eric Laurent    out->stream.common.remove_audio_effect = out_remove_audio_effect;
640be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.get_latency = out_get_latency;
641be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.set_volume = out_set_volume;
642be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.write = out_write;
643be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->stream.get_render_position = out_get_render_position;
644be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
645be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->sample_rate = 44100;
646be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->buffer_size = 512 * 20;
647be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->channels = AUDIO_CHANNEL_OUT_STEREO;
648be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->format = AUDIO_FORMAT_PCM_16_BIT;
649be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
650be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->fd = -1;
651be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->device = devices;
652be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->bt_enabled = adev->bt_enabled;
653be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->suspended = adev->suspended;
654be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
655be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* for now, buffer_duration_us is precalculated and never changed.
656be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin     * if the sample rate or the format ever changes on the fly, we'd have
657be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin     * to recalculate this */
658be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out->buffer_duration_us = ((out->buffer_size * 1000 ) /
659be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                               audio_stream_frame_size(&out->stream.common) /
660be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                               out->sample_rate) * 1000;
661be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!_out_validate_parms(out, format ? *format : 0,
662be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                             channels ? *channels : 0,
663be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                             sample_rate ? *sample_rate : 0)) {
664999d00b91f78f2fe1aa0648aab49bc857bdec8f6Steve Block        ALOGV("invalid parameters");
665be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        ret = -EINVAL;
666be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        goto err_validate_parms;
667be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
668be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
669355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    int err = pthread_create(&out->buf_thread, (const pthread_attr_t *) NULL, _out_buf_thread_func, out);
670355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (err != 0) {
671355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        goto err_validate_parms;
672355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
673355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
674355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    /* PCM format is always 16bit, stereo */
675355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->buf_size = (out->buffer_size * BUF_NUM_PERIODS) / sizeof(int32_t);
676355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->buf = (uint32_t *)malloc(out->buf_size * sizeof(int32_t));
677355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (!out->buf) {
678355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        goto err_validate_parms;
679355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
680355afe9a49d429650c955894220caebc1db3b1cfEric Laurent
681be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* XXX: check return code? */
682be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (adev->bt_enabled)
683be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        _out_init_locked(out, "00:00:00:00:00:00");
684be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
685be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->output = out;
686be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
687be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (format)
688be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        *format = out->format;
689be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (channels)
690be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        *channels = out->channels;
691be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (sample_rate)
692be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        *sample_rate = out->sample_rate;
693be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
694be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&adev->lock);
695be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
696be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    *stream_out = &out->stream;
697be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
698be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
699be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
700be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_validate_parms:
701be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    free(out);
702be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_alloc:
703be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_output_exists:
704be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&adev->lock);
705be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    *stream_out = NULL;
706be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
707be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
708be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
709be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin/* needs the adev->lock held */
710be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_output_stream_locked(struct adev_a2dp *dev,
711be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                            struct astream_out *stream)
712be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
713be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev = (struct adev_a2dp *)dev;
714be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
715be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
716be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* invalid stream? */
717be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!adev->output || adev->output != out) {
7186934b76075fabbd7a1f542b3000b250f4a589492Steve Block        ALOGE("%s: unknown stream %p (ours is %p)", __func__, out, adev->output);
719be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return;
720be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
721be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
722be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&out->lock);
723355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    /* out_write() must not be executed from now on */
724355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    out->bt_enabled = false;
725be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_close_stream_locked(out);
726be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&out->lock);
727355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (out->buf_thread) {
728355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_mutex_lock(&out->buf_lock);
729355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        out->buf_thread_exit = true;
730355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_cond_broadcast(&out->buf_cond);
731355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_mutex_unlock(&out->buf_lock);
732355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_join(out->buf_thread, (void **) NULL);
733355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_cond_destroy(&out->buf_cond);
734355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        pthread_mutex_destroy(&out->buf_lock);
735355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
736355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    if (out->buf) {
737355afe9a49d429650c955894220caebc1db3b1cfEric Laurent        free(out->buf);
738355afe9a49d429650c955894220caebc1db3b1cfEric Laurent    }
739be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
740be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->output = NULL;
741be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    free(out);
742be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
743be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
744be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_output_stream(struct audio_hw_device *dev,
745be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                     struct audio_stream_out *stream)
746be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
747be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev = (struct adev_a2dp *)dev;
748be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct astream_out *out = (struct astream_out *)stream;
749be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
750be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&adev->lock);
751be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev_close_output_stream_locked(adev, out);
752be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&adev->lock);
753be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
754be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
755be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
756be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
757be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev = (struct adev_a2dp *)dev;
758be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct str_parms *parms;
759be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char *str;
760be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char value[8];
761be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
762be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
763be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    parms = str_parms_create_str(kvpairs);
764be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
765be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&adev->lock);
766be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
767be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value,
768be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                            sizeof(value));
769be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret >= 0) {
770be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        adev->bt_enabled = !strcmp(value, "true");
771eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent        if (adev->output)
772eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent            _out_bt_enable(adev->output, adev->bt_enabled);
773be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
774be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
775be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value));
776be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret >= 0) {
777be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        adev->suspended = !strcmp(value, "true");
778eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent        if (adev->output)
779eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent            _out_a2dp_suspend(adev->output, adev->suspended);
780be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    }
781be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
782be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&adev->lock);
783be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
784be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str_parms_destroy(parms);
785be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
786be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
787be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
788be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
789be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic char * adev_get_parameters(const struct audio_hw_device *dev,
790be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                  const char *keys)
791be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
792be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev = (struct adev_a2dp *)dev;
793be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct str_parms *parms;
794be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct str_parms *out_parms;
795be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char *str;
796be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    char value[8];
797be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
798be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
799be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    parms = str_parms_create_str(keys);
800be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    out_parms = str_parms_create();
801be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
802be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&adev->lock);
803be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
804be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = str_parms_get_str(parms, BLUETOOOTH_ENABLED_PARM, value,
805be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                            sizeof(value));
806be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret >= 0)
807be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        str_parms_add_str(out_parms, BLUETOOOTH_ENABLED_PARM,
808be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                          adev->bt_enabled ? "true" : "false");
809be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
810be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    ret = str_parms_get_str(parms, A2DP_SUSPENDED_PARM, value, sizeof(value));
811be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (ret >= 0)
812be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        str_parms_add_str(out_parms, A2DP_SUSPENDED_PARM,
813be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                          adev->suspended ? "true" : "false");
814be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
815be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&adev->lock);
816be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
817be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str = str_parms_to_str(out_parms);
818be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str_parms_destroy(out_parms);
819be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    str_parms_destroy(parms);
820be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
821be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return str;
822be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
823be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
824be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_init_check(const struct audio_hw_device *dev)
825be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
826be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
827be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
828be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
829be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
830be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
831be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
832be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
833be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
834be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_master_volume(struct audio_hw_device *dev, float volume)
835be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
836be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
837be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
838be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
839be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_mode(struct audio_hw_device *dev, int mode)
840be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
841be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* TODO: do we care for the mode? */
842be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
843be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
844be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
845be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
846be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
847be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
848be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
849be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
850be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
851be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
852be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
853be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
854be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
855be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
856be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                         uint32_t sample_rate, int format,
857be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                         int channel_count)
858be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
859be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    /* no input */
860be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
861be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
862be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
863be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open_input_stream(struct audio_hw_device *dev, uint32_t devices,
864be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                  int *format, uint32_t *channels,
865be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                  uint32_t *sample_rate,
866be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                  audio_in_acoustics_t acoustics,
867be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                  struct audio_stream_in **stream_in)
868be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
869be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return -ENOSYS;
870be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
871be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
872be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic void adev_close_input_stream(struct audio_hw_device *dev,
873be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                                   struct audio_stream_in *in)
874be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
875be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return;
876be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
877be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
878be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_dump(const audio_hw_device_t *device, int fd)
879be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
880be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
881be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
882be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
883be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_close(hw_device_t *device)
884be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
885be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev = (struct adev_a2dp *)device;
886be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
887be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_lock(&adev->lock);
888be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (adev->output)
889be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        adev_close_output_stream_locked(adev, adev->output);
890be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_unlock(&adev->lock);
891be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    free(adev);
892be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
893be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
894be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
895be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
896be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic uint32_t adev_get_supported_devices(const struct audio_hw_device *dev)
897be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
898be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return AUDIO_DEVICE_OUT_ALL_A2DP;
899be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
900be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
901be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic int adev_open(const hw_module_t* module, const char* name,
902be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin                     hw_device_t** device)
903be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin{
904be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    struct adev_a2dp *adev;
905be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    int ret;
906be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
907be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
908be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return -EINVAL;
909be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
910be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev = calloc(1, sizeof(struct adev_a2dp));
911be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    if (!adev)
912be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        return -ENOMEM;
913be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
914be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->bt_enabled = true;
915eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent    adev->suspended = false;
916be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    pthread_mutex_init(&adev->lock, NULL);
917eb2093d614aaacd3c61217ca1f15e32576f792caEric Laurent    adev->output = NULL;
918be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
919be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.common.tag = HARDWARE_DEVICE_TAG;
920be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.common.version = 0;
921be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.common.module = (struct hw_module_t *) module;
922be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.common.close = adev_close;
923be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
924be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.get_supported_devices = adev_get_supported_devices;
925be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.init_check = adev_init_check;
926be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.set_voice_volume = adev_set_voice_volume;
927be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.set_master_volume = adev_set_master_volume;
928be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.set_mode = adev_set_mode;
929be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.set_mic_mute = adev_set_mic_mute;
930be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.get_mic_mute = adev_get_mic_mute;
931be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.set_parameters = adev_set_parameters;
932be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.get_parameters = adev_get_parameters;
933be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.get_input_buffer_size = adev_get_input_buffer_size;
934be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.open_output_stream = adev_open_output_stream;
935be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.close_output_stream = adev_close_output_stream;
936be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.open_input_stream = adev_open_input_stream;
937be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.close_input_stream = adev_close_input_stream;
938be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    adev->device.dump = adev_dump;
939be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
940be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    *device = &adev->device.common;
941be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
942be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return 0;
943be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
944be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinerr_str_parms_create:
945be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    free(adev);
946be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    return ret;
947be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin}
948be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
949be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstatic struct hw_module_methods_t hal_module_methods = {
950be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    .open = adev_open,
951be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin};
952be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
953be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavinstruct audio_module HAL_MODULE_INFO_SYM = {
954be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    .common = {
955be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .tag = HARDWARE_MODULE_TAG,
956be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .version_major = 1,
957be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .version_minor = 0,
958be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .id = AUDIO_HARDWARE_MODULE_ID,
959be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .name = "A2DP Audio HW HAL",
960be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .author = "The Android Open Source Project",
961be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin        .methods = &hal_module_methods,
962be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin    },
963be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin};
964be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
965be1ed76e85c96adae9a75f2d43abc16ad4dbde26Dima Zavin
966