blob: 2fb139f89db782b65a7a41ba53fc5a825883da83 [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
2 *
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07003 * Copyright 2009-2012 Broadcom Corporation
The Android Open Source Project5738f832012-12-12 16:00:35 -08004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19/*****************************************************************************
20 *
21 * Filename: audio_a2dp_hw.c
22 *
23 * Description: Implements hal for bluedroid a2dp audio device
24 *
25 *****************************************************************************/
26
Marie Janssen49120dc2015-07-07 16:47:20 -070027#define LOG_TAG "bt_a2dp_hw"
28
The Android Open Source Project5738f832012-12-12 16:00:35 -080029#include <errno.h>
Miao Chou10969122015-06-09 17:39:46 -070030#include <fcntl.h>
Mark Salyzyn40421cb2014-04-17 13:45:20 -070031#include <inttypes.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080032#include <stdint.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080033#include <sys/errno.h>
Miao Chou10969122015-06-09 17:39:46 -070034#include <sys/socket.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080035#include <sys/stat.h>
Miao Chou10969122015-06-09 17:39:46 -070036#include <sys/time.h>
37#include <sys/un.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080038#include <unistd.h>
Miao Chou10969122015-06-09 17:39:46 -070039
Marie Janssen21da6372016-11-02 18:31:55 -070040#include <mutex>
41
The Android Open Source Project5738f832012-12-12 16:00:35 -080042#include <hardware/audio.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080043#include <hardware/hardware.h>
Miao Chou10969122015-06-09 17:39:46 -070044#include <system/audio.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080045
Miao Chou98a96412015-07-08 14:50:32 -070046#include "osi/include/hash_map_utils.h"
Sharvil Nanavati44802762014-12-23 23:08:58 -080047#include "osi/include/log.h"
Pavlin Radoslavovd6121a32016-05-12 11:36:44 -070048#include "osi/include/osi.h"
Miao Chou10969122015-06-09 17:39:46 -070049#include "osi/include/socket_utils/sockets.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080050
Jack Hee2eeff42016-12-07 18:25:17 -080051#include "audio_a2dp_hw.h"
52
The Android Open Source Project5738f832012-12-12 16:00:35 -080053/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080054 * Constants & Macros
55 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080056
57#define CTRL_CHAN_RETRY_COUNT 3
58#define USEC_PER_SEC 1000000L
Myles Watson911d1ae2016-11-28 16:44:40 -080059#define SOCK_SEND_TIMEOUT_MS 2000 /* Timeout for sending */
60#define SOCK_RECV_TIMEOUT_MS 5000 /* Timeout for receiving */
Ajay Panickeref673c52016-12-21 15:37:34 -080061#define SEC_TO_MS 1000
62#define SEC_TO_NS 1000000000
63#define MS_TO_NS 1000000
64#define DELAY_TO_NS 100000
65
66#define MIN_DELAY_MS 100
67#define MAX_DELAY_MS 1000
The Android Open Source Project5738f832012-12-12 16:00:35 -080068
Myles Watson911d1ae2016-11-28 16:44:40 -080069// set WRITE_POLL_MS to 0 for blocking sockets, nonzero for polled non-blocking
70// sockets
Andy Hung32e7c202016-06-14 19:58:58 -070071#define WRITE_POLL_MS 20
72
Myles Watson911d1ae2016-11-28 16:44:40 -080073#define FNLOG() LOG_VERBOSE(LOG_TAG, "%s", __func__);
74#define DEBUG(fmt, ...) \
75 LOG_VERBOSE(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
76#define INFO(fmt, ...) LOG_INFO(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
77#define WARN(fmt, ...) LOG_WARN(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
78#define ERROR(fmt, ...) LOG_ERROR(LOG_TAG, "%s: " fmt, __func__, ##__VA_ARGS__)
The Android Open Source Project5738f832012-12-12 16:00:35 -080079
Myles Watson911d1ae2016-11-28 16:44:40 -080080#define ASSERTC(cond, msg, val) \
81 if (!(cond)) { \
82 ERROR("### ASSERT : %s line %d %s (%d) ###", __FILE__, __LINE__, msg, \
83 val); \
84 }
The Android Open Source Project5738f832012-12-12 16:00:35 -080085
86/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -080087 * Local type definitions
88 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -080089
90typedef enum {
Myles Watson911d1ae2016-11-28 16:44:40 -080091 AUDIO_A2DP_STATE_STARTING,
92 AUDIO_A2DP_STATE_STARTED,
93 AUDIO_A2DP_STATE_STOPPING,
94 AUDIO_A2DP_STATE_STOPPED,
95 /* need explicit set param call to resume (suspend=false) */
96 AUDIO_A2DP_STATE_SUSPENDED,
97 AUDIO_A2DP_STATE_STANDBY /* allows write to autoresume */
The Android Open Source Project5738f832012-12-12 16:00:35 -080098} a2dp_state_t;
99
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700100struct a2dp_stream_in;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800101struct a2dp_stream_out;
102
103struct a2dp_audio_device {
Andy Hungb1a900f2017-03-30 16:28:46 -0700104 // Important: device must be first as an audio_hw_device* may be cast to
105 // a2dp_audio_device* when the type is implicitly known.
Myles Watson911d1ae2016-11-28 16:44:40 -0800106 struct audio_hw_device device;
Andy Hungb1a900f2017-03-30 16:28:46 -0700107 std::recursive_mutex* mutex; // See note below on mutex acquisition order.
Myles Watson911d1ae2016-11-28 16:44:40 -0800108 struct a2dp_stream_in* input;
109 struct a2dp_stream_out* output;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800110};
111
112struct a2dp_config {
Myles Watson911d1ae2016-11-28 16:44:40 -0800113 uint32_t rate;
114 uint32_t channel_mask;
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700115 bool is_stereo_to_mono; // True if fetching Stereo and mixing into Mono
Myles Watson911d1ae2016-11-28 16:44:40 -0800116 int format;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800117};
118
119/* move ctrl_fd outside output stream and keep open until HAL unloaded ? */
120
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700121struct a2dp_stream_common {
Andy Hungb1a900f2017-03-30 16:28:46 -0700122 std::recursive_mutex* mutex; // See note below on mutex acquisition order.
Myles Watson911d1ae2016-11-28 16:44:40 -0800123 int ctrl_fd;
124 int audio_fd;
125 size_t buffer_sz;
126 struct a2dp_config cfg;
127 a2dp_state_t state;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700128};
129
130struct a2dp_stream_out {
Myles Watson911d1ae2016-11-28 16:44:40 -0800131 struct audio_stream_out stream;
132 struct a2dp_stream_common common;
133 uint64_t frames_presented; // frames written, never reset
134 uint64_t frames_rendered; // frames written, reset on standby
The Android Open Source Project5738f832012-12-12 16:00:35 -0800135};
136
137struct a2dp_stream_in {
Myles Watson911d1ae2016-11-28 16:44:40 -0800138 struct audio_stream_in stream;
139 struct a2dp_stream_common common;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800140};
141
Andy Hungb1a900f2017-03-30 16:28:46 -0700142/*
143 * Mutex acquisition order:
144 *
145 * The a2dp_audio_device (adev) mutex must be acquired before
146 * the a2dp_stream_common (out or in) mutex.
147 *
148 * This may differ from other audio HALs.
149 */
150
The Android Open Source Project5738f832012-12-12 16:00:35 -0800151/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800152 * Static variables
153 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800154
Ajay Panickeref673c52016-12-21 15:37:34 -0800155static bool enable_delay_reporting = false;
156
The Android Open Source Project5738f832012-12-12 16:00:35 -0800157/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800158 * Static functions
159 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800160
Myles Watson911d1ae2016-11-28 16:44:40 -0800161static size_t out_get_buffer_size(const struct audio_stream* stream);
Ajay Panickeref673c52016-12-21 15:37:34 -0800162static uint32_t out_get_latency(const struct audio_stream_out* stream);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800163
164/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800165 * Externs
166 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800167
168/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800169 * Functions
170 *****************************************************************************/
Myles Watson911d1ae2016-11-28 16:44:40 -0800171static void a2dp_open_ctrl_path(struct a2dp_stream_common* common);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800172
173/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800174 * Miscellaneous helper functions
175 *****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800176
The Android Open Source Project5738f832012-12-12 16:00:35 -0800177/* logs timestamp with microsec precision
178 pprev is optional in case a dedicated diff is required */
Myles Watson911d1ae2016-11-28 16:44:40 -0800179static void ts_log(UNUSED_ATTR const char* tag, UNUSED_ATTR int val,
180 struct timespec* pprev_opt) {
181 struct timespec now;
182 static struct timespec prev = {0, 0};
183 unsigned long long now_us;
184 unsigned long long diff_us;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800185
Myles Watson911d1ae2016-11-28 16:44:40 -0800186 clock_gettime(CLOCK_MONOTONIC, &now);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800187
Myles Watson911d1ae2016-11-28 16:44:40 -0800188 now_us = now.tv_sec * USEC_PER_SEC + now.tv_nsec / 1000;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800189
Myles Watson911d1ae2016-11-28 16:44:40 -0800190 if (pprev_opt) {
191 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC +
192 (now.tv_nsec - prev.tv_nsec) / 1000;
193 *pprev_opt = now;
194 DEBUG("[%s] ts %08lld, *diff %08lld, val %d", tag, now_us, diff_us, val);
195 } else {
196 diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC +
197 (now.tv_nsec - prev.tv_nsec) / 1000;
198 prev = now;
199 DEBUG("[%s] ts %08lld, diff %08lld, val %d", tag, now_us, diff_us, val);
200 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800201}
202
Myles Watson911d1ae2016-11-28 16:44:40 -0800203static int calc_audiotime_usec(struct a2dp_config cfg, int bytes) {
204 int chan_count = audio_channel_count_from_out_mask(cfg.channel_mask);
205 int bytes_per_sample;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800206
Myles Watson911d1ae2016-11-28 16:44:40 -0800207 switch (cfg.format) {
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800208 case AUDIO_FORMAT_PCM_8_BIT:
209 bytes_per_sample = 1;
210 break;
211 case AUDIO_FORMAT_PCM_16_BIT:
212 bytes_per_sample = 2;
213 break;
214 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
215 bytes_per_sample = 3;
216 break;
217 case AUDIO_FORMAT_PCM_8_24_BIT:
218 bytes_per_sample = 4;
219 break;
220 case AUDIO_FORMAT_PCM_32_BIT:
221 bytes_per_sample = 4;
222 break;
223 default:
224 ASSERTC(false, "unsupported sample format", cfg.format);
225 bytes_per_sample = 2;
226 break;
Myles Watson911d1ae2016-11-28 16:44:40 -0800227 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800228
Myles Watson911d1ae2016-11-28 16:44:40 -0800229 return (
230 int)(((int64_t)bytes * (USEC_PER_SEC / (chan_count * bytes_per_sample))) /
231 cfg.rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800232}
233
234/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800235 *
236 * bluedroid stack adaptation
237 *
238 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800239
Myles Watson911d1ae2016-11-28 16:44:40 -0800240static int skt_connect(const char* path, size_t buffer_sz) {
241 int ret;
242 int skt_fd;
243 int len;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800244
Myles Watson911d1ae2016-11-28 16:44:40 -0800245 INFO("connect to %s (sz %zu)", path, buffer_sz);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800246
Myles Watson911d1ae2016-11-28 16:44:40 -0800247 skt_fd = socket(AF_LOCAL, SOCK_STREAM, 0);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800248
Myles Watson911d1ae2016-11-28 16:44:40 -0800249 if (osi_socket_local_client_connect(
250 skt_fd, path, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM) < 0) {
251 ERROR("failed to connect (%s)", strerror(errno));
252 close(skt_fd);
253 return -1;
254 }
255
256 len = buffer_sz;
257 ret =
258 setsockopt(skt_fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, (int)sizeof(len));
259 if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
260
261 ret =
262 setsockopt(skt_fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, (int)sizeof(len));
263 if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
264
265 /* Socket send/receive timeout value */
266 struct timeval tv;
267 tv.tv_sec = SOCK_SEND_TIMEOUT_MS / 1000;
268 tv.tv_usec = (SOCK_SEND_TIMEOUT_MS % 1000) * 1000;
269
270 ret = setsockopt(skt_fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
271 if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
272
273 tv.tv_sec = SOCK_RECV_TIMEOUT_MS / 1000;
274 tv.tv_usec = (SOCK_RECV_TIMEOUT_MS % 1000) * 1000;
275
276 ret = setsockopt(skt_fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
277 if (ret < 0) ERROR("setsockopt failed (%s)", strerror(errno));
278
279 INFO("connected to stack fd = %d", skt_fd);
280
281 return skt_fd;
282}
283
284static int skt_read(int fd, void* p, size_t len) {
285 ssize_t read;
286
287 FNLOG();
288
289 ts_log("skt_read recv", len, NULL);
290
291 OSI_NO_INTR(read = recv(fd, p, len, MSG_NOSIGNAL));
292 if (read == -1) ERROR("read failed with errno=%d\n", errno);
293
294 return (int)read;
295}
296
297static int skt_write(int fd, const void* p, size_t len) {
298 ssize_t sent;
299 FNLOG();
300
301 ts_log("skt_write", len, NULL);
302
303 if (WRITE_POLL_MS == 0) {
304 // do not poll, use blocking send
305 OSI_NO_INTR(sent = send(fd, p, len, MSG_NOSIGNAL));
306 if (sent == -1) ERROR("write failed with error(%s)", strerror(errno));
307
308 return (int)sent;
309 }
310
311 // use non-blocking send, poll
312 int ms_timeout = SOCK_SEND_TIMEOUT_MS;
313 size_t count = 0;
314 while (count < len) {
315 OSI_NO_INTR(sent = send(fd, p, len - count, MSG_NOSIGNAL | MSG_DONTWAIT));
316 if (sent == -1) {
317 if (errno != EAGAIN && errno != EWOULDBLOCK) {
318 ERROR("write failed with error(%s)", strerror(errno));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800319 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800320 }
321 if (ms_timeout >= WRITE_POLL_MS) {
322 usleep(WRITE_POLL_MS * 1000);
323 ms_timeout -= WRITE_POLL_MS;
324 continue;
325 }
326 WARN("write timeout exceeded, sent %zu bytes", count);
327 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800328 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800329 count += sent;
330 p = (const uint8_t*)p + sent;
331 }
332 return (int)count;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800333}
334
Myles Watson911d1ae2016-11-28 16:44:40 -0800335static int skt_disconnect(int fd) {
336 INFO("fd %d", fd);
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700337
Myles Watson911d1ae2016-11-28 16:44:40 -0800338 if (fd != AUDIO_SKT_DISCONNECTED) {
339 shutdown(fd, SHUT_RDWR);
340 close(fd);
341 }
342 return 0;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700343}
344
The Android Open Source Project5738f832012-12-12 16:00:35 -0800345/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800346 *
347 * AUDIO CONTROL PATH
348 *
349 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800350
Myles Watson911d1ae2016-11-28 16:44:40 -0800351static int a2dp_ctrl_receive(struct a2dp_stream_common* common, void* buffer,
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800352 size_t length) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800353 ssize_t ret;
354 int i;
Pavlin Radoslavovd6121a32016-05-12 11:36:44 -0700355
Myles Watson911d1ae2016-11-28 16:44:40 -0800356 for (i = 0;; i++) {
357 OSI_NO_INTR(ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
358 if (ret > 0) {
359 break;
Eric Laurent7a599b42016-05-11 18:18:54 -0700360 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800361 if (ret == 0) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800362 ERROR("receive control data failed: peer closed");
Myles Watson911d1ae2016-11-28 16:44:40 -0800363 break;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700364 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800365 if (errno != EWOULDBLOCK && errno != EAGAIN) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800366 ERROR("receive control data failed: error(%s)", strerror(errno));
Myles Watson911d1ae2016-11-28 16:44:40 -0800367 break;
368 }
369 if (i == (CTRL_CHAN_RETRY_COUNT - 1)) {
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800370 ERROR("receive control data failed: max retry count");
Myles Watson911d1ae2016-11-28 16:44:40 -0800371 break;
372 }
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800373 INFO("receive control data failed (%s), retrying", strerror(errno));
Myles Watson911d1ae2016-11-28 16:44:40 -0800374 }
375 if (ret <= 0) {
376 skt_disconnect(common->ctrl_fd);
377 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
378 }
379 return ret;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700380}
381
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800382// Sends control info for stream |common|. The data to send is stored in
383// |buffer| and has size |length|.
384// On success, returns the number of octets sent, otherwise -1.
385static int a2dp_ctrl_send(struct a2dp_stream_common* common, const void* buffer,
386 size_t length) {
387 ssize_t sent;
388 size_t remaining = length;
389 int i;
390
391 if (length == 0) return 0; // Nothing to do
392
393 for (i = 0;; i++) {
394 OSI_NO_INTR(sent = send(common->ctrl_fd, buffer, remaining, MSG_NOSIGNAL));
395 if (sent == static_cast<ssize_t>(remaining)) {
396 remaining = 0;
397 break;
398 }
399 if (sent > 0) {
400 buffer = (static_cast<const char*>(buffer) + sent);
401 remaining -= sent;
402 continue;
403 }
404 if (sent < 0) {
405 if (errno != EWOULDBLOCK && errno != EAGAIN) {
406 ERROR("send control data failed: error(%s)", strerror(errno));
407 break;
408 }
409 INFO("send control data failed (%s), retrying", strerror(errno));
410 }
411 if (i >= (CTRL_CHAN_RETRY_COUNT - 1)) {
412 ERROR("send control data failed: max retry count");
413 break;
414 }
415 }
416 if (remaining > 0) {
417 skt_disconnect(common->ctrl_fd);
418 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
419 return -1;
420 }
421 return length;
422}
423
Myles Watson911d1ae2016-11-28 16:44:40 -0800424static int a2dp_command(struct a2dp_stream_common* common, tA2DP_CTRL_CMD cmd) {
425 char ack;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800426
Myles Watson911d1ae2016-11-28 16:44:40 -0800427 DEBUG("A2DP COMMAND %s", audio_a2dp_hw_dump_ctrl_event(cmd));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800428
Myles Watson911d1ae2016-11-28 16:44:40 -0800429 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
Pavlin Radoslavov2a3b9b52018-04-30 13:39:20 -0700430 INFO("starting up or recovering from previous error: command=%s",
431 audio_a2dp_hw_dump_ctrl_event(cmd));
Myles Watson911d1ae2016-11-28 16:44:40 -0800432 a2dp_open_ctrl_path(common);
Eric Laurent7a599b42016-05-11 18:18:54 -0700433 if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) {
Pavlin Radoslavov2a3b9b52018-04-30 13:39:20 -0700434 ERROR("failure to open ctrl path: command=%s",
435 audio_a2dp_hw_dump_ctrl_event(cmd));
Myles Watson911d1ae2016-11-28 16:44:40 -0800436 return -1;
Eric Laurent7a599b42016-05-11 18:18:54 -0700437 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800438 }
Eric Laurent7a599b42016-05-11 18:18:54 -0700439
Myles Watson911d1ae2016-11-28 16:44:40 -0800440 /* send command */
441 ssize_t sent;
442 OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL));
443 if (sent == -1) {
Pavlin Radoslavov2a3b9b52018-04-30 13:39:20 -0700444 ERROR("cmd failed (%s): command=%s", strerror(errno),
445 audio_a2dp_hw_dump_ctrl_event(cmd));
Myles Watson911d1ae2016-11-28 16:44:40 -0800446 skt_disconnect(common->ctrl_fd);
447 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
448 return -1;
449 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800450
Myles Watson911d1ae2016-11-28 16:44:40 -0800451 /* wait for ack byte */
452 if (a2dp_ctrl_receive(common, &ack, 1) < 0) {
453 ERROR("A2DP COMMAND %s: no ACK", audio_a2dp_hw_dump_ctrl_event(cmd));
454 return -1;
455 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800456
Myles Watson911d1ae2016-11-28 16:44:40 -0800457 DEBUG("A2DP COMMAND %s DONE STATUS %d", audio_a2dp_hw_dump_ctrl_event(cmd),
458 ack);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800459
Pavlin Radoslavov2a3b9b52018-04-30 13:39:20 -0700460 if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) {
461 ERROR("A2DP COMMAND %s error %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack);
462 return ack;
463 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800464 if (ack != A2DP_CTRL_ACK_SUCCESS) {
465 ERROR("A2DP COMMAND %s error %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack);
466 return -1;
467 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800468
Myles Watson911d1ae2016-11-28 16:44:40 -0800469 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800470}
471
Myles Watson911d1ae2016-11-28 16:44:40 -0800472static int check_a2dp_ready(struct a2dp_stream_common* common) {
473 if (a2dp_command(common, A2DP_CTRL_CMD_CHECK_READY) < 0) {
474 ERROR("check a2dp ready failed");
475 return -1;
476 }
477 return 0;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700478}
479
Myles Watson911d1ae2016-11-28 16:44:40 -0800480static int a2dp_read_input_audio_config(struct a2dp_stream_common* common) {
481 tA2DP_SAMPLE_RATE sample_rate;
482 tA2DP_CHANNEL_COUNT channel_count;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700483
Myles Watson911d1ae2016-11-28 16:44:40 -0800484 if (a2dp_command(common, A2DP_CTRL_GET_INPUT_AUDIO_CONFIG) < 0) {
485 ERROR("get a2dp input audio config failed");
486 return -1;
487 }
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700488
Myles Watson911d1ae2016-11-28 16:44:40 -0800489 if (a2dp_ctrl_receive(common, &sample_rate, sizeof(tA2DP_SAMPLE_RATE)) < 0)
490 return -1;
491 if (a2dp_ctrl_receive(common, &channel_count, sizeof(tA2DP_CHANNEL_COUNT)) <
492 0) {
493 return -1;
494 }
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700495
Myles Watson911d1ae2016-11-28 16:44:40 -0800496 switch (sample_rate) {
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800497 case 44100:
498 case 48000:
499 common->cfg.rate = sample_rate;
500 break;
501 default:
502 ERROR("Invalid sample rate: %" PRIu32, sample_rate);
503 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800504 }
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700505
Myles Watson911d1ae2016-11-28 16:44:40 -0800506 switch (channel_count) {
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800507 case 1:
508 common->cfg.channel_mask = AUDIO_CHANNEL_IN_MONO;
509 break;
510 case 2:
511 common->cfg.channel_mask = AUDIO_CHANNEL_IN_STEREO;
512 break;
513 default:
514 ERROR("Invalid channel count: %" PRIu32, channel_count);
515 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800516 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800517
Myles Watson911d1ae2016-11-28 16:44:40 -0800518 // TODO: For now input audio format is always hard-coded as PCM 16-bit
519 common->cfg.format = AUDIO_FORMAT_PCM_16_BIT;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800520
Myles Watson911d1ae2016-11-28 16:44:40 -0800521 INFO("got input audio config %d %d", common->cfg.format, common->cfg.rate);
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800522
Myles Watson911d1ae2016-11-28 16:44:40 -0800523 return 0;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800524}
525
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800526static int a2dp_read_output_audio_config(
527 struct a2dp_stream_common* common, btav_a2dp_codec_config_t* codec_config,
528 btav_a2dp_codec_config_t* codec_capability, bool update_stream_config) {
529 struct a2dp_config stream_config;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800530
Myles Watson911d1ae2016-11-28 16:44:40 -0800531 if (a2dp_command(common, A2DP_CTRL_GET_OUTPUT_AUDIO_CONFIG) < 0) {
532 ERROR("get a2dp output audio config failed");
533 return -1;
534 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800535
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800536 // Receive the current codec config
537 if (a2dp_ctrl_receive(common, &codec_config->sample_rate,
538 sizeof(btav_a2dp_codec_sample_rate_t)) < 0) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800539 return -1;
540 }
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800541 if (a2dp_ctrl_receive(common, &codec_config->bits_per_sample,
542 sizeof(btav_a2dp_codec_bits_per_sample_t)) < 0) {
543 return -1;
544 }
545 if (a2dp_ctrl_receive(common, &codec_config->channel_mode,
546 sizeof(btav_a2dp_codec_channel_mode_t)) < 0) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800547 return -1;
548 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800549
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800550 // Receive the current codec capability
551 if (a2dp_ctrl_receive(common, &codec_capability->sample_rate,
552 sizeof(btav_a2dp_codec_sample_rate_t)) < 0) {
553 return -1;
554 }
555 if (a2dp_ctrl_receive(common, &codec_capability->bits_per_sample,
556 sizeof(btav_a2dp_codec_bits_per_sample_t)) < 0) {
557 return -1;
558 }
559 if (a2dp_ctrl_receive(common, &codec_capability->channel_mode,
560 sizeof(btav_a2dp_codec_channel_mode_t)) < 0) {
561 return -1;
562 }
563
564 // Check the codec config sample rate
565 switch (codec_config->sample_rate) {
566 case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
567 stream_config.rate = 44100;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800568 break;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800569 case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
570 stream_config.rate = 48000;
571 break;
572 case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
573 stream_config.rate = 88200;
574 break;
575 case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
576 stream_config.rate = 96000;
577 break;
578 case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
579 stream_config.rate = 176400;
580 break;
581 case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
582 stream_config.rate = 192000;
583 break;
584 case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800585 default:
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800586 ERROR("Invalid sample rate: 0x%x", codec_config->sample_rate);
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800587 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800588 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800589
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800590 // Check the codec config bits per sample
591 switch (codec_config->bits_per_sample) {
592 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
593 stream_config.format = AUDIO_FORMAT_PCM_16_BIT;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800594 break;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800595 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
596 stream_config.format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800597 break;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800598 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
599 stream_config.format = AUDIO_FORMAT_PCM_32_BIT;
600 break;
601 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800602 default:
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800603 ERROR("Invalid bits per sample: 0x%x", codec_config->bits_per_sample);
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800604 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800605 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800606
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800607 // Check the codec config channel mode
608 switch (codec_config->channel_mode) {
609 case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
610 stream_config.channel_mask = AUDIO_CHANNEL_OUT_MONO;
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700611 stream_config.is_stereo_to_mono = true;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800612 break;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800613 case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
614 stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700615 stream_config.is_stereo_to_mono = false;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800616 break;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800617 case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800618 default:
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800619 ERROR("Invalid channel mode: 0x%x", codec_config->channel_mode);
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800620 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800621 }
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700622 if (stream_config.is_stereo_to_mono) {
623 stream_config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
624 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -0800625
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800626 // Update the output stream configuration
627 if (update_stream_config) {
628 common->cfg.rate = stream_config.rate;
629 common->cfg.channel_mask = stream_config.channel_mask;
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700630 common->cfg.is_stereo_to_mono = stream_config.is_stereo_to_mono;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800631 common->cfg.format = stream_config.format;
Pavlin Radoslavovbdd34d22017-04-05 16:18:26 -0700632 common->buffer_sz = audio_a2dp_hw_stream_compute_buffer_size(
Pavlin Radoslavovae9db0f2017-04-04 11:31:29 -0700633 codec_config->sample_rate, codec_config->bits_per_sample,
634 codec_config->channel_mode);
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700635 if (common->cfg.is_stereo_to_mono) {
636 // We need to fetch twice as much data from the Audio framework
637 common->buffer_sz *= 2;
638 }
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800639 }
640
Myles Watson911d1ae2016-11-28 16:44:40 -0800641 INFO(
Pavlin Radoslavov7a69fa42017-12-14 16:35:28 -0800642 "got output codec config (update_stream_config=%s): "
643 "sample_rate=0x%x bits_per_sample=0x%x channel_mode=0x%x",
644 update_stream_config ? "true" : "false", codec_config->sample_rate,
645 codec_config->bits_per_sample, codec_config->channel_mode);
646
647 INFO(
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800648 "got output codec capability: sample_rate=0x%x bits_per_sample=0x%x "
649 "channel_mode=0x%x",
650 codec_capability->sample_rate, codec_capability->bits_per_sample,
651 codec_capability->channel_mode);
652
653 return 0;
654}
655
656static int a2dp_write_output_audio_config(struct a2dp_stream_common* common) {
657 btav_a2dp_codec_config_t codec_config;
658
659 if (a2dp_command(common, A2DP_CTRL_SET_OUTPUT_AUDIO_CONFIG) < 0) {
660 ERROR("set a2dp output audio config failed");
661 return -1;
662 }
663
664 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
665 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
666 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
667
668 switch (common->cfg.rate) {
669 case 44100:
670 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
671 break;
672 case 48000:
673 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
674 break;
675 case 88200:
676 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
677 break;
678 case 96000:
679 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
680 break;
681 case 176400:
682 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
683 break;
684 case 192000:
685 codec_config.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
686 break;
687 default:
688 ERROR("Invalid sample rate: %" PRIu32, common->cfg.rate);
689 return -1;
690 }
691
692 switch (common->cfg.format) {
693 case AUDIO_FORMAT_PCM_16_BIT:
694 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
695 break;
696 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
697 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24;
698 break;
699 case AUDIO_FORMAT_PCM_32_BIT:
700 codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
701 break;
702 case AUDIO_FORMAT_PCM_8_24_BIT:
Chih-Hung Hsiehd4646582018-09-12 15:20:43 -0700703 // All 24-bit audio is expected in AUDIO_FORMAT_PCM_24_BIT_PACKED format
704 FALLTHROUGH_INTENDED; /* FALLTHROUGH */
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800705 default:
706 ERROR("Invalid audio format: 0x%x", common->cfg.format);
707 return -1;
708 }
709
710 switch (common->cfg.channel_mask) {
711 case AUDIO_CHANNEL_OUT_MONO:
712 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
713 break;
714 case AUDIO_CHANNEL_OUT_STEREO:
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700715 if (common->cfg.is_stereo_to_mono) {
716 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
717 } else {
718 codec_config.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
719 }
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -0800720 break;
721 default:
722 ERROR("Invalid channel mask: 0x%x", common->cfg.channel_mask);
723 return -1;
724 }
725
726 // Send the current codec config that has been selected by us
727 if (a2dp_ctrl_send(common, &codec_config.sample_rate,
728 sizeof(btav_a2dp_codec_sample_rate_t)) < 0)
729 return -1;
730 if (a2dp_ctrl_send(common, &codec_config.bits_per_sample,
731 sizeof(btav_a2dp_codec_bits_per_sample_t)) < 0) {
732 return -1;
733 }
734 if (a2dp_ctrl_send(common, &codec_config.channel_mode,
735 sizeof(btav_a2dp_codec_channel_mode_t)) < 0) {
736 return -1;
737 }
738
739 INFO(
740 "sent output codec config: sample_rate=0x%x bits_per_sample=0x%x "
741 "channel_mode=0x%x",
742 codec_config.sample_rate, codec_config.bits_per_sample,
743 codec_config.channel_mode);
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700744
Myles Watson911d1ae2016-11-28 16:44:40 -0800745 return 0;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700746}
747
Ajay Panickeref673c52016-12-21 15:37:34 -0800748static int a2dp_get_presentation_position_cmd(struct a2dp_stream_common* common,
749 uint64_t* bytes, uint16_t* delay,
750 struct timespec* timestamp) {
Pavlin Radoslavov61d1e862018-05-08 18:00:24 -0700751 if ((common->ctrl_fd == AUDIO_SKT_DISCONNECTED) ||
752 (common->state != AUDIO_A2DP_STATE_STARTED)) { // Audio is not streaming
Ajay Panickerd4f25662018-04-05 09:14:51 -0700753 return -1;
754 }
755
Ajay Panickeref673c52016-12-21 15:37:34 -0800756 if (a2dp_command(common, A2DP_CTRL_GET_PRESENTATION_POSITION) < 0) {
757 return -1;
758 }
759
760 if (a2dp_ctrl_receive(common, bytes, sizeof(*bytes)) < 0) {
761 return -1;
762 }
763
764 if (a2dp_ctrl_receive(common, delay, sizeof(*delay)) < 0) {
765 return -1;
766 }
767
768 uint32_t seconds;
769 if (a2dp_ctrl_receive(common, &seconds, sizeof(seconds)) < 0) {
770 return -1;
771 }
772
773 uint32_t nsec;
774 if (a2dp_ctrl_receive(common, &nsec, sizeof(nsec)) < 0) {
775 return -1;
776 }
777
778 timestamp->tv_sec = seconds;
779 timestamp->tv_nsec = nsec;
780 return 0;
781}
782
Myles Watson911d1ae2016-11-28 16:44:40 -0800783static void a2dp_open_ctrl_path(struct a2dp_stream_common* common) {
784 int i;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700785
Andy Hungf95d27b2017-05-01 15:04:57 -0700786 if (common->ctrl_fd != AUDIO_SKT_DISCONNECTED) return; // already connected
787
Myles Watson911d1ae2016-11-28 16:44:40 -0800788 /* retry logic to catch any timing variations on control channel */
789 for (i = 0; i < CTRL_CHAN_RETRY_COUNT; i++) {
790 /* connect control channel if not already connected */
Pavlin Radoslavovae9db0f2017-04-04 11:31:29 -0700791 if ((common->ctrl_fd = skt_connect(
Andy Hungf95d27b2017-05-01 15:04:57 -0700792 A2DP_CTRL_PATH, AUDIO_STREAM_CONTROL_OUTPUT_BUFFER_SZ)) >= 0) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800793 /* success, now check if stack is ready */
794 if (check_a2dp_ready(common) == 0) break;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700795
Myles Watson911d1ae2016-11-28 16:44:40 -0800796 ERROR("error : a2dp not ready, wait 250 ms and retry");
797 usleep(250000);
798 skt_disconnect(common->ctrl_fd);
799 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700800 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800801
802 /* ctrl channel not ready, wait a bit */
803 usleep(250000);
804 }
Mike Lockwood3e8a242f2014-05-23 12:42:24 -0700805}
806
The Android Open Source Project5738f832012-12-12 16:00:35 -0800807/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800808 *
809 * AUDIO DATA PATH
810 *
811 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800812
Myles Watson911d1ae2016-11-28 16:44:40 -0800813static void a2dp_stream_common_init(struct a2dp_stream_common* common) {
Myles Watson911d1ae2016-11-28 16:44:40 -0800814 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800815
Marie Janssen21da6372016-11-02 18:31:55 -0700816 common->mutex = new std::recursive_mutex;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800817
Myles Watson911d1ae2016-11-28 16:44:40 -0800818 common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
819 common->audio_fd = AUDIO_SKT_DISCONNECTED;
820 common->state = AUDIO_A2DP_STATE_STOPPED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800821
Myles Watson911d1ae2016-11-28 16:44:40 -0800822 /* manages max capacity of socket pipe */
823 common->buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800824}
825
Marie Janssen21da6372016-11-02 18:31:55 -0700826static void a2dp_stream_common_destroy(struct a2dp_stream_common* common) {
827 FNLOG();
828
829 delete common->mutex;
830 common->mutex = NULL;
831}
832
Myles Watson911d1ae2016-11-28 16:44:40 -0800833static int start_audio_datapath(struct a2dp_stream_common* common) {
834 INFO("state %d", common->state);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800835
Myles Watson911d1ae2016-11-28 16:44:40 -0800836 int oldstate = common->state;
837 common->state = AUDIO_A2DP_STATE_STARTING;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800838
Myles Watson911d1ae2016-11-28 16:44:40 -0800839 int a2dp_status = a2dp_command(common, A2DP_CTRL_CMD_START);
840 if (a2dp_status < 0) {
841 ERROR("Audiopath start failed (status %d)", a2dp_status);
842 goto error;
843 } else if (a2dp_status == A2DP_CTRL_ACK_INCALL_FAILURE) {
844 ERROR("Audiopath start failed - in call, move to suspended");
845 goto error;
846 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800847
Myles Watson911d1ae2016-11-28 16:44:40 -0800848 /* connect socket if not yet connected */
849 if (common->audio_fd == AUDIO_SKT_DISCONNECTED) {
850 common->audio_fd = skt_connect(A2DP_DATA_PATH, common->buffer_sz);
851 if (common->audio_fd < 0) {
852 ERROR("Audiopath start failed - error opening data socket");
853 goto error;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800854 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800855 }
856 common->state = (a2dp_state_t)AUDIO_A2DP_STATE_STARTED;
Ajay Panickeref673c52016-12-21 15:37:34 -0800857
858 /* check to see if delay reporting is enabled */
859 enable_delay_reporting = delay_reporting_enabled();
860
Myles Watson911d1ae2016-11-28 16:44:40 -0800861 return 0;
Eric Laurent7a599b42016-05-11 18:18:54 -0700862
863error:
Myles Watson911d1ae2016-11-28 16:44:40 -0800864 common->state = (a2dp_state_t)oldstate;
865 return -1;
866}
867
868static int stop_audio_datapath(struct a2dp_stream_common* common) {
869 int oldstate = common->state;
870
871 INFO("state %d", common->state);
872
873 /* prevent any stray output writes from autostarting the stream
874 while stopping audiopath */
875 common->state = AUDIO_A2DP_STATE_STOPPING;
876
877 if (a2dp_command(common, A2DP_CTRL_CMD_STOP) < 0) {
878 ERROR("audiopath stop failed");
Jakub Pawlowski6a059512016-05-25 17:49:32 -0700879 common->state = (a2dp_state_t)oldstate;
Eric Laurent7a599b42016-05-11 18:18:54 -0700880 return -1;
Myles Watson911d1ae2016-11-28 16:44:40 -0800881 }
882
883 common->state = (a2dp_state_t)AUDIO_A2DP_STATE_STOPPED;
884
885 /* disconnect audio path */
886 skt_disconnect(common->audio_fd);
887 common->audio_fd = AUDIO_SKT_DISCONNECTED;
888
889 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800890}
891
Myles Watson911d1ae2016-11-28 16:44:40 -0800892static int suspend_audio_datapath(struct a2dp_stream_common* common,
893 bool standby) {
894 INFO("state %d", common->state);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800895
Myles Watson911d1ae2016-11-28 16:44:40 -0800896 if (common->state == AUDIO_A2DP_STATE_STOPPING) return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800897
Myles Watson911d1ae2016-11-28 16:44:40 -0800898 if (a2dp_command(common, A2DP_CTRL_CMD_SUSPEND) < 0) return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800899
Myles Watson911d1ae2016-11-28 16:44:40 -0800900 if (standby)
901 common->state = AUDIO_A2DP_STATE_STANDBY;
902 else
903 common->state = AUDIO_A2DP_STATE_SUSPENDED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800904
Myles Watson911d1ae2016-11-28 16:44:40 -0800905 /* disconnect audio path */
906 skt_disconnect(common->audio_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800907
Myles Watson911d1ae2016-11-28 16:44:40 -0800908 common->audio_fd = AUDIO_SKT_DISCONNECTED;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800909
Myles Watson911d1ae2016-11-28 16:44:40 -0800910 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800911}
912
The Android Open Source Project5738f832012-12-12 16:00:35 -0800913/*****************************************************************************
Myles Watsonee96a3c2016-11-23 14:49:54 -0800914 *
915 * audio output callbacks
916 *
917 ****************************************************************************/
The Android Open Source Project5738f832012-12-12 16:00:35 -0800918
Myles Watson911d1ae2016-11-28 16:44:40 -0800919static ssize_t out_write(struct audio_stream_out* stream, const void* buffer,
920 size_t bytes) {
921 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
922 int sent = -1;
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700923 size_t write_bytes = bytes;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800924
Myles Watson911d1ae2016-11-28 16:44:40 -0800925 DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800926
Marie Janssen21da6372016-11-02 18:31:55 -0700927 std::unique_lock<std::recursive_mutex> lock(*out->common.mutex);
Myles Watson911d1ae2016-11-28 16:44:40 -0800928 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED ||
929 out->common.state == AUDIO_A2DP_STATE_STOPPING) {
930 DEBUG("stream suspended or closing");
931 goto finish;
932 }
933
934 /* only allow autostarting if we are in stopped or standby */
935 if ((out->common.state == AUDIO_A2DP_STATE_STOPPED) ||
936 (out->common.state == AUDIO_A2DP_STATE_STANDBY)) {
937 if (start_audio_datapath(&out->common) < 0) {
938 goto finish;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800939 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800940 } else if (out->common.state != AUDIO_A2DP_STATE_STARTED) {
941 ERROR("stream not in stopped or standby");
942 goto finish;
943 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800944
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700945 // Mix the stereo into mono if necessary
946 if (out->common.cfg.is_stereo_to_mono) {
947 const size_t frames = bytes / audio_stream_out_frame_size(stream);
948 int16_t* src = (int16_t*)buffer;
949 int16_t* dst = (int16_t*)buffer;
950 for (size_t i = 0; i < frames; i++, dst++, src += 2) {
951 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
952 }
953 write_bytes /= 2;
954 DEBUG("stereo-to-mono mixing: write %zu bytes (fd %d)", write_bytes,
955 out->common.audio_fd);
956 }
957
Marie Janssen21da6372016-11-02 18:31:55 -0700958 lock.unlock();
Pavlin Radoslavov95e81d02017-10-29 11:35:22 -0700959 sent = skt_write(out->common.audio_fd, buffer, write_bytes);
Marie Janssen21da6372016-11-02 18:31:55 -0700960 lock.lock();
Myles Watson911d1ae2016-11-28 16:44:40 -0800961
962 if (sent == -1) {
963 skt_disconnect(out->common.audio_fd);
964 out->common.audio_fd = AUDIO_SKT_DISCONNECTED;
965 if ((out->common.state != AUDIO_A2DP_STATE_SUSPENDED) &&
966 (out->common.state != AUDIO_A2DP_STATE_STOPPING)) {
967 out->common.state = AUDIO_A2DP_STATE_STOPPED;
968 } else {
969 ERROR("write failed : stream suspended, avoid resetting state");
The Android Open Source Project5738f832012-12-12 16:00:35 -0800970 }
Myles Watson911d1ae2016-11-28 16:44:40 -0800971 goto finish;
972 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800973
Myles Watson911d1ae2016-11-28 16:44:40 -0800974finish:;
975 const size_t frames = bytes / audio_stream_out_frame_size(stream);
976 out->frames_rendered += frames;
977 out->frames_presented += frames;
Marie Janssen21da6372016-11-02 18:31:55 -0700978 lock.unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800979
Myles Watson911d1ae2016-11-28 16:44:40 -0800980 // If send didn't work out, sleep to emulate write delay.
981 if (sent == -1) {
982 const int us_delay = calc_audiotime_usec(out->common.cfg, bytes);
983 DEBUG("emulate a2dp write delay (%d us)", us_delay);
984 usleep(us_delay);
985 }
986 return bytes;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800987}
988
Myles Watson911d1ae2016-11-28 16:44:40 -0800989static uint32_t out_get_sample_rate(const struct audio_stream* stream) {
990 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800991
Myles Watson911d1ae2016-11-28 16:44:40 -0800992 DEBUG("rate %" PRIu32, out->common.cfg.rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800993
Myles Watson911d1ae2016-11-28 16:44:40 -0800994 return out->common.cfg.rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800995}
996
Myles Watson911d1ae2016-11-28 16:44:40 -0800997static int out_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
998 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800999
Myles Watson911d1ae2016-11-28 16:44:40 -08001000 DEBUG("out_set_sample_rate : %" PRIu32, rate);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001001
Myles Watson911d1ae2016-11-28 16:44:40 -08001002 out->common.cfg.rate = rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001003
Myles Watson911d1ae2016-11-28 16:44:40 -08001004 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001005}
1006
Myles Watson911d1ae2016-11-28 16:44:40 -08001007static size_t out_get_buffer_size(const struct audio_stream* stream) {
1008 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
1009 // period_size is the AudioFlinger mixer buffer size.
1010 const size_t period_size =
1011 out->common.buffer_sz / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001012
Myles Watson911d1ae2016-11-28 16:44:40 -08001013 DEBUG("socket buffer size: %zu period size: %zu", out->common.buffer_sz,
1014 period_size);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001015
Myles Watson911d1ae2016-11-28 16:44:40 -08001016 return period_size;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001017}
1018
Pavlin Radoslavovbdd34d22017-04-05 16:18:26 -07001019size_t audio_a2dp_hw_stream_compute_buffer_size(
Pavlin Radoslavovae9db0f2017-04-04 11:31:29 -07001020 btav_a2dp_codec_sample_rate_t codec_sample_rate,
1021 btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample,
1022 btav_a2dp_codec_channel_mode_t codec_channel_mode) {
1023 size_t buffer_sz = AUDIO_STREAM_OUTPUT_BUFFER_SZ; // Default value
Pavlin Radoslavovbdd34d22017-04-05 16:18:26 -07001024 const uint64_t time_period_ms = 20; // Conservative 20ms
Pavlin Radoslavovae9db0f2017-04-04 11:31:29 -07001025 uint32_t sample_rate;
1026 uint32_t bits_per_sample;
1027 uint32_t number_of_channels;
1028
1029 // Check the codec config sample rate
1030 switch (codec_sample_rate) {
1031 case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
1032 sample_rate = 44100;
1033 break;
1034 case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
1035 sample_rate = 48000;
1036 break;
1037 case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
1038 sample_rate = 88200;
1039 break;
1040 case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
1041 sample_rate = 96000;
1042 break;
1043 case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
1044 sample_rate = 176400;
1045 break;
1046 case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
1047 sample_rate = 192000;
1048 break;
1049 case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
1050 default:
1051 ERROR("Invalid sample rate: 0x%x", codec_sample_rate);
1052 return buffer_sz;
1053 }
1054
1055 // Check the codec config bits per sample
1056 switch (codec_bits_per_sample) {
1057 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
1058 bits_per_sample = 16;
1059 break;
1060 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
1061 bits_per_sample = 24;
1062 break;
1063 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
1064 bits_per_sample = 32;
1065 break;
1066 case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
1067 default:
1068 ERROR("Invalid bits per sample: 0x%x", codec_bits_per_sample);
1069 return buffer_sz;
1070 }
1071
1072 // Check the codec config channel mode
1073 switch (codec_channel_mode) {
1074 case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
1075 number_of_channels = 1;
1076 break;
1077 case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
1078 number_of_channels = 2;
1079 break;
1080 case BTAV_A2DP_CODEC_CHANNEL_MODE_NONE:
1081 default:
1082 ERROR("Invalid channel mode: 0x%x", codec_channel_mode);
1083 return buffer_sz;
1084 }
1085
1086 //
1087 // The buffer size is computed by using the following formula:
1088 //
1089 // AUDIO_STREAM_OUTPUT_BUFFER_SIZE =
1090 // (TIME_PERIOD_MS * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS *
1091 // SAMPLE_RATE_HZ * NUMBER_OF_CHANNELS * (BITS_PER_SAMPLE / 8)) / 1000
1092 //
1093 // AUDIO_STREAM_OUTPUT_BUFFER_PERIODS controls how the socket buffer is
1094 // divided for AudioFlinger data delivery. The AudioFlinger mixer delivers
1095 // data in chunks of
1096 // (AUDIO_STREAM_OUTPUT_BUFFER_SIZE / AUDIO_STREAM_OUTPUT_BUFFER_PERIODS) .
1097 // If the number of periods is 2, the socket buffer represents "double
1098 // buffering" of the AudioFlinger mixer buffer.
1099 //
1100 // Furthermore, the AudioFlinger expects the buffer size to be a multiple
1101 // of 16 frames.
1102 const size_t divisor = (AUDIO_STREAM_OUTPUT_BUFFER_PERIODS * 16 *
1103 number_of_channels * bits_per_sample) /
1104 8;
1105
1106 buffer_sz = (time_period_ms * AUDIO_STREAM_OUTPUT_BUFFER_PERIODS *
1107 sample_rate * number_of_channels * (bits_per_sample / 8)) /
1108 1000;
1109
1110 // Adjust the buffer size so it can be divided by the divisor
1111 const size_t remainder = buffer_sz % divisor;
1112 if (remainder != 0) {
1113 buffer_sz += divisor - remainder;
1114 }
1115
1116 return buffer_sz;
1117}
1118
Myles Watson911d1ae2016-11-28 16:44:40 -08001119static uint32_t out_get_channels(const struct audio_stream* stream) {
1120 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001121
Myles Watson911d1ae2016-11-28 16:44:40 -08001122 DEBUG("channels 0x%" PRIx32, out->common.cfg.channel_mask);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001123
Myles Watson911d1ae2016-11-28 16:44:40 -08001124 return out->common.cfg.channel_mask;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001125}
1126
Myles Watson911d1ae2016-11-28 16:44:40 -08001127static audio_format_t out_get_format(const struct audio_stream* stream) {
1128 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
1129 DEBUG("format 0x%x", out->common.cfg.format);
1130 return (audio_format_t)out->common.cfg.format;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001131}
1132
Myles Watson911d1ae2016-11-28 16:44:40 -08001133static int out_set_format(UNUSED_ATTR struct audio_stream* stream,
1134 UNUSED_ATTR audio_format_t format) {
1135 DEBUG("setting format not yet supported (0x%x)", format);
1136 return -ENOSYS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001137}
1138
Myles Watson911d1ae2016-11-28 16:44:40 -08001139static int out_standby(struct audio_stream* stream) {
1140 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
1141 int retVal = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001142
Myles Watson911d1ae2016-11-28 16:44:40 -08001143 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001144
Marie Janssen21da6372016-11-02 18:31:55 -07001145 std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
Myles Watson911d1ae2016-11-28 16:44:40 -08001146 // Do nothing in SUSPENDED state.
1147 if (out->common.state != AUDIO_A2DP_STATE_SUSPENDED)
1148 retVal = suspend_audio_datapath(&out->common, true);
1149 out->frames_rendered = 0; // rendered is reset, presented is not
The Android Open Source Project5738f832012-12-12 16:00:35 -08001150
Myles Watson911d1ae2016-11-28 16:44:40 -08001151 return retVal;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001152}
1153
Myles Watson911d1ae2016-11-28 16:44:40 -08001154static int out_dump(UNUSED_ATTR const struct audio_stream* stream,
1155 UNUSED_ATTR int fd) {
1156 FNLOG();
1157 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001158}
1159
Myles Watson911d1ae2016-11-28 16:44:40 -08001160static int out_set_parameters(struct audio_stream* stream,
1161 const char* kvpairs) {
1162 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001163
Myles Watson911d1ae2016-11-28 16:44:40 -08001164 INFO("state %d kvpairs %s", out->common.state, kvpairs);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001165
Myles Watson911d1ae2016-11-28 16:44:40 -08001166 std::unordered_map<std::string, std::string> params =
1167 hash_map_utils_new_from_string_params(kvpairs);
1168 int status = 0;
Miao Chou118242b2015-07-29 14:12:11 -07001169
Myles Watson911d1ae2016-11-28 16:44:40 -08001170 if (params.empty()) return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001171
Marie Janssen21da6372016-11-02 18:31:55 -07001172 std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
Miao Chou118242b2015-07-29 14:12:11 -07001173
Myles Watson911d1ae2016-11-28 16:44:40 -08001174 /* dump params */
1175 hash_map_utils_dump_string_keys_string_values(params);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001176
Myles Watson911d1ae2016-11-28 16:44:40 -08001177 if (params["closing"].compare("true") == 0) {
1178 DEBUG("stream closing, disallow any writes");
1179 out->common.state = AUDIO_A2DP_STATE_STOPPING;
1180 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001181
Myles Watson911d1ae2016-11-28 16:44:40 -08001182 if (params["A2dpSuspended"].compare("true") == 0) {
1183 if (out->common.state == AUDIO_A2DP_STATE_STARTED)
1184 status = suspend_audio_datapath(&out->common, false);
1185 } else {
1186 /* Do not start the streaming automatically. If the phone was streaming
1187 * prior to being suspended, the next out_write shall trigger the
1188 * AVDTP start procedure */
1189 if (out->common.state == AUDIO_A2DP_STATE_SUSPENDED)
1190 out->common.state = AUDIO_A2DP_STATE_STANDBY;
1191 /* Irrespective of the state, return 0 */
1192 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001193
Myles Watson911d1ae2016-11-28 16:44:40 -08001194 return status;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001195}
1196
Myles Watson911d1ae2016-11-28 16:44:40 -08001197static char* out_get_parameters(const struct audio_stream* stream,
1198 const char* keys) {
1199 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001200
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001201 btav_a2dp_codec_config_t codec_config;
1202 btav_a2dp_codec_config_t codec_capability;
1203
Myles Watson911d1ae2016-11-28 16:44:40 -08001204 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001205
Myles Watson911d1ae2016-11-28 16:44:40 -08001206 std::unordered_map<std::string, std::string> params =
1207 hash_map_utils_new_from_string_params(keys);
1208 std::unordered_map<std::string, std::string> return_params;
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001209
Myles Watson911d1ae2016-11-28 16:44:40 -08001210 if (params.empty()) return strdup("");
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001211
Marie Janssen21da6372016-11-02 18:31:55 -07001212 std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001213
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001214 if (a2dp_read_output_audio_config(&out->common, &codec_config,
1215 &codec_capability,
1216 false /* update_stream_config */) < 0) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001217 ERROR("a2dp_read_output_audio_config failed");
1218 goto done;
1219 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001220
Myles Watson911d1ae2016-11-28 16:44:40 -08001221 // Add the format
1222 if (params.find(AUDIO_PARAMETER_STREAM_SUP_FORMATS) != params.end()) {
1223 std::string param;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001224 if (codec_capability.bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16) {
1225 if (!param.empty()) param += "|";
1226 param += "AUDIO_FORMAT_PCM_16_BIT";
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001227 }
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001228 if (codec_capability.bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24) {
1229 if (!param.empty()) param += "|";
1230 param += "AUDIO_FORMAT_PCM_24_BIT_PACKED";
1231 }
1232 if (codec_capability.bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32) {
1233 if (!param.empty()) param += "|";
1234 param += "AUDIO_FORMAT_PCM_32_BIT";
1235 }
1236 if (param.empty()) {
1237 ERROR("Invalid codec capability bits_per_sample=0x%x",
1238 codec_capability.bits_per_sample);
1239 goto done;
1240 } else {
Myles Watson911d1ae2016-11-28 16:44:40 -08001241 return_params[AUDIO_PARAMETER_STREAM_SUP_FORMATS] = param;
1242 }
1243 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001244
Myles Watson911d1ae2016-11-28 16:44:40 -08001245 // Add the sample rate
1246 if (params.find(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES) != params.end()) {
1247 std::string param;
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001248 if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100) {
1249 if (!param.empty()) param += "|";
1250 param += "44100";
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001251 }
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001252 if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000) {
1253 if (!param.empty()) param += "|";
1254 param += "48000";
1255 }
1256 if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200) {
1257 if (!param.empty()) param += "|";
1258 param += "88200";
1259 }
1260 if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000) {
1261 if (!param.empty()) param += "|";
1262 param += "96000";
1263 }
1264 if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400) {
1265 if (!param.empty()) param += "|";
1266 param += "176400";
1267 }
1268 if (codec_capability.sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000) {
1269 if (!param.empty()) param += "|";
1270 param += "192000";
1271 }
1272 if (param.empty()) {
1273 ERROR("Invalid codec capability sample_rate=0x%x",
1274 codec_capability.sample_rate);
1275 goto done;
1276 } else {
Myles Watson911d1ae2016-11-28 16:44:40 -08001277 return_params[AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES] = param;
1278 }
1279 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001280
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001281 // Add the channel mask
1282 if (params.find(AUDIO_PARAMETER_STREAM_SUP_CHANNELS) != params.end()) {
1283 std::string param;
1284 if (codec_capability.channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO) {
1285 if (!param.empty()) param += "|";
1286 param += "AUDIO_CHANNEL_OUT_MONO";
1287 }
1288 if (codec_capability.channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO) {
1289 if (!param.empty()) param += "|";
1290 param += "AUDIO_CHANNEL_OUT_STEREO";
1291 }
1292 if (param.empty()) {
1293 ERROR("Invalid codec capability channel_mode=0x%x",
1294 codec_capability.channel_mode);
1295 goto done;
1296 } else {
1297 return_params[AUDIO_PARAMETER_STREAM_SUP_CHANNELS] = param;
1298 }
1299 }
1300
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001301done:
Myles Watson911d1ae2016-11-28 16:44:40 -08001302 std::string result;
1303 for (const auto& ptr : return_params) {
1304 result += ptr.first + "=" + ptr.second + ";";
1305 }
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001306
Myles Watson911d1ae2016-11-28 16:44:40 -08001307 INFO("get parameters result = %s", result.c_str());
Pavlin Radoslavov4ebaa862016-11-22 11:42:11 -08001308
Myles Watson911d1ae2016-11-28 16:44:40 -08001309 return strdup(result.c_str());
The Android Open Source Project5738f832012-12-12 16:00:35 -08001310}
1311
Myles Watson911d1ae2016-11-28 16:44:40 -08001312static uint32_t out_get_latency(const struct audio_stream_out* stream) {
1313 int latency_us;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001314
Myles Watson911d1ae2016-11-28 16:44:40 -08001315 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001316
Myles Watson911d1ae2016-11-28 16:44:40 -08001317 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001318
Myles Watson911d1ae2016-11-28 16:44:40 -08001319 latency_us =
1320 ((out->common.buffer_sz * 1000) /
1321 audio_stream_out_frame_size(&out->stream) / out->common.cfg.rate) *
1322 1000;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001323
Myles Watson911d1ae2016-11-28 16:44:40 -08001324 return (latency_us / 1000) + 200;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001325}
1326
Myles Watson911d1ae2016-11-28 16:44:40 -08001327static int out_set_volume(UNUSED_ATTR struct audio_stream_out* stream,
1328 UNUSED_ATTR float left, UNUSED_ATTR float right) {
1329 FNLOG();
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001330
Myles Watson911d1ae2016-11-28 16:44:40 -08001331 /* volume controlled in audioflinger mixer (digital) */
The Android Open Source Project5738f832012-12-12 16:00:35 -08001332
Myles Watson911d1ae2016-11-28 16:44:40 -08001333 return -ENOSYS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001334}
1335
Myles Watson911d1ae2016-11-28 16:44:40 -08001336static int out_get_presentation_position(const struct audio_stream_out* stream,
1337 uint64_t* frames,
1338 struct timespec* timestamp) {
1339 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001340
Myles Watson911d1ae2016-11-28 16:44:40 -08001341 FNLOG();
1342 if (stream == NULL || frames == NULL || timestamp == NULL) return -EINVAL;
Eric Laurente1eb6c42015-05-26 15:50:29 -07001343
Marie Janssen21da6372016-11-02 18:31:55 -07001344 std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
Ajay Panickeref673c52016-12-21 15:37:34 -08001345
1346 // bytes is the total number of bytes sent by the Bluetooth stack to a
1347 // remote headset
1348 uint64_t bytes = 0;
1349
1350 // delay_report is the audio delay from the remote headset receiving data to
1351 // the headset playing sound in units of 1/10ms
1352 uint16_t delay_report = 0;
1353
1354 // If for some reason getting a delay fails or delay reports are disabled,
1355 // default to old delay
1356 if (enable_delay_reporting &&
1357 a2dp_get_presentation_position_cmd(&out->common, &bytes, &delay_report,
1358 timestamp) == 0) {
1359 uint64_t delay_ns = delay_report * DELAY_TO_NS;
1360 if (delay_ns > MIN_DELAY_MS * MS_TO_NS &&
1361 delay_ns < MAX_DELAY_MS * MS_TO_NS) {
1362 *frames = bytes / audio_stream_out_frame_size(stream);
1363
1364 timestamp->tv_nsec += delay_ns;
1365 if (timestamp->tv_nsec > 1 * SEC_TO_NS) {
1366 timestamp->tv_sec++;
1367 timestamp->tv_nsec -= SEC_TO_NS;
1368 }
1369 return 0;
1370 }
1371 }
1372
Myles Watson911d1ae2016-11-28 16:44:40 -08001373 uint64_t latency_frames =
1374 (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
1375 if (out->frames_presented >= latency_frames) {
Ajay Panickeref673c52016-12-21 15:37:34 -08001376 clock_gettime(CLOCK_MONOTONIC, timestamp);
Myles Watson911d1ae2016-11-28 16:44:40 -08001377 *frames = out->frames_presented - latency_frames;
Ajay Panickeref673c52016-12-21 15:37:34 -08001378 return 0;
Myles Watson911d1ae2016-11-28 16:44:40 -08001379 }
Ajay Panickeref673c52016-12-21 15:37:34 -08001380
1381 return -EWOULDBLOCK;
Eric Laurente1eb6c42015-05-26 15:50:29 -07001382}
The Android Open Source Project5738f832012-12-12 16:00:35 -08001383
Myles Watson911d1ae2016-11-28 16:44:40 -08001384static int out_get_render_position(const struct audio_stream_out* stream,
1385 uint32_t* dsp_frames) {
1386 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001387
Myles Watson911d1ae2016-11-28 16:44:40 -08001388 FNLOG();
1389 if (stream == NULL || dsp_frames == NULL) return -EINVAL;
Eric Laurente1eb6c42015-05-26 15:50:29 -07001390
Marie Janssen21da6372016-11-02 18:31:55 -07001391 std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
Myles Watson911d1ae2016-11-28 16:44:40 -08001392 uint64_t latency_frames =
1393 (uint64_t)out_get_latency(stream) * out->common.cfg.rate / 1000;
1394 if (out->frames_rendered >= latency_frames) {
1395 *dsp_frames = (uint32_t)(out->frames_rendered - latency_frames);
1396 } else {
1397 *dsp_frames = 0;
1398 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001399 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001400}
1401
Myles Watson911d1ae2016-11-28 16:44:40 -08001402static int out_add_audio_effect(UNUSED_ATTR const struct audio_stream* stream,
1403 UNUSED_ATTR effect_handle_t effect) {
1404 FNLOG();
1405 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001406}
1407
Myles Watson911d1ae2016-11-28 16:44:40 -08001408static int out_remove_audio_effect(
1409 UNUSED_ATTR const struct audio_stream* stream,
1410 UNUSED_ATTR effect_handle_t effect) {
1411 FNLOG();
1412 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001413}
1414
1415/*
1416 * AUDIO INPUT STREAM
1417 */
1418
Myles Watson911d1ae2016-11-28 16:44:40 -08001419static uint32_t in_get_sample_rate(const struct audio_stream* stream) {
1420 struct a2dp_stream_in* in = (struct a2dp_stream_in*)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001421
Myles Watson911d1ae2016-11-28 16:44:40 -08001422 FNLOG();
1423 return in->common.cfg.rate;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001424}
1425
Myles Watson911d1ae2016-11-28 16:44:40 -08001426static int in_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
1427 struct a2dp_stream_in* in = (struct a2dp_stream_in*)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001428
Myles Watson911d1ae2016-11-28 16:44:40 -08001429 FNLOG();
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001430
Myles Watson911d1ae2016-11-28 16:44:40 -08001431 if (in->common.cfg.rate > 0 && in->common.cfg.rate == rate)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001432 return 0;
Myles Watson911d1ae2016-11-28 16:44:40 -08001433 else
1434 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001435}
1436
Myles Watson911d1ae2016-11-28 16:44:40 -08001437static size_t in_get_buffer_size(
1438 UNUSED_ATTR const struct audio_stream* stream) {
1439 FNLOG();
1440 return 320;
1441}
1442
1443static uint32_t in_get_channels(const struct audio_stream* stream) {
1444 struct a2dp_stream_in* in = (struct a2dp_stream_in*)stream;
1445
1446 FNLOG();
1447 return in->common.cfg.channel_mask;
1448}
1449
1450static audio_format_t in_get_format(
1451 UNUSED_ATTR const struct audio_stream* stream) {
1452 FNLOG();
1453 return AUDIO_FORMAT_PCM_16_BIT;
1454}
1455
1456static int in_set_format(UNUSED_ATTR struct audio_stream* stream,
1457 UNUSED_ATTR audio_format_t format) {
1458 FNLOG();
1459 if (format == AUDIO_FORMAT_PCM_16_BIT)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001460 return 0;
Myles Watson911d1ae2016-11-28 16:44:40 -08001461 else
1462 return -1;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001463}
1464
Myles Watson911d1ae2016-11-28 16:44:40 -08001465static int in_standby(UNUSED_ATTR struct audio_stream* stream) {
1466 FNLOG();
1467 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001468}
1469
Myles Watson911d1ae2016-11-28 16:44:40 -08001470static int in_dump(UNUSED_ATTR const struct audio_stream* stream,
1471 UNUSED_ATTR int fd) {
1472 FNLOG();
1473 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001474}
1475
Myles Watson911d1ae2016-11-28 16:44:40 -08001476static int in_set_parameters(UNUSED_ATTR struct audio_stream* stream,
1477 UNUSED_ATTR const char* kvpairs) {
1478 FNLOG();
1479 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001480}
1481
Myles Watson911d1ae2016-11-28 16:44:40 -08001482static char* in_get_parameters(UNUSED_ATTR const struct audio_stream* stream,
1483 UNUSED_ATTR const char* keys) {
1484 FNLOG();
1485 return strdup("");
1486}
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001487
Myles Watson911d1ae2016-11-28 16:44:40 -08001488static int in_set_gain(UNUSED_ATTR struct audio_stream_in* stream,
1489 UNUSED_ATTR float gain) {
1490 FNLOG();
1491 return 0;
1492}
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001493
Myles Watson911d1ae2016-11-28 16:44:40 -08001494static ssize_t in_read(struct audio_stream_in* stream, void* buffer,
1495 size_t bytes) {
1496 struct a2dp_stream_in* in = (struct a2dp_stream_in*)stream;
1497 int read;
1498 int us_delay;
1499
1500 DEBUG("read %zu bytes, state: %d", bytes, in->common.state);
1501
Marie Janssen21da6372016-11-02 18:31:55 -07001502 std::unique_lock<std::recursive_mutex> lock(*in->common.mutex);
Myles Watson911d1ae2016-11-28 16:44:40 -08001503 if (in->common.state == AUDIO_A2DP_STATE_SUSPENDED ||
1504 in->common.state == AUDIO_A2DP_STATE_STOPPING) {
1505 DEBUG("stream suspended");
1506 goto error;
1507 }
1508
1509 /* only allow autostarting if we are in stopped or standby */
1510 if ((in->common.state == AUDIO_A2DP_STATE_STOPPED) ||
1511 (in->common.state == AUDIO_A2DP_STATE_STANDBY)) {
1512 if (start_audio_datapath(&in->common) < 0) {
1513 goto error;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001514 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001515 } else if (in->common.state != AUDIO_A2DP_STATE_STARTED) {
1516 ERROR("stream not in stopped or standby");
1517 goto error;
1518 }
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001519
Marie Janssen21da6372016-11-02 18:31:55 -07001520 lock.unlock();
Myles Watson911d1ae2016-11-28 16:44:40 -08001521 read = skt_read(in->common.audio_fd, buffer, bytes);
Marie Janssen21da6372016-11-02 18:31:55 -07001522 lock.lock();
Myles Watson911d1ae2016-11-28 16:44:40 -08001523 if (read == -1) {
1524 skt_disconnect(in->common.audio_fd);
1525 in->common.audio_fd = AUDIO_SKT_DISCONNECTED;
1526 if ((in->common.state != AUDIO_A2DP_STATE_SUSPENDED) &&
1527 (in->common.state != AUDIO_A2DP_STATE_STOPPING)) {
1528 in->common.state = AUDIO_A2DP_STATE_STOPPED;
1529 } else {
1530 ERROR("read failed : stream suspended, avoid resetting state");
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001531 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001532 goto error;
1533 } else if (read == 0) {
1534 DEBUG("read time out - return zeros");
1535 memset(buffer, 0, bytes);
1536 read = bytes;
1537 }
Marie Janssen21da6372016-11-02 18:31:55 -07001538 lock.unlock();
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001539
Myles Watson911d1ae2016-11-28 16:44:40 -08001540 DEBUG("read %d bytes out of %zu bytes", read, bytes);
1541 return read;
Eric Laurent7a599b42016-05-11 18:18:54 -07001542
1543error:
Myles Watson911d1ae2016-11-28 16:44:40 -08001544 memset(buffer, 0, bytes);
1545 us_delay = calc_audiotime_usec(in->common.cfg, bytes);
1546 DEBUG("emulate a2dp read delay (%d us)", us_delay);
Eric Laurent7a599b42016-05-11 18:18:54 -07001547
Myles Watson911d1ae2016-11-28 16:44:40 -08001548 usleep(us_delay);
1549 return bytes;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001550}
1551
Myles Watson911d1ae2016-11-28 16:44:40 -08001552static uint32_t in_get_input_frames_lost(
1553 UNUSED_ATTR struct audio_stream_in* stream) {
1554 FNLOG();
1555 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001556}
1557
Myles Watson911d1ae2016-11-28 16:44:40 -08001558static int in_add_audio_effect(UNUSED_ATTR const struct audio_stream* stream,
1559 UNUSED_ATTR effect_handle_t effect) {
1560 FNLOG();
1561 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001562}
1563
Myles Watson911d1ae2016-11-28 16:44:40 -08001564static int in_remove_audio_effect(UNUSED_ATTR const struct audio_stream* stream,
1565 UNUSED_ATTR effect_handle_t effect) {
1566 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001567
Myles Watson911d1ae2016-11-28 16:44:40 -08001568 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001569}
1570
Myles Watson911d1ae2016-11-28 16:44:40 -08001571static int adev_open_output_stream(struct audio_hw_device* dev,
Myles Watsond35a6482016-10-27 08:52:16 -07001572 UNUSED_ATTR audio_io_handle_t handle,
1573 UNUSED_ATTR audio_devices_t devices,
1574 UNUSED_ATTR audio_output_flags_t flags,
Myles Watson911d1ae2016-11-28 16:44:40 -08001575 struct audio_config* config,
1576 struct audio_stream_out** stream_out,
1577 UNUSED_ATTR const char* address)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001578
1579{
Myles Watson911d1ae2016-11-28 16:44:40 -08001580 struct a2dp_audio_device* a2dp_dev = (struct a2dp_audio_device*)dev;
1581 struct a2dp_stream_out* out;
1582 int ret = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001583
Myles Watson911d1ae2016-11-28 16:44:40 -08001584 INFO("opening output");
Andy Hungb1a900f2017-03-30 16:28:46 -07001585 // protect against adev->output and stream_out from being inconsistent
1586 std::lock_guard<std::recursive_mutex> lock(*a2dp_dev->mutex);
Myles Watson911d1ae2016-11-28 16:44:40 -08001587 out = (struct a2dp_stream_out*)calloc(1, sizeof(struct a2dp_stream_out));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001588
Myles Watson911d1ae2016-11-28 16:44:40 -08001589 if (!out) return -ENOMEM;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001590
Myles Watson911d1ae2016-11-28 16:44:40 -08001591 out->stream.common.get_sample_rate = out_get_sample_rate;
1592 out->stream.common.set_sample_rate = out_set_sample_rate;
1593 out->stream.common.get_buffer_size = out_get_buffer_size;
1594 out->stream.common.get_channels = out_get_channels;
1595 out->stream.common.get_format = out_get_format;
1596 out->stream.common.set_format = out_set_format;
1597 out->stream.common.standby = out_standby;
1598 out->stream.common.dump = out_dump;
1599 out->stream.common.set_parameters = out_set_parameters;
1600 out->stream.common.get_parameters = out_get_parameters;
1601 out->stream.common.add_audio_effect = out_add_audio_effect;
1602 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1603 out->stream.get_latency = out_get_latency;
1604 out->stream.set_volume = out_set_volume;
1605 out->stream.write = out_write;
1606 out->stream.get_render_position = out_get_render_position;
1607 out->stream.get_presentation_position = out_get_presentation_position;
Eric Laurente1eb6c42015-05-26 15:50:29 -07001608
Myles Watson911d1ae2016-11-28 16:44:40 -08001609 /* initialize a2dp specifics */
1610 a2dp_stream_common_init(&out->common);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001611
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001612 // Make sure we always have the feeding parameters configured
1613 btav_a2dp_codec_config_t codec_config;
1614 btav_a2dp_codec_config_t codec_capability;
1615 if (a2dp_read_output_audio_config(&out->common, &codec_config,
1616 &codec_capability,
1617 true /* update_stream_config */) < 0) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001618 ERROR("a2dp_read_output_audio_config failed");
1619 ret = -1;
1620 goto err_open;
1621 }
Andy Hungf95d27b2017-05-01 15:04:57 -07001622 // a2dp_read_output_audio_config() opens the socket control path (or fails)
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001623
Myles Watson911d1ae2016-11-28 16:44:40 -08001624 /* set output config values */
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001625 if (config != nullptr) {
1626 // Try to use the config parameters and send it to the remote side
1627 // TODO: Shall we use out_set_format() and similar?
1628 if (config->format != 0) out->common.cfg.format = config->format;
1629 if (config->sample_rate != 0) out->common.cfg.rate = config->sample_rate;
1630 if (config->channel_mask != 0)
1631 out->common.cfg.channel_mask = config->channel_mask;
1632 if ((out->common.cfg.format != 0) || (out->common.cfg.rate != 0) ||
1633 (out->common.cfg.channel_mask != 0)) {
1634 if (a2dp_write_output_audio_config(&out->common) < 0) {
1635 ERROR("a2dp_write_output_audio_config failed");
1636 ret = -1;
1637 goto err_open;
1638 }
1639 // Read again and make sure we use the same parameters as the remote side
1640 if (a2dp_read_output_audio_config(&out->common, &codec_config,
1641 &codec_capability,
1642 true /* update_stream_config */) < 0) {
1643 ERROR("a2dp_read_output_audio_config failed");
1644 ret = -1;
1645 goto err_open;
1646 }
1647 }
Myles Watson911d1ae2016-11-28 16:44:40 -08001648 config->format = out_get_format((const struct audio_stream*)&out->stream);
1649 config->sample_rate =
1650 out_get_sample_rate((const struct audio_stream*)&out->stream);
1651 config->channel_mask =
1652 out_get_channels((const struct audio_stream*)&out->stream);
Pavlin Radoslavov5ce01162016-12-05 13:02:26 -08001653
Pavlin Radoslavovae9db0f2017-04-04 11:31:29 -07001654 INFO(
1655 "Output stream config: format=0x%x sample_rate=%d channel_mask=0x%x "
1656 "buffer_sz=%zu",
1657 config->format, config->sample_rate, config->channel_mask,
1658 out->common.buffer_sz);
Myles Watson911d1ae2016-11-28 16:44:40 -08001659 }
1660 *stream_out = &out->stream;
1661 a2dp_dev->output = out;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001662
Myles Watson911d1ae2016-11-28 16:44:40 -08001663 DEBUG("success");
1664 /* Delay to ensure Headset is in proper state when START is initiated from
1665 * DUT immediately after the connection due to ongoing music playback. */
1666 usleep(250000);
1667 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001668
1669err_open:
Marie Janssen21da6372016-11-02 18:31:55 -07001670 a2dp_stream_common_destroy(&out->common);
Myles Watson911d1ae2016-11-28 16:44:40 -08001671 free(out);
1672 *stream_out = NULL;
1673 a2dp_dev->output = NULL;
1674 ERROR("failed");
1675 return ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001676}
1677
Myles Watson911d1ae2016-11-28 16:44:40 -08001678static void adev_close_output_stream(struct audio_hw_device* dev,
1679 struct audio_stream_out* stream) {
1680 struct a2dp_audio_device* a2dp_dev = (struct a2dp_audio_device*)dev;
1681 struct a2dp_stream_out* out = (struct a2dp_stream_out*)stream;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001682
Stanley Tng05cc6c72018-10-10 18:57:29 -07001683 INFO("%s: state %d", __func__, out->common.state);
1684
Andy Hungb1a900f2017-03-30 16:28:46 -07001685 // prevent interference with adev_set_parameters.
1686 std::lock_guard<std::recursive_mutex> lock(*a2dp_dev->mutex);
1687 {
1688 std::lock_guard<std::recursive_mutex> lock(*out->common.mutex);
1689 const a2dp_state_t state = out->common.state;
1690 INFO("closing output (state %d)", (int)state);
1691 if ((state == AUDIO_A2DP_STATE_STARTED) ||
1692 (state == AUDIO_A2DP_STATE_STOPPING)) {
1693 stop_audio_datapath(&out->common);
1694 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001695
Andy Hungb1a900f2017-03-30 16:28:46 -07001696 skt_disconnect(out->common.ctrl_fd);
1697 out->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
Myles Watson911d1ae2016-11-28 16:44:40 -08001698 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001699
Marie Janssen21da6372016-11-02 18:31:55 -07001700 a2dp_stream_common_destroy(&out->common);
Myles Watson911d1ae2016-11-28 16:44:40 -08001701 free(stream);
1702 a2dp_dev->output = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001703
Myles Watson911d1ae2016-11-28 16:44:40 -08001704 DEBUG("done");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001705}
1706
Myles Watson911d1ae2016-11-28 16:44:40 -08001707static int adev_set_parameters(struct audio_hw_device* dev,
1708 const char* kvpairs) {
1709 struct a2dp_audio_device* a2dp_dev = (struct a2dp_audio_device*)dev;
Myles Watson911d1ae2016-11-28 16:44:40 -08001710 int retval = 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001711
Andy Hungb1a900f2017-03-30 16:28:46 -07001712 // prevent interference with adev_close_output_stream
1713 std::lock_guard<std::recursive_mutex> lock(*a2dp_dev->mutex);
1714 struct a2dp_stream_out* out = a2dp_dev->output;
1715
Myles Watson911d1ae2016-11-28 16:44:40 -08001716 if (out == NULL) return retval;
Eric Laurent71ac7a72014-10-29 17:17:31 -07001717
Myles Watson911d1ae2016-11-28 16:44:40 -08001718 INFO("state %d", out->common.state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001719
Myles Watson911d1ae2016-11-28 16:44:40 -08001720 retval =
1721 out->stream.common.set_parameters((struct audio_stream*)out, kvpairs);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001722
Myles Watson911d1ae2016-11-28 16:44:40 -08001723 return retval;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001724}
1725
Myles Watson911d1ae2016-11-28 16:44:40 -08001726static char* adev_get_parameters(UNUSED_ATTR const struct audio_hw_device* dev,
1727 const char* keys) {
1728 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001729
Myles Watson911d1ae2016-11-28 16:44:40 -08001730 std::unordered_map<std::string, std::string> params =
1731 hash_map_utils_new_from_string_params(keys);
1732 hash_map_utils_dump_string_keys_string_values(params);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001733
Myles Watson911d1ae2016-11-28 16:44:40 -08001734 return strdup("");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001735}
1736
Myles Watson911d1ae2016-11-28 16:44:40 -08001737static int adev_init_check(UNUSED_ATTR const struct audio_hw_device* dev) {
1738 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001739
Myles Watson911d1ae2016-11-28 16:44:40 -08001740 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001741}
1742
Myles Watson911d1ae2016-11-28 16:44:40 -08001743static int adev_set_voice_volume(UNUSED_ATTR struct audio_hw_device* dev,
1744 UNUSED_ATTR float volume) {
1745 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001746
Myles Watson911d1ae2016-11-28 16:44:40 -08001747 return -ENOSYS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001748}
1749
Myles Watson911d1ae2016-11-28 16:44:40 -08001750static int adev_set_master_volume(UNUSED_ATTR struct audio_hw_device* dev,
1751 UNUSED_ATTR float volume) {
1752 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001753
Myles Watson911d1ae2016-11-28 16:44:40 -08001754 return -ENOSYS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001755}
1756
Myles Watson911d1ae2016-11-28 16:44:40 -08001757static int adev_set_mode(UNUSED_ATTR struct audio_hw_device* dev,
1758 UNUSED_ATTR audio_mode_t mode) {
1759 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001760
Myles Watson911d1ae2016-11-28 16:44:40 -08001761 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001762}
1763
Myles Watson911d1ae2016-11-28 16:44:40 -08001764static int adev_set_mic_mute(UNUSED_ATTR struct audio_hw_device* dev,
1765 UNUSED_ATTR bool state) {
1766 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001767
Myles Watson911d1ae2016-11-28 16:44:40 -08001768 return -ENOSYS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001769}
1770
Myles Watson911d1ae2016-11-28 16:44:40 -08001771static int adev_get_mic_mute(UNUSED_ATTR const struct audio_hw_device* dev,
1772 UNUSED_ATTR bool* state) {
1773 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001774
Myles Watson911d1ae2016-11-28 16:44:40 -08001775 return -ENOSYS;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001776}
1777
Myles Watson911d1ae2016-11-28 16:44:40 -08001778static size_t adev_get_input_buffer_size(
1779 UNUSED_ATTR const struct audio_hw_device* dev,
1780 UNUSED_ATTR const struct audio_config* config) {
1781 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001782
Myles Watson911d1ae2016-11-28 16:44:40 -08001783 return 320;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001784}
1785
Myles Watson911d1ae2016-11-28 16:44:40 -08001786static int adev_open_input_stream(struct audio_hw_device* dev,
Myles Watsond35a6482016-10-27 08:52:16 -07001787 UNUSED_ATTR audio_io_handle_t handle,
1788 UNUSED_ATTR audio_devices_t devices,
Myles Watson911d1ae2016-11-28 16:44:40 -08001789 UNUSED_ATTR struct audio_config* config,
1790 struct audio_stream_in** stream_in,
Myles Watsond35a6482016-10-27 08:52:16 -07001791 UNUSED_ATTR audio_input_flags_t flags,
Myles Watson911d1ae2016-11-28 16:44:40 -08001792 UNUSED_ATTR const char* address,
1793 UNUSED_ATTR audio_source_t source) {
1794 struct a2dp_audio_device* a2dp_dev = (struct a2dp_audio_device*)dev;
1795 struct a2dp_stream_in* in;
1796 int ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001797
Myles Watson911d1ae2016-11-28 16:44:40 -08001798 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001799
Andy Hungb1a900f2017-03-30 16:28:46 -07001800 // protect against adev->input and stream_in from being inconsistent
1801 std::lock_guard<std::recursive_mutex> lock(*a2dp_dev->mutex);
Myles Watson911d1ae2016-11-28 16:44:40 -08001802 in = (struct a2dp_stream_in*)calloc(1, sizeof(struct a2dp_stream_in));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001803
Myles Watson911d1ae2016-11-28 16:44:40 -08001804 if (!in) return -ENOMEM;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001805
Myles Watson911d1ae2016-11-28 16:44:40 -08001806 in->stream.common.get_sample_rate = in_get_sample_rate;
1807 in->stream.common.set_sample_rate = in_set_sample_rate;
1808 in->stream.common.get_buffer_size = in_get_buffer_size;
1809 in->stream.common.get_channels = in_get_channels;
1810 in->stream.common.get_format = in_get_format;
1811 in->stream.common.set_format = in_set_format;
1812 in->stream.common.standby = in_standby;
1813 in->stream.common.dump = in_dump;
1814 in->stream.common.set_parameters = in_set_parameters;
1815 in->stream.common.get_parameters = in_get_parameters;
1816 in->stream.common.add_audio_effect = in_add_audio_effect;
1817 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1818 in->stream.set_gain = in_set_gain;
1819 in->stream.read = in_read;
1820 in->stream.get_input_frames_lost = in_get_input_frames_lost;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001821
Myles Watson911d1ae2016-11-28 16:44:40 -08001822 /* initialize a2dp specifics */
1823 a2dp_stream_common_init(&in->common);
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001824
Myles Watson911d1ae2016-11-28 16:44:40 -08001825 *stream_in = &in->stream;
1826 a2dp_dev->input = in;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001827
Myles Watson911d1ae2016-11-28 16:44:40 -08001828 if (a2dp_read_input_audio_config(&in->common) < 0) {
1829 ERROR("a2dp_read_input_audio_config failed (%s)", strerror(errno));
1830 ret = -1;
1831 goto err_open;
1832 }
Andy Hungf95d27b2017-05-01 15:04:57 -07001833 // a2dp_read_input_audio_config() opens socket control path (or fails)
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001834
Myles Watson911d1ae2016-11-28 16:44:40 -08001835 DEBUG("success");
1836 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001837
1838err_open:
Marie Janssen21da6372016-11-02 18:31:55 -07001839 a2dp_stream_common_destroy(&in->common);
Myles Watson911d1ae2016-11-28 16:44:40 -08001840 free(in);
1841 *stream_in = NULL;
1842 a2dp_dev->input = NULL;
1843 ERROR("failed");
1844 return ret;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001845}
1846
Myles Watson911d1ae2016-11-28 16:44:40 -08001847static void adev_close_input_stream(struct audio_hw_device* dev,
1848 struct audio_stream_in* stream) {
1849 struct a2dp_audio_device* a2dp_dev = (struct a2dp_audio_device*)dev;
1850 struct a2dp_stream_in* in = (struct a2dp_stream_in*)stream;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -08001851
Andy Hungb1a900f2017-03-30 16:28:46 -07001852 std::lock_guard<std::recursive_mutex> lock(*a2dp_dev->mutex);
1853 {
1854 std::lock_guard<std::recursive_mutex> lock(*in->common.mutex);
1855 const a2dp_state_t state = in->common.state;
1856 INFO("closing input (state %d)", (int)state);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001857
Andy Hungb1a900f2017-03-30 16:28:46 -07001858 if ((state == AUDIO_A2DP_STATE_STARTED) ||
1859 (state == AUDIO_A2DP_STATE_STOPPING))
1860 stop_audio_datapath(&in->common);
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001861
Andy Hungb1a900f2017-03-30 16:28:46 -07001862 skt_disconnect(in->common.ctrl_fd);
1863 in->common.ctrl_fd = AUDIO_SKT_DISCONNECTED;
1864 }
Marie Janssen21da6372016-11-02 18:31:55 -07001865 a2dp_stream_common_destroy(&in->common);
Myles Watson911d1ae2016-11-28 16:44:40 -08001866 free(stream);
1867 a2dp_dev->input = NULL;
Mike Lockwood3e8a242f2014-05-23 12:42:24 -07001868
Myles Watson911d1ae2016-11-28 16:44:40 -08001869 DEBUG("done");
The Android Open Source Project5738f832012-12-12 16:00:35 -08001870}
1871
Myles Watson911d1ae2016-11-28 16:44:40 -08001872static int adev_dump(UNUSED_ATTR const audio_hw_device_t* device,
1873 UNUSED_ATTR int fd) {
1874 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001875
Myles Watson911d1ae2016-11-28 16:44:40 -08001876 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001877}
1878
Myles Watson911d1ae2016-11-28 16:44:40 -08001879static int adev_close(hw_device_t* device) {
Andy Hungb1a900f2017-03-30 16:28:46 -07001880 struct a2dp_audio_device* a2dp_dev = (struct a2dp_audio_device*)device;
Myles Watson911d1ae2016-11-28 16:44:40 -08001881 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001882
Andy Hungb1a900f2017-03-30 16:28:46 -07001883 delete a2dp_dev->mutex;
1884 a2dp_dev->mutex = nullptr;
Myles Watson911d1ae2016-11-28 16:44:40 -08001885 free(device);
1886 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001887}
1888
1889static int adev_open(const hw_module_t* module, const char* name,
Myles Watson911d1ae2016-11-28 16:44:40 -08001890 hw_device_t** device) {
1891 struct a2dp_audio_device* adev;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001892
Myles Watson911d1ae2016-11-28 16:44:40 -08001893 INFO(" adev_open in A2dp_hw module");
1894 FNLOG();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001895
Myles Watson911d1ae2016-11-28 16:44:40 -08001896 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
1897 ERROR("interface %s not matching [%s]", name, AUDIO_HARDWARE_INTERFACE);
1898 return -EINVAL;
1899 }
The Android Open Source Project5738f832012-12-12 16:00:35 -08001900
Myles Watson911d1ae2016-11-28 16:44:40 -08001901 adev = (struct a2dp_audio_device*)calloc(1, sizeof(struct a2dp_audio_device));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001902
Myles Watson911d1ae2016-11-28 16:44:40 -08001903 if (!adev) return -ENOMEM;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001904
Andy Hungb1a900f2017-03-30 16:28:46 -07001905 adev->mutex = new std::recursive_mutex;
1906
Myles Watson911d1ae2016-11-28 16:44:40 -08001907 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1908 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1909 adev->device.common.module = (struct hw_module_t*)module;
1910 adev->device.common.close = adev_close;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001911
Myles Watson911d1ae2016-11-28 16:44:40 -08001912 adev->device.init_check = adev_init_check;
1913 adev->device.set_voice_volume = adev_set_voice_volume;
1914 adev->device.set_master_volume = adev_set_master_volume;
1915 adev->device.set_mode = adev_set_mode;
1916 adev->device.set_mic_mute = adev_set_mic_mute;
1917 adev->device.get_mic_mute = adev_get_mic_mute;
1918 adev->device.set_parameters = adev_set_parameters;
1919 adev->device.get_parameters = adev_get_parameters;
1920 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1921 adev->device.open_output_stream = adev_open_output_stream;
1922 adev->device.close_output_stream = adev_close_output_stream;
1923 adev->device.open_input_stream = adev_open_input_stream;
1924 adev->device.close_input_stream = adev_close_input_stream;
1925 adev->device.dump = adev_dump;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001926
Myles Watson911d1ae2016-11-28 16:44:40 -08001927 adev->output = NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001928
Myles Watson911d1ae2016-11-28 16:44:40 -08001929 *device = &adev->device.common;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001930
Myles Watson911d1ae2016-11-28 16:44:40 -08001931 return 0;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001932}
1933
1934static struct hw_module_methods_t hal_module_methods = {
1935 .open = adev_open,
1936};
1937
Myles Watson911d1ae2016-11-28 16:44:40 -08001938__attribute__((
1939 visibility("default"))) struct audio_module HAL_MODULE_INFO_SYM = {
1940 .common =
1941 {
1942 .tag = HARDWARE_MODULE_TAG,
1943 .version_major = 1,
1944 .version_minor = 0,
1945 .id = AUDIO_HARDWARE_MODULE_ID,
1946 .name = "A2DP Audio HW HAL",
1947 .author = "The Android Open Source Project",
1948 .methods = &hal_module_methods,
1949 },
The Android Open Source Project5738f832012-12-12 16:00:35 -08001950};