blob: 805e2cde32e08f1aa85b0a72705a5a8170adab27 [file] [log] [blame]
Amit Pundir4e375822019-04-18 16:46:10 +05301/*
Amit Pundir456949d2020-02-18 22:44:16 +05302 * Copyright (C) 2012 The Android Open Source Project
Amit Pundir4e375822019-04-18 16:46:10 +05303 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Amit Pundir456949d2020-02-18 22:44:16 +053015 *
16 * Copied as it is from device/google/cuttlefish/guest/hals/audio/audio_hw.c
17 * and fixed couple of typos pointed out by Lint during review.
Amit Pundir4e375822019-04-18 16:46:10 +053018 */
19
Amit Pundir456949d2020-02-18 22:44:16 +053020#define LOG_TAG "audio_hw_generic"
Amit Pundir4e375822019-04-18 16:46:10 +053021
Amit Pundir456949d2020-02-18 22:44:16 +053022#include <assert.h>
Amit Pundir4e375822019-04-18 16:46:10 +053023#include <errno.h>
Amit Pundir456949d2020-02-18 22:44:16 +053024#include <inttypes.h>
Amit Pundir4e375822019-04-18 16:46:10 +053025#include <pthread.h>
26#include <stdint.h>
Amit Pundir4e375822019-04-18 16:46:10 +053027#include <stdlib.h>
Amit Pundir456949d2020-02-18 22:44:16 +053028#include <sys/time.h>
29#include <dlfcn.h>
30#include <fcntl.h>
Amit Pundir4e375822019-04-18 16:46:10 +053031#include <unistd.h>
32
33#include <log/log.h>
Amit Pundir456949d2020-02-18 22:44:16 +053034#include <cutils/list.h>
Amit Pundir4e375822019-04-18 16:46:10 +053035#include <cutils/str_parms.h>
Amit Pundir4e375822019-04-18 16:46:10 +053036
37#include <hardware/hardware.h>
38#include <system/audio.h>
39#include <hardware/audio.h>
Amit Pundir4e375822019-04-18 16:46:10 +053040#include <tinyalsa/asoundlib.h>
Amit Pundir456949d2020-02-18 22:44:16 +053041
42#define PCM_CARD 0
43#define PCM_DEVICE 0
Amit Pundir4e375822019-04-18 16:46:10 +053044
45
Amit Pundir456949d2020-02-18 22:44:16 +053046#define OUT_PERIOD_MS 15
47#define OUT_PERIOD_COUNT 4
Amit Pundir4e375822019-04-18 16:46:10 +053048
Amit Pundir456949d2020-02-18 22:44:16 +053049#define IN_PERIOD_MS 15
50#define IN_PERIOD_COUNT 4
Amit Pundir4e375822019-04-18 16:46:10 +053051
Amit Pundir456949d2020-02-18 22:44:16 +053052struct generic_audio_device {
53 struct audio_hw_device device; // Constant after init
54 pthread_mutex_t lock;
55 bool mic_mute; // Protected by this->lock
56 struct mixer* mixer; // Protected by this->lock
57 struct listnode out_streams; // Record for output streams, protected by this->lock
58 struct listnode in_streams; // Record for input streams, protected by this->lock
59 audio_patch_handle_t next_patch_handle; // Protected by this->lock
Amit Pundir4e375822019-04-18 16:46:10 +053060};
61
Amit Pundir456949d2020-02-18 22:44:16 +053062/* If not NULL, this is a pointer to the fallback module.
63 * This really is the original goldfish audio device /dev/eac which we will use
64 * if no alsa devices are detected.
65 */
66static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state);
67static int adev_get_microphones(const audio_hw_device_t *dev,
68 struct audio_microphone_characteristic_t *mic_array,
69 size_t *mic_count);
Amit Pundir4e375822019-04-18 16:46:10 +053070
71
Amit Pundir456949d2020-02-18 22:44:16 +053072typedef struct audio_vbuffer {
73 pthread_mutex_t lock;
74 uint8_t * data;
75 size_t frame_size;
76 size_t frame_count;
77 size_t head;
78 size_t tail;
79 size_t live;
80} audio_vbuffer_t;
Amit Pundir4e375822019-04-18 16:46:10 +053081
Amit Pundir456949d2020-02-18 22:44:16 +053082static int audio_vbuffer_init (audio_vbuffer_t * audio_vbuffer, size_t frame_count,
83 size_t frame_size) {
84 if (!audio_vbuffer) {
85 return -EINVAL;
Amit Pundir4e375822019-04-18 16:46:10 +053086 }
Amit Pundir456949d2020-02-18 22:44:16 +053087 audio_vbuffer->frame_size = frame_size;
88 audio_vbuffer->frame_count = frame_count;
89 size_t bytes = frame_count * frame_size;
90 audio_vbuffer->data = calloc(bytes, 1);
91 if (!audio_vbuffer->data) {
92 return -ENOMEM;
93 }
94 audio_vbuffer->head = 0;
95 audio_vbuffer->tail = 0;
96 audio_vbuffer->live = 0;
97 pthread_mutex_init (&audio_vbuffer->lock, (const pthread_mutexattr_t *) NULL);
Amit Pundir4e375822019-04-18 16:46:10 +053098 return 0;
99}
100
Amit Pundir456949d2020-02-18 22:44:16 +0530101static int audio_vbuffer_destroy (audio_vbuffer_t * audio_vbuffer) {
102 if (!audio_vbuffer) {
103 return -EINVAL;
104 }
105 free(audio_vbuffer->data);
106 pthread_mutex_destroy(&audio_vbuffer->lock);
107 return 0;
108}
109
110static int audio_vbuffer_live (audio_vbuffer_t * audio_vbuffer) {
111 if (!audio_vbuffer) {
112 return -EINVAL;
113 }
114 pthread_mutex_lock (&audio_vbuffer->lock);
115 int live = audio_vbuffer->live;
116 pthread_mutex_unlock (&audio_vbuffer->lock);
117 return live;
118}
119
120#define MIN(a,b) (((a)<(b))?(a):(b))
121static size_t audio_vbuffer_write (audio_vbuffer_t * audio_vbuffer, const void * buffer, size_t frame_count) {
122 size_t frames_written = 0;
123 pthread_mutex_lock (&audio_vbuffer->lock);
124
125 while (frame_count != 0) {
126 int frames = 0;
127 if (audio_vbuffer->live == 0 || audio_vbuffer->head > audio_vbuffer->tail) {
128 frames = MIN(frame_count, audio_vbuffer->frame_count - audio_vbuffer->head);
129 } else if (audio_vbuffer->head < audio_vbuffer->tail) {
130 frames = MIN(frame_count, audio_vbuffer->tail - (audio_vbuffer->head));
131 } else {
132 // Full
133 break;
134 }
135 memcpy(&audio_vbuffer->data[audio_vbuffer->head*audio_vbuffer->frame_size],
136 &((uint8_t*)buffer)[frames_written*audio_vbuffer->frame_size],
137 frames*audio_vbuffer->frame_size);
138 audio_vbuffer->live += frames;
139 frames_written += frames;
140 frame_count -= frames;
141 audio_vbuffer->head = (audio_vbuffer->head + frames) % audio_vbuffer->frame_count;
142 }
143
144 pthread_mutex_unlock (&audio_vbuffer->lock);
145 return frames_written;
146}
147
148static size_t audio_vbuffer_read (audio_vbuffer_t * audio_vbuffer, void * buffer, size_t frame_count) {
149 size_t frames_read = 0;
150 pthread_mutex_lock (&audio_vbuffer->lock);
151
152 while (frame_count != 0) {
153 int frames = 0;
154 if (audio_vbuffer->live == audio_vbuffer->frame_count ||
155 audio_vbuffer->tail > audio_vbuffer->head) {
156 frames = MIN(frame_count, audio_vbuffer->frame_count - audio_vbuffer->tail);
157 } else if (audio_vbuffer->tail < audio_vbuffer->head) {
158 frames = MIN(frame_count, audio_vbuffer->head - audio_vbuffer->tail);
159 } else {
160 break;
161 }
162 memcpy(&((uint8_t*)buffer)[frames_read*audio_vbuffer->frame_size],
163 &audio_vbuffer->data[audio_vbuffer->tail*audio_vbuffer->frame_size],
164 frames*audio_vbuffer->frame_size);
165 audio_vbuffer->live -= frames;
166 frames_read += frames;
167 frame_count -= frames;
168 audio_vbuffer->tail = (audio_vbuffer->tail + frames) % audio_vbuffer->frame_count;
169 }
170
171 pthread_mutex_unlock (&audio_vbuffer->lock);
172 return frames_read;
173}
174
175struct generic_stream_out {
176 struct audio_stream_out stream; // Constant after init
177 pthread_mutex_t lock;
178 struct generic_audio_device *dev; // Constant after init
179 uint32_t num_devices; // Protected by this->lock
180 audio_devices_t devices[AUDIO_PATCH_PORTS_MAX]; // Protected by this->lock
181 struct audio_config req_config; // Constant after init
182 struct pcm_config pcm_config; // Constant after init
183 audio_vbuffer_t buffer; // Constant after init
184
185 // Time & Position Keeping
186 bool standby; // Protected by this->lock
187 uint64_t underrun_position; // Protected by this->lock
188 struct timespec underrun_time; // Protected by this->lock
189 uint64_t last_write_time_us; // Protected by this->lock
190 uint64_t frames_total_buffered; // Protected by this->lock
191 uint64_t frames_written; // Protected by this->lock
192 uint64_t frames_rendered; // Protected by this->lock
193
194 // Worker
195 pthread_t worker_thread; // Constant after init
196 pthread_cond_t worker_wake; // Protected by this->lock
197 bool worker_standby; // Protected by this->lock
198 bool worker_exit; // Protected by this->lock
199
200 audio_io_handle_t handle; // Constant after init
201 audio_patch_handle_t patch_handle; // Protected by this->dev->lock
202
203 struct listnode stream_node; // Protected by this->dev->lock
204};
205
206struct generic_stream_in {
207 struct audio_stream_in stream; // Constant after init
208 pthread_mutex_t lock;
209 struct generic_audio_device *dev; // Constant after init
210 audio_devices_t device; // Protected by this->lock
211 struct audio_config req_config; // Constant after init
212 struct pcm *pcm; // Protected by this->lock
213 struct pcm_config pcm_config; // Constant after init
214 int16_t *stereo_to_mono_buf; // Protected by this->lock
215 size_t stereo_to_mono_buf_size; // Protected by this->lock
216 audio_vbuffer_t buffer; // Protected by this->lock
217
218 // Time & Position Keeping
219 bool standby; // Protected by this->lock
220 int64_t standby_position; // Protected by this->lock
221 struct timespec standby_exit_time;// Protected by this->lock
222 int64_t standby_frames_read; // Protected by this->lock
223
224 // Worker
225 pthread_t worker_thread; // Constant after init
226 pthread_cond_t worker_wake; // Protected by this->lock
227 bool worker_standby; // Protected by this->lock
228 bool worker_exit; // Protected by this->lock
229
230 audio_io_handle_t handle; // Constant after init
231 audio_patch_handle_t patch_handle; // Protected by this->dev->lock
232
233 struct listnode stream_node; // Protected by this->dev->lock
234};
235
236static struct pcm_config pcm_config_out = {
237 .channels = 2,
238 .rate = 0,
239 .period_size = 0,
240 .period_count = OUT_PERIOD_COUNT,
241 .format = PCM_FORMAT_S16_LE,
242 .start_threshold = 0,
243};
244
245static struct pcm_config pcm_config_in = {
246 .channels = 2,
247 .rate = 0,
248 .period_size = 0,
249 .period_count = IN_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = 0,
252 .stop_threshold = INT_MAX,
253};
254
255static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
256static unsigned int audio_device_ref_count = 0;
257
Amit Pundir4e375822019-04-18 16:46:10 +0530258static uint32_t out_get_sample_rate(const struct audio_stream *stream)
259{
Amit Pundir456949d2020-02-18 22:44:16 +0530260 struct generic_stream_out *out = (struct generic_stream_out *)stream;
261 return out->req_config.sample_rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530262}
263
264static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
265{
Amit Pundir4e375822019-04-18 16:46:10 +0530266 return -ENOSYS;
267}
268
269static size_t out_get_buffer_size(const struct audio_stream *stream)
270{
Amit Pundir456949d2020-02-18 22:44:16 +0530271 struct generic_stream_out *out = (struct generic_stream_out *)stream;
272 int size = out->pcm_config.period_size *
273 audio_stream_out_frame_size(&out->stream);
Amit Pundir4e375822019-04-18 16:46:10 +0530274
Amit Pundir456949d2020-02-18 22:44:16 +0530275 return size;
Amit Pundir4e375822019-04-18 16:46:10 +0530276}
277
278static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
279{
Amit Pundir456949d2020-02-18 22:44:16 +0530280 struct generic_stream_out *out = (struct generic_stream_out *)stream;
281 return out->req_config.channel_mask;
Amit Pundir4e375822019-04-18 16:46:10 +0530282}
283
284static audio_format_t out_get_format(const struct audio_stream *stream)
285{
Amit Pundir456949d2020-02-18 22:44:16 +0530286 struct generic_stream_out *out = (struct generic_stream_out *)stream;
287
288 return out->req_config.format;
Amit Pundir4e375822019-04-18 16:46:10 +0530289}
290
291static int out_set_format(struct audio_stream *stream, audio_format_t format)
292{
Amit Pundir4e375822019-04-18 16:46:10 +0530293 return -ENOSYS;
294}
295
Amit Pundir4e375822019-04-18 16:46:10 +0530296static int out_dump(const struct audio_stream *stream, int fd)
297{
Amit Pundir456949d2020-02-18 22:44:16 +0530298 struct generic_stream_out *out = (struct generic_stream_out *)stream;
299 pthread_mutex_lock(&out->lock);
300 dprintf(fd, "\tout_dump:\n"
301 "\t\tsample rate: %u\n"
302 "\t\tbuffer size: %zu\n"
303 "\t\tchannel mask: %08x\n"
304 "\t\tformat: %d\n"
305 "\t\tdevice(s): ",
306 out_get_sample_rate(stream),
307 out_get_buffer_size(stream),
308 out_get_channels(stream),
309 out_get_format(stream));
310 if (out->num_devices == 0) {
311 dprintf(fd, "%08x\n", AUDIO_DEVICE_NONE);
312 } else {
313 for (uint32_t i = 0; i < out->num_devices; i++) {
314 if (i != 0) {
315 dprintf(fd, ", ");
316 }
317 dprintf(fd, "%08x", out->devices[i]);
318 }
319 dprintf(fd, "\n");
320 }
321 dprintf(fd, "\t\taudio dev: %p\n\n", out->dev);
322 pthread_mutex_unlock(&out->lock);
Amit Pundir4e375822019-04-18 16:46:10 +0530323 return 0;
324}
325
326static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
327{
Amit Pundir4e375822019-04-18 16:46:10 +0530328 struct str_parms *parms;
329 char value[32];
Amit Pundir456949d2020-02-18 22:44:16 +0530330 int success;
331 int ret = -EINVAL;
Amit Pundir4e375822019-04-18 16:46:10 +0530332
Amit Pundir456949d2020-02-18 22:44:16 +0530333 if (kvpairs == NULL || kvpairs[0] == 0) {
334 return 0;
335 }
Amit Pundir4e375822019-04-18 16:46:10 +0530336 parms = str_parms_create_str(kvpairs);
Amit Pundir456949d2020-02-18 22:44:16 +0530337 success = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
338 value, sizeof(value));
339 // As the hal version is 3.0, it must not use set parameters API to set audio devices.
340 // Instead, it should use create_audio_patch API.
341 assert(("Must not use set parameters API to set audio devices", success < 0));
Amit Pundir4e375822019-04-18 16:46:10 +0530342
Amit Pundir456949d2020-02-18 22:44:16 +0530343 if (str_parms_has_key(parms, AUDIO_PARAMETER_STREAM_FORMAT)) {
344 // match the return value of out_set_format
345 ret = -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530346 }
347
348 str_parms_destroy(parms);
Amit Pundir456949d2020-02-18 22:44:16 +0530349
350 if (ret == -EINVAL) {
351 ALOGW("%s(), unsupported parameter %s", __func__, kvpairs);
352 // There is not any key supported for set_parameters API.
353 // Return error when there is non-null value passed in.
354 }
Amit Pundir4e375822019-04-18 16:46:10 +0530355 return ret;
356}
357
358static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
359{
Amit Pundir456949d2020-02-18 22:44:16 +0530360 struct generic_stream_out *out = (struct generic_stream_out *)stream;
361 struct str_parms *query = str_parms_create_str(keys);
362 char *str = NULL;
363 char value[256];
364 struct str_parms *reply = str_parms_create();
365 int ret;
366 bool get = false;
367
368 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
369 if (ret >= 0) {
370 pthread_mutex_lock(&out->lock);
371 audio_devices_t device = AUDIO_DEVICE_NONE;
372 for (uint32_t i = 0; i < out->num_devices; i++) {
373 device |= out->devices[i];
374 }
375 str_parms_add_int(reply, AUDIO_PARAMETER_STREAM_ROUTING, device);
376 pthread_mutex_unlock(&out->lock);
377 get = true;
378 }
379
380 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
381 value[0] = 0;
382 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
383 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
384 get = true;
385 }
386
387 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_FORMAT)) {
388 value[0] = 0;
389 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
390 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_FORMAT, value);
391 get = true;
392 }
393
394 if (get) {
395 str = str_parms_to_str(reply);
396 }
397 else {
398 ALOGD("%s Unsupported parameter: %s", __FUNCTION__, keys);
399 }
400
401 str_parms_destroy(query);
402 str_parms_destroy(reply);
403 return str;
Amit Pundir4e375822019-04-18 16:46:10 +0530404}
405
406static uint32_t out_get_latency(const struct audio_stream_out *stream)
407{
Amit Pundir456949d2020-02-18 22:44:16 +0530408 struct generic_stream_out *out = (struct generic_stream_out *)stream;
409 return (out->pcm_config.period_size * 1000) / out->pcm_config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530410}
411
412static int out_set_volume(struct audio_stream_out *stream, float left,
Amit Pundir456949d2020-02-18 22:44:16 +0530413 float right)
Amit Pundir4e375822019-04-18 16:46:10 +0530414{
Amit Pundir456949d2020-02-18 22:44:16 +0530415 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530416}
417
Amit Pundir456949d2020-02-18 22:44:16 +0530418static void *out_write_worker(void * args)
Amit Pundir4e375822019-04-18 16:46:10 +0530419{
Amit Pundir456949d2020-02-18 22:44:16 +0530420 struct generic_stream_out *out = (struct generic_stream_out *)args;
421 struct pcm *pcm = NULL;
422 uint8_t *buffer = NULL;
423 int buffer_frames;
424 int buffer_size;
425 bool restart = false;
426 bool shutdown = false;
427 while (true) {
428 pthread_mutex_lock(&out->lock);
429 while (out->worker_standby || restart) {
430 restart = false;
431 if (pcm) {
432 pcm_close(pcm); // Frees pcm
433 pcm = NULL;
434 free(buffer);
435 buffer=NULL;
436 }
437 if (out->worker_exit) {
438 break;
439 }
440 pthread_cond_wait(&out->worker_wake, &out->lock);
Amit Pundir4e375822019-04-18 16:46:10 +0530441 }
Amit Pundir456949d2020-02-18 22:44:16 +0530442
443 if (out->worker_exit) {
444 if (!out->worker_standby) {
445 ALOGE("Out worker not in standby before exiting");
446 }
447 shutdown = true;
448 }
449
450 while (!shutdown && audio_vbuffer_live(&out->buffer) == 0) {
451 pthread_cond_wait(&out->worker_wake, &out->lock);
452 }
453
454 if (shutdown) {
455 pthread_mutex_unlock(&out->lock);
456 break;
457 }
458
459 if (!pcm) {
460 pcm = pcm_open(PCM_CARD, PCM_DEVICE,
461 PCM_OUT | PCM_MONOTONIC, &out->pcm_config);
462 if (!pcm_is_ready(pcm)) {
463 ALOGE("pcm_open(out) failed: %s: channels %d format %d rate %d",
464 pcm_get_error(pcm),
465 out->pcm_config.channels,
466 out->pcm_config.format,
467 out->pcm_config.rate
468 );
469 pthread_mutex_unlock(&out->lock);
470 break;
471 }
472 buffer_frames = out->pcm_config.period_size;
473 buffer_size = pcm_frames_to_bytes(pcm, buffer_frames);
474 buffer = malloc(buffer_size);
475 if (!buffer) {
476 ALOGE("could not allocate write buffer");
477 pthread_mutex_unlock(&out->lock);
478 break;
479 }
480 }
481 int frames = audio_vbuffer_read(&out->buffer, buffer, buffer_frames);
482 pthread_mutex_unlock(&out->lock);
483 int ret = pcm_write(pcm, buffer, pcm_frames_to_bytes(pcm, frames));
484 if (ret != 0) {
485 ALOGE("pcm_write failed %s", pcm_get_error(pcm));
486 restart = true;
487 }
488 }
489 if (buffer) {
490 free(buffer);
Amit Pundir4e375822019-04-18 16:46:10 +0530491 }
492
Amit Pundir456949d2020-02-18 22:44:16 +0530493 return NULL;
494}
Amit Pundir4e375822019-04-18 16:46:10 +0530495
Amit Pundir456949d2020-02-18 22:44:16 +0530496// Call with in->lock held
497static void get_current_output_position(struct generic_stream_out *out,
498 uint64_t * position,
499 struct timespec * timestamp) {
500 struct timespec curtime = { .tv_sec = 0, .tv_nsec = 0 };
501 clock_gettime(CLOCK_MONOTONIC, &curtime);
502 const int64_t now_us = (curtime.tv_sec * 1000000000LL + curtime.tv_nsec) / 1000;
503 if (timestamp) {
504 *timestamp = curtime;
Amit Pundir4e375822019-04-18 16:46:10 +0530505 }
Amit Pundir456949d2020-02-18 22:44:16 +0530506 int64_t position_since_underrun;
507 if (out->standby) {
508 position_since_underrun = 0;
509 } else {
510 const int64_t first_us = (out->underrun_time.tv_sec * 1000000000LL +
511 out->underrun_time.tv_nsec) / 1000;
512 position_since_underrun = (now_us - first_us) *
513 out_get_sample_rate(&out->stream.common) /
514 1000000;
515 if (position_since_underrun < 0) {
516 position_since_underrun = 0;
517 }
518 }
519 *position = out->underrun_position + position_since_underrun;
520
521 // The device will reuse the same output stream leading to periods of
522 // underrun.
523 if (*position > out->frames_written) {
524 ALOGW("Not supplying enough data to HAL, expected position %" PRIu64 " , only wrote "
525 "%" PRIu64,
526 *position, out->frames_written);
527
528 *position = out->frames_written;
529 out->underrun_position = *position;
530 out->underrun_time = curtime;
531 out->frames_total_buffered = 0;
532 }
533}
534
535
536static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
537 size_t bytes)
538{
539 struct generic_stream_out *out = (struct generic_stream_out *)stream;
540 const size_t frames = bytes / audio_stream_out_frame_size(stream);
541
542 pthread_mutex_lock(&out->lock);
543
544 if (out->worker_standby) {
545 out->worker_standby = false;
546 }
547
548 uint64_t current_position;
549 struct timespec current_time;
550
551 get_current_output_position(out, &current_position, &current_time);
552 const uint64_t now_us = (current_time.tv_sec * 1000000000LL +
553 current_time.tv_nsec) / 1000;
554 if (out->standby) {
555 out->standby = false;
556 out->underrun_time = current_time;
557 out->frames_rendered = 0;
558 out->frames_total_buffered = 0;
559 }
560
561 size_t frames_written = audio_vbuffer_write(&out->buffer, buffer, frames);
562 pthread_cond_signal(&out->worker_wake);
563
564 /* Implementation just consumes bytes if we start getting backed up */
565 out->frames_written += frames;
566 out->frames_rendered += frames;
567 out->frames_total_buffered += frames;
568
569 // We simulate the audio device blocking when it's write buffers become
570 // full.
571
572 // At the beginning or after an underrun, try to fill up the vbuffer.
573 // This will be throttled by the PlaybackThread
574 int frames_sleep = out->frames_total_buffered < out->buffer.frame_count ? 0 : frames;
575
576 uint64_t sleep_time_us = frames_sleep * 1000000LL /
577 out_get_sample_rate(&stream->common);
578
579 // If the write calls are delayed, subtract time off of the sleep to
580 // compensate
581 uint64_t time_since_last_write_us = now_us - out->last_write_time_us;
582 if (time_since_last_write_us < sleep_time_us) {
583 sleep_time_us -= time_since_last_write_us;
584 } else {
585 sleep_time_us = 0;
586 }
587 out->last_write_time_us = now_us + sleep_time_us;
588
Amit Pundir4e375822019-04-18 16:46:10 +0530589 pthread_mutex_unlock(&out->lock);
590
Amit Pundir456949d2020-02-18 22:44:16 +0530591 if (sleep_time_us > 0) {
592 usleep(sleep_time_us);
Amit Pundir4e375822019-04-18 16:46:10 +0530593 }
594
Amit Pundir456949d2020-02-18 22:44:16 +0530595 if (frames_written < frames) {
596 ALOGW("Hardware backing HAL too slow, could only write %zu of %zu frames", frames_written, frames);
597 }
Amit Pundir4e375822019-04-18 16:46:10 +0530598
Amit Pundir456949d2020-02-18 22:44:16 +0530599 /* Always consume all bytes */
600 return bytes;
Amit Pundir4e375822019-04-18 16:46:10 +0530601}
602
603static int out_get_presentation_position(const struct audio_stream_out *stream,
604 uint64_t *frames, struct timespec *timestamp)
Amit Pundir456949d2020-02-18 22:44:16 +0530605
Amit Pundir4e375822019-04-18 16:46:10 +0530606{
Amit Pundir456949d2020-02-18 22:44:16 +0530607 if (stream == NULL || frames == NULL || timestamp == NULL) {
608 return -EINVAL;
609 }
610 struct generic_stream_out *out = (struct generic_stream_out *)stream;
Amit Pundir4e375822019-04-18 16:46:10 +0530611
Amit Pundir456949d2020-02-18 22:44:16 +0530612 pthread_mutex_lock(&out->lock);
613 get_current_output_position(out, frames, timestamp);
614 pthread_mutex_unlock(&out->lock);
Amit Pundir4e375822019-04-18 16:46:10 +0530615
Amit Pundir456949d2020-02-18 22:44:16 +0530616 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530617}
618
Amit Pundir456949d2020-02-18 22:44:16 +0530619static int out_get_render_position(const struct audio_stream_out *stream,
620 uint32_t *dsp_frames)
621{
622 if (stream == NULL || dsp_frames == NULL) {
623 return -EINVAL;
624 }
625 struct generic_stream_out *out = (struct generic_stream_out *)stream;
626 pthread_mutex_lock(&out->lock);
627 *dsp_frames = out->frames_rendered;
628 pthread_mutex_unlock(&out->lock);
629 return 0;
630}
631
632// Must be called with out->lock held
633static void do_out_standby(struct generic_stream_out *out)
634{
635 int frames_sleep = 0;
636 uint64_t sleep_time_us = 0;
637 if (out->standby) {
638 return;
639 }
640 while (true) {
641 get_current_output_position(out, &out->underrun_position, NULL);
642 frames_sleep = out->frames_written - out->underrun_position;
643
644 if (frames_sleep == 0) {
645 break;
646 }
647
648 sleep_time_us = frames_sleep * 1000000LL /
649 out_get_sample_rate(&out->stream.common);
650
651 pthread_mutex_unlock(&out->lock);
652 usleep(sleep_time_us);
653 pthread_mutex_lock(&out->lock);
654 }
655 out->worker_standby = true;
656 out->standby = true;
657}
658
659static int out_standby(struct audio_stream *stream)
660{
661 struct generic_stream_out *out = (struct generic_stream_out *)stream;
662 pthread_mutex_lock(&out->lock);
663 do_out_standby(out);
664 pthread_mutex_unlock(&out->lock);
665 return 0;
666}
Amit Pundir4e375822019-04-18 16:46:10 +0530667
668static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
669{
Amit Pundir456949d2020-02-18 22:44:16 +0530670 // out_add_audio_effect is a no op
Amit Pundir4e375822019-04-18 16:46:10 +0530671 return 0;
672}
673
674static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
675{
Amit Pundir456949d2020-02-18 22:44:16 +0530676 // out_remove_audio_effect is a no op
Amit Pundir4e375822019-04-18 16:46:10 +0530677 return 0;
678}
679
680static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
Amit Pundir456949d2020-02-18 22:44:16 +0530681 int64_t *timestamp)
Amit Pundir4e375822019-04-18 16:46:10 +0530682{
Amit Pundir456949d2020-02-18 22:44:16 +0530683 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530684}
685
Amit Pundir4e375822019-04-18 16:46:10 +0530686static uint32_t in_get_sample_rate(const struct audio_stream *stream)
687{
Amit Pundir456949d2020-02-18 22:44:16 +0530688 struct generic_stream_in *in = (struct generic_stream_in *)stream;
689 return in->req_config.sample_rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530690}
691
692static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
693{
Amit Pundir4e375822019-04-18 16:46:10 +0530694 return -ENOSYS;
695}
696
Amit Pundir456949d2020-02-18 22:44:16 +0530697static int refine_output_parameters(uint32_t *sample_rate, audio_format_t *format, audio_channel_mask_t *channel_mask)
698{
699 static const uint32_t sample_rates [] = {8000,11025,16000,22050,24000,32000,
700 44100,48000};
701 static const int sample_rates_count = sizeof(sample_rates)/sizeof(uint32_t);
702 bool inval = false;
703 if (*format != AUDIO_FORMAT_PCM_16_BIT) {
704 *format = AUDIO_FORMAT_PCM_16_BIT;
705 inval = true;
706 }
707
708 int channel_count = popcount(*channel_mask);
709 if (channel_count != 1 && channel_count != 2) {
710 *channel_mask = AUDIO_CHANNEL_IN_STEREO;
711 inval = true;
712 }
713
714 int i;
715 for (i = 0; i < sample_rates_count; i++) {
716 if (*sample_rate < sample_rates[i]) {
717 *sample_rate = sample_rates[i];
718 inval=true;
719 break;
720 }
721 else if (*sample_rate == sample_rates[i]) {
722 break;
723 }
724 else if (i == sample_rates_count-1) {
725 // Cap it to the highest rate we support
726 *sample_rate = sample_rates[i];
727 inval=true;
728 }
729 }
730
731 if (inval) {
732 return -EINVAL;
733 }
734 return 0;
735}
736
737static int refine_input_parameters(uint32_t *sample_rate, audio_format_t *format, audio_channel_mask_t *channel_mask)
738{
739 static const uint32_t sample_rates [] = {8000, 11025, 16000, 22050, 44100, 48000};
740 static const int sample_rates_count = sizeof(sample_rates)/sizeof(uint32_t);
741 bool inval = false;
742 // Only PCM_16_bit is supported. If this is changed, stereo to mono drop
743 // must be fixed in in_read
744 if (*format != AUDIO_FORMAT_PCM_16_BIT) {
745 *format = AUDIO_FORMAT_PCM_16_BIT;
746 inval = true;
747 }
748
749 int channel_count = popcount(*channel_mask);
750 if (channel_count != 1 && channel_count != 2) {
751 *channel_mask = AUDIO_CHANNEL_IN_STEREO;
752 inval = true;
753 }
754
755 int i;
756 for (i = 0; i < sample_rates_count; i++) {
757 if (*sample_rate < sample_rates[i]) {
758 *sample_rate = sample_rates[i];
759 inval=true;
760 break;
761 }
762 else if (*sample_rate == sample_rates[i]) {
763 break;
764 }
765 else if (i == sample_rates_count-1) {
766 // Cap it to the highest rate we support
767 *sample_rate = sample_rates[i];
768 inval=true;
769 }
770 }
771
772 if (inval) {
773 return -EINVAL;
774 }
775 return 0;
776}
777
778static int check_input_parameters(uint32_t sample_rate, audio_format_t format,
779 audio_channel_mask_t channel_mask)
780{
781 return refine_input_parameters(&sample_rate, &format, &channel_mask);
782}
783
784static size_t get_input_buffer_size(uint32_t sample_rate, audio_format_t format,
785 audio_channel_mask_t channel_mask)
786{
787 size_t size;
788 int channel_count = popcount(channel_mask);
789 if (check_input_parameters(sample_rate, format, channel_mask) != 0)
790 return 0;
791
792 size = sample_rate*IN_PERIOD_MS/1000;
793 // Audioflinger expects audio buffers to be multiple of 16 frames
794 size = ((size + 15) / 16) * 16;
795 size *= sizeof(short) * channel_count;
796
797 return size;
798}
799
800
Amit Pundir4e375822019-04-18 16:46:10 +0530801static size_t in_get_buffer_size(const struct audio_stream *stream)
802{
Amit Pundir456949d2020-02-18 22:44:16 +0530803 struct generic_stream_in *in = (struct generic_stream_in *)stream;
804 int size = get_input_buffer_size(in->req_config.sample_rate,
805 in->req_config.format,
806 in->req_config.channel_mask);
807
808 return size;
Amit Pundir4e375822019-04-18 16:46:10 +0530809}
810
811static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
812{
Amit Pundir456949d2020-02-18 22:44:16 +0530813 struct generic_stream_in *in = (struct generic_stream_in *)stream;
814 return in->req_config.channel_mask;
Amit Pundir4e375822019-04-18 16:46:10 +0530815}
816
817static audio_format_t in_get_format(const struct audio_stream *stream)
818{
Amit Pundir456949d2020-02-18 22:44:16 +0530819 struct generic_stream_in *in = (struct generic_stream_in *)stream;
820 return in->req_config.format;
Amit Pundir4e375822019-04-18 16:46:10 +0530821}
822
823static int in_set_format(struct audio_stream *stream, audio_format_t format)
824{
825 return -ENOSYS;
826}
827
Amit Pundir4e375822019-04-18 16:46:10 +0530828static int in_dump(const struct audio_stream *stream, int fd)
829{
Amit Pundir456949d2020-02-18 22:44:16 +0530830 struct generic_stream_in *in = (struct generic_stream_in *)stream;
831
832 pthread_mutex_lock(&in->lock);
833 dprintf(fd, "\tin_dump:\n"
834 "\t\tsample rate: %u\n"
835 "\t\tbuffer size: %zu\n"
836 "\t\tchannel mask: %08x\n"
837 "\t\tformat: %d\n"
838 "\t\tdevice: %08x\n"
839 "\t\taudio dev: %p\n\n",
840 in_get_sample_rate(stream),
841 in_get_buffer_size(stream),
842 in_get_channels(stream),
843 in_get_format(stream),
844 in->device,
845 in->dev);
846 pthread_mutex_unlock(&in->lock);
Amit Pundir4e375822019-04-18 16:46:10 +0530847 return 0;
848}
849
850static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
851{
Amit Pundir456949d2020-02-18 22:44:16 +0530852 struct str_parms *parms;
853 char value[32];
854 int success;
855 int ret = -EINVAL;
856
857 if (kvpairs == NULL || kvpairs[0] == 0) {
858 return 0;
859 }
860 parms = str_parms_create_str(kvpairs);
861 success = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING,
862 value, sizeof(value));
863 // As the hal version is 3.0, it must not use set parameters API to set audio device.
864 // Instead, it should use create_audio_patch API.
865 assert(("Must not use set parameters API to set audio devices", success < 0));
866
867 if (str_parms_has_key(parms, AUDIO_PARAMETER_STREAM_FORMAT)) {
868 // match the return value of in_set_format
869 ret = -ENOSYS;
870 }
871
872 str_parms_destroy(parms);
873
874 if (ret == -EINVAL) {
875 ALOGW("%s(), unsupported parameter %s", __func__, kvpairs);
876 // There is not any key supported for set_parameters API.
877 // Return error when there is non-null value passed in.
878 }
879 return ret;
Amit Pundir4e375822019-04-18 16:46:10 +0530880}
881
882static char * in_get_parameters(const struct audio_stream *stream,
Amit Pundir456949d2020-02-18 22:44:16 +0530883 const char *keys)
Amit Pundir4e375822019-04-18 16:46:10 +0530884{
Amit Pundir456949d2020-02-18 22:44:16 +0530885 struct generic_stream_in *in = (struct generic_stream_in *)stream;
886 struct str_parms *query = str_parms_create_str(keys);
887 char *str = NULL;
888 char value[256];
889 struct str_parms *reply = str_parms_create();
890 int ret;
891 bool get = false;
892
893 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
894 if (ret >= 0) {
895 str_parms_add_int(reply, AUDIO_PARAMETER_STREAM_ROUTING, in->device);
896 get = true;
897 }
898
899 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
900 value[0] = 0;
901 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
902 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
903 get = true;
904 }
905
906 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_FORMAT)) {
907 value[0] = 0;
908 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
909 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_FORMAT, value);
910 get = true;
911 }
912
913 if (get) {
914 str = str_parms_to_str(reply);
915 }
916 else {
917 ALOGD("%s Unsupported parameter: %s", __FUNCTION__, keys);
918 }
919
920 str_parms_destroy(query);
921 str_parms_destroy(reply);
922 return str;
Amit Pundir4e375822019-04-18 16:46:10 +0530923}
924
925static int in_set_gain(struct audio_stream_in *stream, float gain)
926{
Amit Pundir456949d2020-02-18 22:44:16 +0530927 // in_set_gain is a no op
Amit Pundir4e375822019-04-18 16:46:10 +0530928 return 0;
929}
930
Amit Pundir456949d2020-02-18 22:44:16 +0530931// Call with in->lock held
932static void get_current_input_position(struct generic_stream_in *in,
933 int64_t * position,
934 struct timespec * timestamp) {
935 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
936 clock_gettime(CLOCK_MONOTONIC, &t);
937 const int64_t now_us = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
938 if (timestamp) {
939 *timestamp = t;
940 }
941 int64_t position_since_standby;
942 if (in->standby) {
943 position_since_standby = 0;
944 } else {
945 const int64_t first_us = (in->standby_exit_time.tv_sec * 1000000000LL +
946 in->standby_exit_time.tv_nsec) / 1000;
947 position_since_standby = (now_us - first_us) *
948 in_get_sample_rate(&in->stream.common) /
949 1000000;
950 if (position_since_standby < 0) {
951 position_since_standby = 0;
952 }
953 }
954 *position = in->standby_position + position_since_standby;
955}
956
957// Must be called with in->lock held
958static void do_in_standby(struct generic_stream_in *in)
Amit Pundir4e375822019-04-18 16:46:10 +0530959{
Amit Pundir456949d2020-02-18 22:44:16 +0530960 if (in->standby) {
961 return;
962 }
963 in->worker_standby = true;
964 get_current_input_position(in, &in->standby_position, NULL);
965 in->standby = true;
966}
967
968static int in_standby(struct audio_stream *stream)
969{
970 struct generic_stream_in *in = (struct generic_stream_in *)stream;
971 pthread_mutex_lock(&in->lock);
972 do_in_standby(in);
973 pthread_mutex_unlock(&in->lock);
974 return 0;
975}
976
977static void *in_read_worker(void * args)
978{
979 struct generic_stream_in *in = (struct generic_stream_in *)args;
980 struct pcm *pcm = NULL;
981 uint8_t *buffer = NULL;
982 size_t buffer_frames;
983 int buffer_size;
984
985 bool restart = false;
986 bool shutdown = false;
987 while (true) {
988 pthread_mutex_lock(&in->lock);
989 while (in->worker_standby || restart) {
990 restart = false;
991 if (pcm) {
992 pcm_close(pcm); // Frees pcm
993 pcm = NULL;
994 free(buffer);
995 buffer=NULL;
996 }
997 if (in->worker_exit) {
998 break;
999 }
1000 pthread_cond_wait(&in->worker_wake, &in->lock);
1001 }
1002
1003 if (in->worker_exit) {
1004 if (!in->worker_standby) {
1005 ALOGE("In worker not in standby before exiting");
1006 }
1007 shutdown = true;
1008 }
1009 if (shutdown) {
1010 pthread_mutex_unlock(&in->lock);
1011 break;
1012 }
1013 if (!pcm) {
1014 pcm = pcm_open(PCM_CARD, PCM_DEVICE,
1015 PCM_IN | PCM_MONOTONIC, &in->pcm_config);
1016 if (!pcm_is_ready(pcm)) {
1017 ALOGE("pcm_open(in) failed: %s: channels %d format %d rate %d",
1018 pcm_get_error(pcm),
1019 in->pcm_config.channels,
1020 in->pcm_config.format,
1021 in->pcm_config.rate
1022 );
1023 pthread_mutex_unlock(&in->lock);
1024 break;
1025 }
1026 buffer_frames = in->pcm_config.period_size;
1027 buffer_size = pcm_frames_to_bytes(pcm, buffer_frames);
1028 buffer = malloc(buffer_size);
1029 if (!buffer) {
1030 ALOGE("could not allocate worker read buffer");
1031 pthread_mutex_unlock(&in->lock);
1032 break;
1033 }
1034 }
1035 pthread_mutex_unlock(&in->lock);
1036 int ret = pcm_read(pcm, buffer, pcm_frames_to_bytes(pcm, buffer_frames));
1037 if (ret != 0) {
1038 ALOGW("pcm_read failed %s", pcm_get_error(pcm));
1039 restart = true;
1040 continue;
1041 }
1042
1043 pthread_mutex_lock(&in->lock);
1044 size_t frames_written = audio_vbuffer_write(&in->buffer, buffer, buffer_frames);
1045 pthread_mutex_unlock(&in->lock);
1046
1047 if (frames_written != buffer_frames) {
1048 ALOGW("in_read_worker only could write %zu / %zu frames", frames_written, buffer_frames);
1049 }
1050 }
1051 if (buffer) {
1052 free(buffer);
1053 }
1054 return NULL;
1055}
1056
1057static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
1058 size_t bytes)
1059{
1060 struct generic_stream_in *in = (struct generic_stream_in *)stream;
1061 struct generic_audio_device *adev = in->dev;
1062 const size_t frames = bytes / audio_stream_in_frame_size(stream);
1063 bool mic_mute = false;
1064 size_t read_bytes = 0;
1065
1066 adev_get_mic_mute(&adev->device, &mic_mute);
1067 pthread_mutex_lock(&in->lock);
1068
1069 if (in->worker_standby) {
1070 in->worker_standby = false;
1071 }
1072 pthread_cond_signal(&in->worker_wake);
1073
1074 int64_t current_position;
1075 struct timespec current_time;
1076
1077 get_current_input_position(in, &current_position, &current_time);
1078 if (in->standby) {
1079 in->standby = false;
1080 in->standby_exit_time = current_time;
1081 in->standby_frames_read = 0;
1082 }
1083
1084 const int64_t frames_available = current_position - in->standby_position - in->standby_frames_read;
1085 assert(frames_available >= 0);
1086
1087 const size_t frames_wait = ((uint64_t)frames_available > frames) ? 0 : frames - frames_available;
1088
1089 int64_t sleep_time_us = frames_wait * 1000000LL /
1090 in_get_sample_rate(&stream->common);
1091
1092 pthread_mutex_unlock(&in->lock);
1093
1094 if (sleep_time_us > 0) {
1095 usleep(sleep_time_us);
1096 }
1097
1098 pthread_mutex_lock(&in->lock);
1099 int read_frames = 0;
1100 if (in->standby) {
1101 ALOGW("Input put to sleep while read in progress");
1102 goto exit;
1103 }
1104 in->standby_frames_read += frames;
1105
1106 if (popcount(in->req_config.channel_mask) == 1 &&
1107 in->pcm_config.channels == 2) {
1108 // Need to resample to mono
1109 if (in->stereo_to_mono_buf_size < bytes*2) {
1110 in->stereo_to_mono_buf = realloc(in->stereo_to_mono_buf,
1111 bytes*2);
1112 if (!in->stereo_to_mono_buf) {
1113 ALOGE("Failed to allocate stereo_to_mono_buff");
1114 goto exit;
1115 }
1116 }
1117
1118 read_frames = audio_vbuffer_read(&in->buffer, in->stereo_to_mono_buf, frames);
1119
1120 // Currently only pcm 16 is supported.
1121 uint16_t *src = (uint16_t *)in->stereo_to_mono_buf;
1122 uint16_t *dst = (uint16_t *)buffer;
1123 size_t i;
1124 // Resample stereo 16 to mono 16 by dropping one channel.
1125 // The stereo stream is interleaved L-R-L-R
1126 for (i = 0; i < frames; i++) {
1127 *dst = *src;
1128 src += 2;
1129 dst += 1;
1130 }
1131 } else {
1132 read_frames = audio_vbuffer_read(&in->buffer, buffer, frames);
1133 }
1134
1135exit:
1136 read_bytes = read_frames*audio_stream_in_frame_size(stream);
1137
1138 if (mic_mute) {
1139 read_bytes = 0;
1140 }
1141
1142 if (read_bytes < bytes) {
1143 memset (&((uint8_t *)buffer)[read_bytes], 0, bytes-read_bytes);
1144 }
1145
1146 pthread_mutex_unlock(&in->lock);
1147
Amit Pundir4e375822019-04-18 16:46:10 +05301148 return bytes;
1149}
1150
1151static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
1152{
1153 return 0;
1154}
1155
Amit Pundir456949d2020-02-18 22:44:16 +05301156static int in_get_capture_position(const struct audio_stream_in *stream,
1157 int64_t *frames, int64_t *time)
1158{
1159 struct generic_stream_in *in = (struct generic_stream_in *)stream;
1160 pthread_mutex_lock(&in->lock);
1161 struct timespec current_time;
1162 get_current_input_position(in, frames, &current_time);
1163 *time = (current_time.tv_sec * 1000000000LL + current_time.tv_nsec);
1164 pthread_mutex_unlock(&in->lock);
1165 return 0;
1166}
1167
1168static int in_get_active_microphones(const struct audio_stream_in *stream,
1169 struct audio_microphone_characteristic_t *mic_array,
1170 size_t *mic_count)
1171{
1172 return adev_get_microphones(NULL, mic_array, mic_count);
1173}
1174
Amit Pundir4e375822019-04-18 16:46:10 +05301175static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1176{
Amit Pundir456949d2020-02-18 22:44:16 +05301177 // in_add_audio_effect is a no op
Amit Pundir4e375822019-04-18 16:46:10 +05301178 return 0;
1179}
1180
1181static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
1182{
Amit Pundir456949d2020-02-18 22:44:16 +05301183 // in_add_audio_effect is a no op
Amit Pundir4e375822019-04-18 16:46:10 +05301184 return 0;
1185}
1186
1187static int adev_open_output_stream(struct audio_hw_device *dev,
Amit Pundir456949d2020-02-18 22:44:16 +05301188 audio_io_handle_t handle,
1189 audio_devices_t devices,
1190 audio_output_flags_t flags,
1191 struct audio_config *config,
1192 struct audio_stream_out **stream_out,
1193 const char *address __unused)
Amit Pundir4e375822019-04-18 16:46:10 +05301194{
Amit Pundir456949d2020-02-18 22:44:16 +05301195 struct generic_audio_device *adev = (struct generic_audio_device *)dev;
1196 struct generic_stream_out *out;
Amit Pundir4e375822019-04-18 16:46:10 +05301197 int ret = 0;
1198
Amit Pundir456949d2020-02-18 22:44:16 +05301199 if (refine_output_parameters(&config->sample_rate, &config->format, &config->channel_mask)) {
1200 ALOGE("Error opening output stream format %d, channel_mask %04x, sample_rate %u",
1201 config->format, config->channel_mask, config->sample_rate);
1202 ret = -EINVAL;
1203 goto error;
1204 }
Amit Pundir4e375822019-04-18 16:46:10 +05301205
Amit Pundir456949d2020-02-18 22:44:16 +05301206 out = (struct generic_stream_out *)calloc(1, sizeof(struct generic_stream_out));
1207
Amit Pundir4e375822019-04-18 16:46:10 +05301208 if (!out)
1209 return -ENOMEM;
1210
1211 out->stream.common.get_sample_rate = out_get_sample_rate;
1212 out->stream.common.set_sample_rate = out_set_sample_rate;
1213 out->stream.common.get_buffer_size = out_get_buffer_size;
1214 out->stream.common.get_channels = out_get_channels;
1215 out->stream.common.get_format = out_get_format;
1216 out->stream.common.set_format = out_set_format;
1217 out->stream.common.standby = out_standby;
1218 out->stream.common.dump = out_dump;
1219 out->stream.common.set_parameters = out_set_parameters;
1220 out->stream.common.get_parameters = out_get_parameters;
1221 out->stream.common.add_audio_effect = out_add_audio_effect;
1222 out->stream.common.remove_audio_effect = out_remove_audio_effect;
1223 out->stream.get_latency = out_get_latency;
1224 out->stream.set_volume = out_set_volume;
1225 out->stream.write = out_write;
1226 out->stream.get_render_position = out_get_render_position;
Amit Pundir4e375822019-04-18 16:46:10 +05301227 out->stream.get_presentation_position = out_get_presentation_position;
Amit Pundir456949d2020-02-18 22:44:16 +05301228 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Amit Pundir4e375822019-04-18 16:46:10 +05301229
Amit Pundir456949d2020-02-18 22:44:16 +05301230 out->handle = handle;
Amit Pundir4e375822019-04-18 16:46:10 +05301231
Amit Pundir456949d2020-02-18 22:44:16 +05301232 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
1233 out->dev = adev;
1234 // Only 1 device is expected despite the argument being named 'devices'
1235 out->num_devices = 1;
1236 out->devices[0] = devices;
1237 memcpy(&out->req_config, config, sizeof(struct audio_config));
1238 memcpy(&out->pcm_config, &pcm_config_out, sizeof(struct pcm_config));
1239 out->pcm_config.rate = config->sample_rate;
1240 out->pcm_config.period_size = out->pcm_config.rate*OUT_PERIOD_MS/1000;
1241
1242 out->standby = true;
1243 out->underrun_position = 0;
1244 out->underrun_time.tv_sec = 0;
1245 out->underrun_time.tv_nsec = 0;
1246 out->last_write_time_us = 0;
1247 out->frames_total_buffered = 0;
1248 out->frames_written = 0;
1249 out->frames_rendered = 0;
1250
1251 ret = audio_vbuffer_init(&out->buffer,
1252 out->pcm_config.period_size*out->pcm_config.period_count,
1253 out->pcm_config.channels *
1254 pcm_format_to_bits(out->pcm_config.format) >> 3);
1255 if (ret == 0) {
1256 pthread_cond_init(&out->worker_wake, NULL);
1257 out->worker_standby = true;
1258 out->worker_exit = false;
1259 pthread_create(&out->worker_thread, NULL, out_write_worker, out);
1260
Amit Pundir4e375822019-04-18 16:46:10 +05301261 }
1262
Amit Pundir456949d2020-02-18 22:44:16 +05301263 pthread_mutex_lock(&adev->lock);
1264 list_add_tail(&adev->out_streams, &out->stream_node);
1265 pthread_mutex_unlock(&adev->lock);
Amit Pundir4e375822019-04-18 16:46:10 +05301266
1267 *stream_out = &out->stream;
1268
Amit Pundir456949d2020-02-18 22:44:16 +05301269error:
Amit Pundir4e375822019-04-18 16:46:10 +05301270
1271 return ret;
1272}
1273
Amit Pundir456949d2020-02-18 22:44:16 +05301274// This must be called with adev->lock held.
1275struct generic_stream_out *get_stream_out_by_io_handle_l(
1276 struct generic_audio_device *adev, audio_io_handle_t handle) {
1277 struct listnode *node;
1278
1279 list_for_each(node, &adev->out_streams) {
1280 struct generic_stream_out *out = node_to_item(
1281 node, struct generic_stream_out, stream_node);
1282 if (out->handle == handle) {
1283 return out;
1284 }
1285 }
1286 return NULL;
1287}
1288
Amit Pundir4e375822019-04-18 16:46:10 +05301289static void adev_close_output_stream(struct audio_hw_device *dev,
Amit Pundir456949d2020-02-18 22:44:16 +05301290 struct audio_stream_out *stream)
Amit Pundir4e375822019-04-18 16:46:10 +05301291{
Amit Pundir456949d2020-02-18 22:44:16 +05301292 struct generic_stream_out *out = (struct generic_stream_out *)stream;
1293 pthread_mutex_lock(&out->lock);
1294 do_out_standby(out);
1295
1296 out->worker_exit = true;
1297 pthread_cond_signal(&out->worker_wake);
1298 pthread_mutex_unlock(&out->lock);
1299
1300 pthread_join(out->worker_thread, NULL);
1301 pthread_mutex_destroy(&out->lock);
1302 audio_vbuffer_destroy(&out->buffer);
1303
1304 struct generic_audio_device *adev = (struct generic_audio_device *) dev;
1305 pthread_mutex_lock(&adev->lock);
1306 list_remove(&out->stream_node);
1307 pthread_mutex_unlock(&adev->lock);
Amit Pundir4e375822019-04-18 16:46:10 +05301308 free(stream);
1309}
1310
1311static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
1312{
Amit Pundir456949d2020-02-18 22:44:16 +05301313 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +05301314}
1315
1316static char * adev_get_parameters(const struct audio_hw_device *dev,
Amit Pundir456949d2020-02-18 22:44:16 +05301317 const char *keys)
Amit Pundir4e375822019-04-18 16:46:10 +05301318{
Amit Pundir4e375822019-04-18 16:46:10 +05301319 return strdup("");
1320}
1321
1322static int adev_init_check(const struct audio_hw_device *dev)
1323{
Amit Pundir4e375822019-04-18 16:46:10 +05301324 return 0;
1325}
1326
1327static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
1328{
Amit Pundir456949d2020-02-18 22:44:16 +05301329 // adev_set_voice_volume is a no op (simulates phones)
1330 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +05301331}
1332
1333static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
1334{
Amit Pundir4e375822019-04-18 16:46:10 +05301335 return -ENOSYS;
1336}
1337
1338static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
1339{
Amit Pundir4e375822019-04-18 16:46:10 +05301340 return -ENOSYS;
1341}
1342
1343static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
1344{
Amit Pundir4e375822019-04-18 16:46:10 +05301345 return -ENOSYS;
1346}
1347
1348static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
1349{
Amit Pundir4e375822019-04-18 16:46:10 +05301350 return -ENOSYS;
1351}
1352
1353static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
1354{
Amit Pundir456949d2020-02-18 22:44:16 +05301355 // adev_set_mode is a no op (simulates phones)
Amit Pundir4e375822019-04-18 16:46:10 +05301356 return 0;
1357}
1358
1359static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
1360{
Amit Pundir456949d2020-02-18 22:44:16 +05301361 struct generic_audio_device *adev = (struct generic_audio_device *)dev;
1362 pthread_mutex_lock(&adev->lock);
1363 adev->mic_mute = state;
1364 pthread_mutex_unlock(&adev->lock);
1365 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +05301366}
1367
1368static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1369{
Amit Pundir456949d2020-02-18 22:44:16 +05301370 struct generic_audio_device *adev = (struct generic_audio_device *)dev;
1371 pthread_mutex_lock(&adev->lock);
1372 *state = adev->mic_mute;
1373 pthread_mutex_unlock(&adev->lock);
1374 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +05301375}
1376
Amit Pundir456949d2020-02-18 22:44:16 +05301377
Amit Pundir4e375822019-04-18 16:46:10 +05301378static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Amit Pundir456949d2020-02-18 22:44:16 +05301379 const struct audio_config *config)
Amit Pundir4e375822019-04-18 16:46:10 +05301380{
Amit Pundir456949d2020-02-18 22:44:16 +05301381 return get_input_buffer_size(config->sample_rate, config->format, config->channel_mask);
Amit Pundir4e375822019-04-18 16:46:10 +05301382}
1383
Amit Pundir456949d2020-02-18 22:44:16 +05301384// This must be called with adev->lock held.
1385struct generic_stream_in *get_stream_in_by_io_handle_l(
1386 struct generic_audio_device *adev, audio_io_handle_t handle) {
1387 struct listnode *node;
1388
1389 list_for_each(node, &adev->in_streams) {
1390 struct generic_stream_in *in = node_to_item(
1391 node, struct generic_stream_in, stream_node);
1392 if (in->handle == handle) {
1393 return in;
1394 }
1395 }
1396 return NULL;
1397}
1398
1399static void adev_close_input_stream(struct audio_hw_device *dev,
1400 struct audio_stream_in *stream)
Amit Pundir4e375822019-04-18 16:46:10 +05301401{
Amit Pundir456949d2020-02-18 22:44:16 +05301402 struct generic_stream_in *in = (struct generic_stream_in *)stream;
1403 pthread_mutex_lock(&in->lock);
1404 do_in_standby(in);
Amit Pundir4e375822019-04-18 16:46:10 +05301405
Amit Pundir456949d2020-02-18 22:44:16 +05301406 in->worker_exit = true;
1407 pthread_cond_signal(&in->worker_wake);
1408 pthread_mutex_unlock(&in->lock);
1409 pthread_join(in->worker_thread, NULL);
Amit Pundir4e375822019-04-18 16:46:10 +05301410
Amit Pundir456949d2020-02-18 22:44:16 +05301411 if (in->stereo_to_mono_buf != NULL) {
1412 free(in->stereo_to_mono_buf);
1413 in->stereo_to_mono_buf_size = 0;
1414 }
1415
1416 pthread_mutex_destroy(&in->lock);
1417 audio_vbuffer_destroy(&in->buffer);
1418
1419 struct generic_audio_device *adev = (struct generic_audio_device *) dev;
1420 pthread_mutex_lock(&adev->lock);
1421 list_remove(&in->stream_node);
1422 pthread_mutex_unlock(&adev->lock);
1423 free(stream);
1424}
1425
1426
1427static int adev_open_input_stream(struct audio_hw_device *dev,
1428 audio_io_handle_t handle,
1429 audio_devices_t devices,
1430 struct audio_config *config,
1431 struct audio_stream_in **stream_in,
1432 audio_input_flags_t flags __unused,
1433 const char *address __unused,
1434 audio_source_t source __unused)
1435{
1436 struct generic_audio_device *adev = (struct generic_audio_device *)dev;
1437 struct generic_stream_in *in;
1438 int ret = 0;
1439 if (refine_input_parameters(&config->sample_rate, &config->format, &config->channel_mask)) {
1440 ALOGE("Error opening input stream format %d, channel_mask %04x, sample_rate %u",
1441 config->format, config->channel_mask, config->sample_rate);
1442 ret = -EINVAL;
1443 goto error;
1444 }
1445
1446 in = (struct generic_stream_in *)calloc(1, sizeof(struct generic_stream_in));
1447 if (!in) {
1448 ret = -ENOMEM;
1449 goto error;
1450 }
Amit Pundir4e375822019-04-18 16:46:10 +05301451
1452 in->stream.common.get_sample_rate = in_get_sample_rate;
Amit Pundir456949d2020-02-18 22:44:16 +05301453 in->stream.common.set_sample_rate = in_set_sample_rate; // no op
Amit Pundir4e375822019-04-18 16:46:10 +05301454 in->stream.common.get_buffer_size = in_get_buffer_size;
1455 in->stream.common.get_channels = in_get_channels;
1456 in->stream.common.get_format = in_get_format;
Amit Pundir456949d2020-02-18 22:44:16 +05301457 in->stream.common.set_format = in_set_format; // no op
Amit Pundir4e375822019-04-18 16:46:10 +05301458 in->stream.common.standby = in_standby;
1459 in->stream.common.dump = in_dump;
1460 in->stream.common.set_parameters = in_set_parameters;
1461 in->stream.common.get_parameters = in_get_parameters;
Amit Pundir456949d2020-02-18 22:44:16 +05301462 in->stream.common.add_audio_effect = in_add_audio_effect; // no op
1463 in->stream.common.remove_audio_effect = in_remove_audio_effect; // no op
1464 in->stream.set_gain = in_set_gain; // no op
Amit Pundir4e375822019-04-18 16:46:10 +05301465 in->stream.read = in_read;
Amit Pundir456949d2020-02-18 22:44:16 +05301466 in->stream.get_input_frames_lost = in_get_input_frames_lost; // no op
1467 in->stream.get_capture_position = in_get_capture_position;
1468 in->stream.get_active_microphones = in_get_active_microphones;
1469
1470 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
1471 in->dev = adev;
1472 in->device = devices;
1473 memcpy(&in->req_config, config, sizeof(struct audio_config));
1474 memcpy(&in->pcm_config, &pcm_config_in, sizeof(struct pcm_config));
1475 in->pcm_config.rate = config->sample_rate;
1476 in->pcm_config.period_size = in->pcm_config.rate*IN_PERIOD_MS/1000;
1477
1478 in->stereo_to_mono_buf = NULL;
1479 in->stereo_to_mono_buf_size = 0;
1480
1481 in->standby = true;
1482 in->standby_position = 0;
1483 in->standby_exit_time.tv_sec = 0;
1484 in->standby_exit_time.tv_nsec = 0;
1485 in->standby_frames_read = 0;
1486
1487 ret = audio_vbuffer_init(&in->buffer,
1488 in->pcm_config.period_size*in->pcm_config.period_count,
1489 in->pcm_config.channels *
1490 pcm_format_to_bits(in->pcm_config.format) >> 3);
1491 if (ret == 0) {
1492 pthread_cond_init(&in->worker_wake, NULL);
1493 in->worker_standby = true;
1494 in->worker_exit = false;
1495 pthread_create(&in->worker_thread, NULL, in_read_worker, in);
1496 }
1497 in->handle = handle;
1498
1499 pthread_mutex_lock(&adev->lock);
1500 list_add_tail(&adev->in_streams, &in->stream_node);
1501 pthread_mutex_unlock(&adev->lock);
Amit Pundir4e375822019-04-18 16:46:10 +05301502
1503 *stream_in = &in->stream;
Amit Pundir456949d2020-02-18 22:44:16 +05301504
1505error:
1506 return ret;
1507}
1508
1509
1510static int adev_dump(const audio_hw_device_t *dev, int fd)
1511{
Amit Pundir4e375822019-04-18 16:46:10 +05301512 return 0;
1513}
1514
Amit Pundir456949d2020-02-18 22:44:16 +05301515static int adev_get_microphones(const audio_hw_device_t *dev,
1516 struct audio_microphone_characteristic_t *mic_array,
1517 size_t *mic_count)
Amit Pundir4e375822019-04-18 16:46:10 +05301518{
Amit Pundir456949d2020-02-18 22:44:16 +05301519 if (mic_count == NULL) {
1520 return -ENOSYS;
1521 }
Amit Pundir4e375822019-04-18 16:46:10 +05301522
Amit Pundir456949d2020-02-18 22:44:16 +05301523 if (*mic_count == 0) {
1524 *mic_count = 1;
1525 return 0;
1526 }
1527
1528 if (mic_array == NULL) {
1529 return -ENOSYS;
1530 }
1531
1532 strncpy(mic_array->device_id, "mic_goldfish", AUDIO_MICROPHONE_ID_MAX_LEN - 1);
1533 mic_array->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
1534 strncpy(mic_array->address, AUDIO_BOTTOM_MICROPHONE_ADDRESS,
1535 AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
1536 memset(mic_array->channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
1537 sizeof(mic_array->channel_mapping));
1538 mic_array->location = AUDIO_MICROPHONE_LOCATION_UNKNOWN;
1539 mic_array->group = 0;
1540 mic_array->index_in_the_group = 0;
1541 mic_array->sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
1542 mic_array->max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
1543 mic_array->min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
1544 mic_array->directionality = AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN;
1545 mic_array->num_frequency_responses = 0;
1546 mic_array->geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
1547 mic_array->geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
1548 mic_array->geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
1549 mic_array->orientation.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
1550 mic_array->orientation.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
1551 mic_array->orientation.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
1552
1553 *mic_count = 1;
Amit Pundir4e375822019-04-18 16:46:10 +05301554 return 0;
1555}
1556
Amit Pundir456949d2020-02-18 22:44:16 +05301557static int adev_create_audio_patch(struct audio_hw_device *dev,
1558 unsigned int num_sources,
1559 const struct audio_port_config *sources,
1560 unsigned int num_sinks,
1561 const struct audio_port_config *sinks,
1562 audio_patch_handle_t *handle) {
1563 if (num_sources != 1 || num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
1564 return -EINVAL;
1565 }
1566
1567 if (sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
1568 // If source is a device, the number of sinks should be 1.
1569 if (num_sinks != 1 || sinks[0].type != AUDIO_PORT_TYPE_MIX) {
1570 return -EINVAL;
1571 }
1572 } else if (sources[0].type == AUDIO_PORT_TYPE_MIX) {
1573 // If source is a mix, all sinks should be device.
1574 for (unsigned int i = 0; i < num_sinks; i++) {
1575 if (sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
1576 ALOGE("%s() invalid sink type %#x for mix source", __func__, sinks[i].type);
1577 return -EINVAL;
1578 }
1579 }
1580 } else {
1581 // All other cases are invalid.
1582 return -EINVAL;
1583 }
1584
1585 struct generic_audio_device* adev = (struct generic_audio_device*) dev;
1586 int ret = 0;
1587 bool generatedPatchHandle = false;
1588 pthread_mutex_lock(&adev->lock);
1589 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
1590 *handle = ++adev->next_patch_handle;
1591 generatedPatchHandle = true;
1592 }
1593
1594 // Only handle patches for mix->devices and device->mix case.
1595 if (sources[0].type == AUDIO_PORT_TYPE_DEVICE) {
1596 struct generic_stream_in *in =
1597 get_stream_in_by_io_handle_l(adev, sinks[0].ext.mix.handle);
1598 if (in == NULL) {
1599 ALOGE("%s()can not find stream with handle(%d)", __func__, sources[0].ext.mix.handle);
1600 ret = -EINVAL;
1601 goto error;
1602 }
1603
1604 // Check if the patch handle match the recorded one if a valid patch handle is passed.
1605 if (!generatedPatchHandle && in->patch_handle != *handle) {
1606 ALOGE("%s() the patch handle(%d) does not match recorded one(%d) for stream "
1607 "with handle(%d) when creating audio patch for device->mix",
1608 __func__, *handle, in->patch_handle, in->handle);
1609 ret = -EINVAL;
1610 goto error;
1611 }
1612 pthread_mutex_lock(&in->lock);
1613 in->device = sources[0].ext.device.type;
1614 pthread_mutex_unlock(&in->lock);
1615 in->patch_handle = *handle;
1616 } else {
1617 struct generic_stream_out *out =
1618 get_stream_out_by_io_handle_l(adev, sources[0].ext.mix.handle);
1619 if (out == NULL) {
1620 ALOGE("%s()can not find stream with handle(%d)", __func__, sources[0].ext.mix.handle);
1621 ret = -EINVAL;
1622 goto error;
1623 }
1624
1625 // Check if the patch handle match the recorded one if a valid patch handle is passed.
1626 if (!generatedPatchHandle && out->patch_handle != *handle) {
1627 ALOGE("%s() the patch handle(%d) does not match recorded one(%d) for stream "
1628 "with handle(%d) when creating audio patch for mix->device",
1629 __func__, *handle, out->patch_handle, out->handle);
1630 ret = -EINVAL;
1631 pthread_mutex_unlock(&out->lock);
1632 goto error;
1633 }
1634 pthread_mutex_lock(&out->lock);
1635 for (out->num_devices = 0; out->num_devices < num_sinks; out->num_devices++) {
1636 out->devices[out->num_devices] = sinks[out->num_devices].ext.device.type;
1637 }
1638 pthread_mutex_unlock(&out->lock);
1639 out->patch_handle = *handle;
1640 }
1641
1642error:
1643 if (ret != 0 && generatedPatchHandle) {
1644 *handle = AUDIO_PATCH_HANDLE_NONE;
1645 }
1646 pthread_mutex_unlock(&adev->lock);
Amit Pundir4e375822019-04-18 16:46:10 +05301647 return 0;
1648}
1649
Amit Pundir456949d2020-02-18 22:44:16 +05301650// This must be called with adev->lock held.
1651struct generic_stream_out *get_stream_out_by_patch_handle_l(
1652 struct generic_audio_device *adev, audio_patch_handle_t patch_handle) {
1653 struct listnode *node;
1654
1655 list_for_each(node, &adev->out_streams) {
1656 struct generic_stream_out *out = node_to_item(
1657 node, struct generic_stream_out, stream_node);
1658 if (out->patch_handle == patch_handle) {
1659 return out;
1660 }
1661 }
1662 return NULL;
1663}
1664
1665// This must be called with adev->lock held.
1666struct generic_stream_in *get_stream_in_by_patch_handle_l(
1667 struct generic_audio_device *adev, audio_patch_handle_t patch_handle) {
1668 struct listnode *node;
1669
1670 list_for_each(node, &adev->in_streams) {
1671 struct generic_stream_in *in = node_to_item(
1672 node, struct generic_stream_in, stream_node);
1673 if (in->patch_handle == patch_handle) {
1674 return in;
1675 }
1676 }
1677 return NULL;
1678}
1679
1680static int adev_release_audio_patch(struct audio_hw_device *dev,
1681 audio_patch_handle_t patch_handle) {
1682 struct generic_audio_device *adev = (struct generic_audio_device *) dev;
1683
1684 pthread_mutex_lock(&adev->lock);
1685 struct generic_stream_out *out = get_stream_out_by_patch_handle_l(adev, patch_handle);
1686 if (out != NULL) {
1687 pthread_mutex_lock(&out->lock);
1688 out->num_devices = 0;
1689 memset(out->devices, 0, sizeof(out->devices));
1690 pthread_mutex_unlock(&out->lock);
1691 out->patch_handle = AUDIO_PATCH_HANDLE_NONE;
1692 pthread_mutex_unlock(&adev->lock);
1693 return 0;
1694 }
1695 struct generic_stream_in *in = get_stream_in_by_patch_handle_l(adev, patch_handle);
1696 if (in != NULL) {
1697 pthread_mutex_lock(&in->lock);
1698 in->device = AUDIO_DEVICE_NONE;
1699 pthread_mutex_unlock(&in->lock);
1700 in->patch_handle = AUDIO_PATCH_HANDLE_NONE;
1701 pthread_mutex_unlock(&adev->lock);
1702 return 0;
1703 }
1704
1705 pthread_mutex_unlock(&adev->lock);
1706 ALOGW("%s() cannot find stream for patch handle: %d", __func__, patch_handle);
1707 return -EINVAL;
1708}
1709
1710static int adev_close(hw_device_t *dev)
1711{
1712 struct generic_audio_device *adev = (struct generic_audio_device *)dev;
1713 int ret = 0;
1714 if (!adev)
1715 return 0;
1716
1717 pthread_mutex_lock(&adev_init_lock);
1718
1719 if (audio_device_ref_count == 0) {
1720 ALOGE("adev_close called when ref_count 0");
1721 ret = -EINVAL;
1722 goto error;
1723 }
1724
1725 if ((--audio_device_ref_count) == 0) {
1726 if (adev->mixer) {
1727 mixer_close(adev->mixer);
1728 }
1729 free(adev);
1730 }
1731
1732error:
1733 pthread_mutex_unlock(&adev_init_lock);
1734 return ret;
1735}
1736
Amit Pundir4e375822019-04-18 16:46:10 +05301737static int adev_open(const hw_module_t* module, const char* name,
Amit Pundir456949d2020-02-18 22:44:16 +05301738 hw_device_t** device)
Amit Pundir4e375822019-04-18 16:46:10 +05301739{
Amit Pundir456949d2020-02-18 22:44:16 +05301740 static struct generic_audio_device *adev;
Amit Pundir4e375822019-04-18 16:46:10 +05301741
1742 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
1743 return -EINVAL;
1744
Amit Pundir456949d2020-02-18 22:44:16 +05301745 pthread_mutex_lock(&adev_init_lock);
1746 if (audio_device_ref_count != 0) {
1747 *device = &adev->device.common;
1748 audio_device_ref_count++;
1749 ALOGV("%s: returning existing instance of adev", __func__);
1750 ALOGV("%s: exit", __func__);
1751 goto unlock;
1752 }
1753 adev = calloc(1, sizeof(struct generic_audio_device));
Amit Pundir4e375822019-04-18 16:46:10 +05301754
Amit Pundir456949d2020-02-18 22:44:16 +05301755 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
Amit Pundir4e375822019-04-18 16:46:10 +05301756
Amit Pundir456949d2020-02-18 22:44:16 +05301757 adev->device.common.tag = HARDWARE_DEVICE_TAG;
1758 adev->device.common.version = AUDIO_DEVICE_API_VERSION_3_0;
1759 adev->device.common.module = (struct hw_module_t *) module;
1760 adev->device.common.close = adev_close;
Amit Pundir4e375822019-04-18 16:46:10 +05301761
Amit Pundir456949d2020-02-18 22:44:16 +05301762 adev->device.init_check = adev_init_check; // no op
1763 adev->device.set_voice_volume = adev_set_voice_volume; // no op
1764 adev->device.set_master_volume = adev_set_master_volume; // no op
1765 adev->device.get_master_volume = adev_get_master_volume; // no op
1766 adev->device.set_master_mute = adev_set_master_mute; // no op
1767 adev->device.get_master_mute = adev_get_master_mute; // no op
1768 adev->device.set_mode = adev_set_mode; // no op
1769 adev->device.set_mic_mute = adev_set_mic_mute;
1770 adev->device.get_mic_mute = adev_get_mic_mute;
1771 adev->device.set_parameters = adev_set_parameters; // no op
1772 adev->device.get_parameters = adev_get_parameters; // no op
1773 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
1774 adev->device.open_output_stream = adev_open_output_stream;
1775 adev->device.close_output_stream = adev_close_output_stream;
1776 adev->device.open_input_stream = adev_open_input_stream;
1777 adev->device.close_input_stream = adev_close_input_stream;
1778 adev->device.dump = adev_dump;
1779 adev->device.get_microphones = adev_get_microphones;
1780 adev->device.create_audio_patch = adev_create_audio_patch;
1781 adev->device.release_audio_patch = adev_release_audio_patch;
Amit Pundir4e375822019-04-18 16:46:10 +05301782
Amit Pundir456949d2020-02-18 22:44:16 +05301783 *device = &adev->device.common;
1784
1785 adev->next_patch_handle = AUDIO_PATCH_HANDLE_NONE;
1786 list_init(&adev->out_streams);
1787 list_init(&adev->in_streams);
1788
1789 adev->mixer = mixer_open(PCM_CARD);
1790 struct mixer_ctl *ctl;
1791
1792 // Set default mixer ctls
1793 // Enable channels and set volume
1794 for (int i = 0; i < (int)mixer_get_num_ctls(adev->mixer); i++) {
1795 ctl = mixer_get_ctl(adev->mixer, i);
1796 ALOGD("mixer %d name %s", i, mixer_ctl_get_name(ctl));
1797 if (!strcmp(mixer_ctl_get_name(ctl), "Master Playback Volume") ||
1798 !strcmp(mixer_ctl_get_name(ctl), "Capture Volume")) {
1799 for (int z = 0; z < (int)mixer_ctl_get_num_values(ctl); z++) {
1800 ALOGD("set ctl %d to %d", z, 100);
1801 mixer_ctl_set_percent(ctl, z, 100);
1802 }
1803 continue;
1804 }
1805 if (!strcmp(mixer_ctl_get_name(ctl), "Master Playback Switch") ||
1806 !strcmp(mixer_ctl_get_name(ctl), "Capture Switch")) {
1807 for (int z = 0; z < (int)mixer_ctl_get_num_values(ctl); z++) {
1808 ALOGD("set ctl %d to %d", z, 1);
1809 mixer_ctl_set_value(ctl, z, 1);
1810 }
1811 continue;
1812 }
1813 }
1814
1815 audio_device_ref_count++;
1816
1817unlock:
1818 pthread_mutex_unlock(&adev_init_lock);
Amit Pundir4e375822019-04-18 16:46:10 +05301819 return 0;
1820}
1821
1822static struct hw_module_methods_t hal_module_methods = {
1823 .open = adev_open,
1824};
1825
1826struct audio_module HAL_MODULE_INFO_SYM = {
1827 .common = {
1828 .tag = HARDWARE_MODULE_TAG,
1829 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1830 .hal_api_version = HARDWARE_HAL_API_VERSION,
1831 .id = AUDIO_HARDWARE_MODULE_ID,
Amit Pundir456949d2020-02-18 22:44:16 +05301832 .name = "Generic audio HW HAL",
Amit Pundir4e375822019-04-18 16:46:10 +05301833 .author = "The Android Open Source Project",
1834 .methods = &hal_module_methods,
1835 },
1836};