blob: 3c7ea6b02930d4505916f9cf45e371bc601ed811 [file] [log] [blame]
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Christopher N. Hesse2f6f8582017-01-28 12:46:15 +01003 * Copyright (C) 2017 Christopher N. Hesse <raymanfx@gmail.com>
Andreas Schneider759368f2017-02-02 16:11:14 +01004 * Copyright (C) 2017 Andreas Schneider <asn@cryptomilk.org>
stenkinevgeniy44335362018-05-07 18:00:13 +00005 * Copyright (C) 2018 The LineageOS Project
Christopher N. Hesse297a6362017-01-28 12:40:45 +01006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
21/*#define LOG_NDEBUG 0*/
22/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
28
29#define _GNU_SOURCE
30#include <errno.h>
31#include <pthread.h>
32#include <stdint.h>
33#include <sys/time.h>
34#include <stdlib.h>
35#include <math.h>
36#include <dlfcn.h>
Christopher N. Hesse297a6362017-01-28 12:40:45 +010037
38#include <cutils/log.h>
39#include <cutils/str_parms.h>
40#include <cutils/atomic.h>
41#include <cutils/sched_policy.h>
42#include <cutils/properties.h>
43
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010044#include <samsung_audio.h>
45
Christopher N. Hesse297a6362017-01-28 12:40:45 +010046#include <hardware/audio_effect.h>
47#include <system/thread_defs.h>
48#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
50#include "audio_hw.h"
Christopher N. Hesse757ac412017-01-28 14:42:48 +010051#include "compress_offload.h"
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +010052#include "voice.h"
Christopher N. Hesse297a6362017-01-28 12:40:45 +010053
54#include "sound/compress_params.h"
55
Christopher N. Hesse297a6362017-01-28 12:40:45 +010056
57/* TODO: the following PCM device profiles could be read from a config file */
58static struct pcm_device_profile pcm_device_playback = {
59 .config = {
60 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
61 .rate = PLAYBACK_DEFAULT_SAMPLING_RATE,
62 .period_size = PLAYBACK_PERIOD_SIZE,
63 .period_count = PLAYBACK_PERIOD_COUNT,
64 .format = PCM_FORMAT_S16_LE,
65 .start_threshold = PLAYBACK_START_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
66 .stop_threshold = PLAYBACK_STOP_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
67 .silence_threshold = 0,
68 .silence_size = UINT_MAX,
69 .avail_min = PLAYBACK_AVAILABLE_MIN,
70 },
71 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010072 .id = SOUND_PLAYBACK_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010073 .type = PCM_PLAYBACK,
74 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
stenkinevgeniy3de97672018-05-20 14:18:53 +000075 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|
76 AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
77 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010078};
79
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010080static struct pcm_device_profile pcm_device_deep_buffer = {
81 .config = {
82 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
83 .rate = DEEP_BUFFER_OUTPUT_SAMPLING_RATE,
84 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
85 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
86 .format = PCM_FORMAT_S16_LE,
87 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
88 .stop_threshold = INT_MAX,
89 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
90 },
91 .card = SOUND_CARD,
92 .id = SOUND_DEEP_BUFFER_DEVICE,
93 .type = PCM_PLAYBACK,
94 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
stenkinevgeniy3de97672018-05-20 14:18:53 +000095 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|
96 AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
97 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010098};
99
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100100static struct pcm_device_profile pcm_device_capture = {
101 .config = {
102 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
103 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
104 .period_size = CAPTURE_PERIOD_SIZE,
105 .period_count = CAPTURE_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = CAPTURE_START_THRESHOLD,
108 .stop_threshold = 0,
109 .silence_threshold = 0,
110 .avail_min = 0,
111 },
112 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100113 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100114 .type = PCM_CAPTURE,
115 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
116};
117
118static struct pcm_device_profile pcm_device_capture_low_latency = {
119 .config = {
120 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
121 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
122 .period_size = CAPTURE_PERIOD_SIZE_LOW_LATENCY,
123 .period_count = CAPTURE_PERIOD_COUNT_LOW_LATENCY,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = CAPTURE_START_THRESHOLD,
126 .stop_threshold = 0,
127 .silence_threshold = 0,
128 .avail_min = 0,
129 },
130 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100131 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100132 .type = PCM_CAPTURE_LOW_LATENCY,
133 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
134};
135
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100136static struct pcm_device_profile pcm_device_capture_sco = {
137 .config = {
138 .channels = SCO_DEFAULT_CHANNEL_COUNT,
139 .rate = SCO_DEFAULT_SAMPLING_RATE,
140 .period_size = SCO_PERIOD_SIZE,
141 .period_count = SCO_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = CAPTURE_START_THRESHOLD,
144 .stop_threshold = 0,
145 .silence_threshold = 0,
146 .avail_min = 0,
147 },
148 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100149 .id = SOUND_CAPTURE_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100150 .type = PCM_CAPTURE,
151 .devices = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
152};
153
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100154static struct pcm_device_profile * const pcm_devices[] = {
155 &pcm_device_playback,
156 &pcm_device_capture,
157 &pcm_device_capture_low_latency,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100158 &pcm_device_capture_sco,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100159 NULL,
160};
161
162static const char * const use_case_table[AUDIO_USECASE_MAX] = {
163 [USECASE_AUDIO_PLAYBACK] = "playback",
164 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "playback multi-channel",
165 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Andreas Schneiderdf6fc8a2017-02-14 11:38:41 +0100166 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "playback deep-buffer",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100167 [USECASE_AUDIO_CAPTURE] = "capture",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100168 [USECASE_VOICE_CALL] = "voice-call",
169};
170
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100171#define STRING_TO_ENUM(string) { #string, string }
172
173static unsigned int audio_device_ref_count;
174
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100175struct string_to_enum {
176 const char *name;
177 uint32_t value;
178};
179
180static const struct string_to_enum out_channels_name_to_enum_table[] = {
181 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
182 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
183 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
184};
185
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200186static struct audio_device *adev = NULL;
187
188static amplifier_device_t * get_amplifier_device(void)
189{
190 if (adev)
191 return adev->amp;
192
193 return NULL;
194}
195
196static int amplifier_open(void)
197{
198 int rc;
199 amplifier_module_t *module;
200
201 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
202 (const hw_module_t **) &module);
203 if (rc) {
Christopher N. Hessec487bbe2018-07-12 13:51:43 +0200204 if (rc == -ENOENT) {
205 // no amplifier HAL present
206 return -ENOENT;
207 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200208 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
209 __func__, strerror(-rc));
210 return -ENODEV;
211 }
212
213 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
214 if (rc) {
215 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
216 __func__, strerror(-rc));
217 return -ENODEV;
218 }
219
220 return 0;
221}
222
223static int amplifier_set_input_devices(uint32_t devices)
224{
225 amplifier_device_t *amp = get_amplifier_device();
226 if (amp && amp->set_input_devices)
227 return amp->set_input_devices(amp, devices);
228
229 return 0;
230}
231
232static int amplifier_set_output_devices(uint32_t devices)
233{
234 amplifier_device_t *amp = get_amplifier_device();
235 if (amp && amp->set_output_devices)
236 return amp->set_output_devices(amp, devices);
237
238 return 0;
239}
240
241static int amplifier_enable_devices(uint32_t devices, bool enable)
242{
243 amplifier_device_t *amp = get_amplifier_device();
244 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
245 devices < SND_DEVICE_OUT_END;
246
247 if (amp && amp->enable_output_devices && is_output)
248 return amp->enable_output_devices(amp, devices, enable);
249
250 if (amp && amp->enable_input_devices && !is_output)
251 return amp->enable_input_devices(amp, devices, enable);
252
253 return 0;
254}
255
256static int amplifier_set_mode(audio_mode_t mode)
257{
258 amplifier_device_t *amp = get_amplifier_device();
259 if (amp && amp->set_mode)
260 return amp->set_mode(amp, mode);
261
262 return 0;
263}
264
265static int amplifier_output_stream_start(struct audio_stream_out *stream,
266 bool offload)
267{
268 amplifier_device_t *amp = get_amplifier_device();
269 if (amp && amp->output_stream_start)
270 return amp->output_stream_start(amp, stream, offload);
271
272 return 0;
273}
274
275static int amplifier_input_stream_start(struct audio_stream_in *stream)
276{
277 amplifier_device_t *amp = get_amplifier_device();
278 if (amp && amp->input_stream_start)
279 return amp->input_stream_start(amp, stream);
280
281 return 0;
282}
283
284static int amplifier_output_stream_standby(struct audio_stream_out *stream)
285{
286 amplifier_device_t *amp = get_amplifier_device();
287 if (amp && amp->output_stream_standby)
288 return amp->output_stream_standby(amp, stream);
289
290 return 0;
291}
292
293static int amplifier_input_stream_standby(struct audio_stream_in *stream)
294{
295 amplifier_device_t *amp = get_amplifier_device();
296 if (amp && amp->input_stream_standby)
297 return amp->input_stream_standby(amp, stream);
298
299 return 0;
300}
301
302static int amplifier_set_parameters(struct str_parms *parms)
303{
304 amplifier_device_t *amp = get_amplifier_device();
305 if (amp && amp->set_parameters)
306 return amp->set_parameters(amp, parms);
307
308 return 0;
309}
310
311static int amplifier_close(void)
312{
313 amplifier_device_t *amp = get_amplifier_device();
314 if (amp)
315 amplifier_device_close(amp);
316
317 return 0;
318}
319
Andreas Schneider759368f2017-02-02 16:11:14 +0100320struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
321 struct timespec ret;
322 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100323
324 if (time0.tv_nsec > time1.tv_nsec) {
325 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
326 time0.tv_nsec -= (long int) (1E9 * xsec);
327 time0.tv_sec += xsec;
328 }
329
330 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
331 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
332 time0.tv_nsec += (long int) (1E9 * xsec);
333 time0.tv_sec -= xsec;
334 }
335
Paul Keithf114e2e2017-02-14 20:41:33 -0600336 ret.tv_sec = labs(time1.tv_sec - time0.tv_sec);
337 ret.tv_nsec = labs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100338
339 return ret;
340}
341
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100342static bool is_supported_format(audio_format_t format)
343{
344 if (format == AUDIO_FORMAT_MP3 ||
345 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
346 return true;
347
348 return false;
349}
350
351static int get_snd_codec_id(audio_format_t format)
352{
353 int id = 0;
354
355 switch (format & AUDIO_FORMAT_MAIN_MASK) {
356 case AUDIO_FORMAT_MP3:
357 id = SND_AUDIOCODEC_MP3;
358 break;
359 case AUDIO_FORMAT_AAC:
360 id = SND_AUDIOCODEC_AAC;
361 break;
362 default:
363 ALOGE("%s: Unsupported audio format", __func__);
364 }
365
366 return id;
367}
368
369/* Array to store sound devices */
370static const char * const device_table[SND_DEVICE_MAX] = {
371 [SND_DEVICE_NONE] = "none",
372 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100373 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100374 [SND_DEVICE_OUT_SPEAKER] = "speaker",
375 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
376 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100377 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100378 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100379 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100380 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100381 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100382 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100383 [SND_DEVICE_OUT_VOICE_BT_SCO] = "voice-bt-sco-headset",
384 [SND_DEVICE_OUT_VOICE_BT_SCO_WB] = "voice-bt-sco-headset-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100385 [SND_DEVICE_OUT_HDMI] = "hdmi",
386 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
387 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100388
389 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100390 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100391 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
392 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100393 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100394 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
395 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100396 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
397 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100398 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100399 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100400 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100401 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100402 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100403 [SND_DEVICE_IN_VOICE_BT_SCO_MIC] = "voice-bt-sco-mic",
404 [SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB] = "voice-bt-sco-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100405 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
406 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
407 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100408 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
409 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100410};
411
412static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
413{
414 struct mixer_card *mixer_card;
415 struct listnode *node;
416
417 list_for_each(node, &adev->mixer_list) {
418 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
419 if (mixer_card->card == card)
420 return mixer_card;
421 }
422 return NULL;
423}
424
425static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
426{
427 struct mixer_card *mixer_card;
428 struct listnode *node;
429
430 list_for_each(node, &usecase->mixer_list) {
431 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
432 if (mixer_card->card == card)
433 return mixer_card;
434 }
435 return NULL;
436}
437
438static void free_mixer_list(struct audio_device *adev)
439{
440 struct mixer_card *mixer_card;
441 struct listnode *node;
442 struct listnode *next;
443
444 list_for_each_safe(node, next, &adev->mixer_list) {
445 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
446 list_remove(node);
447 audio_route_free(mixer_card->audio_route);
448 free(mixer_card);
449 }
450}
451
452static int mixer_init(struct audio_device *adev)
453{
454 int i;
455 int card;
456 int retry_num;
457 struct mixer *mixer;
458 struct audio_route *audio_route;
459 char mixer_path[PATH_MAX];
460 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100461 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100462
463 list_init(&adev->mixer_list);
464
465 for (i = 0; pcm_devices[i] != NULL; i++) {
466 card = pcm_devices[i]->card;
467 if (adev_get_mixer_for_card(adev, card) == NULL) {
468 retry_num = 0;
469 do {
470 mixer = mixer_open(card);
471 if (mixer == NULL) {
472 if (++retry_num > RETRY_NUMBER) {
473 ALOGE("%s unable to open the mixer for--card %d, aborting.",
474 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100475 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100476 goto error;
477 }
478 usleep(RETRY_US);
479 }
480 } while (mixer == NULL);
481
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100482 sprintf(mixer_path, "/vendor/etc/mixer_paths_%d.xml", card);
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100483 if (access(mixer_path, F_OK) == -1) {
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100484 ALOGW("%s: Failed to open mixer paths from %s, retrying with legacy location",
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100485 __func__, mixer_path);
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100486 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
487 if (access(mixer_path, F_OK) == -1) {
488 ALOGE("%s: Failed to load a mixer paths configuration, your system will crash",
489 __func__);
490 }
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100491 }
492
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100493 audio_route = audio_route_init(card, mixer_path);
494 if (!audio_route) {
495 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
496 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100497 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100498 goto error;
499 }
500 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100501 if (mixer_card == NULL) {
502 ret = -ENOMEM;
503 goto error;
504 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100505 mixer_card->card = card;
506 mixer_card->mixer = mixer;
507 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100508
509 /* Do not sleep on first enable_snd_device() */
510 mixer_card->dsp_poweroff_time.tv_sec = 1;
511 mixer_card->dsp_poweroff_time.tv_nsec = 0;
512
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100513 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
514 }
515 }
516
517 return 0;
518
519error:
520 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100521 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100522}
523
524static const char *get_snd_device_name(snd_device_t snd_device)
525{
526 const char *name = NULL;
527
Andreas Schneideradb788d2017-02-13 15:19:36 +0100528 if (snd_device == SND_DEVICE_NONE ||
Andreas Schneiderdde54c02017-02-15 14:10:58 +0100529 (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100530 name = device_table[snd_device];
531
532 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
533
534 return name;
535}
536
537static const char *get_snd_device_display_name(snd_device_t snd_device)
538{
539 const char *name = get_snd_device_name(snd_device);
540
541 if (name == NULL)
542 name = "SND DEVICE NOT FOUND";
543
544 return name;
545}
546
547static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
548{
549 int i;
550
551 devices &= ~AUDIO_DEVICE_BIT_IN;
552 for (i = 0; pcm_devices[i] != NULL; i++) {
553 if ((pcm_devices[i]->type == uc_type) &&
554 (devices & pcm_devices[i]->devices))
555 break;
556 }
557 return pcm_devices[i];
558}
559
560static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
561 audio_usecase_t uc_id)
562{
563 struct audio_usecase *usecase;
564 struct listnode *node;
565
566 list_for_each(node, &adev->usecase_list) {
567 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
568 if (usecase->id == uc_id)
569 return usecase;
570 }
571 return NULL;
572}
573
574static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
575 usecase_type_t type)
576{
577 struct audio_usecase *usecase;
578 struct listnode *node;
579
580 list_for_each(node, &adev->usecase_list) {
581 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
582 if (usecase->type & type)
583 return usecase;
584 }
585 return NULL;
586}
587
588/* always called with adev lock held */
589static int set_voice_volume_l(struct audio_device *adev, float volume)
590{
591 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100592
593 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100594 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100595 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100596
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100597 return err;
598}
599
600
601static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
602{
603
604 audio_mode_t mode = adev->mode;
605 snd_device_t snd_device = SND_DEVICE_NONE;
606
607 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
608 if (devices == AUDIO_DEVICE_NONE ||
609 devices & AUDIO_DEVICE_BIT_IN) {
610 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
611 goto exit;
612 }
613
614 if (mode == AUDIO_MODE_IN_CALL) {
615 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
616 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100617 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Fevax51bd12c2017-03-15 10:56:39 -0300618 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100619 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100620 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
621 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
622 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100623 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100624 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100625
626 if (voice_session_uses_wideband(adev->voice.session)) {
627 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
628 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
629 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300630 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100631 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO_WB;
Andreas Schneider59486fa2017-02-06 09:16:39 +0100632 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
633 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
634 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
635 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
636 }
637 }
638
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100639 if (snd_device != SND_DEVICE_NONE) {
640 goto exit;
641 }
642 }
643
644 if (popcount(devices) == 2) {
645 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
646 AUDIO_DEVICE_OUT_SPEAKER)) {
647 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
648 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
649 AUDIO_DEVICE_OUT_SPEAKER)) {
650 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
651 } else {
652 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
653 goto exit;
654 }
655 if (snd_device != SND_DEVICE_NONE) {
656 goto exit;
657 }
658 }
659
660 if (popcount(devices) != 1) {
661 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
662 goto exit;
663 }
664
665 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
666 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
667 snd_device = SND_DEVICE_OUT_HEADPHONES;
668 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
669 snd_device = SND_DEVICE_OUT_SPEAKER;
670 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
671 snd_device = SND_DEVICE_OUT_BT_SCO;
672 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100673 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100674 } else {
675 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
676 }
677exit:
678 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
679 return snd_device;
680}
681
682static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
683{
684 audio_source_t source;
685 audio_mode_t mode = adev->mode;
686 audio_devices_t in_device;
687 audio_channel_mask_t channel_mask;
688 snd_device_t snd_device = SND_DEVICE_NONE;
689 struct stream_in *active_input = NULL;
690 struct audio_usecase *usecase;
691
692 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
693 if (usecase != NULL) {
694 active_input = (struct stream_in *)usecase->stream;
695 }
696 source = (active_input == NULL) ?
697 AUDIO_SOURCE_DEFAULT : active_input->source;
698
Andreas Schneider757e2d82017-02-10 19:28:35 +0100699 in_device = (active_input == NULL) ?
700 AUDIO_DEVICE_NONE :
701 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100702 channel_mask = (active_input == NULL) ?
703 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
704
705 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
706 __func__, out_device, in_device);
707 if (mode == AUDIO_MODE_IN_CALL) {
708 if (out_device == AUDIO_DEVICE_NONE) {
709 ALOGE("%s: No output device set for voice call", __func__);
710 goto exit;
711 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100712
Andreas Schneider82f32482017-02-06 09:00:48 +0100713 snd_device = SND_DEVICE_IN_VOICE_MIC;
714 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100715 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100716 }
717
718 if (voice_session_uses_twomic(adev->voice.session)) {
719 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
720 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
721 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
722 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
723 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
724 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100725 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100726
727 if (voice_session_uses_wideband(adev->voice.session)) {
728 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
729 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
730 }
731
732 if (voice_session_uses_twomic(adev->voice.session)) {
733 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
734 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
735 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
736 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
737 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
738 }
739 }
740 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100741
742 /* BT SCO */
743 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Andreas Schneider05bc1882017-02-09 14:03:11 +0100744
stenkinevgeniy097e2942018-05-22 18:06:48 +0000745 if (voice_session_uses_wideband(adev->voice.session)) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100746 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB;
stenkinevgeniy097e2942018-05-22 18:06:48 +0000747 } else {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100748 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC;
Andreas Schneider05bc1882017-02-09 14:03:11 +0100749 }
750 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100751 } else if (source == AUDIO_SOURCE_CAMCORDER) {
752 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
753 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
754 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
755 }
756 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
757 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100758 if (snd_device == SND_DEVICE_NONE) {
759 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
760 }
761 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
762 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
763 }
764 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
765 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
766 in_device = AUDIO_DEVICE_IN_BACK_MIC;
767 if (active_input) {
768 if (active_input->enable_aec) {
769 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
770 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
771 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
772 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
773 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
774 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100775 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100776 }
777 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
778 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
779 }
780 }
781 /* TODO: set echo reference */
782 }
783 } else if (source == AUDIO_SOURCE_DEFAULT) {
784 goto exit;
785 }
786
787
788 if (snd_device != SND_DEVICE_NONE) {
789 goto exit;
790 }
791
792 if (in_device != AUDIO_DEVICE_NONE &&
793 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
794 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
795 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100796 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100797 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
798 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
799 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
800 snd_device = SND_DEVICE_IN_HEADSET_MIC;
801 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
802 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
803 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
804 snd_device = SND_DEVICE_IN_HDMI_MIC;
805 } else {
806 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100807 ALOGW("%s: Using default earpiece-mic", __func__);
808 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100809 }
810 } else {
811 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100812 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100813 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
814 snd_device = SND_DEVICE_IN_HEADSET_MIC;
815 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
816 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
817 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100818 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100819 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
820 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
821 } else {
822 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100823 ALOGW("%s: Using default earpiece-mic", __func__);
824 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100825 }
826 }
827exit:
828 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
829 return snd_device;
830}
831
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100832#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100833static int set_hdmi_channels(struct audio_device *adev, int channel_count)
834{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100835 (void)adev;
836 (void)channel_count;
837 /* TODO */
838
839 return 0;
840}
841
842static int edid_get_max_channels(struct audio_device *adev)
843{
844 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100845 (void)adev;
846
847 /* TODO */
848 return max_channels;
849}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100850#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100851
852/* Delay in Us */
853static int64_t render_latency(audio_usecase_t usecase)
854{
855 (void)usecase;
856 /* TODO */
857 return 0;
858}
859
860static int enable_snd_device(struct audio_device *adev,
861 struct audio_usecase *uc_info,
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100862 snd_device_t snd_device)
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100863{
864 struct mixer_card *mixer_card;
865 struct listnode *node;
866 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100867#ifdef DSP_POWEROFF_DELAY
868 struct timespec activation_time;
869 struct timespec elapsed_time;
870#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100871
872 if (snd_device_name == NULL)
873 return -EINVAL;
874
875 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
876 ALOGV("Request to enable combo device: enable individual devices\n");
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100877 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER);
878 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100879 return 0;
880 }
881 adev->snd_dev_ref_cnt[snd_device]++;
882 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
883 ALOGV("%s: snd_device(%d: %s) is already active",
884 __func__, snd_device, snd_device_name);
885 return 0;
886 }
887
888 ALOGV("%s: snd_device(%d: %s)", __func__,
889 snd_device, snd_device_name);
890
891 list_for_each(node, &uc_info->mixer_list) {
892 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100893
894#ifdef DSP_POWEROFF_DELAY
895 clock_gettime(CLOCK_MONOTONIC, &activation_time);
896
Andreas Schneider58735a92017-02-13 16:48:17 +0100897 elapsed_time = time_spec_diff(activation_time,
898 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100899 if (elapsed_time.tv_sec == 0) {
900 long elapsed_usec = elapsed_time.tv_nsec / 1000;
901
902 if (elapsed_usec < DSP_POWEROFF_DELAY) {
903 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
904 }
905 }
Andreas Schneider759368f2017-02-02 16:11:14 +0100906#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200907
908 amplifier_enable_devices(snd_device, true);
909
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100910 audio_route_apply_and_update_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100911 }
912
913 return 0;
914}
915
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100916int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100917 struct audio_usecase *uc_info,
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100918 snd_device_t snd_device)
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100919{
920 struct mixer_card *mixer_card;
921 struct listnode *node;
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100922 struct audio_usecase *out_uc_info = get_usecase_from_type(adev, PCM_PLAYBACK);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100923 const char *snd_device_name = get_snd_device_name(snd_device);
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100924 const char *out_snd_device_name = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100925
926 if (snd_device_name == NULL)
927 return -EINVAL;
928
929 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
930 ALOGV("Request to disable combo device: disable individual devices\n");
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100931 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER);
932 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100933 return 0;
934 }
935
936 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
937 ALOGE("%s: device ref cnt is already 0", __func__);
938 return -EINVAL;
939 }
940 adev->snd_dev_ref_cnt[snd_device]--;
941 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
942 ALOGV("%s: snd_device(%d: %s)", __func__,
943 snd_device, snd_device_name);
944 list_for_each(node, &uc_info->mixer_list) {
945 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100946 audio_route_reset_and_update_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse719630a2018-02-12 01:47:48 +0100947 if (snd_device > SND_DEVICE_IN_BEGIN && out_uc_info != NULL) {
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100948 /*
949 * Cycle the rx device to eliminate routing conflicts.
950 * This prevents issues when an input route shares mixer controls with an output
951 * route.
952 */
953 out_snd_device_name = get_snd_device_name(out_uc_info->out_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100954 audio_route_apply_and_update_path(mixer_card->audio_route, out_snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100955 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200956
957 amplifier_enable_devices(snd_device, false);
Andreas Schneider759368f2017-02-02 16:11:14 +0100958#ifdef DSP_POWEROFF_DELAY
959 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
960#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100961 }
962 }
963 return 0;
964}
965
stenkinevgeniyb81e05f2018-05-08 12:02:35 +0000966static void check_and_route_usecases(struct audio_device *adev,
967 struct audio_usecase *uc_info,
968 usecase_type_t type,
969 snd_device_t snd_device)
970{
971 struct listnode *node;
972 struct audio_usecase *usecase;
973 bool switch_device[AUDIO_USECASE_MAX], need_switch = false;
974 snd_device_t usecase_snd_device = SND_DEVICE_NONE;
975 int i;
976
977 /*
978 * This function is to make sure that all the usecases that are active on
979 * the hardware codec backend are always routed to any one device that is
980 * handled by the hardware codec.
981 * For example, if low-latency and deep-buffer usecases are currently active
982 * on speaker and out_set_parameters(headset) is received on low-latency
983 * output, then we have to make sure deep-buffer is also switched to headset or
984 * if audio-record and voice-call usecases are currently
985 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
986 * is received for voice call then we have to make sure that audio-record
987 * usecase is also switched to earpiece i.e.
988 * because of the limitation that both the devices cannot be enabled
989 * at the same time as they share the same backend.
990 */
991 /* Disable all the usecases on the shared backend other than the
992 specified usecase */
993 for (i = 0; i < AUDIO_USECASE_MAX; i++)
994 switch_device[i] = false;
995
996 list_for_each(node, &adev->usecase_list) {
997 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
998 if (usecase->type != type || usecase == uc_info)
999 continue;
1000 usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device :
1001 usecase->in_snd_device;
1002 if (usecase_snd_device != snd_device) {
1003 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1004 __func__, use_case_table[usecase->id],
1005 get_snd_device_name(usecase_snd_device));
1006 switch_device[usecase->id] = true;
1007 need_switch = true;
1008 }
1009 }
1010 if (need_switch) {
1011 list_for_each(node, &adev->usecase_list) {
1012 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
1013 usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device :
1014 usecase->in_snd_device;
1015 if (switch_device[usecase->id]) {
1016 disable_snd_device(adev, usecase, usecase_snd_device);
1017 enable_snd_device(adev, usecase, snd_device);
1018 if (type == PCM_PLAYBACK)
1019 usecase->out_snd_device = snd_device;
1020 else
1021 usecase->in_snd_device = snd_device;
1022 }
1023 }
1024 }
1025}
1026
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001027static int select_devices(struct audio_device *adev,
1028 audio_usecase_t uc_id)
1029{
1030 snd_device_t out_snd_device = SND_DEVICE_NONE;
1031 snd_device_t in_snd_device = SND_DEVICE_NONE;
1032 struct audio_usecase *usecase = NULL;
1033 struct audio_usecase *vc_usecase = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001034 struct stream_in *active_input = NULL;
1035 struct stream_out *active_out;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001036
1037 ALOGV("%s: usecase(%d)", __func__, uc_id);
1038
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001039 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
1040 if (usecase != NULL) {
1041 active_input = (struct stream_in *)usecase->stream;
1042 }
1043
1044 usecase = get_usecase_from_id(adev, uc_id);
1045 if (usecase == NULL) {
1046 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1047 return -EINVAL;
1048 }
1049 active_out = (struct stream_out *)usecase->stream;
1050
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001051
1052 /*
1053 * If the voice call is active, use the sound devices of voice call usecase
1054 * so that it would not result any device switch. All the usecases will
1055 * be switched to new device when select_devices() is called for voice call
1056 * usecase.
1057 */
1058 if (usecase->type != VOICE_CALL && adev->voice.in_call) {
1059 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
1060 if (vc_usecase == NULL) {
1061 ALOGE("%s: Could not find the voice call usecase", __func__);
1062 } else {
stenkinevgeniy5ca267a2018-05-30 15:43:14 +00001063 in_snd_device = vc_usecase->in_snd_device;
1064 out_snd_device = vc_usecase->out_snd_device;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001065 }
1066 }
1067
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001068 if (usecase->type == VOICE_CALL) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001069 usecase->devices = active_out->devices;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001070 prepare_voice_session(adev->voice.session, active_out->devices);
1071 out_snd_device = get_output_snd_device(adev, active_out->devices);
1072 in_snd_device = get_input_snd_device(adev, active_out->devices);
1073 } else if (usecase->type == PCM_PLAYBACK) {
1074 usecase->devices = active_out->devices;
1075 in_snd_device = SND_DEVICE_NONE;
1076 if (out_snd_device == SND_DEVICE_NONE) {
1077 out_snd_device = get_output_snd_device(adev, active_out->devices);
1078 if (active_out == adev->primary_output &&
1079 active_input &&
1080 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1081 select_devices(adev, active_input->usecase);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001082 }
1083 }
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001084 } else if (usecase->type == PCM_CAPTURE) {
1085 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
1086 out_snd_device = SND_DEVICE_NONE;
1087 if (in_snd_device == SND_DEVICE_NONE) {
1088 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
1089 adev->primary_output && !adev->primary_output->standby) {
1090 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
1091 } else {
1092 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001093 }
1094 }
1095 }
1096
1097 if (out_snd_device == usecase->out_snd_device &&
1098 in_snd_device == usecase->in_snd_device) {
1099 return 0;
1100 }
1101
1102 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
1103 out_snd_device, get_snd_device_display_name(out_snd_device),
1104 in_snd_device, get_snd_device_display_name(in_snd_device));
1105
1106
1107 /* Disable current sound devices */
1108 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001109 disable_snd_device(adev, usecase, usecase->out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001110 }
1111
1112 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001113 disable_snd_device(adev, usecase, usecase->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001114 }
1115
1116 /* Enable new sound devices */
1117 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +01001118 /* We need to update the audio path if we switch the out devices */
1119 if (adev->voice.in_call) {
1120 set_voice_session_audio_path(adev->voice.session);
1121 }
1122
stenkinevgeniyb81e05f2018-05-08 12:02:35 +00001123 check_and_route_usecases(adev, usecase, PCM_PLAYBACK, out_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001124 enable_snd_device(adev, usecase, out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001125 }
1126
1127 if (in_snd_device != SND_DEVICE_NONE) {
stenkinevgeniyb81e05f2018-05-08 12:02:35 +00001128 check_and_route_usecases(adev, usecase, PCM_CAPTURE, in_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001129 enable_snd_device(adev, usecase, in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001130 }
1131
1132 usecase->in_snd_device = in_snd_device;
1133 usecase->out_snd_device = out_snd_device;
1134
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02001135 /* Rely on amplifier_set_devices to distinguish between in/out devices */
1136 amplifier_set_input_devices(in_snd_device);
1137 amplifier_set_output_devices(out_snd_device);
1138
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001139 return 0;
1140}
1141
1142
1143static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
1144static int do_in_standby_l(struct stream_in *in);
1145
1146#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001147static void get_capture_delay(struct stream_in *in,
1148 size_t frames __unused,
1149 struct echo_reference_buffer *buffer)
1150{
1151 ALOGVV("%s: enter:)", __func__);
1152 /* read frames available in kernel driver buffer */
1153 unsigned int kernel_frames;
1154 struct timespec tstamp;
1155 long buf_delay;
1156 long rsmp_delay;
1157 long kernel_delay;
1158 long delay_ns;
1159 struct pcm_device *pcm_device;
1160
1161 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1162 struct pcm_device, stream_list_node);
1163
1164 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1165 buffer->time_stamp.tv_sec = 0;
1166 buffer->time_stamp.tv_nsec = 0;
1167 buffer->delay_ns = 0;
1168 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1169 return;
1170 }
1171
1172 /* read frames available in audio HAL input buffer
1173 * add number of frames being read as we want the capture time of first sample
1174 * in current buffer */
1175 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1176 * at requested sampling rate */
1177 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1178 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1179
1180 /* add delay introduced by resampler */
1181 rsmp_delay = 0;
1182 if (in->resampler) {
1183 rsmp_delay = in->resampler->delay_ns(in->resampler);
1184 }
1185
1186 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1187
1188 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1189
1190 buffer->time_stamp = tstamp;
1191 buffer->delay_ns = delay_ns;
1192 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1193 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1194 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1195 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1196 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1197 in->read_buf_frames, in->proc_buf_frames, frames);
1198}
1199
1200static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1201{
1202 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1203 struct echo_reference_buffer b;
1204 b.delay_ns = 0;
1205 struct pcm_device *pcm_device;
1206
1207 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1208 struct pcm_device, stream_list_node);
1209
1210 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1211 "b.frame_count = [%zd]",
1212 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1213 if (in->ref_buf_frames < frames) {
1214 if (in->ref_buf_size < frames) {
1215 in->ref_buf_size = frames;
1216 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1217 ALOG_ASSERT((in->ref_buf != NULL),
1218 "update_echo_reference() failed to reallocate ref_buf");
1219 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1220 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1221 }
1222 b.frame_count = frames - in->ref_buf_frames;
1223 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1224
1225 get_capture_delay(in, frames, &b);
1226
1227 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1228 {
1229 in->ref_buf_frames += b.frame_count;
1230 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1231 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1232 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1233 }
1234 } else
1235 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1236 return b.delay_ns;
1237}
1238
1239static int set_preprocessor_param(effect_handle_t handle,
1240 effect_param_t *param)
1241{
1242 uint32_t size = sizeof(int);
Basil Gelloefdfdba2018-05-21 18:29:12 +03001243 uint32_t bufsize = sizeof(effect_param_t) +
1244 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1245 param->vsize;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001246
1247 int status = (*handle)->command(handle,
1248 EFFECT_CMD_SET_PARAM,
Basil Gelloefdfdba2018-05-21 18:29:12 +03001249 bufsize,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001250 param,
1251 &size,
1252 &param->status);
1253 if (status == 0)
1254 status = param->status;
1255
1256 return status;
1257}
1258
1259static int set_preprocessor_echo_delay(effect_handle_t handle,
1260 int32_t delay_us)
1261{
Basil Gelloefdfdba2018-05-21 18:29:12 +03001262 const uint32_t param_size = sizeof(uint32_t);
1263 const uint32_t value_size = sizeof(uint32_t);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001264
Basil Gelloefdfdba2018-05-21 18:29:12 +03001265 const uint32_t param_padded_size =
1266 ((param_size - 1) / sizeof(int) + 1) * sizeof(int);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001267
Basil Gelloefdfdba2018-05-21 18:29:12 +03001268 const uint32_t bufsize = sizeof(effect_param_t) +
1269 param_padded_size + value_size;
1270
1271 uint8_t buf[bufsize];
1272 memset(&buf, 0, bufsize);
1273
1274 effect_param_t *effect_param = (effect_param_t *)&buf;
1275
1276 effect_param->psize = param_size;
1277 effect_param->vsize = value_size;
1278
1279 *(uint32_t *)&buf[sizeof(effect_param_t)] = AEC_PARAM_ECHO_DELAY;
1280 *(int32_t *)&buf[sizeof(effect_param_t) + param_padded_size] = delay_us;
1281
1282 return set_preprocessor_param(handle, effect_param);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001283}
1284
1285static void push_echo_reference(struct stream_in *in, size_t frames)
1286{
1287 ALOGVV("%s: enter:)", __func__);
1288 /* read frames from echo reference buffer and update echo delay
1289 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1290
1291 int32_t delay_us = update_echo_reference(in, frames)/1000;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001292 int i;
1293 audio_buffer_t buf;
1294
1295 if (in->ref_buf_frames < frames)
1296 frames = in->ref_buf_frames;
1297
1298 buf.frameCount = frames;
1299 buf.raw = in->ref_buf;
1300
1301 for (i = 0; i < in->num_preprocessors; i++) {
1302 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1303 continue;
1304 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1305 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1306 &buf,
1307 NULL);
1308 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1309 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1310 }
1311
1312 in->ref_buf_frames -= buf.frameCount;
1313 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1314 __func__, in->ref_buf_frames, in->config.channels);
1315 if (in->ref_buf_frames) {
1316 memcpy(in->ref_buf,
1317 in->ref_buf + buf.frameCount * in->config.channels,
1318 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1319 }
1320}
1321
1322static void put_echo_reference(struct audio_device *adev,
1323 struct echo_reference_itfe *reference)
1324{
1325 ALOGV("%s: enter:)", __func__);
1326 int32_t prev_generation = adev->echo_reference_generation;
1327 struct stream_out *out = adev->primary_output;
1328
1329 if (adev->echo_reference != NULL &&
1330 reference == adev->echo_reference) {
1331 /* echo reference is taken from the low latency output stream used
1332 * for voice use cases */
1333 adev->echo_reference = NULL;
1334 android_atomic_inc(&adev->echo_reference_generation);
1335 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1336 // if the primary output is in standby or did not pick the echo reference yet
1337 // we can safely get rid of it here.
1338 // otherwise, out_write() or out_standby() will detect the change in echo reference
1339 // generation and release the echo reference owned by the stream.
1340 if ((out->echo_reference_generation != prev_generation) || out->standby)
1341 release_echo_reference(reference);
1342 } else {
1343 release_echo_reference(reference);
1344 }
1345 ALOGV("release_echo_reference");
1346 }
1347}
1348
1349static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1350 audio_format_t format __unused,
1351 uint32_t channel_count,
1352 uint32_t sampling_rate)
1353{
1354 ALOGV("%s: enter:)", __func__);
1355 put_echo_reference(adev, adev->echo_reference);
1356 /* echo reference is taken from the low latency output stream used
1357 * for voice use cases */
1358 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1359 !adev->primary_output->standby) {
1360 struct audio_stream *stream =
1361 &adev->primary_output->stream.common;
1362 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1363 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1364 ALOGV("Calling create_echo_reference");
1365 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1366 channel_count,
1367 sampling_rate,
1368 AUDIO_FORMAT_PCM_16_BIT,
1369 wr_channel_count,
1370 wr_sampling_rate,
1371 &adev->echo_reference);
1372 if (status == 0)
1373 android_atomic_inc(&adev->echo_reference_generation);
1374 }
1375 return adev->echo_reference;
1376}
1377
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001378static int get_playback_delay(struct stream_out *out,
1379 size_t frames,
1380 struct echo_reference_buffer *buffer)
1381{
1382 unsigned int kernel_frames;
1383 int status;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001384 struct pcm_device *pcm_device;
1385
1386 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1387 struct pcm_device, stream_list_node);
1388
1389 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1390 if (status < 0) {
1391 buffer->time_stamp.tv_sec = 0;
1392 buffer->time_stamp.tv_nsec = 0;
1393 buffer->delay_ns = 0;
1394 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1395 "setting playbackTimestamp to 0");
1396 return status;
1397 }
1398
1399 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1400
1401 /* adjust render time stamp with delay added by current driver buffer.
1402 * Add the duration of current frame as we want the render time of the last
1403 * sample being written. */
1404 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1405 out->config.rate);
1406 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1407 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1408
1409 return 0;
1410}
1411
1412#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1413 do { \
1414 if (fct_status != 0) \
1415 status = fct_status; \
1416 else if (cmd_status != 0) \
1417 status = cmd_status; \
1418 } while(0)
1419
1420static int in_configure_reverse(struct stream_in *in)
1421{
1422 int32_t cmd_status;
1423 uint32_t size = sizeof(int);
1424 effect_config_t config;
1425 int32_t status = 0;
1426 int32_t fct_status = 0;
1427 int i;
1428 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1429 if (in->num_preprocessors > 0) {
1430 config.inputCfg.channels = in->main_channels;
1431 config.outputCfg.channels = in->main_channels;
1432 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1433 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1434 config.inputCfg.samplingRate = in->requested_rate;
1435 config.outputCfg.samplingRate = in->requested_rate;
1436 config.inputCfg.mask =
1437 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1438 config.outputCfg.mask =
1439 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1440
1441 for (i = 0; i < in->num_preprocessors; i++)
1442 {
1443 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1444 continue;
1445 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1446 in->preprocessors[i].effect_itfe,
1447 EFFECT_CMD_SET_CONFIG_REVERSE,
1448 sizeof(effect_config_t),
1449 &config,
1450 &size,
1451 &cmd_status);
1452 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1453 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1454 }
1455 }
1456 return status;
1457}
1458
1459#define MAX_NUM_CHANNEL_CONFIGS 10
1460
1461static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1462 struct effect_info_s *effect_info)
1463{
1464 /* size and format of the cmd are defined in hardware/audio_effect.h */
1465 effect_handle_t effect = effect_info->effect_itfe;
1466 uint32_t cmd_size = 2 * sizeof(uint32_t);
1467 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1468 /* reply = status + number of configs (n) + n x channel_config_t */
1469 uint32_t reply_size =
1470 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1471 int32_t reply[reply_size];
1472 int32_t cmd_status;
1473
1474 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1475 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1476 ALOG_ASSERT((effect_info->channel_configs == NULL),
1477 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1478
1479 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1480 * This error will be interpreted as if the effect supports the main_channels but does not
1481 * support any aux_channels */
1482 cmd_status = (*effect)->command(effect,
1483 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1484 cmd_size,
1485 (void*)&cmd,
1486 &reply_size,
1487 (void*)&reply);
1488
1489 if (cmd_status != 0) {
1490 ALOGV("in_read_audio_effect_channel_configs(): "
1491 "fx->command returned %d", cmd_status);
1492 return;
1493 }
1494
1495 if (reply[0] != 0) {
1496 ALOGW("in_read_audio_effect_channel_configs(): "
1497 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1498 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1499 return;
1500 }
1501
1502 /* the feature is not supported */
1503 ALOGV("in_read_audio_effect_channel_configs()(): "
1504 "Feature supported and adding %d channel configs to the list", reply[1]);
1505 effect_info->num_channel_configs = reply[1];
1506 effect_info->channel_configs =
1507 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1508 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1509}
1510
1511
1512#define NUM_IN_AUX_CNL_CONFIGS 2
1513static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1514 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1515 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1516};
1517static uint32_t in_get_aux_channels(struct stream_in *in)
1518{
1519 int i;
1520 channel_config_t new_chcfg = {0, 0};
1521
1522 if (in->num_preprocessors == 0)
1523 return 0;
1524
1525 /* do not enable dual mic configurations when capturing from other microphones than
1526 * main or sub */
1527 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1528 return 0;
1529
1530 /* retain most complex aux channels configuration compatible with requested main channels and
1531 * supported by audio driver and all pre processors */
1532 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1533 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1534 if (cur_chcfg->main_channels == in->main_channels) {
1535 size_t match_cnt;
1536 size_t idx_preproc;
1537 for (idx_preproc = 0, match_cnt = 0;
1538 /* no need to continue if at least one preprocessor doesn't match */
1539 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1540 idx_preproc++) {
1541 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1542 size_t idx_chcfg;
1543
1544 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1545 if (memcmp(effect_info->channel_configs + idx_chcfg,
1546 cur_chcfg,
1547 sizeof(channel_config_t)) == 0) {
1548 match_cnt++;
1549 break;
1550 }
1551 }
1552 }
1553 /* if all preprocessors match, we have a candidate */
1554 if (match_cnt == (size_t)in->num_preprocessors) {
1555 /* retain most complex aux channels configuration */
1556 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1557 new_chcfg = *cur_chcfg;
1558 }
1559 }
1560 }
1561 }
1562
1563 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1564
1565 return new_chcfg.aux_channels;
1566}
1567
1568static int in_configure_effect_channels(effect_handle_t effect,
1569 channel_config_t *channel_config)
1570{
1571 int status = 0;
1572 int fct_status;
1573 int32_t cmd_status;
1574 uint32_t reply_size;
1575 effect_config_t config;
1576 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1577
1578 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1579 channel_config->main_channels,
1580 channel_config->aux_channels);
1581
1582 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1583 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1584 reply_size = sizeof(effect_config_t);
1585 fct_status = (*effect)->command(effect,
1586 EFFECT_CMD_GET_CONFIG,
1587 0,
1588 NULL,
1589 &reply_size,
1590 &config);
1591 if (fct_status != 0) {
1592 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1593 return fct_status;
1594 }
1595
1596 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1597 config.outputCfg.channels = config.inputCfg.channels;
1598 reply_size = sizeof(uint32_t);
1599 fct_status = (*effect)->command(effect,
1600 EFFECT_CMD_SET_CONFIG,
1601 sizeof(effect_config_t),
1602 &config,
1603 &reply_size,
1604 &cmd_status);
1605 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1606
1607 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1608 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1609 reply_size = sizeof(uint32_t);
1610 fct_status = (*effect)->command(effect,
1611 EFFECT_CMD_SET_FEATURE_CONFIG,
1612 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1613 cmd,
1614 &reply_size,
1615 &cmd_status);
1616 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1617
1618 /* some implementations need to be re-enabled after a config change */
1619 reply_size = sizeof(uint32_t);
1620 fct_status = (*effect)->command(effect,
1621 EFFECT_CMD_ENABLE,
1622 0,
1623 NULL,
1624 &reply_size,
1625 &cmd_status);
1626 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1627
1628 return status;
1629}
1630
1631static int in_reconfigure_channels(struct stream_in *in,
1632 effect_handle_t effect,
1633 channel_config_t *channel_config,
1634 bool config_changed) {
1635
1636 int status = 0;
1637
1638 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1639 config_changed, effect);
1640
1641 /* if config changed, reconfigure all previously added effects */
1642 if (config_changed) {
1643 int i;
1644 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1645 for (i = 0; i < in->num_preprocessors; i++)
1646 {
1647 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1648 channel_config);
1649 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1650 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1651 if (cur_status != 0) {
1652 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1653 "%d with channels: [%04x][%04x]",
1654 cur_status,
1655 i,
1656 channel_config->main_channels,
1657 channel_config->aux_channels);
1658 status = cur_status;
1659 }
1660 }
1661 } else if (effect != NULL && channel_config->aux_channels) {
1662 /* if aux channels config did not change but aux channels are present,
1663 * we still need to configure the effect being added */
1664 status = in_configure_effect_channels(effect, channel_config);
1665 }
1666 return status;
1667}
1668
1669static void in_update_aux_channels(struct stream_in *in,
1670 effect_handle_t effect)
1671{
1672 uint32_t aux_channels;
1673 channel_config_t channel_config;
1674 int status;
1675
1676 aux_channels = in_get_aux_channels(in);
1677
1678 channel_config.main_channels = in->main_channels;
1679 channel_config.aux_channels = aux_channels;
1680 status = in_reconfigure_channels(in,
1681 effect,
1682 &channel_config,
1683 (aux_channels != in->aux_channels));
1684
1685 if (status != 0) {
1686 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1687 /* resetting aux channels configuration */
1688 aux_channels = 0;
1689 channel_config.aux_channels = 0;
1690 in_reconfigure_channels(in, effect, &channel_config, true);
1691 }
1692 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1693 if (in->aux_channels != aux_channels) {
1694 in->aux_channels_changed = true;
1695 in->aux_channels = aux_channels;
1696 do_in_standby_l(in);
1697 }
1698}
1699#endif
1700
1701/* This function reads PCM data and:
1702 * - resample if needed
1703 * - process if pre-processors are attached
1704 * - discard unwanted channels
1705 */
1706static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1707{
1708 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001709 size_t src_channels = in->config.channels;
1710 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1711 int i;
1712 void *proc_buf_out;
1713 struct pcm_device *pcm_device;
1714 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1715#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001716 audio_buffer_t in_buf;
1717 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001718 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1719#endif
1720
1721 /* Additional channels might be added on top of main_channels:
1722 * - aux_channels (by processing effects)
1723 * - extra channels due to HW limitations
1724 * In case of additional channels, we cannot work inplace
1725 */
1726 if (has_additional_channels)
1727 proc_buf_out = in->proc_buf_out;
1728 else
1729 proc_buf_out = buffer;
1730
1731 if (list_empty(&in->pcm_dev_list)) {
1732 ALOGE("%s: pcm device list empty", __func__);
1733 return -EINVAL;
1734 }
1735
1736 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1737 struct pcm_device, stream_list_node);
1738
1739#ifdef PREPROCESSING_ENABLED
1740 if (has_processing) {
1741 /* since all the processing below is done in frames and using the config.channels
1742 * as the number of channels, no changes is required in case aux_channels are present */
1743 while (frames_wr < frames) {
1744 /* first reload enough frames at the end of process input buffer */
1745 if (in->proc_buf_frames < (size_t)frames) {
1746 ssize_t frames_rd;
1747 if (in->proc_buf_size < (size_t)frames) {
1748 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1749 in->proc_buf_size = (size_t)frames;
1750 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1751 ALOG_ASSERT((in->proc_buf_in != NULL),
1752 "process_frames() failed to reallocate proc_buf_in");
1753 if (has_additional_channels) {
1754 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1755 ALOG_ASSERT((in->proc_buf_out != NULL),
1756 "process_frames() failed to reallocate proc_buf_out");
1757 proc_buf_out = in->proc_buf_out;
1758 }
1759 }
1760 frames_rd = read_frames(in,
1761 in->proc_buf_in +
1762 in->proc_buf_frames * in->config.channels,
1763 frames - in->proc_buf_frames);
1764 if (frames_rd < 0) {
1765 /* Return error code */
1766 frames_wr = frames_rd;
1767 break;
1768 }
1769 in->proc_buf_frames += frames_rd;
1770 }
1771
1772 if (in->echo_reference != NULL) {
1773 push_echo_reference(in, in->proc_buf_frames);
1774 }
1775
1776 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1777 * the maximum number of frames to be consumed and produced by process() */
1778 in_buf.frameCount = in->proc_buf_frames;
1779 in_buf.s16 = in->proc_buf_in;
1780 out_buf.frameCount = frames - frames_wr;
1781 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1782
1783 /* FIXME: this works because of current pre processing library implementation that
1784 * does the actual process only when the last enabled effect process is called.
1785 * The generic solution is to have an output buffer for each effect and pass it as
1786 * input to the next.
1787 */
1788 for (i = 0; i < in->num_preprocessors; i++) {
1789 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1790 &in_buf,
1791 &out_buf);
1792 }
1793
1794 /* process() has updated the number of frames consumed and produced in
1795 * in_buf.frameCount and out_buf.frameCount respectively
1796 * move remaining frames to the beginning of in->proc_buf_in */
1797 in->proc_buf_frames -= in_buf.frameCount;
1798
1799 if (in->proc_buf_frames) {
1800 memcpy(in->proc_buf_in,
1801 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1802 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1803 }
1804
1805 /* if not enough frames were passed to process(), read more and retry. */
1806 if (out_buf.frameCount == 0) {
1807 ALOGW("No frames produced by preproc");
1808 continue;
1809 }
1810
1811 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1812 frames_wr += out_buf.frameCount;
1813 } else {
1814 /* The effect does not comply to the API. In theory, we should never end up here! */
1815 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1816 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1817 frames_wr = frames;
1818 }
1819 }
1820 }
1821 else
1822#endif //PREPROCESSING_ENABLED
1823 {
1824 /* No processing effects attached */
1825 if (has_additional_channels) {
1826 /* With additional channels, we cannot use original buffer */
1827 if (in->proc_buf_size < (size_t)frames) {
1828 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1829 in->proc_buf_size = (size_t)frames;
1830 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1831 ALOG_ASSERT((in->proc_buf_out != NULL),
1832 "process_frames() failed to reallocate proc_buf_out");
1833 proc_buf_out = in->proc_buf_out;
1834 }
1835 }
1836 frames_wr = read_frames(in, proc_buf_out, frames);
1837 }
1838
1839 /* Remove all additional channels that have been added on top of main_channels:
1840 * - aux_channels
1841 * - extra channels from HW due to HW limitations
1842 * Assumption is made that the channels are interleaved and that the main
1843 * channels are first. */
1844
1845 if (has_additional_channels)
1846 {
1847 int16_t* src_buffer = (int16_t *)proc_buf_out;
1848 int16_t* dst_buffer = (int16_t *)buffer;
1849
1850 if (dst_channels == 1) {
1851 for (i = frames_wr; i > 0; i--)
1852 {
1853 *dst_buffer++ = *src_buffer;
1854 src_buffer += src_channels;
1855 }
1856 } else {
1857 for (i = frames_wr; i > 0; i--)
1858 {
1859 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1860 dst_buffer += dst_channels;
1861 src_buffer += src_channels;
1862 }
1863 }
1864 }
1865
1866 return frames_wr;
1867}
1868
1869static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1870 struct resampler_buffer* buffer)
1871{
1872 struct stream_in *in;
1873 struct pcm_device *pcm_device;
1874
1875 if (buffer_provider == NULL || buffer == NULL)
1876 return -EINVAL;
1877
1878 in = (struct stream_in *)((char *)buffer_provider -
1879 offsetof(struct stream_in, buf_provider));
1880
1881 if (list_empty(&in->pcm_dev_list)) {
1882 buffer->raw = NULL;
1883 buffer->frame_count = 0;
1884 in->read_status = -ENODEV;
1885 return -ENODEV;
1886 }
1887
1888 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1889 struct pcm_device, stream_list_node);
1890
1891 if (in->read_buf_frames == 0) {
1892 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1893 if (in->read_buf_size < in->config.period_size) {
1894 in->read_buf_size = in->config.period_size;
1895 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
1896 ALOG_ASSERT((in->read_buf != NULL),
1897 "get_next_buffer() failed to reallocate read_buf");
1898 }
1899
1900 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
1901
1902 if (in->read_status != 0) {
1903 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1904 buffer->raw = NULL;
1905 buffer->frame_count = 0;
1906 return in->read_status;
1907 }
1908 in->read_buf_frames = in->config.period_size;
1909
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001910 }
1911
1912 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
1913 in->read_buf_frames : buffer->frame_count;
1914 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
1915 in->config.channels;
1916 return in->read_status;
1917}
1918
1919static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1920 struct resampler_buffer* buffer)
1921{
1922 struct stream_in *in;
1923
1924 if (buffer_provider == NULL || buffer == NULL)
1925 return;
1926
1927 in = (struct stream_in *)((char *)buffer_provider -
1928 offsetof(struct stream_in, buf_provider));
1929
1930 in->read_buf_frames -= buffer->frame_count;
1931}
1932
1933/* read_frames() reads frames from kernel driver, down samples to capture rate
1934 * if necessary and output the number of frames requested to the buffer specified */
1935static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
1936{
1937 ssize_t frames_wr = 0;
1938
1939 struct pcm_device *pcm_device;
1940
1941 if (list_empty(&in->pcm_dev_list)) {
1942 ALOGE("%s: pcm device list empty", __func__);
1943 return -EINVAL;
1944 }
1945
1946 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1947 struct pcm_device, stream_list_node);
1948
1949 while (frames_wr < frames) {
1950 size_t frames_rd = frames - frames_wr;
1951 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
1952 __func__,frames_rd,frames_wr,in->config.channels);
1953 if (in->resampler != NULL) {
1954 in->resampler->resample_from_provider(in->resampler,
1955 (int16_t *)((char *)buffer +
1956 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
1957 &frames_rd);
1958 } else {
1959 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01001960 .raw = NULL,
1961 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001962 };
1963 get_next_buffer(&in->buf_provider, &buf);
1964 if (buf.raw != NULL) {
1965 memcpy((char *)buffer +
1966 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
1967 buf.raw,
1968 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
1969 frames_rd = buf.frame_count;
1970 }
1971 release_buffer(&in->buf_provider, &buf);
1972 }
1973 /* in->read_status is updated by getNextBuffer() also called by
1974 * in->resampler->resample_from_provider() */
1975 if (in->read_status != 0)
1976 return in->read_status;
1977
1978 frames_wr += frames_rd;
1979 }
1980 return frames_wr;
1981}
1982
1983static int in_release_pcm_devices(struct stream_in *in)
1984{
1985 struct pcm_device *pcm_device;
1986 struct listnode *node;
1987 struct listnode *next;
1988
1989 list_for_each_safe(node, next, &in->pcm_dev_list) {
1990 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
1991 list_remove(node);
1992 free(pcm_device);
1993 }
1994
1995 return 0;
1996}
1997
1998static int stop_input_stream(struct stream_in *in)
1999{
2000 struct audio_usecase *uc_info;
2001 struct audio_device *adev = in->dev;
2002
2003 adev->active_input = NULL;
2004 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2005 in->usecase, use_case_table[in->usecase]);
2006 uc_info = get_usecase_from_id(adev, in->usecase);
2007 if (uc_info == NULL) {
2008 ALOGE("%s: Could not find the usecase (%d) in the list",
2009 __func__, in->usecase);
2010 return -EINVAL;
2011 }
2012
2013 /* Disable the tx device */
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002014 disable_snd_device(adev, uc_info, uc_info->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002015
2016 list_remove(&uc_info->adev_list_node);
2017 free(uc_info);
2018
2019 if (list_empty(&in->pcm_dev_list)) {
2020 ALOGE("%s: pcm device list empty", __func__);
2021 return -EINVAL;
2022 }
2023
2024 in_release_pcm_devices(in);
2025 list_init(&in->pcm_dev_list);
2026
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002027 ALOGV("%s: exit", __func__);
2028 return 0;
2029}
2030
2031static int start_input_stream(struct stream_in *in)
2032{
2033 /* Enable output device and stream routing controls */
2034 int ret = 0;
2035 bool recreate_resampler = false;
2036 struct audio_usecase *uc_info;
2037 struct audio_device *adev = in->dev;
2038 struct pcm_device_profile *pcm_profile;
2039 struct pcm_device *pcm_device;
2040
2041 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2042 adev->active_input = in;
2043 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2044 if (pcm_profile == NULL) {
2045 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2046 __func__, in->usecase);
2047 ret = -EINVAL;
2048 goto error_config;
2049 }
2050
2051 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002052 if (uc_info == NULL) {
2053 ret = -ENOMEM;
2054 goto error_config;
2055 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002056 uc_info->id = in->usecase;
2057 uc_info->type = PCM_CAPTURE;
2058 uc_info->stream = (struct audio_stream *)in;
2059 uc_info->devices = in->devices;
2060 uc_info->in_snd_device = SND_DEVICE_NONE;
2061 uc_info->out_snd_device = SND_DEVICE_NONE;
2062
2063 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002064 if (pcm_device == NULL) {
2065 free(uc_info);
2066 ret = -ENOMEM;
2067 goto error_config;
2068 }
2069
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002070 pcm_device->pcm_profile = pcm_profile;
2071 list_init(&in->pcm_dev_list);
2072 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2073
2074 list_init(&uc_info->mixer_list);
2075 list_add_tail(&uc_info->mixer_list,
2076 &adev_get_mixer_for_card(adev,
2077 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2078
2079 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2080
2081 select_devices(adev, in->usecase);
2082
2083 /* Config should be updated as profile can be changed between different calls
2084 * to this function:
2085 * - Trigger resampler creation
2086 * - Config needs to be updated */
2087 if (in->config.rate != pcm_profile->config.rate) {
2088 recreate_resampler = true;
2089 }
2090 in->config = pcm_profile->config;
2091
2092#ifdef PREPROCESSING_ENABLED
2093 if (in->aux_channels_changed) {
2094 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2095 recreate_resampler = true;
2096 }
2097#endif
2098
2099 if (in->requested_rate != in->config.rate) {
2100 recreate_resampler = true;
2101 }
2102
2103 if (recreate_resampler) {
2104 if (in->resampler) {
2105 release_resampler(in->resampler);
2106 in->resampler = NULL;
2107 }
2108 in->buf_provider.get_next_buffer = get_next_buffer;
2109 in->buf_provider.release_buffer = release_buffer;
2110 ret = create_resampler(in->config.rate,
2111 in->requested_rate,
2112 in->config.channels,
2113 RESAMPLER_QUALITY_DEFAULT,
2114 &in->buf_provider,
2115 &in->resampler);
2116 }
2117
2118#ifdef PREPROCESSING_ENABLED
2119 if (in->enable_aec && in->echo_reference == NULL) {
2120 in->echo_reference = get_echo_reference(adev,
2121 AUDIO_FORMAT_PCM_16_BIT,
2122 audio_channel_count_from_in_mask(in->main_channels),
2123 in->requested_rate
2124 );
2125 }
2126
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002127#endif
2128
2129 /* Open the PCM device.
2130 * The HW is limited to support only the default pcm_profile settings.
2131 * As such a change in aux_channels will not have an effect.
2132 */
2133 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2134 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2135 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2136 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2137
stenkinevgeniy44335362018-05-07 18:00:13 +00002138 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002139 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2140
stenkinevgeniy44335362018-05-07 18:00:13 +00002141 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2142 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2143 pcm_close(pcm_device->pcm);
2144 pcm_device->pcm = NULL;
2145 ret = -EIO;
2146 goto error_open;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002147 }
2148
2149 /* force read and proc buffer reallocation in case of frame size or
2150 * channel count change */
2151 in->proc_buf_frames = 0;
2152 in->proc_buf_size = 0;
2153 in->read_buf_size = 0;
2154 in->read_buf_frames = 0;
2155
2156 /* if no supported sample rate is available, use the resampler */
2157 if (in->resampler) {
2158 in->resampler->reset(in->resampler);
2159 }
2160
2161 ALOGV("%s: exit", __func__);
2162 return ret;
2163
2164error_open:
2165 if (in->resampler) {
2166 release_resampler(in->resampler);
2167 in->resampler = NULL;
2168 }
2169 stop_input_stream(in);
2170
2171error_config:
2172 ALOGV("%s: exit: status(%d)", __func__, ret);
2173 adev->active_input = NULL;
2174 return ret;
2175}
2176
2177void lock_input_stream(struct stream_in *in)
2178{
2179 pthread_mutex_lock(&in->pre_lock);
2180 pthread_mutex_lock(&in->lock);
2181 pthread_mutex_unlock(&in->pre_lock);
2182}
2183
2184void lock_output_stream(struct stream_out *out)
2185{
2186 pthread_mutex_lock(&out->pre_lock);
2187 pthread_mutex_lock(&out->lock);
2188 pthread_mutex_unlock(&out->pre_lock);
2189}
2190
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002191static int uc_release_pcm_devices(struct audio_usecase *usecase)
2192{
2193 struct stream_out *out = (struct stream_out *)usecase->stream;
2194 struct pcm_device *pcm_device;
2195 struct listnode *node;
2196 struct listnode *next;
2197
2198 list_for_each_safe(node, next, &out->pcm_dev_list) {
2199 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2200 list_remove(node);
2201 free(pcm_device);
2202 }
2203 list_init(&usecase->mixer_list);
2204
2205 return 0;
2206}
2207
2208static int uc_select_pcm_devices(struct audio_usecase *usecase)
2209
2210{
2211 struct stream_out *out = (struct stream_out *)usecase->stream;
2212 struct pcm_device *pcm_device;
2213 struct pcm_device_profile *pcm_profile;
2214 struct mixer_card *mixer_card;
2215 audio_devices_t devices = usecase->devices;
2216
2217 list_init(&usecase->mixer_list);
2218 list_init(&out->pcm_dev_list);
2219
2220 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2221 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002222 if (pcm_device == NULL) {
2223 return -ENOMEM;
2224 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002225 pcm_device->pcm_profile = pcm_profile;
2226 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2227 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2228 if (mixer_card == NULL) {
2229 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2230 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2231 }
2232 devices &= ~pcm_profile->devices;
2233 }
2234
2235 return 0;
2236}
2237
2238static int out_close_pcm_devices(struct stream_out *out)
2239{
2240 struct pcm_device *pcm_device;
2241 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002242
2243 list_for_each(node, &out->pcm_dev_list) {
2244 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002245 if (pcm_device->pcm) {
2246 pcm_close(pcm_device->pcm);
2247 pcm_device->pcm = NULL;
2248 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002249 }
2250
2251 return 0;
2252}
2253
2254static int out_open_pcm_devices(struct stream_out *out)
2255{
2256 struct pcm_device *pcm_device;
2257 struct listnode *node;
2258 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002259 int pcm_device_card;
2260 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002261
2262 list_for_each(node, &out->pcm_dev_list) {
2263 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002264 pcm_device_card = pcm_device->pcm_profile->card;
2265 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002266
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002267 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2268 pcm_device_id = pcm_device_deep_buffer.id;
2269
2270 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2271 __func__, pcm_device_card, pcm_device_id);
2272
2273 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
stenkinevgeniy2ef158a2018-05-08 06:52:05 +00002274 PCM_OUT | PCM_MONOTONIC, &out->config);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002275
2276 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2277 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2278 pcm_device->pcm = NULL;
2279 ret = -EIO;
2280 goto error_open;
2281 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002282 }
2283 return ret;
2284
2285error_open:
2286 out_close_pcm_devices(out);
2287 return ret;
2288}
2289
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002290int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002291{
2292 struct audio_device *adev = out->dev;
2293 struct audio_usecase *uc_info;
2294
2295 uc_info = get_usecase_from_id(adev, out->usecase);
2296 if (uc_info == NULL) {
2297 ALOGE("%s: Could not find the usecase (%d) in the list",
2298 __func__, out->usecase);
2299 return -EINVAL;
2300 }
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002301 disable_snd_device(adev, uc_info, uc_info->out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002302 uc_release_pcm_devices(uc_info);
2303 list_remove(&uc_info->adev_list_node);
2304 free(uc_info);
2305
2306 return 0;
2307}
2308
Andreas Schneider56204f62017-01-31 08:17:32 +01002309int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002310{
2311 struct audio_device *adev = out->dev;
2312 struct audio_usecase *uc_info;
2313
2314 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002315 if (uc_info == NULL) {
2316 return -ENOMEM;
2317 }
2318
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002319 uc_info->id = out->usecase;
2320 uc_info->type = PCM_PLAYBACK;
2321 uc_info->stream = (struct audio_stream *)out;
2322 uc_info->devices = out->devices;
2323 uc_info->in_snd_device = SND_DEVICE_NONE;
2324 uc_info->out_snd_device = SND_DEVICE_NONE;
2325 uc_select_pcm_devices(uc_info);
2326
2327 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2328 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002329
2330 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002331}
2332
2333static int stop_output_stream(struct stream_out *out)
2334{
2335 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002336 bool do_disable = true;
2337
2338 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2339 out->usecase, use_case_table[out->usecase]);
2340
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002341 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002342
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002343 if (do_disable)
2344 ret = disable_output_path_l(out);
2345
2346 ALOGV("%s: exit: status(%d)", __func__, ret);
2347 return ret;
2348}
2349
2350static int start_output_stream(struct stream_out *out)
2351{
2352 int ret = 0;
2353 struct audio_device *adev = out->dev;
2354
2355 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2356 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2357
Andreas Schneider56204f62017-01-31 08:17:32 +01002358 ret = enable_output_path_l(out);
2359 if (ret != 0) {
2360 goto error_config;
2361 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002362
2363 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2364 out->compr = NULL;
2365 ret = out_open_pcm_devices(out);
2366 if (ret != 0)
2367 goto error_open;
2368#ifdef PREPROCESSING_ENABLED
2369 out->echo_reference = NULL;
2370 out->echo_reference_generation = adev->echo_reference_generation;
2371 if (adev->echo_reference != NULL)
2372 out->echo_reference = adev->echo_reference;
2373#endif
2374 } else {
2375 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2376 COMPRESS_IN, &out->compr_config);
2377 if (out->compr && !is_compress_ready(out->compr)) {
2378 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2379 compress_close(out->compr);
2380 out->compr = NULL;
2381 ret = -EIO;
2382 goto error_open;
2383 }
2384 if (out->offload_callback)
2385 compress_nonblock(out->compr, out->non_blocking);
2386
2387 if (adev->offload_fx_start_output != NULL)
2388 adev->offload_fx_start_output(out->handle);
2389 }
2390 ALOGV("%s: exit", __func__);
2391 return 0;
2392error_open:
2393 stop_output_stream(out);
2394error_config:
2395 return ret;
2396}
2397
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002398int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002399{
2400 struct audio_usecase *uc_info;
2401
2402 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002403 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002404
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002405 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002406
2407 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2408 if (uc_info == NULL) {
2409 ALOGE("%s: Could not find the usecase (%d) in the list",
2410 __func__, USECASE_VOICE_CALL);
2411 return -EINVAL;
2412 }
2413
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002414 disable_snd_device(adev, uc_info, uc_info->out_snd_device);
2415 disable_snd_device(adev, uc_info, uc_info->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002416
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002417 list_remove(&uc_info->adev_list_node);
2418 free(uc_info);
2419
2420 ALOGV("%s: exit", __func__);
2421 return 0;
2422}
2423
2424/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002425int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002426{
2427 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002428 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002429
2430 ALOGV("%s: enter", __func__);
2431
2432 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002433 if (uc_info == NULL) {
2434 ret = -ENOMEM;
2435 goto exit;
2436 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002437 /*
2438 * We set this early so that functions called after this is being set
2439 * can use it. It is e.g. needed in select_devices() to inform the RILD
2440 * which output device we use.
2441 */
2442 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002443
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002444 uc_info->id = USECASE_VOICE_CALL;
2445 uc_info->type = VOICE_CALL;
2446 uc_info->stream = (struct audio_stream *)adev->primary_output;
2447 uc_info->devices = adev->primary_output->devices;
2448 uc_info->in_snd_device = SND_DEVICE_NONE;
2449 uc_info->out_snd_device = SND_DEVICE_NONE;
2450
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002451 list_init(&uc_info->mixer_list);
2452 list_add_tail(&uc_info->mixer_list,
2453 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002454
2455 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2456
2457 select_devices(adev, USECASE_VOICE_CALL);
2458
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002459 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002460
2461 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002462 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002463
Andreas Schneider56204f62017-01-31 08:17:32 +01002464exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002465 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002466 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002467}
2468
2469static int check_input_parameters(uint32_t sample_rate,
2470 audio_format_t format,
2471 int channel_count)
2472{
2473 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2474
2475 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2476
2477 switch (sample_rate) {
2478 case 8000:
2479 case 11025:
2480 case 12000:
2481 case 16000:
2482 case 22050:
2483 case 24000:
2484 case 32000:
2485 case 44100:
2486 case 48000:
2487 break;
2488 default:
2489 return -EINVAL;
2490 }
2491
2492 return 0;
2493}
2494
2495static size_t get_input_buffer_size(uint32_t sample_rate,
2496 audio_format_t format,
2497 int channel_count,
2498 usecase_type_t usecase_type,
2499 audio_devices_t devices)
2500{
2501 size_t size = 0;
2502 struct pcm_device_profile *pcm_profile;
2503
2504 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2505 return 0;
2506
2507 pcm_profile = get_pcm_device(usecase_type, devices);
2508 if (pcm_profile == NULL)
2509 return 0;
2510
2511 /*
2512 * take resampling into account and return the closest majoring
2513 * multiple of 16 frames, as audioflinger expects audio buffers to
2514 * be a multiple of 16 frames
2515 */
2516 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2517 size = ((size + 15) / 16) * 16;
2518
2519 return (size * channel_count * audio_bytes_per_sample(format));
2520
2521}
2522
2523static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526
2527 return out->sample_rate;
2528}
2529
2530static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2531{
2532 (void)stream;
2533 (void)rate;
2534 return -ENOSYS;
2535}
2536
2537static size_t out_get_buffer_size(const struct audio_stream *stream)
2538{
2539 struct stream_out *out = (struct stream_out *)stream;
2540
2541 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2542 return out->compr_config.fragment_size;
2543 }
2544
2545 return out->config.period_size *
2546 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2547}
2548
2549static uint32_t out_get_channels(const struct audio_stream *stream)
2550{
2551 struct stream_out *out = (struct stream_out *)stream;
2552
2553 return out->channel_mask;
2554}
2555
2556static audio_format_t out_get_format(const struct audio_stream *stream)
2557{
2558 struct stream_out *out = (struct stream_out *)stream;
2559
2560 return out->format;
2561}
2562
2563static int out_set_format(struct audio_stream *stream, audio_format_t format)
2564{
2565 (void)stream;
2566 (void)format;
2567 return -ENOSYS;
2568}
2569
2570static int do_out_standby_l(struct stream_out *out)
2571{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002572 int status = 0;
2573
2574 out->standby = true;
2575 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2576 out_close_pcm_devices(out);
2577#ifdef PREPROCESSING_ENABLED
2578 /* stop writing to echo reference */
2579 if (out->echo_reference != NULL) {
2580 out->echo_reference->write(out->echo_reference, NULL);
2581 if (out->echo_reference_generation != adev->echo_reference_generation) {
2582 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2583 release_echo_reference(out->echo_reference);
2584 out->echo_reference_generation = adev->echo_reference_generation;
2585 }
2586 out->echo_reference = NULL;
2587 }
2588#endif
2589 } else {
2590 stop_compressed_output_l(out);
2591 out->gapless_mdata.encoder_delay = 0;
2592 out->gapless_mdata.encoder_padding = 0;
2593 if (out->compr != NULL) {
2594 compress_close(out->compr);
2595 out->compr = NULL;
2596 }
2597 }
2598 status = stop_output_stream(out);
2599
2600 return status;
2601}
2602
2603static int out_standby(struct audio_stream *stream)
2604{
2605 struct stream_out *out = (struct stream_out *)stream;
2606 struct audio_device *adev = out->dev;
2607
2608 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2609 out->usecase, use_case_table[out->usecase]);
2610 lock_output_stream(out);
2611 if (!out->standby) {
2612 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002613 amplifier_output_stream_standby((struct audio_stream_out *) stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002614 do_out_standby_l(out);
2615 pthread_mutex_unlock(&adev->lock);
2616 }
2617 pthread_mutex_unlock(&out->lock);
2618 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002619
2620 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2621
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002622 return 0;
2623}
2624
2625static int out_dump(const struct audio_stream *stream, int fd)
2626{
2627 (void)stream;
2628 (void)fd;
2629
2630 return 0;
2631}
2632
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002633static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2634{
2635 struct stream_out *out = (struct stream_out *)stream;
2636 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002637 struct listnode *node;
2638 struct str_parms *parms;
2639 char value[32];
2640 int ret, val = 0;
2641 struct audio_usecase *uc_info;
2642 bool do_standby = false;
2643 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002644#ifdef PREPROCESSING_ENABLED
2645 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2646#endif
2647
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002648 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%#x) "
2649 "adev->mode(%#x)",
2650 __func__, out->usecase, use_case_table[out->usecase], kvpairs,
2651 out->devices, adev->mode);
2652
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002653 parms = str_parms_create_str(kvpairs);
2654 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2655 if (ret >= 0) {
2656 val = atoi(value);
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002657
2658 ALOGV("%s: routing: usecase(%d: %s) devices=(%#x) adev->mode(%#x)",
2659 __func__, out->usecase, use_case_table[out->usecase], val,
2660 adev->mode);
2661
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002662 pthread_mutex_lock(&adev->lock_inputs);
2663 lock_output_stream(out);
2664 pthread_mutex_lock(&adev->lock);
2665#ifdef PREPROCESSING_ENABLED
2666 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2667 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2668 /* reset active input:
2669 * - to attach the echo reference
2670 * - because a change in output device may change mic settings */
2671 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2672 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2673 in = adev->active_input;
2674 }
2675 }
2676#endif
Christopher N. Hesse33affb82017-11-16 17:01:37 +01002677 if (val != SND_DEVICE_NONE) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002678 bool bt_sco_active = false;
2679
2680 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2681 bt_sco_active = true;
2682 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002683 out->devices = val;
2684
2685 if (!out->standby) {
2686 uc_info = get_usecase_from_id(adev, out->usecase);
2687 if (uc_info == NULL) {
2688 ALOGE("%s: Could not find the usecase (%d) in the list",
2689 __func__, out->usecase);
2690 } else {
2691 list_for_each(node, &out->pcm_dev_list) {
2692 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2693 if ((pcm_device->pcm_profile->devices & val) == 0)
2694 do_standby = true;
2695 val &= ~pcm_device->pcm_profile->devices;
2696 }
2697 if (val != 0)
2698 do_standby = true;
2699 }
2700 if (do_standby)
2701 do_out_standby_l(out);
2702 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002703 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2704 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002705 select_devices(adev, out->usecase);
2706 }
2707 }
2708
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002709 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002710 (out == adev->primary_output)) {
2711 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002712 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2713 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002714 (out == adev->primary_output)) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002715 /* Turn on bluetooth if needed */
2716 if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002717 select_devices(adev, USECASE_VOICE_CALL);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002718 start_voice_session_bt_sco(adev->voice.session);
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002719 } else {
2720 /*
2721 * When we select different devices we need to restart the
2722 * voice call. The modem closes the stream on its end and
2723 * we do not get any output.
2724 */
2725 stop_voice_call(adev);
2726 start_voice_call(adev);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002727 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002728 }
2729 }
2730
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002731 pthread_mutex_unlock(&adev->lock);
2732 pthread_mutex_unlock(&out->lock);
2733#ifdef PREPROCESSING_ENABLED
2734 if (in) {
2735 /* The lock on adev->lock_inputs prevents input stream from being closed */
2736 lock_input_stream(in);
2737 pthread_mutex_lock(&adev->lock);
2738 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2739 do_in_standby_l(in);
2740 pthread_mutex_unlock(&adev->lock);
2741 pthread_mutex_unlock(&in->lock);
2742 }
2743#endif
2744 pthread_mutex_unlock(&adev->lock_inputs);
2745 }
2746
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002747 amplifier_set_parameters(parms);
2748
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002749 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2750 parse_compress_metadata(out, parms);
2751 }
2752
2753 str_parms_destroy(parms);
2754
2755 if (ret > 0)
2756 ret = 0;
2757 ALOGV("%s: exit: code(%d)", __func__, ret);
2758 return ret;
2759}
2760
2761static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2762{
2763 struct stream_out *out = (struct stream_out *)stream;
2764 struct str_parms *query = str_parms_create_str(keys);
2765 char *str;
2766 char value[256];
2767 struct str_parms *reply = str_parms_create();
2768 size_t i, j;
2769 int ret;
2770 bool first = true;
2771 ALOGV("%s: enter: keys - %s", __func__, keys);
2772 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2773 if (ret >= 0) {
2774 value[0] = '\0';
2775 i = 0;
2776 while (out->supported_channel_masks[i] != 0) {
2777 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2778 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2779 if (!first) {
2780 strcat(value, "|");
2781 }
2782 strcat(value, out_channels_name_to_enum_table[j].name);
2783 first = false;
2784 break;
2785 }
2786 }
2787 i++;
2788 }
2789 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2790 str = str_parms_to_str(reply);
2791 } else {
2792 str = strdup(keys);
2793 }
2794 str_parms_destroy(query);
2795 str_parms_destroy(reply);
2796 ALOGV("%s: exit: returns - %s", __func__, str);
2797 return str;
2798}
2799
2800static uint32_t out_get_latency(const struct audio_stream_out *stream)
2801{
2802 struct stream_out *out = (struct stream_out *)stream;
2803
2804 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2805 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2806
2807 return (out->config.period_count * out->config.period_size * 1000) /
2808 (out->config.rate);
2809}
2810
2811static int out_set_volume(struct audio_stream_out *stream, float left,
2812 float right)
2813{
2814 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002815
2816 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2817 /* only take left channel into account: the API is for stereo anyway */
2818 out->muted = (left == 0.0f);
2819 return 0;
2820 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002821 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002822 }
2823
2824 return -ENOSYS;
2825}
2826
Andreas Schneider3b643832017-01-31 11:48:22 +01002827#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002828static int fast_set_affinity(pid_t tid) {
2829 cpu_set_t cpu_set;
2830 int cpu_num;
2831 const char *irq_procfs = "/proc/asound/irq_affinity";
2832 FILE *fp;
2833
2834 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2835 ALOGW("Procfs node %s not found", irq_procfs);
2836 return -1;
2837 }
2838
2839 if (fscanf(fp, "%d", &cpu_num) != 1) {
2840 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2841 fclose(fp);
2842 return -1;
2843 }
2844 fclose(fp);
2845
2846 CPU_ZERO(&cpu_set);
2847 CPU_SET(cpu_num, &cpu_set);
2848 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2849}
Andreas Schneider3b643832017-01-31 11:48:22 +01002850#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002851
2852static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2853 size_t bytes)
2854{
2855 struct stream_out *out = (struct stream_out *)stream;
2856 struct audio_device *adev = out->dev;
2857 ssize_t ret = 0;
2858 struct pcm_device *pcm_device;
2859 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002860#ifdef PREPROCESSING_ENABLED
stenkinevgeniyd0a02c02018-05-08 07:17:53 +00002861 size_t frame_size = audio_stream_out_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002862 size_t in_frames = bytes / frame_size;
2863 size_t out_frames = in_frames;
2864 struct stream_in *in = NULL;
2865#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002866
2867 lock_output_stream(out);
2868
Andreas Schneider3b643832017-01-31 11:48:22 +01002869#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002870 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002871 pid_t tid = gettid();
2872 int err;
2873
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002874 err = fast_set_affinity(tid);
2875 if (err < 0) {
2876 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2877 }
2878 out->is_fastmixer_affinity_set = true;
2879 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002880#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002881
2882 if (out->standby) {
2883#ifdef PREPROCESSING_ENABLED
2884 pthread_mutex_unlock(&out->lock);
2885 /* Prevent input stream from being closed */
2886 pthread_mutex_lock(&adev->lock_inputs);
2887 lock_output_stream(out);
2888 if (!out->standby) {
2889 pthread_mutex_unlock(&adev->lock_inputs);
2890 goto false_alarm;
2891 }
2892#endif
2893 pthread_mutex_lock(&adev->lock);
2894 ret = start_output_stream(out);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002895 if (ret == 0) {
2896 amplifier_output_stream_start(stream, out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD);
2897 }
2898
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002899 /* ToDo: If use case is compress offload should return 0 */
2900 if (ret != 0) {
2901 pthread_mutex_unlock(&adev->lock);
2902#ifdef PREPROCESSING_ENABLED
2903 pthread_mutex_unlock(&adev->lock_inputs);
2904#endif
2905 goto exit;
2906 }
2907 out->standby = false;
2908
2909#ifdef PREPROCESSING_ENABLED
2910 /* A change in output device may change the microphone selection */
2911 if (adev->active_input &&
2912 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2913 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2914 in = adev->active_input;
2915 ALOGV("%s: enter:) force_input_standby true", __func__);
2916 }
2917#endif
2918 pthread_mutex_unlock(&adev->lock);
2919#ifdef PREPROCESSING_ENABLED
2920 if (!in) {
2921 /* Leave mutex locked iff in != NULL */
2922 pthread_mutex_unlock(&adev->lock_inputs);
2923 }
2924#endif
2925 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002926#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002927false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002928#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002929
2930 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002931 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002932 return ret;
2933 } else {
2934#ifdef PREPROCESSING_ENABLED
2935 if (android_atomic_acquire_load(&adev->echo_reference_generation)
2936 != out->echo_reference_generation) {
2937 pthread_mutex_lock(&adev->lock);
2938 if (out->echo_reference != NULL) {
2939 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2940 release_echo_reference(out->echo_reference);
2941 }
2942 // note that adev->echo_reference_generation here can be different from the one
2943 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
2944 // with what has been set by get_echo_reference() or put_echo_reference()
2945 out->echo_reference_generation = adev->echo_reference_generation;
2946 out->echo_reference = adev->echo_reference;
2947 ALOGV("%s: update echo reference generation %d", __func__,
2948 out->echo_reference_generation);
2949 pthread_mutex_unlock(&adev->lock);
2950 }
2951#endif
2952
2953 if (out->muted)
2954 memset((void *)buffer, 0, bytes);
2955 list_for_each(node, &out->pcm_dev_list) {
2956 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002957 if (pcm_device->pcm) {
2958#ifdef PREPROCESSING_ENABLED
2959 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
2960 struct echo_reference_buffer b;
2961 b.raw = (void *)buffer;
2962 b.frame_count = in_frames;
2963
2964 get_playback_delay(out, out_frames, &b);
2965 out->echo_reference->write(out->echo_reference, &b);
2966 }
2967#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002968 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
stenkinevgeniyd0a02c02018-05-08 07:17:53 +00002969 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002970 if (pcm_device->status != 0)
2971 ret = pcm_device->status;
2972 }
2973 }
2974 if (ret == 0)
2975 out->written += bytes / (out->config.channels * sizeof(short));
2976 }
2977
2978exit:
2979 pthread_mutex_unlock(&out->lock);
2980
2981 if (ret != 0) {
2982 list_for_each(node, &out->pcm_dev_list) {
2983 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2984 if (pcm_device->pcm && pcm_device->status != 0)
2985 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
2986 }
2987 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002988 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
2989 clock_gettime(CLOCK_MONOTONIC, &t);
2990 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
2991 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
2992 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2993 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
2994 if (sleep_time > 0) {
2995 usleep(sleep_time);
2996 } else {
2997 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
2998 sleep_time = 0;
2999 }
3000 out->last_write_time_us = now + sleep_time;
3001 // last_write_time_us is an approximation of when the (simulated) alsa
3002 // buffer is believed completely full. The usleep above waits for more space
3003 // in the buffer, but by the end of the sleep the buffer is considered
3004 // topped-off.
3005 //
3006 // On the subsequent out_write(), we measure the elapsed time spent in
3007 // the mixer. This is subtracted from the sleep estimate based on frames,
3008 // thereby accounting for drain in the alsa buffer during mixing.
3009 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003010 }
3011
3012#ifdef PREPROCESSING_ENABLED
3013 if (in) {
3014 /* The lock on adev->lock_inputs prevents input stream from being closed */
3015 lock_input_stream(in);
3016 pthread_mutex_lock(&adev->lock);
3017 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3018 do_in_standby_l(in);
3019 pthread_mutex_unlock(&adev->lock);
3020 pthread_mutex_unlock(&in->lock);
3021 /* This mutex was left locked iff in != NULL */
3022 pthread_mutex_unlock(&adev->lock_inputs);
3023 }
3024#endif
3025
3026 return bytes;
3027}
3028
3029static int out_get_render_position(const struct audio_stream_out *stream,
3030 uint32_t *dsp_frames)
3031{
3032 struct stream_out *out = (struct stream_out *)stream;
3033 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003034 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3035 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003036 } else
3037 return -EINVAL;
3038}
3039
3040static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3041{
3042 (void)stream;
3043 (void)effect;
3044 return 0;
3045}
3046
3047static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3048{
3049 (void)stream;
3050 (void)effect;
3051 return 0;
3052}
3053
3054static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3055 int64_t *timestamp)
3056{
3057 (void)stream;
3058 (void)timestamp;
3059 return -EINVAL;
3060}
3061
3062static int out_get_presentation_position(const struct audio_stream_out *stream,
3063 uint64_t *frames, struct timespec *timestamp)
3064{
3065 struct stream_out *out = (struct stream_out *)stream;
Victor Lourme5869cd32018-03-26 19:36:07 +02003066 int ret = -EINVAL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003067
3068 lock_output_stream(out);
3069
3070 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003071 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003072 } else {
3073 /* FIXME: which device to read from? */
3074 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003075 struct pcm_device *pcm_device;
3076 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003077 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003078
Andreas Schneiderd6359182017-02-08 16:58:22 +01003079 list_for_each(node, &out->pcm_dev_list) {
3080 pcm_device = node_to_item(node,
3081 struct pcm_device,
3082 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003083
Andreas Schneiderd6359182017-02-08 16:58:22 +01003084 if (pcm_device->pcm != NULL) {
3085 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3086 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3087 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3088 /* This adjustment accounts for buffering after app processor.
3089 It is based on estimated DSP latency per use case, rather than exact. */
3090 signed_frames -=
3091 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3092
3093 /* It would be unusual for this value to be negative, but check just in case ... */
3094 if (signed_frames >= 0) {
3095 *frames = signed_frames;
3096 ret = 0;
3097 goto done;
3098 }
Andreas Schneiderd6359182017-02-08 16:58:22 +01003099 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003100 }
3101 }
3102 }
3103 }
3104
Andreas Schneiderd6359182017-02-08 16:58:22 +01003105done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003106 pthread_mutex_unlock(&out->lock);
3107
3108 return ret;
3109}
3110
3111static int out_set_callback(struct audio_stream_out *stream,
3112 stream_callback_t callback, void *cookie)
3113{
3114 struct stream_out *out = (struct stream_out *)stream;
3115
3116 ALOGV("%s", __func__);
3117 lock_output_stream(out);
3118 out->offload_callback = callback;
3119 out->offload_cookie = cookie;
3120 pthread_mutex_unlock(&out->lock);
3121 return 0;
3122}
3123
3124static int out_pause(struct audio_stream_out* stream)
3125{
3126 struct stream_out *out = (struct stream_out *)stream;
3127 int status = -ENOSYS;
3128 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003129 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3130 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003131 return status;
3132}
3133
3134static int out_resume(struct audio_stream_out* stream)
3135{
3136 struct stream_out *out = (struct stream_out *)stream;
3137 int status = -ENOSYS;
3138 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003139 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3140 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003141 return status;
3142}
3143
3144static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3145{
3146 struct stream_out *out = (struct stream_out *)stream;
3147 int status = -ENOSYS;
3148 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003149 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3150 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003151 return status;
3152}
3153
3154static int out_flush(struct audio_stream_out* stream)
3155{
3156 struct stream_out *out = (struct stream_out *)stream;
3157 ALOGV("%s", __func__);
3158 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003159 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003160 }
3161 return -ENOSYS;
3162}
3163
3164/** audio_stream_in implementation **/
3165static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3166{
3167 struct stream_in *in = (struct stream_in *)stream;
3168
3169 return in->requested_rate;
3170}
3171
3172static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3173{
3174 (void)stream;
3175 (void)rate;
3176 return -ENOSYS;
3177}
3178
3179static uint32_t in_get_channels(const struct audio_stream *stream)
3180{
3181 struct stream_in *in = (struct stream_in *)stream;
3182
3183 return in->main_channels;
3184}
3185
3186static audio_format_t in_get_format(const struct audio_stream *stream)
3187{
3188 (void)stream;
3189 return AUDIO_FORMAT_PCM_16_BIT;
3190}
3191
3192static int in_set_format(struct audio_stream *stream, audio_format_t format)
3193{
3194 (void)stream;
3195 (void)format;
3196
3197 return -ENOSYS;
3198}
3199
3200static size_t in_get_buffer_size(const struct audio_stream *stream)
3201{
3202 struct stream_in *in = (struct stream_in *)stream;
3203
3204 return get_input_buffer_size(in->requested_rate,
3205 in_get_format(stream),
3206 audio_channel_count_from_in_mask(in->main_channels),
3207 in->usecase_type,
3208 in->devices);
3209}
3210
3211static int in_close_pcm_devices(struct stream_in *in)
3212{
3213 struct pcm_device *pcm_device;
3214 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003215
3216 list_for_each(node, &in->pcm_dev_list) {
3217 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3218 if (pcm_device) {
3219 if (pcm_device->pcm)
3220 pcm_close(pcm_device->pcm);
3221 pcm_device->pcm = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003222 }
3223 }
3224 return 0;
3225}
3226
3227
3228/* must be called with stream and hw device mutex locked */
3229static int do_in_standby_l(struct stream_in *in)
3230{
3231 int status = 0;
3232
3233#ifdef PREPROCESSING_ENABLED
3234 struct audio_device *adev = in->dev;
3235#endif
3236 if (!in->standby) {
3237
3238 in_close_pcm_devices(in);
3239
3240#ifdef PREPROCESSING_ENABLED
3241 if (in->echo_reference != NULL) {
3242 /* stop reading from echo reference */
3243 in->echo_reference->read(in->echo_reference, NULL);
3244 put_echo_reference(adev, in->echo_reference);
3245 in->echo_reference = NULL;
3246 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003247#endif // PREPROCESSING_ENABLED
3248
3249 status = stop_input_stream(in);
3250
3251 if (in->read_buf) {
3252 free(in->read_buf);
3253 in->read_buf = NULL;
3254 }
3255
3256 in->standby = 1;
3257 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003258
3259 in->last_read_time_us = 0;
3260
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003261 return 0;
3262}
3263
3264// called with adev->lock_inputs locked
3265static int in_standby_l(struct stream_in *in)
3266{
3267 struct audio_device *adev = in->dev;
3268 int status = 0;
3269 lock_input_stream(in);
3270 if (!in->standby) {
3271 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003272 amplifier_input_stream_standby((struct audio_stream_in *) in);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003273 status = do_in_standby_l(in);
3274 pthread_mutex_unlock(&adev->lock);
3275 }
3276 pthread_mutex_unlock(&in->lock);
3277 return status;
3278}
3279
3280static int in_standby(struct audio_stream *stream)
3281{
3282 struct stream_in *in = (struct stream_in *)stream;
3283 struct audio_device *adev = in->dev;
3284 int status;
3285 ALOGV("%s: enter", __func__);
3286 pthread_mutex_lock(&adev->lock_inputs);
3287 status = in_standby_l(in);
3288 pthread_mutex_unlock(&adev->lock_inputs);
3289 ALOGV("%s: exit: status(%d)", __func__, status);
3290 return status;
3291}
3292
3293static int in_dump(const struct audio_stream *stream, int fd)
3294{
3295 (void)stream;
3296 (void)fd;
3297
3298 return 0;
3299}
3300
3301static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3302{
3303 struct stream_in *in = (struct stream_in *)stream;
3304 struct audio_device *adev = in->dev;
3305 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003306 char value[32];
3307 int ret, val = 0;
3308 struct audio_usecase *uc_info;
3309 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003310 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003311
3312 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3313 parms = str_parms_create_str(kvpairs);
3314
3315 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3316
3317 pthread_mutex_lock(&adev->lock_inputs);
3318 lock_input_stream(in);
3319 pthread_mutex_lock(&adev->lock);
3320 if (ret >= 0) {
3321 val = atoi(value);
3322 /* no audio source uses val == 0 */
3323 if (((int)in->source != val) && (val != 0)) {
3324 in->source = val;
3325 }
3326 }
3327
3328 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3329 if (ret >= 0) {
3330 val = atoi(value);
3331 if (((int)in->devices != val) && (val != 0)) {
3332 in->devices = val;
3333 /* If recording is in progress, change the tx device to new device */
3334 if (!in->standby) {
3335 uc_info = get_usecase_from_id(adev, in->usecase);
3336 if (uc_info == NULL) {
3337 ALOGE("%s: Could not find the usecase (%d) in the list",
3338 __func__, in->usecase);
3339 } else {
3340 if (list_empty(&in->pcm_dev_list))
3341 ALOGE("%s: pcm device list empty", __func__);
3342 else {
3343 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3344 struct pcm_device, stream_list_node);
3345 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3346 do_standby = true;
3347 }
3348 }
3349 }
3350 if (do_standby) {
3351 ret = do_in_standby_l(in);
3352 } else
3353 ret = select_devices(adev, in->usecase);
3354 }
3355 }
3356 }
3357 pthread_mutex_unlock(&adev->lock);
3358 pthread_mutex_unlock(&in->lock);
3359 pthread_mutex_unlock(&adev->lock_inputs);
3360 str_parms_destroy(parms);
3361
3362 if (ret > 0)
3363 ret = 0;
3364
3365 ALOGV("%s: exit: status(%d)", __func__, ret);
3366 return ret;
3367}
3368
3369static char* in_get_parameters(const struct audio_stream *stream,
3370 const char *keys)
3371{
3372 (void)stream;
3373 (void)keys;
3374
3375 return strdup("");
3376}
3377
3378static int in_set_gain(struct audio_stream_in *stream, float gain)
3379{
3380 (void)stream;
3381 (void)gain;
3382
3383 return 0;
3384}
3385
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003386static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3387 size_t bytes)
3388{
3389 struct stream_in *in = (struct stream_in *)stream;
3390 struct audio_device *adev = in->dev;
3391 ssize_t frames = -1;
3392 int ret = -1;
3393 int read_and_process_successful = false;
3394
3395 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003396
3397 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3398 lock_input_stream(in);
3399
Andreas Schneider3b643832017-01-31 11:48:22 +01003400#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003401 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003402 pid_t tid = gettid();
3403 int err;
3404
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003405 err = fast_set_affinity(tid);
3406 if (err < 0) {
3407 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3408 }
3409 in->is_fastcapture_affinity_set = true;
3410 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003411#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003412
3413 if (in->standby) {
3414 pthread_mutex_unlock(&in->lock);
3415 pthread_mutex_lock(&adev->lock_inputs);
3416 lock_input_stream(in);
3417 if (!in->standby) {
3418 pthread_mutex_unlock(&adev->lock_inputs);
3419 goto false_alarm;
3420 }
3421 pthread_mutex_lock(&adev->lock);
3422 ret = start_input_stream(in);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003423 if (ret == 0) {
3424 amplifier_input_stream_start(stream);
3425 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003426 pthread_mutex_unlock(&adev->lock);
3427 pthread_mutex_unlock(&adev->lock_inputs);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003428
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003429 if (ret != 0) {
3430 goto exit;
3431 }
3432 in->standby = 0;
3433 }
3434false_alarm:
3435
3436 if (!list_empty(&in->pcm_dev_list)) {
stenkinevgeniy44335362018-05-07 18:00:13 +00003437 /*
3438 * Read PCM and:
3439 * - resample if needed
3440 * - process if pre-processors are attached
3441 * - discard unwanted channels
3442 */
3443 frames = read_and_process_frames(in, buffer, frames_rq);
3444 if (frames >= 0)
3445 read_and_process_successful = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003446 }
3447
3448 /*
3449 * Instead of writing zeroes here, we could trust the hardware
3450 * to always provide zeroes when muted.
3451 */
3452 if (read_and_process_successful == true && adev->mic_mute)
3453 memset(buffer, 0, bytes);
3454
3455exit:
3456 pthread_mutex_unlock(&in->lock);
3457
3458 if (read_and_process_successful == false) {
3459 in_standby(&in->stream.common);
3460 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003461 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3462 clock_gettime(CLOCK_MONOTONIC, &t);
3463 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3464
3465 // we do a full sleep when exiting standby.
3466 const bool standby = in->last_read_time_us == 0;
3467 const int64_t elapsed_time_since_last_read = standby ?
3468 0 : now - in->last_read_time_us;
3469 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3470 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3471 if (sleep_time > 0) {
3472 usleep(sleep_time);
3473 } else {
3474 sleep_time = 0;
3475 }
3476 in->last_read_time_us = now + sleep_time;
3477 // last_read_time_us is an approximation of when the (simulated) alsa
3478 // buffer is drained by the read, and is empty.
3479 //
3480 // On the subsequent in_read(), we measure the elapsed time spent in
3481 // the recording thread. This is subtracted from the sleep estimate based on frames,
3482 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003483 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003484 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003485
3486 if (bytes > 0) {
3487 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3488 }
3489
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003490 return bytes;
3491}
3492
3493static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3494{
3495 (void)stream;
3496
3497 return 0;
3498}
3499
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003500static int in_get_capture_position(const struct audio_stream_in *stream,
3501 int64_t *frames, int64_t *time)
3502{
3503 if (stream == NULL || frames == NULL || time == NULL) {
3504 return -EINVAL;
3505 }
3506
3507 struct stream_in *in = (struct stream_in *)stream;
3508 struct pcm_device *pcm_device;
3509 int ret = -ENOSYS;
3510
3511 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3512 struct pcm_device, stream_list_node);
3513
3514 pthread_mutex_lock(&in->lock);
3515 if (pcm_device->pcm) {
3516 struct timespec timestamp;
3517 unsigned int avail;
3518 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3519 *frames = in->frames_read + avail;
3520 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3521 ret = 0;
3522 }
3523 }
3524
3525 pthread_mutex_unlock(&in->lock);
3526 return ret;
3527}
3528
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003529static int add_remove_audio_effect(const struct audio_stream *stream,
3530 effect_handle_t effect,
3531 bool enable)
3532{
3533 struct stream_in *in = (struct stream_in *)stream;
3534 struct audio_device *adev = in->dev;
3535 int status = 0;
3536 effect_descriptor_t desc;
3537#ifdef PREPROCESSING_ENABLED
3538 int i;
3539#endif
3540 status = (*effect)->get_descriptor(effect, &desc);
3541 if (status != 0)
3542 return status;
3543
3544 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3545
3546 pthread_mutex_lock(&adev->lock_inputs);
3547 lock_input_stream(in);
3548 pthread_mutex_lock(&in->dev->lock);
3549#ifndef PREPROCESSING_ENABLED
3550 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3551 in->enable_aec != enable &&
3552 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3553 in->enable_aec = enable;
3554 if (!in->standby)
3555 select_devices(in->dev, in->usecase);
3556 }
3557#else
3558 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3559 status = -ENOSYS;
3560 goto exit;
3561 }
3562 if ( enable == true ) {
3563 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3564 /* add the supported channel of the effect in the channel_configs */
3565 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3566 in->num_preprocessors ++;
3567 /* check compatibility between main channel supported and possible auxiliary channels */
3568 in_update_aux_channels(in, effect);//wesley crash
3569 in->aux_channels_changed = true;
3570 } else {
3571 /* if ( enable == false ) */
3572 if (in->num_preprocessors <= 0) {
3573 status = -ENOSYS;
3574 goto exit;
3575 }
3576 status = -EINVAL;
3577 for (i=0; i < in->num_preprocessors; i++) {
3578 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3579 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3580 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3581 in->preprocessors[i - 1].num_channel_configs =
3582 in->preprocessors[i].num_channel_configs;
3583 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3584 continue;
3585 }
3586 if ( in->preprocessors[i].effect_itfe == effect ) {
3587 ALOGV("add_remove_audio_effect found fx at index %d", i);
3588 free(in->preprocessors[i].channel_configs);
3589 status = 0;
3590 }
3591 }
3592 if (status != 0)
3593 goto exit;
3594 in->num_preprocessors--;
3595 /* if we remove one effect, at least the last proproc should be reset */
3596 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3597 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3598 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3599 in->aux_channels_changed = false;
3600 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3601 }
3602 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3603
3604 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3605 in->enable_aec = enable;
3606 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3607 if (!in->standby) {
3608 select_devices(in->dev, in->usecase);
3609 do_in_standby_l(in);
3610 }
3611 if (in->enable_aec == true) {
3612 in_configure_reverse(in);
3613 }
3614 }
3615exit:
3616#endif
3617 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3618 pthread_mutex_unlock(&in->dev->lock);
3619 pthread_mutex_unlock(&in->lock);
3620 pthread_mutex_unlock(&adev->lock_inputs);
3621 return status;
3622}
3623
3624static int in_add_audio_effect(const struct audio_stream *stream,
3625 effect_handle_t effect)
3626{
3627 ALOGV("%s: effect %p", __func__, effect);
3628 return add_remove_audio_effect(stream, effect, true);
3629}
3630
3631static int in_remove_audio_effect(const struct audio_stream *stream,
3632 effect_handle_t effect)
3633{
3634 ALOGV("%s: effect %p", __func__, effect);
3635 return add_remove_audio_effect(stream, effect, false);
3636}
3637
3638static int adev_open_output_stream(struct audio_hw_device *dev,
3639 audio_io_handle_t handle,
3640 audio_devices_t devices,
3641 audio_output_flags_t flags,
3642 struct audio_config *config,
3643 struct audio_stream_out **stream_out,
3644 const char *address __unused)
3645{
3646 struct audio_device *adev = (struct audio_device *)dev;
3647 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003648 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003649 struct pcm_device_profile *pcm_profile;
3650
3651 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3652 __func__, config->sample_rate, config->channel_mask, devices, flags);
3653 *stream_out = NULL;
3654 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003655 if (out == NULL) {
3656 ret = -ENOMEM;
3657 goto error_config;
3658 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003659
3660 if (devices == AUDIO_DEVICE_NONE)
3661 devices = AUDIO_DEVICE_OUT_SPEAKER;
3662
3663 out->flags = flags;
3664 out->devices = devices;
3665 out->dev = adev;
3666 out->format = config->format;
3667 out->sample_rate = config->sample_rate;
3668 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3669 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3670 out->handle = handle;
3671
3672 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3673 if (pcm_profile == NULL) {
3674 ret = -EINVAL;
3675 goto error_open;
3676 }
3677 out->config = pcm_profile->config;
3678
3679 /* Init use case and pcm_config */
3680 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3681 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3682 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3683 ALOGE("%s: Unsupported Offload information", __func__);
3684 ret = -EINVAL;
3685 goto error_open;
3686 }
3687 if (!is_supported_format(config->offload_info.format)) {
3688 ALOGE("%s: Unsupported audio format", __func__);
3689 ret = -EINVAL;
3690 goto error_open;
3691 }
3692
3693 out->compr_config.codec = (struct snd_codec *)
3694 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003695 if (out->compr_config.codec == NULL) {
3696 ret = -ENOMEM;
3697 goto error_open;
3698 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003699
3700 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3701 if (config->offload_info.channel_mask)
3702 out->channel_mask = config->offload_info.channel_mask;
3703 else if (config->channel_mask)
3704 out->channel_mask = config->channel_mask;
3705 out->format = config->offload_info.format;
3706 out->sample_rate = config->offload_info.sample_rate;
3707
3708 out->stream.set_callback = out_set_callback;
3709 out->stream.pause = out_pause;
3710 out->stream.resume = out_resume;
3711 out->stream.drain = out_drain;
3712 out->stream.flush = out_flush;
3713
3714 out->compr_config.codec->id =
3715 get_snd_codec_id(config->offload_info.format);
3716 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3717 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3718 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3719 out->compr_config.codec->bit_rate =
3720 config->offload_info.bit_rate;
3721 out->compr_config.codec->ch_in =
3722 audio_channel_count_from_out_mask(config->channel_mask);
3723 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3724
3725 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3726 out->non_blocking = 1;
3727
3728 out->send_new_metadata = 1;
3729 create_offload_callback_thread(out);
3730 out->offload_state = OFFLOAD_STATE_IDLE;
3731
3732 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3733 __func__, config->offload_info.version,
3734 config->offload_info.bit_rate);
3735 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3736 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003737 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003738 out->sample_rate = out->config.rate;
3739 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3740 } else {
3741 out->usecase = USECASE_AUDIO_PLAYBACK;
3742 out->sample_rate = out->config.rate;
3743 }
3744
3745 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3746 if (adev->primary_output == NULL)
3747 adev->primary_output = out;
3748 else {
3749 ALOGE("%s: Primary output is already opened", __func__);
3750 ret = -EEXIST;
3751 goto error_open;
3752 }
3753 }
3754
3755 /* Check if this usecase is already existing */
3756 pthread_mutex_lock(&adev->lock);
3757 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3758 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3759 pthread_mutex_unlock(&adev->lock);
3760 ret = -EEXIST;
3761 goto error_open;
3762 }
3763 pthread_mutex_unlock(&adev->lock);
3764
3765 out->stream.common.get_sample_rate = out_get_sample_rate;
3766 out->stream.common.set_sample_rate = out_set_sample_rate;
3767 out->stream.common.get_buffer_size = out_get_buffer_size;
3768 out->stream.common.get_channels = out_get_channels;
3769 out->stream.common.get_format = out_get_format;
3770 out->stream.common.set_format = out_set_format;
3771 out->stream.common.standby = out_standby;
3772 out->stream.common.dump = out_dump;
3773 out->stream.common.set_parameters = out_set_parameters;
3774 out->stream.common.get_parameters = out_get_parameters;
3775 out->stream.common.add_audio_effect = out_add_audio_effect;
3776 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3777 out->stream.get_latency = out_get_latency;
3778 out->stream.set_volume = out_set_volume;
3779 out->stream.write = out_write;
3780 out->stream.get_render_position = out_get_render_position;
3781 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3782 out->stream.get_presentation_position = out_get_presentation_position;
3783
3784 out->standby = 1;
3785 /* out->muted = false; by calloc() */
3786 /* out->written = 0; by calloc() */
3787
3788 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3789 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3790 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3791
3792 config->format = out->stream.common.get_format(&out->stream.common);
3793 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3794 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3795
3796 out->is_fastmixer_affinity_set = false;
3797
3798 *stream_out = &out->stream;
3799 ALOGV("%s: exit", __func__);
3800 return 0;
3801
3802error_open:
3803 free(out);
3804 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003805error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003806 ALOGV("%s: exit: ret %d", __func__, ret);
3807 return ret;
3808}
3809
3810static void adev_close_output_stream(struct audio_hw_device *dev,
3811 struct audio_stream_out *stream)
3812{
3813 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003814 (void)dev;
3815
3816 ALOGV("%s: enter", __func__);
3817 out_standby(&stream->common);
3818 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3819 destroy_offload_callback_thread(out);
3820
3821 if (out->compr_config.codec != NULL)
3822 free(out->compr_config.codec);
3823 }
3824 pthread_cond_destroy(&out->cond);
3825 pthread_mutex_destroy(&out->lock);
3826 free(stream);
3827 ALOGV("%s: exit", __func__);
3828}
3829
3830static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3831{
3832 struct audio_device *adev = (struct audio_device *)dev;
3833 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003834 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003835#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003836 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003837#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003838 int ret;
3839
3840 ALOGV("%s: enter: %s", __func__, kvpairs);
3841
3842 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003843
Andreas Schneider05bc1882017-02-09 14:03:11 +01003844 /******************************************************
3845 *** BT SCO
3846 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003847 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3848 if (ret >= 0) {
3849 /* When set to false, HAL should disable EC and NS
3850 * But it is currently not supported.
3851 */
3852 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003853 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003854 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003855 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003856 }
3857
Andreas Schneider05bc1882017-02-09 14:03:11 +01003858 ret = str_parms_get_str(parms,
3859 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3860 value,
3861 sizeof(value));
3862 if (ret >= 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01003863 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3864 adev->voice.bluetooth_wb = true;
Andreas Schneider05bc1882017-02-09 14:03:11 +01003865 } else {
3866 adev->voice.bluetooth_wb = false;
3867 }
3868 }
3869
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003870 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3871 if (ret >= 0) {
3872 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3873 adev->screen_off = false;
3874 else
3875 adev->screen_off = true;
3876 }
3877
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003878#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003879 ret = str_parms_get_int(parms, "rotation", &val);
3880 if (ret >= 0) {
3881 bool reverse_speakers = false;
3882 switch(val) {
3883 /* FIXME: note that the code below assumes that the speakers are in the correct placement
3884 relative to the user when the device is rotated 90deg from its default rotation. This
3885 assumption is device-specific, not platform-specific like this code. */
3886 case 270:
3887 reverse_speakers = true;
3888 break;
3889 case 0:
3890 case 90:
3891 case 180:
3892 break;
3893 default:
3894 ALOGE("%s: unexpected rotation of %d", __func__, val);
3895 }
3896 pthread_mutex_lock(&adev->lock);
3897 if (adev->speaker_lr_swap != reverse_speakers) {
3898 adev->speaker_lr_swap = reverse_speakers;
3899 /* only update the selected device if there is active pcm playback */
3900 struct audio_usecase *usecase;
3901 struct listnode *node;
3902 list_for_each(node, &adev->usecase_list) {
3903 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
3904 if (usecase->type == PCM_PLAYBACK) {
3905 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003906 break;
3907 }
3908 }
3909 }
3910 pthread_mutex_unlock(&adev->lock);
3911 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003912#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003913
3914 str_parms_destroy(parms);
3915
3916 if (ret > 0)
3917 ret = 0;
3918
3919 ALOGV("%s: exit with code(%d)", __func__, ret);
3920 return ret;
3921}
3922
3923static char* adev_get_parameters(const struct audio_hw_device *dev,
3924 const char *keys)
3925{
3926 (void)dev;
3927 (void)keys;
3928
3929 return strdup("");
3930}
3931
3932static int adev_init_check(const struct audio_hw_device *dev)
3933{
3934 (void)dev;
3935
3936 return 0;
3937}
3938
3939static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3940{
3941 int ret = 0;
3942 struct audio_device *adev = (struct audio_device *)dev;
3943 pthread_mutex_lock(&adev->lock);
3944 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003945 adev->voice.volume = volume;
3946 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003947 pthread_mutex_unlock(&adev->lock);
3948 return ret;
3949}
3950
3951static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
3952{
3953 (void)dev;
3954 (void)volume;
3955
3956 return -ENOSYS;
3957}
3958
3959static int adev_get_master_volume(struct audio_hw_device *dev,
3960 float *volume)
3961{
3962 (void)dev;
3963 (void)volume;
3964
3965 return -ENOSYS;
3966}
3967
3968static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
3969{
3970 (void)dev;
3971 (void)muted;
3972
3973 return -ENOSYS;
3974}
3975
3976static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
3977{
3978 (void)dev;
3979 (void)muted;
3980
3981 return -ENOSYS;
3982}
3983
3984static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3985{
3986 struct audio_device *adev = (struct audio_device *)dev;
3987
3988 pthread_mutex_lock(&adev->lock);
3989 if (adev->mode != mode) {
3990 ALOGI("%s mode = %d", __func__, mode);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003991 if (amplifier_set_mode(mode) != 0) {
3992 ALOGE("Failed setting amplifier mode");
3993 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003994 adev->mode = mode;
Christopher N. Hesse6c0020c2017-11-17 20:41:11 +01003995
3996 if ((mode == AUDIO_MODE_NORMAL) && adev->voice.in_call) {
3997 stop_voice_call(adev);
3998 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003999 }
4000 pthread_mutex_unlock(&adev->lock);
4001 return 0;
4002}
4003
4004static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4005{
4006 struct audio_device *adev = (struct audio_device *)dev;
4007 int err = 0;
4008
4009 pthread_mutex_lock(&adev->lock);
4010 adev->mic_mute = state;
4011
4012 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004013 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004014 }
4015
4016 pthread_mutex_unlock(&adev->lock);
4017 return err;
4018}
4019
4020static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4021{
4022 struct audio_device *adev = (struct audio_device *)dev;
4023
4024 *state = adev->mic_mute;
4025
4026 return 0;
4027}
4028
4029static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4030 const struct audio_config *config)
4031{
4032 (void)dev;
4033
4034 /* NOTE: we default to built in mic which may cause a mismatch between what we
4035 * report here and the actual buffer size
4036 */
4037 return get_input_buffer_size(config->sample_rate,
4038 config->format,
4039 audio_channel_count_from_in_mask(config->channel_mask),
4040 PCM_CAPTURE /* usecase_type */,
4041 AUDIO_DEVICE_IN_BUILTIN_MIC);
4042}
4043
4044static int adev_open_input_stream(struct audio_hw_device *dev,
4045 audio_io_handle_t handle __unused,
4046 audio_devices_t devices,
4047 struct audio_config *config,
4048 struct audio_stream_in **stream_in,
4049 audio_input_flags_t flags,
4050 const char *address __unused,
4051 audio_source_t source)
4052{
4053 struct audio_device *adev = (struct audio_device *)dev;
4054 struct stream_in *in;
4055 struct pcm_device_profile *pcm_profile;
4056
4057 ALOGV("%s: enter", __func__);
4058
4059 *stream_in = NULL;
4060 if (check_input_parameters(config->sample_rate, config->format,
4061 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4062 return -EINVAL;
4063
stenkinevgeniy44335362018-05-07 18:00:13 +00004064 usecase_type_t usecase_type = flags & AUDIO_INPUT_FLAG_FAST ?
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004065 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4066 pcm_profile = get_pcm_device(usecase_type, devices);
4067 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4068 // a low latency profile may not exist for that device, fall back
4069 // to regular capture. the MixerThread automatically changes
4070 // to non-fast capture based on the buffer size.
4071 flags &= ~AUDIO_INPUT_FLAG_FAST;
4072 usecase_type = PCM_CAPTURE;
4073 pcm_profile = get_pcm_device(usecase_type, devices);
4074 }
4075 if (pcm_profile == NULL)
4076 return -EINVAL;
4077
4078 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004079 if (in == NULL) {
4080 return -ENOMEM;
4081 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004082
4083 in->stream.common.get_sample_rate = in_get_sample_rate;
4084 in->stream.common.set_sample_rate = in_set_sample_rate;
4085 in->stream.common.get_buffer_size = in_get_buffer_size;
4086 in->stream.common.get_channels = in_get_channels;
4087 in->stream.common.get_format = in_get_format;
4088 in->stream.common.set_format = in_set_format;
4089 in->stream.common.standby = in_standby;
4090 in->stream.common.dump = in_dump;
4091 in->stream.common.set_parameters = in_set_parameters;
4092 in->stream.common.get_parameters = in_get_parameters;
4093 in->stream.common.add_audio_effect = in_add_audio_effect;
4094 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4095 in->stream.set_gain = in_set_gain;
4096 in->stream.read = in_read;
4097 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004098 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004099
4100 in->devices = devices;
4101 in->source = source;
4102 in->dev = adev;
4103 in->standby = 1;
4104 in->main_channels = config->channel_mask;
4105 in->requested_rate = config->sample_rate;
4106 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4107 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4108 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004109 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004110 /* HW codec is limited to default channels. No need to update with
4111 * requested channels */
4112 in->config = pcm_profile->config;
4113
4114 /* Update config params with the requested sample rate and channels */
stenkinevgeniy44335362018-05-07 18:00:13 +00004115 in->usecase = USECASE_AUDIO_CAPTURE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004116 in->usecase_type = usecase_type;
4117
4118 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4119 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4120
4121 in->is_fastcapture_affinity_set = false;
4122
4123 *stream_in = &in->stream;
4124 ALOGV("%s: exit", __func__);
4125 return 0;
4126}
4127
4128static void adev_close_input_stream(struct audio_hw_device *dev,
4129 struct audio_stream_in *stream)
4130{
4131 struct audio_device *adev = (struct audio_device *)dev;
4132 struct stream_in *in = (struct stream_in*)stream;
4133 ALOGV("%s", __func__);
4134
4135 /* prevent concurrent out_set_parameters, or out_write from standby */
4136 pthread_mutex_lock(&adev->lock_inputs);
4137
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004138 if (in->read_buf) {
4139 free(in->read_buf);
4140 in->read_buf = NULL;
4141 }
4142
4143 if (in->resampler) {
4144 release_resampler(in->resampler);
4145 in->resampler = NULL;
4146 }
4147
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004148#ifdef PREPROCESSING_ENABLED
4149 int i;
4150
4151 for (i=0; i<in->num_preprocessors; i++) {
4152 free(in->preprocessors[i].channel_configs);
4153 }
4154
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004155 if (in->proc_buf_in) {
4156 free(in->proc_buf_in);
4157 in->proc_buf_in = NULL;
4158 }
4159
4160 if (in->proc_buf_out) {
4161 free(in->proc_buf_out);
4162 in->proc_buf_out = NULL;
4163 }
4164
4165 if (in->ref_buf) {
4166 free(in->ref_buf);
4167 in->ref_buf = NULL;
4168 }
4169
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004170#endif
4171
4172 in_standby_l(in);
4173 free(stream);
4174
4175 pthread_mutex_unlock(&adev->lock_inputs);
4176
4177 return;
4178}
4179
4180static int adev_dump(const audio_hw_device_t *device, int fd)
4181{
4182 (void)device;
4183 (void)fd;
4184
4185 return 0;
4186}
4187
4188static int adev_close(hw_device_t *device)
4189{
4190 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004191 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004192 audio_device_ref_count--;
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004193 if (audio_device_ref_count == 0) {
4194 if (amplifier_close() != 0) {
4195 ALOGE("Amplifier close failed");
4196 }
4197 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004198 free(adev->snd_dev_ref_cnt);
4199 free_mixer_list(adev);
4200 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004201
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004202 adev = NULL;
4203
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004204 return 0;
4205}
4206
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004207/* This returns true if the input parameter looks at all plausible as a low latency period size,
4208 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4209 * just that it _might_ work.
4210 */
4211static bool period_size_is_plausible_for_low_latency(int period_size)
4212{
4213 switch (period_size) {
4214 case 64:
4215 case 96:
4216 case 128:
4217 case 192:
4218 case 256:
4219 return true;
4220 default:
4221 return false;
4222 }
4223}
4224
4225static int adev_open(const hw_module_t *module, const char *name,
4226 hw_device_t **device)
4227{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004228 ALOGV("%s: enter", __func__);
4229 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4230
Andreas Schneider56204f62017-01-31 08:17:32 +01004231 *device = NULL;
4232
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004233 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004234 if (adev == NULL) {
4235 return -ENOMEM;
4236 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004237
4238 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4239 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4240 adev->device.common.module = (struct hw_module_t *)module;
4241 adev->device.common.close = adev_close;
4242
4243 adev->device.init_check = adev_init_check;
4244 adev->device.set_voice_volume = adev_set_voice_volume;
4245 adev->device.set_master_volume = adev_set_master_volume;
4246 adev->device.get_master_volume = adev_get_master_volume;
4247 adev->device.set_master_mute = adev_set_master_mute;
4248 adev->device.get_master_mute = adev_get_master_mute;
4249 adev->device.set_mode = adev_set_mode;
4250 adev->device.set_mic_mute = adev_set_mic_mute;
4251 adev->device.get_mic_mute = adev_get_mic_mute;
4252 adev->device.set_parameters = adev_set_parameters;
4253 adev->device.get_parameters = adev_get_parameters;
4254 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4255 adev->device.open_output_stream = adev_open_output_stream;
4256 adev->device.close_output_stream = adev_close_output_stream;
4257 adev->device.open_input_stream = adev_open_input_stream;
4258 adev->device.close_input_stream = adev_close_input_stream;
4259 adev->device.dump = adev_dump;
4260
4261 /* Set the default route before the PCM stream is opened */
4262 adev->mode = AUDIO_MODE_NORMAL;
4263 adev->active_input = NULL;
4264 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004265
4266 adev->voice.volume = 1.0f;
4267 adev->voice.bluetooth_nrec = true;
4268 adev->voice.in_call = false;
Christopher N. Hessee4a1c592018-01-16 18:33:38 +01004269 adev->voice.bluetooth_wb = false;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004270
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004271 /* adev->cur_hdmi_channels = 0; by calloc() */
4272 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004273 if (adev->snd_dev_ref_cnt == NULL) {
4274 free(adev);
4275 return -ENOMEM;
4276 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004277
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004278 adev->ns_in_voice_rec = false;
4279
4280 list_init(&adev->usecase_list);
4281
4282 if (mixer_init(adev) != 0) {
4283 free(adev->snd_dev_ref_cnt);
4284 free(adev);
4285 ALOGE("%s: Failed to init, aborting.", __func__);
4286 *device = NULL;
4287 return -EINVAL;
4288 }
4289
4290 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4291 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4292 if (adev->offload_fx_lib == NULL) {
4293 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4294 } else {
4295 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4296 adev->offload_fx_start_output =
4297 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4298 "visualizer_hal_start_output");
4299 adev->offload_fx_stop_output =
4300 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4301 "visualizer_hal_stop_output");
4302 }
4303 }
4304
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004305 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004306 if (adev->voice.session == NULL) {
4307 ALOGE("%s: Failed to initialize voice session data", __func__);
4308
4309 free(adev->snd_dev_ref_cnt);
4310 free(adev);
4311
4312 *device = NULL;
4313 return -EINVAL;
4314 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004315
Christopher N. Hessec487bbe2018-07-12 13:51:43 +02004316 if (amplifier_open() != -ENOENT) {
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004317 ALOGE("Amplifier initialization failed");
4318 }
4319
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004320 *device = &adev->device.common;
4321
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004322 audio_device_ref_count++;
4323
4324 char value[PROPERTY_VALUE_MAX];
4325 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4326 int trial = atoi(value);
4327 if (period_size_is_plausible_for_low_latency(trial)) {
4328
4329 pcm_device_playback.config.period_size = trial;
4330 pcm_device_playback.config.start_threshold =
4331 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4332 pcm_device_playback.config.stop_threshold =
4333 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4334
4335 pcm_device_capture_low_latency.config.period_size = trial;
4336 }
4337 }
4338
4339 ALOGV("%s: exit", __func__);
4340 return 0;
4341}
4342
4343static struct hw_module_methods_t hal_module_methods = {
4344 .open = adev_open,
4345};
4346
4347struct audio_module HAL_MODULE_INFO_SYM = {
4348 .common = {
4349 .tag = HARDWARE_MODULE_TAG,
4350 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4351 .hal_api_version = HARDWARE_HAL_API_VERSION,
4352 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004353 .name = "Samsung Audio HAL",
4354 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004355 .methods = &hal_module_methods,
4356 },
4357};