blob: bd156343162eb52870bf6822798ebd66708f7a91 [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>
Christopher N. Hesse297a6362017-01-28 12:40:45 +01005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#define LOG_TAG "audio_hw_primary"
20/*#define LOG_NDEBUG 0*/
21/*#define VERY_VERY_VERBOSE_LOGGING*/
22#ifdef VERY_VERY_VERBOSE_LOGGING
23#define ALOGVV ALOGV
24#else
25#define ALOGVV(a...) do { } while(0)
26#endif
27
28#define _GNU_SOURCE
29#include <errno.h>
30#include <pthread.h>
31#include <stdint.h>
32#include <sys/time.h>
33#include <stdlib.h>
34#include <math.h>
35#include <dlfcn.h>
Christopher N. Hesse297a6362017-01-28 12:40:45 +010036
37#include <cutils/log.h>
38#include <cutils/str_parms.h>
39#include <cutils/atomic.h>
40#include <cutils/sched_policy.h>
41#include <cutils/properties.h>
42
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010043#include <samsung_audio.h>
44
Christopher N. Hesse297a6362017-01-28 12:40:45 +010045#include <hardware/audio_effect.h>
46#include <system/thread_defs.h>
47#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
49#include "audio_hw.h"
Christopher N. Hesse757ac412017-01-28 14:42:48 +010050#include "compress_offload.h"
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +010051#include "voice.h"
Christopher N. Hesse297a6362017-01-28 12:40:45 +010052
53#include "sound/compress_params.h"
54
Christopher N. Hesse297a6362017-01-28 12:40:45 +010055
56/* TODO: the following PCM device profiles could be read from a config file */
57static struct pcm_device_profile pcm_device_playback = {
58 .config = {
59 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
60 .rate = PLAYBACK_DEFAULT_SAMPLING_RATE,
61 .period_size = PLAYBACK_PERIOD_SIZE,
62 .period_count = PLAYBACK_PERIOD_COUNT,
63 .format = PCM_FORMAT_S16_LE,
64 .start_threshold = PLAYBACK_START_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
65 .stop_threshold = PLAYBACK_STOP_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
66 .silence_threshold = 0,
67 .silence_size = UINT_MAX,
68 .avail_min = PLAYBACK_AVAILABLE_MIN,
69 },
70 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010071 .id = SOUND_PLAYBACK_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010072 .type = PCM_PLAYBACK,
73 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
Fevax86ac2342017-02-08 09:52:12 +010074 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010075};
76
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010077static struct pcm_device_profile pcm_device_deep_buffer = {
78 .config = {
79 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
80 .rate = DEEP_BUFFER_OUTPUT_SAMPLING_RATE,
81 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
82 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
83 .format = PCM_FORMAT_S16_LE,
84 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
85 .stop_threshold = INT_MAX,
86 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
87 },
88 .card = SOUND_CARD,
89 .id = SOUND_DEEP_BUFFER_DEVICE,
90 .type = PCM_PLAYBACK,
91 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
Fevax86ac2342017-02-08 09:52:12 +010092 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010093};
94
Christopher N. Hesse297a6362017-01-28 12:40:45 +010095static struct pcm_device_profile pcm_device_capture = {
96 .config = {
97 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
98 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
99 .period_size = CAPTURE_PERIOD_SIZE,
100 .period_count = CAPTURE_PERIOD_COUNT,
101 .format = PCM_FORMAT_S16_LE,
102 .start_threshold = CAPTURE_START_THRESHOLD,
103 .stop_threshold = 0,
104 .silence_threshold = 0,
105 .avail_min = 0,
106 },
107 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100108 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100109 .type = PCM_CAPTURE,
110 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
111};
112
113static struct pcm_device_profile pcm_device_capture_low_latency = {
114 .config = {
115 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
116 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
117 .period_size = CAPTURE_PERIOD_SIZE_LOW_LATENCY,
118 .period_count = CAPTURE_PERIOD_COUNT_LOW_LATENCY,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = CAPTURE_START_THRESHOLD,
121 .stop_threshold = 0,
122 .silence_threshold = 0,
123 .avail_min = 0,
124 },
125 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100126 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100127 .type = PCM_CAPTURE_LOW_LATENCY,
128 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
129};
130
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100131#ifdef SOUND_CAPTURE_LOOPBACK_AEC_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100132static struct pcm_device_profile pcm_device_capture_loopback_aec = {
133 .config = {
134 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
135 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
136 .period_size = CAPTURE_PERIOD_SIZE,
137 .period_count = CAPTURE_PERIOD_COUNT,
138 .format = PCM_FORMAT_S16_LE,
139 .start_threshold = CAPTURE_START_THRESHOLD,
140 .stop_threshold = 0,
141 .silence_threshold = 0,
142 .avail_min = 0,
143 },
144 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100145 .id = SOUND_CAPTURE_LOOPBACK_AEC_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100146 .type = PCM_CAPTURE,
147 .devices = SND_DEVICE_IN_LOOPBACK_AEC,
148};
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100149#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100150
151static struct pcm_device_profile pcm_device_playback_sco = {
152 .config = {
153 .channels = SCO_DEFAULT_CHANNEL_COUNT,
154 .rate = SCO_DEFAULT_SAMPLING_RATE,
155 .period_size = SCO_PERIOD_SIZE,
156 .period_count = SCO_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158 .start_threshold = SCO_START_THRESHOLD,
159 .stop_threshold = SCO_STOP_THRESHOLD,
160 .silence_threshold = 0,
161 .avail_min = SCO_AVAILABLE_MIN,
162 },
163 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100164 .id = SOUND_PLAYBACK_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100165 .type = PCM_PLAYBACK,
166 .devices =
167 AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
168 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
169};
170
171static struct pcm_device_profile pcm_device_capture_sco = {
172 .config = {
173 .channels = SCO_DEFAULT_CHANNEL_COUNT,
174 .rate = SCO_DEFAULT_SAMPLING_RATE,
175 .period_size = SCO_PERIOD_SIZE,
176 .period_count = SCO_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = CAPTURE_START_THRESHOLD,
179 .stop_threshold = 0,
180 .silence_threshold = 0,
181 .avail_min = 0,
182 },
183 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100184 .id = SOUND_CAPTURE_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100185 .type = PCM_CAPTURE,
186 .devices = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
187};
188
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100189#ifdef SOUND_CAPTURE_HOTWORD_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100190static struct pcm_device_profile pcm_device_hotword_streaming = {
191 .config = {
192 .channels = 1,
193 .rate = 16000,
194 .period_size = CAPTURE_PERIOD_SIZE,
195 .period_count = CAPTURE_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = CAPTURE_START_THRESHOLD,
198 .stop_threshold = 0,
199 .silence_threshold = 0,
200 .avail_min = 0,
201 },
202 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100203 .id = SOUND_CAPTURE_HOTWORD_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100204 .type = PCM_HOTWORD_STREAMING,
205 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC
206};
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100207#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100208
209static struct pcm_device_profile * const pcm_devices[] = {
210 &pcm_device_playback,
211 &pcm_device_capture,
212 &pcm_device_capture_low_latency,
213 &pcm_device_playback_sco,
214 &pcm_device_capture_sco,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100215#ifdef SOUND_CAPTURE_LOOPBACK_AEC_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100216 &pcm_device_capture_loopback_aec,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100217#endif
218#ifdef SOUND_CAPTURE_HOTWORD_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100219 &pcm_device_hotword_streaming,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100220#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100221 NULL,
222};
223
224static const char * const use_case_table[AUDIO_USECASE_MAX] = {
225 [USECASE_AUDIO_PLAYBACK] = "playback",
226 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "playback multi-channel",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Andreas Schneiderdf6fc8a2017-02-14 11:38:41 +0100228 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "playback deep-buffer",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100229 [USECASE_AUDIO_CAPTURE] = "capture",
230 [USECASE_AUDIO_CAPTURE_HOTWORD] = "capture-hotword",
231 [USECASE_VOICE_CALL] = "voice-call",
232};
233
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100234#define STRING_TO_ENUM(string) { #string, string }
235
236static unsigned int audio_device_ref_count;
237
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100238struct string_to_enum {
239 const char *name;
240 uint32_t value;
241};
242
243static const struct string_to_enum out_channels_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
245 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
246 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
247};
248
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200249static struct audio_device *adev = NULL;
250
251static amplifier_device_t * get_amplifier_device(void)
252{
253 if (adev)
254 return adev->amp;
255
256 return NULL;
257}
258
259static int amplifier_open(void)
260{
261 int rc;
262 amplifier_module_t *module;
263
264 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
265 (const hw_module_t **) &module);
266 if (rc) {
267 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
268 __func__, strerror(-rc));
269 return -ENODEV;
270 }
271
272 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
273 if (rc) {
274 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
275 __func__, strerror(-rc));
276 return -ENODEV;
277 }
278
279 return 0;
280}
281
282static int amplifier_set_input_devices(uint32_t devices)
283{
284 amplifier_device_t *amp = get_amplifier_device();
285 if (amp && amp->set_input_devices)
286 return amp->set_input_devices(amp, devices);
287
288 return 0;
289}
290
291static int amplifier_set_output_devices(uint32_t devices)
292{
293 amplifier_device_t *amp = get_amplifier_device();
294 if (amp && amp->set_output_devices)
295 return amp->set_output_devices(amp, devices);
296
297 return 0;
298}
299
300static int amplifier_enable_devices(uint32_t devices, bool enable)
301{
302 amplifier_device_t *amp = get_amplifier_device();
303 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
304 devices < SND_DEVICE_OUT_END;
305
306 if (amp && amp->enable_output_devices && is_output)
307 return amp->enable_output_devices(amp, devices, enable);
308
309 if (amp && amp->enable_input_devices && !is_output)
310 return amp->enable_input_devices(amp, devices, enable);
311
312 return 0;
313}
314
315static int amplifier_set_mode(audio_mode_t mode)
316{
317 amplifier_device_t *amp = get_amplifier_device();
318 if (amp && amp->set_mode)
319 return amp->set_mode(amp, mode);
320
321 return 0;
322}
323
324static int amplifier_output_stream_start(struct audio_stream_out *stream,
325 bool offload)
326{
327 amplifier_device_t *amp = get_amplifier_device();
328 if (amp && amp->output_stream_start)
329 return amp->output_stream_start(amp, stream, offload);
330
331 return 0;
332}
333
334static int amplifier_input_stream_start(struct audio_stream_in *stream)
335{
336 amplifier_device_t *amp = get_amplifier_device();
337 if (amp && amp->input_stream_start)
338 return amp->input_stream_start(amp, stream);
339
340 return 0;
341}
342
343static int amplifier_output_stream_standby(struct audio_stream_out *stream)
344{
345 amplifier_device_t *amp = get_amplifier_device();
346 if (amp && amp->output_stream_standby)
347 return amp->output_stream_standby(amp, stream);
348
349 return 0;
350}
351
352static int amplifier_input_stream_standby(struct audio_stream_in *stream)
353{
354 amplifier_device_t *amp = get_amplifier_device();
355 if (amp && amp->input_stream_standby)
356 return amp->input_stream_standby(amp, stream);
357
358 return 0;
359}
360
361static int amplifier_set_parameters(struct str_parms *parms)
362{
363 amplifier_device_t *amp = get_amplifier_device();
364 if (amp && amp->set_parameters)
365 return amp->set_parameters(amp, parms);
366
367 return 0;
368}
369
370static int amplifier_close(void)
371{
372 amplifier_device_t *amp = get_amplifier_device();
373 if (amp)
374 amplifier_device_close(amp);
375
376 return 0;
377}
378
Andreas Schneider759368f2017-02-02 16:11:14 +0100379struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
380 struct timespec ret;
381 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100382
383 if (time0.tv_nsec > time1.tv_nsec) {
384 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
385 time0.tv_nsec -= (long int) (1E9 * xsec);
386 time0.tv_sec += xsec;
387 }
388
389 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
390 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
391 time0.tv_nsec += (long int) (1E9 * xsec);
392 time0.tv_sec -= xsec;
393 }
394
Paul Keithf114e2e2017-02-14 20:41:33 -0600395 ret.tv_sec = labs(time1.tv_sec - time0.tv_sec);
396 ret.tv_nsec = labs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100397
398 return ret;
399}
400
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100401static bool is_supported_format(audio_format_t format)
402{
403 if (format == AUDIO_FORMAT_MP3 ||
404 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
405 return true;
406
407 return false;
408}
409
410static int get_snd_codec_id(audio_format_t format)
411{
412 int id = 0;
413
414 switch (format & AUDIO_FORMAT_MAIN_MASK) {
415 case AUDIO_FORMAT_MP3:
416 id = SND_AUDIOCODEC_MP3;
417 break;
418 case AUDIO_FORMAT_AAC:
419 id = SND_AUDIOCODEC_AAC;
420 break;
421 default:
422 ALOGE("%s: Unsupported audio format", __func__);
423 }
424
425 return id;
426}
427
428/* Array to store sound devices */
429static const char * const device_table[SND_DEVICE_MAX] = {
430 [SND_DEVICE_NONE] = "none",
431 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100432 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100433 [SND_DEVICE_OUT_SPEAKER] = "speaker",
434 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
435 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100436 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100437 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100438 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100439 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100440 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100441 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100442 [SND_DEVICE_OUT_VOICE_BT_SCO] = "voice-bt-sco-headset",
443 [SND_DEVICE_OUT_VOICE_BT_SCO_WB] = "voice-bt-sco-headset-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100444 [SND_DEVICE_OUT_HDMI] = "hdmi",
445 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
446 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100447
448 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100449 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100450 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
451 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100452 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100453 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
454 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100455 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
456 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100457 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100458 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100459 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100460 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100461 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100462 [SND_DEVICE_IN_VOICE_BT_SCO_MIC] = "voice-bt-sco-mic",
463 [SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB] = "voice-bt-sco-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100464 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
465 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
466 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100467 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
468 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100469 [SND_DEVICE_IN_LOOPBACK_AEC] = "loopback-aec",
470};
471
472static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
473{
474 struct mixer_card *mixer_card;
475 struct listnode *node;
476
477 list_for_each(node, &adev->mixer_list) {
478 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
479 if (mixer_card->card == card)
480 return mixer_card;
481 }
482 return NULL;
483}
484
485static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
486{
487 struct mixer_card *mixer_card;
488 struct listnode *node;
489
490 list_for_each(node, &usecase->mixer_list) {
491 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
492 if (mixer_card->card == card)
493 return mixer_card;
494 }
495 return NULL;
496}
497
498static void free_mixer_list(struct audio_device *adev)
499{
500 struct mixer_card *mixer_card;
501 struct listnode *node;
502 struct listnode *next;
503
504 list_for_each_safe(node, next, &adev->mixer_list) {
505 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
506 list_remove(node);
507 audio_route_free(mixer_card->audio_route);
508 free(mixer_card);
509 }
510}
511
512static int mixer_init(struct audio_device *adev)
513{
514 int i;
515 int card;
516 int retry_num;
517 struct mixer *mixer;
518 struct audio_route *audio_route;
519 char mixer_path[PATH_MAX];
520 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100521 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100522
523 list_init(&adev->mixer_list);
524
525 for (i = 0; pcm_devices[i] != NULL; i++) {
526 card = pcm_devices[i]->card;
527 if (adev_get_mixer_for_card(adev, card) == NULL) {
528 retry_num = 0;
529 do {
530 mixer = mixer_open(card);
531 if (mixer == NULL) {
532 if (++retry_num > RETRY_NUMBER) {
533 ALOGE("%s unable to open the mixer for--card %d, aborting.",
534 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100535 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100536 goto error;
537 }
538 usleep(RETRY_US);
539 }
540 } while (mixer == NULL);
541
542 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100543 if (access(mixer_path, F_OK) == -1) {
544 ALOGE("%s: Failed to load mixer paths from %s, your system is going to crash",
545 __func__, mixer_path);
546 }
547
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100548 audio_route = audio_route_init(card, mixer_path);
549 if (!audio_route) {
550 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
551 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100552 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100553 goto error;
554 }
555 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100556 if (mixer_card == NULL) {
557 ret = -ENOMEM;
558 goto error;
559 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100560 mixer_card->card = card;
561 mixer_card->mixer = mixer;
562 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100563
564 /* Do not sleep on first enable_snd_device() */
565 mixer_card->dsp_poweroff_time.tv_sec = 1;
566 mixer_card->dsp_poweroff_time.tv_nsec = 0;
567
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100568 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
569 }
570 }
571
572 return 0;
573
574error:
575 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100576 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100577}
578
579static const char *get_snd_device_name(snd_device_t snd_device)
580{
581 const char *name = NULL;
582
Andreas Schneideradb788d2017-02-13 15:19:36 +0100583 if (snd_device == SND_DEVICE_NONE ||
Andreas Schneiderdde54c02017-02-15 14:10:58 +0100584 (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100585 name = device_table[snd_device];
586
587 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
588
589 return name;
590}
591
592static const char *get_snd_device_display_name(snd_device_t snd_device)
593{
594 const char *name = get_snd_device_name(snd_device);
595
596 if (name == NULL)
597 name = "SND DEVICE NOT FOUND";
598
599 return name;
600}
601
602static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
603{
604 int i;
605
606 devices &= ~AUDIO_DEVICE_BIT_IN;
607 for (i = 0; pcm_devices[i] != NULL; i++) {
608 if ((pcm_devices[i]->type == uc_type) &&
609 (devices & pcm_devices[i]->devices))
610 break;
611 }
612 return pcm_devices[i];
613}
614
615static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
616 audio_usecase_t uc_id)
617{
618 struct audio_usecase *usecase;
619 struct listnode *node;
620
621 list_for_each(node, &adev->usecase_list) {
622 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
623 if (usecase->id == uc_id)
624 return usecase;
625 }
626 return NULL;
627}
628
629static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
630 usecase_type_t type)
631{
632 struct audio_usecase *usecase;
633 struct listnode *node;
634
635 list_for_each(node, &adev->usecase_list) {
636 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
637 if (usecase->type & type)
638 return usecase;
639 }
640 return NULL;
641}
642
643/* always called with adev lock held */
644static int set_voice_volume_l(struct audio_device *adev, float volume)
645{
646 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100647
648 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100649 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100650 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100651
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100652 return err;
653}
654
655
656static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
657{
658
659 audio_mode_t mode = adev->mode;
660 snd_device_t snd_device = SND_DEVICE_NONE;
661
662 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
663 if (devices == AUDIO_DEVICE_NONE ||
664 devices & AUDIO_DEVICE_BIT_IN) {
665 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
666 goto exit;
667 }
668
669 if (mode == AUDIO_MODE_IN_CALL) {
670 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
671 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100672 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Fevax51bd12c2017-03-15 10:56:39 -0300673 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100674 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100675 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
676 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
677 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100678 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100679 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100680
681 if (voice_session_uses_wideband(adev->voice.session)) {
682 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
683 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
684 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300685 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100686 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO_WB;
Andreas Schneider59486fa2017-02-06 09:16:39 +0100687 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
688 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
689 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
690 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
691 }
692 }
693
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100694 if (snd_device != SND_DEVICE_NONE) {
695 goto exit;
696 }
697 }
698
699 if (popcount(devices) == 2) {
700 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
701 AUDIO_DEVICE_OUT_SPEAKER)) {
702 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
703 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
704 AUDIO_DEVICE_OUT_SPEAKER)) {
705 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
706 } else {
707 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
708 goto exit;
709 }
710 if (snd_device != SND_DEVICE_NONE) {
711 goto exit;
712 }
713 }
714
715 if (popcount(devices) != 1) {
716 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
717 goto exit;
718 }
719
720 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
721 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
722 snd_device = SND_DEVICE_OUT_HEADPHONES;
723 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
724 snd_device = SND_DEVICE_OUT_SPEAKER;
725 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
726 snd_device = SND_DEVICE_OUT_BT_SCO;
727 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100728 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100729 } else {
730 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
731 }
732exit:
733 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
734 return snd_device;
735}
736
737static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
738{
739 audio_source_t source;
740 audio_mode_t mode = adev->mode;
741 audio_devices_t in_device;
742 audio_channel_mask_t channel_mask;
743 snd_device_t snd_device = SND_DEVICE_NONE;
744 struct stream_in *active_input = NULL;
745 struct audio_usecase *usecase;
746
747 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
748 if (usecase != NULL) {
749 active_input = (struct stream_in *)usecase->stream;
750 }
751 source = (active_input == NULL) ?
752 AUDIO_SOURCE_DEFAULT : active_input->source;
753
Andreas Schneider757e2d82017-02-10 19:28:35 +0100754 in_device = (active_input == NULL) ?
755 AUDIO_DEVICE_NONE :
756 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100757 channel_mask = (active_input == NULL) ?
758 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
759
760 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
761 __func__, out_device, in_device);
762 if (mode == AUDIO_MODE_IN_CALL) {
763 if (out_device == AUDIO_DEVICE_NONE) {
764 ALOGE("%s: No output device set for voice call", __func__);
765 goto exit;
766 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100767
Andreas Schneider82f32482017-02-06 09:00:48 +0100768 snd_device = SND_DEVICE_IN_VOICE_MIC;
769 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100770 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100771 }
772
773 if (voice_session_uses_twomic(adev->voice.session)) {
774 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
775 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
776 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
777 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
778 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
779 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100780 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100781
782 if (voice_session_uses_wideband(adev->voice.session)) {
783 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
784 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
785 }
786
787 if (voice_session_uses_twomic(adev->voice.session)) {
788 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
789 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
790 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
791 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
792 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
793 }
794 }
795 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100796
797 /* BT SCO */
798 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
799 snd_device = SND_DEVICE_IN_VOICE_MIC;
800
801 if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Fevax51bd12c2017-03-15 10:56:39 -0300802 if (voice_session_uses_wideband(adev->voice.session)) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100803 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300804 } else {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100805 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC;
Fevax51bd12c2017-03-15 10:56:39 -0300806 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100807 } else if (voice_session_uses_twomic(adev->voice.session)) {
808 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
809 }
810 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100811 } else if (source == AUDIO_SOURCE_CAMCORDER) {
812 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
813 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
814 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
815 }
816 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
817 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100818 if (snd_device == SND_DEVICE_NONE) {
819 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
820 }
821 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
822 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
823 }
824 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
825 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
826 in_device = AUDIO_DEVICE_IN_BACK_MIC;
827 if (active_input) {
828 if (active_input->enable_aec) {
829 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
830 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
831 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
832 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
833 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
834 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100835 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100836 }
837 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
838 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
839 }
840 }
841 /* TODO: set echo reference */
842 }
843 } else if (source == AUDIO_SOURCE_DEFAULT) {
844 goto exit;
845 }
846
847
848 if (snd_device != SND_DEVICE_NONE) {
849 goto exit;
850 }
851
852 if (in_device != AUDIO_DEVICE_NONE &&
853 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
854 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
855 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100856 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100857 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
858 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
859 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
860 snd_device = SND_DEVICE_IN_HEADSET_MIC;
861 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
862 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
863 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
864 snd_device = SND_DEVICE_IN_HDMI_MIC;
865 } else {
866 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100867 ALOGW("%s: Using default earpiece-mic", __func__);
868 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100869 }
870 } else {
871 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100872 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100873 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
874 snd_device = SND_DEVICE_IN_HEADSET_MIC;
875 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
876 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
877 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100878 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100879 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
880 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
881 } else {
882 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100883 ALOGW("%s: Using default earpiece-mic", __func__);
884 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100885 }
886 }
887exit:
888 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
889 return snd_device;
890}
891
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100892#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100893static int set_hdmi_channels(struct audio_device *adev, int channel_count)
894{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100895 (void)adev;
896 (void)channel_count;
897 /* TODO */
898
899 return 0;
900}
901
902static int edid_get_max_channels(struct audio_device *adev)
903{
904 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100905 (void)adev;
906
907 /* TODO */
908 return max_channels;
909}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100910#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100911
912/* Delay in Us */
913static int64_t render_latency(audio_usecase_t usecase)
914{
915 (void)usecase;
916 /* TODO */
917 return 0;
918}
919
920static int enable_snd_device(struct audio_device *adev,
921 struct audio_usecase *uc_info,
922 snd_device_t snd_device,
923 bool update_mixer)
924{
925 struct mixer_card *mixer_card;
926 struct listnode *node;
927 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100928#ifdef DSP_POWEROFF_DELAY
929 struct timespec activation_time;
930 struct timespec elapsed_time;
931#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100932
933 if (snd_device_name == NULL)
934 return -EINVAL;
935
936 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
937 ALOGV("Request to enable combo device: enable individual devices\n");
938 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
939 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
940 return 0;
941 }
942 adev->snd_dev_ref_cnt[snd_device]++;
943 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
944 ALOGV("%s: snd_device(%d: %s) is already active",
945 __func__, snd_device, snd_device_name);
946 return 0;
947 }
948
949 ALOGV("%s: snd_device(%d: %s)", __func__,
950 snd_device, snd_device_name);
951
952 list_for_each(node, &uc_info->mixer_list) {
953 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100954
955#ifdef DSP_POWEROFF_DELAY
956 clock_gettime(CLOCK_MONOTONIC, &activation_time);
957
Andreas Schneider58735a92017-02-13 16:48:17 +0100958 elapsed_time = time_spec_diff(activation_time,
959 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100960 if (elapsed_time.tv_sec == 0) {
961 long elapsed_usec = elapsed_time.tv_nsec / 1000;
962
963 if (elapsed_usec < DSP_POWEROFF_DELAY) {
964 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
965 }
966 }
967 update_mixer = true;
968#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200969
970 amplifier_enable_devices(snd_device, true);
971
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100972 audio_route_apply_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100973 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100974 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100975 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100976 }
977
978 return 0;
979}
980
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100981int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100982 struct audio_usecase *uc_info,
983 snd_device_t snd_device,
984 bool update_mixer)
985{
986 struct mixer_card *mixer_card;
987 struct listnode *node;
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100988 struct audio_usecase *out_uc_info = get_usecase_from_type(adev, PCM_PLAYBACK);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100989 const char *snd_device_name = get_snd_device_name(snd_device);
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100990 const char *out_snd_device_name = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100991
992 if (snd_device_name == NULL)
993 return -EINVAL;
994
995 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
996 ALOGV("Request to disable combo device: disable individual devices\n");
997 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
998 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
999 return 0;
1000 }
1001
1002 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1003 ALOGE("%s: device ref cnt is already 0", __func__);
1004 return -EINVAL;
1005 }
1006 adev->snd_dev_ref_cnt[snd_device]--;
1007 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
1008 ALOGV("%s: snd_device(%d: %s)", __func__,
1009 snd_device, snd_device_name);
1010 list_for_each(node, &uc_info->mixer_list) {
1011 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +01001012#ifdef DSP_POWEROFF_DELAY
1013 update_mixer = true;
1014#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001015 audio_route_reset_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse11ef2112018-02-02 23:19:42 +01001016 if (out_uc_info != NULL) {
1017 /*
1018 * Cycle the rx device to eliminate routing conflicts.
1019 * This prevents issues when an input route shares mixer controls with an output
1020 * route.
1021 */
1022 out_snd_device_name = get_snd_device_name(out_uc_info->out_snd_device);
1023 audio_route_apply_path(mixer_card->audio_route, out_snd_device_name);
1024 }
Andreas Schneider759368f2017-02-02 16:11:14 +01001025 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001026 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +01001027 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02001028
1029 amplifier_enable_devices(snd_device, false);
Andreas Schneider759368f2017-02-02 16:11:14 +01001030#ifdef DSP_POWEROFF_DELAY
1031 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
1032#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001033 }
1034 }
1035 return 0;
1036}
1037
1038static int select_devices(struct audio_device *adev,
1039 audio_usecase_t uc_id)
1040{
1041 snd_device_t out_snd_device = SND_DEVICE_NONE;
1042 snd_device_t in_snd_device = SND_DEVICE_NONE;
1043 struct audio_usecase *usecase = NULL;
1044 struct audio_usecase *vc_usecase = NULL;
1045 struct listnode *node;
1046 struct stream_in *active_input = NULL;
1047 struct stream_out *active_out;
1048 struct mixer_card *mixer_card;
1049
1050 ALOGV("%s: usecase(%d)", __func__, uc_id);
1051
1052 if (uc_id == USECASE_AUDIO_CAPTURE_HOTWORD)
1053 return 0;
1054
1055 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
1056 if (usecase != NULL) {
1057 active_input = (struct stream_in *)usecase->stream;
1058 }
1059
1060 usecase = get_usecase_from_id(adev, uc_id);
1061 if (usecase == NULL) {
1062 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1063 return -EINVAL;
1064 }
1065 active_out = (struct stream_out *)usecase->stream;
1066
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001067
1068 /*
1069 * If the voice call is active, use the sound devices of voice call usecase
1070 * so that it would not result any device switch. All the usecases will
1071 * be switched to new device when select_devices() is called for voice call
1072 * usecase.
1073 */
1074 if (usecase->type != VOICE_CALL && adev->voice.in_call) {
1075 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
1076 if (vc_usecase == NULL) {
1077 ALOGE("%s: Could not find the voice call usecase", __func__);
1078 } else {
Christopher N. Hesse77880a22017-11-17 20:27:50 +01001079 ALOGV("%s: in call, reusing devices (rx: %s, tx: %s)", __func__,
1080 get_snd_device_display_name(vc_usecase->out_snd_device),
1081 get_snd_device_display_name(vc_usecase->in_snd_device));
1082 usecase->devices = vc_usecase->devices;
1083 return 0;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001084 }
1085 }
1086
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001087 if (usecase->type == VOICE_CALL) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001088 usecase->devices = active_out->devices;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001089 prepare_voice_session(adev->voice.session, active_out->devices);
1090 out_snd_device = get_output_snd_device(adev, active_out->devices);
1091 in_snd_device = get_input_snd_device(adev, active_out->devices);
1092 } else if (usecase->type == PCM_PLAYBACK) {
1093 usecase->devices = active_out->devices;
1094 in_snd_device = SND_DEVICE_NONE;
1095 if (out_snd_device == SND_DEVICE_NONE) {
1096 out_snd_device = get_output_snd_device(adev, active_out->devices);
1097 if (active_out == adev->primary_output &&
1098 active_input &&
1099 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1100 select_devices(adev, active_input->usecase);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001101 }
1102 }
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001103 } else if (usecase->type == PCM_CAPTURE) {
1104 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
1105 out_snd_device = SND_DEVICE_NONE;
1106 if (in_snd_device == SND_DEVICE_NONE) {
1107 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
1108 adev->primary_output && !adev->primary_output->standby) {
1109 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
1110 } else {
1111 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001112 }
1113 }
1114 }
1115
1116 if (out_snd_device == usecase->out_snd_device &&
1117 in_snd_device == usecase->in_snd_device) {
1118 return 0;
1119 }
1120
1121 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
1122 out_snd_device, get_snd_device_display_name(out_snd_device),
1123 in_snd_device, get_snd_device_display_name(in_snd_device));
1124
1125
1126 /* Disable current sound devices */
1127 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001128 disable_snd_device(adev, usecase, usecase->out_snd_device, false);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001129 }
1130
1131 if (usecase->in_snd_device != SND_DEVICE_NONE) {
1132 disable_snd_device(adev, usecase, usecase->in_snd_device, false);
1133 }
1134
1135 /* Enable new sound devices */
1136 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +01001137 /* We need to update the audio path if we switch the out devices */
1138 if (adev->voice.in_call) {
1139 set_voice_session_audio_path(adev->voice.session);
1140 }
1141
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001142 enable_snd_device(adev, usecase, out_snd_device, false);
1143 }
1144
1145 if (in_snd_device != SND_DEVICE_NONE) {
1146 enable_snd_device(adev, usecase, in_snd_device, false);
1147 }
1148
1149 list_for_each(node, &usecase->mixer_list) {
1150 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
1151 audio_route_update_mixer(mixer_card->audio_route);
1152 }
1153
1154 usecase->in_snd_device = in_snd_device;
1155 usecase->out_snd_device = out_snd_device;
1156
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02001157 /* Rely on amplifier_set_devices to distinguish between in/out devices */
1158 amplifier_set_input_devices(in_snd_device);
1159 amplifier_set_output_devices(out_snd_device);
1160
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001161 return 0;
1162}
1163
1164
1165static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
1166static int do_in_standby_l(struct stream_in *in);
1167
1168#ifdef PREPROCESSING_ENABLED
1169static void get_capture_reference_delay(struct stream_in *in,
1170 size_t frames __unused,
1171 struct echo_reference_buffer *buffer)
1172{
1173 ALOGVV("%s: enter:)", __func__);
1174
1175 /* read frames available in kernel driver buffer */
1176 unsigned int kernel_frames;
1177 struct timespec tstamp;
1178 long buf_delay;
1179 long kernel_delay;
1180 long delay_ns;
1181 struct pcm_device *ref_device;
1182 long rsmp_delay = 0;
1183
1184 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1185 struct pcm_device, stream_list_node);
1186
1187 if (pcm_get_htimestamp(ref_device->pcm, &kernel_frames, &tstamp) < 0) {
1188 buffer->time_stamp.tv_sec = 0;
1189 buffer->time_stamp.tv_nsec = 0;
1190 buffer->delay_ns = 0;
1191 ALOGW("read get_capture_reference_delay(): pcm_htimestamp error");
1192 return;
1193 }
1194
1195 /* adjust render time stamp with delay added by current driver buffer.
1196 * Add the duration of current frame as we want the render time of the last
1197 * sample being written. */
1198
1199 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / ref_device->pcm_profile->config.rate);
1200
1201 buffer->time_stamp = tstamp;
1202 buffer->delay_ns = kernel_delay;
1203
1204 ALOGVV("get_capture_reference_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5d],"
1205 " delay_ns: [%d] , frames:[%zd]",
1206 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns, frames);
1207}
1208
1209static void get_capture_delay(struct stream_in *in,
1210 size_t frames __unused,
1211 struct echo_reference_buffer *buffer)
1212{
1213 ALOGVV("%s: enter:)", __func__);
1214 /* read frames available in kernel driver buffer */
1215 unsigned int kernel_frames;
1216 struct timespec tstamp;
1217 long buf_delay;
1218 long rsmp_delay;
1219 long kernel_delay;
1220 long delay_ns;
1221 struct pcm_device *pcm_device;
1222
1223 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1224 struct pcm_device, stream_list_node);
1225
1226 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1227 buffer->time_stamp.tv_sec = 0;
1228 buffer->time_stamp.tv_nsec = 0;
1229 buffer->delay_ns = 0;
1230 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1231 return;
1232 }
1233
1234 /* read frames available in audio HAL input buffer
1235 * add number of frames being read as we want the capture time of first sample
1236 * in current buffer */
1237 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1238 * at requested sampling rate */
1239 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1240 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1241
1242 /* add delay introduced by resampler */
1243 rsmp_delay = 0;
1244 if (in->resampler) {
1245 rsmp_delay = in->resampler->delay_ns(in->resampler);
1246 }
1247
1248 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1249
1250 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1251
1252 buffer->time_stamp = tstamp;
1253 buffer->delay_ns = delay_ns;
1254 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1255 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1256 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1257 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1258 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1259 in->read_buf_frames, in->proc_buf_frames, frames);
1260}
1261
1262static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1263{
1264 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1265 struct echo_reference_buffer b;
1266 b.delay_ns = 0;
1267 struct pcm_device *pcm_device;
1268
1269 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1270 struct pcm_device, stream_list_node);
1271
1272 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1273 "b.frame_count = [%zd]",
1274 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1275 if (in->ref_buf_frames < frames) {
1276 if (in->ref_buf_size < frames) {
1277 in->ref_buf_size = frames;
1278 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1279 ALOG_ASSERT((in->ref_buf != NULL),
1280 "update_echo_reference() failed to reallocate ref_buf");
1281 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1282 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1283 }
1284 b.frame_count = frames - in->ref_buf_frames;
1285 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1286
1287 get_capture_delay(in, frames, &b);
1288
1289 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1290 {
1291 in->ref_buf_frames += b.frame_count;
1292 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1293 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1294 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1295 }
1296 } else
1297 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1298 return b.delay_ns;
1299}
1300
1301static int set_preprocessor_param(effect_handle_t handle,
1302 effect_param_t *param)
1303{
1304 uint32_t size = sizeof(int);
1305 uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1306 param->vsize;
1307
1308 int status = (*handle)->command(handle,
1309 EFFECT_CMD_SET_PARAM,
1310 sizeof (effect_param_t) + psize,
1311 param,
1312 &size,
1313 &param->status);
1314 if (status == 0)
1315 status = param->status;
1316
1317 return status;
1318}
1319
1320static int set_preprocessor_echo_delay(effect_handle_t handle,
1321 int32_t delay_us)
1322{
1323 struct {
1324 effect_param_t param;
1325 uint32_t data_0;
1326 int32_t data_1;
1327 } buf;
1328 memset(&buf, 0, sizeof(buf));
1329
1330 buf.param.psize = sizeof(uint32_t);
1331 buf.param.vsize = sizeof(uint32_t);
1332 buf.data_0 = AEC_PARAM_ECHO_DELAY;
1333 buf.data_1 = delay_us;
1334
1335 return set_preprocessor_param(handle, &buf.param);
1336}
1337
1338static void push_echo_reference(struct stream_in *in, size_t frames)
1339{
1340 ALOGVV("%s: enter:)", __func__);
1341 /* read frames from echo reference buffer and update echo delay
1342 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1343
1344 int32_t delay_us = update_echo_reference(in, frames)/1000;
1345 int32_t size_in_bytes = 0;
1346 int i;
1347 audio_buffer_t buf;
1348
1349 if (in->ref_buf_frames < frames)
1350 frames = in->ref_buf_frames;
1351
1352 buf.frameCount = frames;
1353 buf.raw = in->ref_buf;
1354
1355 for (i = 0; i < in->num_preprocessors; i++) {
1356 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1357 continue;
1358 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1359 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1360 &buf,
1361 NULL);
1362 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1363 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1364 }
1365
1366 in->ref_buf_frames -= buf.frameCount;
1367 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1368 __func__, in->ref_buf_frames, in->config.channels);
1369 if (in->ref_buf_frames) {
1370 memcpy(in->ref_buf,
1371 in->ref_buf + buf.frameCount * in->config.channels,
1372 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1373 }
1374}
1375
1376static void put_echo_reference(struct audio_device *adev,
1377 struct echo_reference_itfe *reference)
1378{
1379 ALOGV("%s: enter:)", __func__);
1380 int32_t prev_generation = adev->echo_reference_generation;
1381 struct stream_out *out = adev->primary_output;
1382
1383 if (adev->echo_reference != NULL &&
1384 reference == adev->echo_reference) {
1385 /* echo reference is taken from the low latency output stream used
1386 * for voice use cases */
1387 adev->echo_reference = NULL;
1388 android_atomic_inc(&adev->echo_reference_generation);
1389 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1390 // if the primary output is in standby or did not pick the echo reference yet
1391 // we can safely get rid of it here.
1392 // otherwise, out_write() or out_standby() will detect the change in echo reference
1393 // generation and release the echo reference owned by the stream.
1394 if ((out->echo_reference_generation != prev_generation) || out->standby)
1395 release_echo_reference(reference);
1396 } else {
1397 release_echo_reference(reference);
1398 }
1399 ALOGV("release_echo_reference");
1400 }
1401}
1402
1403static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1404 audio_format_t format __unused,
1405 uint32_t channel_count,
1406 uint32_t sampling_rate)
1407{
1408 ALOGV("%s: enter:)", __func__);
1409 put_echo_reference(adev, adev->echo_reference);
1410 /* echo reference is taken from the low latency output stream used
1411 * for voice use cases */
1412 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1413 !adev->primary_output->standby) {
1414 struct audio_stream *stream =
1415 &adev->primary_output->stream.common;
1416 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1417 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1418 ALOGV("Calling create_echo_reference");
1419 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1420 channel_count,
1421 sampling_rate,
1422 AUDIO_FORMAT_PCM_16_BIT,
1423 wr_channel_count,
1424 wr_sampling_rate,
1425 &adev->echo_reference);
1426 if (status == 0)
1427 android_atomic_inc(&adev->echo_reference_generation);
1428 }
1429 return adev->echo_reference;
1430}
1431
1432#ifdef HW_AEC_LOOPBACK
1433static int get_hw_echo_reference(struct stream_in *in)
1434{
1435 struct pcm_device_profile *ref_pcm_profile;
1436 struct pcm_device *ref_device;
1437 struct audio_device *adev = in->dev;
1438
1439 in->hw_echo_reference = false;
1440
1441 if (adev->primary_output!= NULL &&
1442 !adev->primary_output->standby &&
1443 adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1444 adev->primary_output->devices == AUDIO_DEVICE_OUT_SPEAKER) {
1445 struct audio_stream *stream = &adev->primary_output->stream.common;
1446
1447 // TODO: currently there is no low latency mode for aec reference.
1448 ref_pcm_profile = get_pcm_device(PCM_CAPTURE, pcm_device_capture_loopback_aec.devices);
1449 if (ref_pcm_profile == NULL) {
1450 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1451 __func__, pcm_device_capture_loopback_aec.devices);
1452 return -EINVAL;
1453 }
1454
1455 ref_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01001456 if (ref_device == NULL) {
1457 return -ENOMEM;
1458 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001459 ref_device->pcm_profile = ref_pcm_profile;
1460
1461 ALOGV("%s: ref_device rate:%d, ch:%d", __func__, ref_pcm_profile->config.rate, ref_pcm_profile->config.channels);
1462 ref_device->pcm = pcm_open(ref_device->pcm_profile->card, ref_device->pcm_profile->id, PCM_IN | PCM_MONOTONIC, &ref_device->pcm_profile->config);
1463
1464 if (ref_device->pcm && !pcm_is_ready(ref_device->pcm)) {
1465 ALOGE("%s: %s", __func__, pcm_get_error(ref_device->pcm));
1466 pcm_close(ref_device->pcm);
1467 ref_device->pcm = NULL;
1468 return -EIO;
1469 }
1470 list_add_tail(&in->pcm_dev_list, &ref_device->stream_list_node);
1471
1472 in->hw_echo_reference = true;
1473
1474 ALOGV("%s: hw_echo_reference is true", __func__);
1475 }
1476
1477 return 0;
1478}
1479#endif
1480
1481static int get_playback_delay(struct stream_out *out,
1482 size_t frames,
1483 struct echo_reference_buffer *buffer)
1484{
1485 unsigned int kernel_frames;
1486 int status;
1487 int primary_pcm = 0;
1488 struct pcm_device *pcm_device;
1489
1490 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1491 struct pcm_device, stream_list_node);
1492
1493 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1494 if (status < 0) {
1495 buffer->time_stamp.tv_sec = 0;
1496 buffer->time_stamp.tv_nsec = 0;
1497 buffer->delay_ns = 0;
1498 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1499 "setting playbackTimestamp to 0");
1500 return status;
1501 }
1502
1503 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1504
1505 /* adjust render time stamp with delay added by current driver buffer.
1506 * Add the duration of current frame as we want the render time of the last
1507 * sample being written. */
1508 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1509 out->config.rate);
1510 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1511 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1512
1513 return 0;
1514}
1515
1516#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1517 do { \
1518 if (fct_status != 0) \
1519 status = fct_status; \
1520 else if (cmd_status != 0) \
1521 status = cmd_status; \
1522 } while(0)
1523
1524static int in_configure_reverse(struct stream_in *in)
1525{
1526 int32_t cmd_status;
1527 uint32_t size = sizeof(int);
1528 effect_config_t config;
1529 int32_t status = 0;
1530 int32_t fct_status = 0;
1531 int i;
1532 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1533 if (in->num_preprocessors > 0) {
1534 config.inputCfg.channels = in->main_channels;
1535 config.outputCfg.channels = in->main_channels;
1536 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1537 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1538 config.inputCfg.samplingRate = in->requested_rate;
1539 config.outputCfg.samplingRate = in->requested_rate;
1540 config.inputCfg.mask =
1541 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1542 config.outputCfg.mask =
1543 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1544
1545 for (i = 0; i < in->num_preprocessors; i++)
1546 {
1547 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1548 continue;
1549 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1550 in->preprocessors[i].effect_itfe,
1551 EFFECT_CMD_SET_CONFIG_REVERSE,
1552 sizeof(effect_config_t),
1553 &config,
1554 &size,
1555 &cmd_status);
1556 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1557 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1558 }
1559 }
1560 return status;
1561}
1562
1563#define MAX_NUM_CHANNEL_CONFIGS 10
1564
1565static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1566 struct effect_info_s *effect_info)
1567{
1568 /* size and format of the cmd are defined in hardware/audio_effect.h */
1569 effect_handle_t effect = effect_info->effect_itfe;
1570 uint32_t cmd_size = 2 * sizeof(uint32_t);
1571 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1572 /* reply = status + number of configs (n) + n x channel_config_t */
1573 uint32_t reply_size =
1574 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1575 int32_t reply[reply_size];
1576 int32_t cmd_status;
1577
1578 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1579 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1580 ALOG_ASSERT((effect_info->channel_configs == NULL),
1581 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1582
1583 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1584 * This error will be interpreted as if the effect supports the main_channels but does not
1585 * support any aux_channels */
1586 cmd_status = (*effect)->command(effect,
1587 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1588 cmd_size,
1589 (void*)&cmd,
1590 &reply_size,
1591 (void*)&reply);
1592
1593 if (cmd_status != 0) {
1594 ALOGV("in_read_audio_effect_channel_configs(): "
1595 "fx->command returned %d", cmd_status);
1596 return;
1597 }
1598
1599 if (reply[0] != 0) {
1600 ALOGW("in_read_audio_effect_channel_configs(): "
1601 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1602 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1603 return;
1604 }
1605
1606 /* the feature is not supported */
1607 ALOGV("in_read_audio_effect_channel_configs()(): "
1608 "Feature supported and adding %d channel configs to the list", reply[1]);
1609 effect_info->num_channel_configs = reply[1];
1610 effect_info->channel_configs =
1611 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1612 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1613}
1614
1615
1616#define NUM_IN_AUX_CNL_CONFIGS 2
1617static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1618 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1619 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1620};
1621static uint32_t in_get_aux_channels(struct stream_in *in)
1622{
1623 int i;
1624 channel_config_t new_chcfg = {0, 0};
1625
1626 if (in->num_preprocessors == 0)
1627 return 0;
1628
1629 /* do not enable dual mic configurations when capturing from other microphones than
1630 * main or sub */
1631 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1632 return 0;
1633
1634 /* retain most complex aux channels configuration compatible with requested main channels and
1635 * supported by audio driver and all pre processors */
1636 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1637 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1638 if (cur_chcfg->main_channels == in->main_channels) {
1639 size_t match_cnt;
1640 size_t idx_preproc;
1641 for (idx_preproc = 0, match_cnt = 0;
1642 /* no need to continue if at least one preprocessor doesn't match */
1643 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1644 idx_preproc++) {
1645 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1646 size_t idx_chcfg;
1647
1648 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1649 if (memcmp(effect_info->channel_configs + idx_chcfg,
1650 cur_chcfg,
1651 sizeof(channel_config_t)) == 0) {
1652 match_cnt++;
1653 break;
1654 }
1655 }
1656 }
1657 /* if all preprocessors match, we have a candidate */
1658 if (match_cnt == (size_t)in->num_preprocessors) {
1659 /* retain most complex aux channels configuration */
1660 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1661 new_chcfg = *cur_chcfg;
1662 }
1663 }
1664 }
1665 }
1666
1667 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1668
1669 return new_chcfg.aux_channels;
1670}
1671
1672static int in_configure_effect_channels(effect_handle_t effect,
1673 channel_config_t *channel_config)
1674{
1675 int status = 0;
1676 int fct_status;
1677 int32_t cmd_status;
1678 uint32_t reply_size;
1679 effect_config_t config;
1680 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1681
1682 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1683 channel_config->main_channels,
1684 channel_config->aux_channels);
1685
1686 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1687 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1688 reply_size = sizeof(effect_config_t);
1689 fct_status = (*effect)->command(effect,
1690 EFFECT_CMD_GET_CONFIG,
1691 0,
1692 NULL,
1693 &reply_size,
1694 &config);
1695 if (fct_status != 0) {
1696 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1697 return fct_status;
1698 }
1699
1700 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1701 config.outputCfg.channels = config.inputCfg.channels;
1702 reply_size = sizeof(uint32_t);
1703 fct_status = (*effect)->command(effect,
1704 EFFECT_CMD_SET_CONFIG,
1705 sizeof(effect_config_t),
1706 &config,
1707 &reply_size,
1708 &cmd_status);
1709 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1710
1711 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1712 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1713 reply_size = sizeof(uint32_t);
1714 fct_status = (*effect)->command(effect,
1715 EFFECT_CMD_SET_FEATURE_CONFIG,
1716 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1717 cmd,
1718 &reply_size,
1719 &cmd_status);
1720 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1721
1722 /* some implementations need to be re-enabled after a config change */
1723 reply_size = sizeof(uint32_t);
1724 fct_status = (*effect)->command(effect,
1725 EFFECT_CMD_ENABLE,
1726 0,
1727 NULL,
1728 &reply_size,
1729 &cmd_status);
1730 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1731
1732 return status;
1733}
1734
1735static int in_reconfigure_channels(struct stream_in *in,
1736 effect_handle_t effect,
1737 channel_config_t *channel_config,
1738 bool config_changed) {
1739
1740 int status = 0;
1741
1742 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1743 config_changed, effect);
1744
1745 /* if config changed, reconfigure all previously added effects */
1746 if (config_changed) {
1747 int i;
1748 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1749 for (i = 0; i < in->num_preprocessors; i++)
1750 {
1751 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1752 channel_config);
1753 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1754 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1755 if (cur_status != 0) {
1756 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1757 "%d with channels: [%04x][%04x]",
1758 cur_status,
1759 i,
1760 channel_config->main_channels,
1761 channel_config->aux_channels);
1762 status = cur_status;
1763 }
1764 }
1765 } else if (effect != NULL && channel_config->aux_channels) {
1766 /* if aux channels config did not change but aux channels are present,
1767 * we still need to configure the effect being added */
1768 status = in_configure_effect_channels(effect, channel_config);
1769 }
1770 return status;
1771}
1772
1773static void in_update_aux_channels(struct stream_in *in,
1774 effect_handle_t effect)
1775{
1776 uint32_t aux_channels;
1777 channel_config_t channel_config;
1778 int status;
1779
1780 aux_channels = in_get_aux_channels(in);
1781
1782 channel_config.main_channels = in->main_channels;
1783 channel_config.aux_channels = aux_channels;
1784 status = in_reconfigure_channels(in,
1785 effect,
1786 &channel_config,
1787 (aux_channels != in->aux_channels));
1788
1789 if (status != 0) {
1790 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1791 /* resetting aux channels configuration */
1792 aux_channels = 0;
1793 channel_config.aux_channels = 0;
1794 in_reconfigure_channels(in, effect, &channel_config, true);
1795 }
1796 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1797 if (in->aux_channels != aux_channels) {
1798 in->aux_channels_changed = true;
1799 in->aux_channels = aux_channels;
1800 do_in_standby_l(in);
1801 }
1802}
1803#endif
1804
1805/* This function reads PCM data and:
1806 * - resample if needed
1807 * - process if pre-processors are attached
1808 * - discard unwanted channels
1809 */
1810static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1811{
1812 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001813 size_t src_channels = in->config.channels;
1814 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1815 int i;
1816 void *proc_buf_out;
1817 struct pcm_device *pcm_device;
1818 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1819#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001820 audio_buffer_t in_buf;
1821 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001822 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1823#endif
1824
1825 /* Additional channels might be added on top of main_channels:
1826 * - aux_channels (by processing effects)
1827 * - extra channels due to HW limitations
1828 * In case of additional channels, we cannot work inplace
1829 */
1830 if (has_additional_channels)
1831 proc_buf_out = in->proc_buf_out;
1832 else
1833 proc_buf_out = buffer;
1834
1835 if (list_empty(&in->pcm_dev_list)) {
1836 ALOGE("%s: pcm device list empty", __func__);
1837 return -EINVAL;
1838 }
1839
1840 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1841 struct pcm_device, stream_list_node);
1842
1843#ifdef PREPROCESSING_ENABLED
1844 if (has_processing) {
1845 /* since all the processing below is done in frames and using the config.channels
1846 * as the number of channels, no changes is required in case aux_channels are present */
1847 while (frames_wr < frames) {
1848 /* first reload enough frames at the end of process input buffer */
1849 if (in->proc_buf_frames < (size_t)frames) {
1850 ssize_t frames_rd;
1851 if (in->proc_buf_size < (size_t)frames) {
1852 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1853 in->proc_buf_size = (size_t)frames;
1854 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1855 ALOG_ASSERT((in->proc_buf_in != NULL),
1856 "process_frames() failed to reallocate proc_buf_in");
1857 if (has_additional_channels) {
1858 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1859 ALOG_ASSERT((in->proc_buf_out != NULL),
1860 "process_frames() failed to reallocate proc_buf_out");
1861 proc_buf_out = in->proc_buf_out;
1862 }
1863 }
1864 frames_rd = read_frames(in,
1865 in->proc_buf_in +
1866 in->proc_buf_frames * in->config.channels,
1867 frames - in->proc_buf_frames);
1868 if (frames_rd < 0) {
1869 /* Return error code */
1870 frames_wr = frames_rd;
1871 break;
1872 }
1873 in->proc_buf_frames += frames_rd;
1874 }
1875
1876 if (in->echo_reference != NULL) {
1877 push_echo_reference(in, in->proc_buf_frames);
1878 }
1879
1880 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1881 * the maximum number of frames to be consumed and produced by process() */
1882 in_buf.frameCount = in->proc_buf_frames;
1883 in_buf.s16 = in->proc_buf_in;
1884 out_buf.frameCount = frames - frames_wr;
1885 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1886
1887 /* FIXME: this works because of current pre processing library implementation that
1888 * does the actual process only when the last enabled effect process is called.
1889 * The generic solution is to have an output buffer for each effect and pass it as
1890 * input to the next.
1891 */
1892 for (i = 0; i < in->num_preprocessors; i++) {
1893 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1894 &in_buf,
1895 &out_buf);
1896 }
1897
1898 /* process() has updated the number of frames consumed and produced in
1899 * in_buf.frameCount and out_buf.frameCount respectively
1900 * move remaining frames to the beginning of in->proc_buf_in */
1901 in->proc_buf_frames -= in_buf.frameCount;
1902
1903 if (in->proc_buf_frames) {
1904 memcpy(in->proc_buf_in,
1905 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1906 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1907 }
1908
1909 /* if not enough frames were passed to process(), read more and retry. */
1910 if (out_buf.frameCount == 0) {
1911 ALOGW("No frames produced by preproc");
1912 continue;
1913 }
1914
1915 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1916 frames_wr += out_buf.frameCount;
1917 } else {
1918 /* The effect does not comply to the API. In theory, we should never end up here! */
1919 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1920 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1921 frames_wr = frames;
1922 }
1923 }
1924 }
1925 else
1926#endif //PREPROCESSING_ENABLED
1927 {
1928 /* No processing effects attached */
1929 if (has_additional_channels) {
1930 /* With additional channels, we cannot use original buffer */
1931 if (in->proc_buf_size < (size_t)frames) {
1932 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1933 in->proc_buf_size = (size_t)frames;
1934 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1935 ALOG_ASSERT((in->proc_buf_out != NULL),
1936 "process_frames() failed to reallocate proc_buf_out");
1937 proc_buf_out = in->proc_buf_out;
1938 }
1939 }
1940 frames_wr = read_frames(in, proc_buf_out, frames);
1941 }
1942
1943 /* Remove all additional channels that have been added on top of main_channels:
1944 * - aux_channels
1945 * - extra channels from HW due to HW limitations
1946 * Assumption is made that the channels are interleaved and that the main
1947 * channels are first. */
1948
1949 if (has_additional_channels)
1950 {
1951 int16_t* src_buffer = (int16_t *)proc_buf_out;
1952 int16_t* dst_buffer = (int16_t *)buffer;
1953
1954 if (dst_channels == 1) {
1955 for (i = frames_wr; i > 0; i--)
1956 {
1957 *dst_buffer++ = *src_buffer;
1958 src_buffer += src_channels;
1959 }
1960 } else {
1961 for (i = frames_wr; i > 0; i--)
1962 {
1963 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1964 dst_buffer += dst_channels;
1965 src_buffer += src_channels;
1966 }
1967 }
1968 }
1969
1970 return frames_wr;
1971}
1972
1973static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1974 struct resampler_buffer* buffer)
1975{
1976 struct stream_in *in;
1977 struct pcm_device *pcm_device;
1978
1979 if (buffer_provider == NULL || buffer == NULL)
1980 return -EINVAL;
1981
1982 in = (struct stream_in *)((char *)buffer_provider -
1983 offsetof(struct stream_in, buf_provider));
1984
1985 if (list_empty(&in->pcm_dev_list)) {
1986 buffer->raw = NULL;
1987 buffer->frame_count = 0;
1988 in->read_status = -ENODEV;
1989 return -ENODEV;
1990 }
1991
1992 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1993 struct pcm_device, stream_list_node);
1994
1995 if (in->read_buf_frames == 0) {
1996 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1997 if (in->read_buf_size < in->config.period_size) {
1998 in->read_buf_size = in->config.period_size;
1999 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
2000 ALOG_ASSERT((in->read_buf != NULL),
2001 "get_next_buffer() failed to reallocate read_buf");
2002 }
2003
2004 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
2005
2006 if (in->read_status != 0) {
2007 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
2008 buffer->raw = NULL;
2009 buffer->frame_count = 0;
2010 return in->read_status;
2011 }
2012 in->read_buf_frames = in->config.period_size;
2013
2014#ifdef PREPROCESSING_ENABLED
2015#ifdef HW_AEC_LOOPBACK
2016 if (in->hw_echo_reference) {
2017 struct pcm_device *temp_device = NULL;
2018 struct pcm_device *ref_device = NULL;
2019 struct listnode *node = NULL;
2020 struct echo_reference_buffer b;
2021 size_t size_hw_ref_bytes;
2022 size_t size_hw_ref_frames;
2023 int read_status = 0;
2024
2025 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
2026 struct pcm_device, stream_list_node);
2027 list_for_each(node, &in->pcm_dev_list) {
2028 temp_device = node_to_item(node, struct pcm_device, stream_list_node);
2029 if (temp_device->pcm_profile->id == 1) {
2030 ref_device = temp_device;
2031 break;
2032 }
2033 }
2034 if (ref_device) {
2035 size_hw_ref_bytes = pcm_frames_to_bytes(ref_device->pcm, ref_device->pcm_profile->config.period_size);
2036 size_hw_ref_frames = ref_device->pcm_profile->config.period_size;
2037 if (in->hw_ref_buf_size < size_hw_ref_frames) {
2038 in->hw_ref_buf_size = size_hw_ref_frames;
2039 in->hw_ref_buf = (int16_t *) realloc(in->hw_ref_buf, size_hw_ref_bytes);
2040 ALOG_ASSERT((in->hw_ref_buf != NULL),
2041 "get_next_buffer() failed to reallocate hw_ref_buf");
2042 ALOGV("get_next_buffer(): hw_ref_buf %p extended to %zd bytes",
2043 in->hw_ref_buf, size_hw_ref_bytes);
2044 }
2045
2046 read_status = pcm_read(ref_device->pcm, (void*)in->hw_ref_buf, size_hw_ref_bytes);
2047 if (read_status != 0) {
2048 ALOGE("process_frames() pcm_read error for HW reference %d", read_status);
2049 b.raw = NULL;
2050 b.frame_count = 0;
2051 }
2052 else {
2053 get_capture_reference_delay(in, size_hw_ref_frames, &b);
2054 b.raw = (void *)in->hw_ref_buf;
2055 b.frame_count = size_hw_ref_frames;
2056 if (b.delay_ns != 0)
2057 b.delay_ns = -b.delay_ns; // as this is capture delay, it needs to be subtracted from the microphone delay
2058 in->echo_reference->write(in->echo_reference, &b);
2059 }
2060 }
2061 }
2062#endif // HW_AEC_LOOPBACK
2063#endif // PREPROCESSING_ENABLED
2064 }
2065
2066 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
2067 in->read_buf_frames : buffer->frame_count;
2068 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
2069 in->config.channels;
2070 return in->read_status;
2071}
2072
2073static void release_buffer(struct resampler_buffer_provider *buffer_provider,
2074 struct resampler_buffer* buffer)
2075{
2076 struct stream_in *in;
2077
2078 if (buffer_provider == NULL || buffer == NULL)
2079 return;
2080
2081 in = (struct stream_in *)((char *)buffer_provider -
2082 offsetof(struct stream_in, buf_provider));
2083
2084 in->read_buf_frames -= buffer->frame_count;
2085}
2086
2087/* read_frames() reads frames from kernel driver, down samples to capture rate
2088 * if necessary and output the number of frames requested to the buffer specified */
2089static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
2090{
2091 ssize_t frames_wr = 0;
2092
2093 struct pcm_device *pcm_device;
2094
2095 if (list_empty(&in->pcm_dev_list)) {
2096 ALOGE("%s: pcm device list empty", __func__);
2097 return -EINVAL;
2098 }
2099
2100 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
2101 struct pcm_device, stream_list_node);
2102
2103 while (frames_wr < frames) {
2104 size_t frames_rd = frames - frames_wr;
2105 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
2106 __func__,frames_rd,frames_wr,in->config.channels);
2107 if (in->resampler != NULL) {
2108 in->resampler->resample_from_provider(in->resampler,
2109 (int16_t *)((char *)buffer +
2110 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
2111 &frames_rd);
2112 } else {
2113 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01002114 .raw = NULL,
2115 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002116 };
2117 get_next_buffer(&in->buf_provider, &buf);
2118 if (buf.raw != NULL) {
2119 memcpy((char *)buffer +
2120 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
2121 buf.raw,
2122 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
2123 frames_rd = buf.frame_count;
2124 }
2125 release_buffer(&in->buf_provider, &buf);
2126 }
2127 /* in->read_status is updated by getNextBuffer() also called by
2128 * in->resampler->resample_from_provider() */
2129 if (in->read_status != 0)
2130 return in->read_status;
2131
2132 frames_wr += frames_rd;
2133 }
2134 return frames_wr;
2135}
2136
2137static int in_release_pcm_devices(struct stream_in *in)
2138{
2139 struct pcm_device *pcm_device;
2140 struct listnode *node;
2141 struct listnode *next;
2142
2143 list_for_each_safe(node, next, &in->pcm_dev_list) {
2144 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2145 list_remove(node);
2146 free(pcm_device);
2147 }
2148
2149 return 0;
2150}
2151
2152static int stop_input_stream(struct stream_in *in)
2153{
2154 struct audio_usecase *uc_info;
2155 struct audio_device *adev = in->dev;
2156
2157 adev->active_input = NULL;
2158 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2159 in->usecase, use_case_table[in->usecase]);
2160 uc_info = get_usecase_from_id(adev, in->usecase);
2161 if (uc_info == NULL) {
2162 ALOGE("%s: Could not find the usecase (%d) in the list",
2163 __func__, in->usecase);
2164 return -EINVAL;
2165 }
2166
2167 /* Disable the tx device */
2168 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2169
2170 list_remove(&uc_info->adev_list_node);
2171 free(uc_info);
2172
2173 if (list_empty(&in->pcm_dev_list)) {
2174 ALOGE("%s: pcm device list empty", __func__);
2175 return -EINVAL;
2176 }
2177
2178 in_release_pcm_devices(in);
2179 list_init(&in->pcm_dev_list);
2180
2181#ifdef HW_AEC_LOOPBACK
2182 if (in->hw_echo_reference)
2183 {
2184 in->hw_echo_reference = false;
2185 }
2186#endif
2187
2188 ALOGV("%s: exit", __func__);
2189 return 0;
2190}
2191
2192static int start_input_stream(struct stream_in *in)
2193{
2194 /* Enable output device and stream routing controls */
2195 int ret = 0;
2196 bool recreate_resampler = false;
2197 struct audio_usecase *uc_info;
2198 struct audio_device *adev = in->dev;
2199 struct pcm_device_profile *pcm_profile;
2200 struct pcm_device *pcm_device;
2201
2202 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2203 adev->active_input = in;
2204 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2205 if (pcm_profile == NULL) {
2206 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2207 __func__, in->usecase);
2208 ret = -EINVAL;
2209 goto error_config;
2210 }
2211
2212 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002213 if (uc_info == NULL) {
2214 ret = -ENOMEM;
2215 goto error_config;
2216 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002217 uc_info->id = in->usecase;
2218 uc_info->type = PCM_CAPTURE;
2219 uc_info->stream = (struct audio_stream *)in;
2220 uc_info->devices = in->devices;
2221 uc_info->in_snd_device = SND_DEVICE_NONE;
2222 uc_info->out_snd_device = SND_DEVICE_NONE;
2223
2224 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002225 if (pcm_device == NULL) {
2226 free(uc_info);
2227 ret = -ENOMEM;
2228 goto error_config;
2229 }
2230
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002231 pcm_device->pcm_profile = pcm_profile;
2232 list_init(&in->pcm_dev_list);
2233 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2234
2235 list_init(&uc_info->mixer_list);
2236 list_add_tail(&uc_info->mixer_list,
2237 &adev_get_mixer_for_card(adev,
2238 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2239
2240 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2241
2242 select_devices(adev, in->usecase);
2243
2244 /* Config should be updated as profile can be changed between different calls
2245 * to this function:
2246 * - Trigger resampler creation
2247 * - Config needs to be updated */
2248 if (in->config.rate != pcm_profile->config.rate) {
2249 recreate_resampler = true;
2250 }
2251 in->config = pcm_profile->config;
2252
2253#ifdef PREPROCESSING_ENABLED
2254 if (in->aux_channels_changed) {
2255 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2256 recreate_resampler = true;
2257 }
2258#endif
2259
2260 if (in->requested_rate != in->config.rate) {
2261 recreate_resampler = true;
2262 }
2263
2264 if (recreate_resampler) {
2265 if (in->resampler) {
2266 release_resampler(in->resampler);
2267 in->resampler = NULL;
2268 }
2269 in->buf_provider.get_next_buffer = get_next_buffer;
2270 in->buf_provider.release_buffer = release_buffer;
2271 ret = create_resampler(in->config.rate,
2272 in->requested_rate,
2273 in->config.channels,
2274 RESAMPLER_QUALITY_DEFAULT,
2275 &in->buf_provider,
2276 &in->resampler);
2277 }
2278
2279#ifdef PREPROCESSING_ENABLED
2280 if (in->enable_aec && in->echo_reference == NULL) {
2281 in->echo_reference = get_echo_reference(adev,
2282 AUDIO_FORMAT_PCM_16_BIT,
2283 audio_channel_count_from_in_mask(in->main_channels),
2284 in->requested_rate
2285 );
2286 }
2287
2288#ifdef HW_AEC_LOOPBACK
2289 if (in->enable_aec) {
2290 ret = get_hw_echo_reference(in);
2291 if (ret!=0)
2292 goto error_open;
2293
2294 /* force ref buffer reallocation */
2295 in->hw_ref_buf_size = 0;
2296 }
2297#endif
2298#endif
2299
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002300 if (in->dev->voice.in_call) {
2301 ALOGV("%s: in_call, not handling PCMs", __func__);
2302 goto skip_pcm_handling;
2303 }
2304
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002305 /* Open the PCM device.
2306 * The HW is limited to support only the default pcm_profile settings.
2307 * As such a change in aux_channels will not have an effect.
2308 */
2309 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2310 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2311 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2312 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2313
2314 if (pcm_profile->type == PCM_HOTWORD_STREAMING) {
2315 if (!adev->sound_trigger_open_for_streaming) {
2316 ALOGE("%s: No handle to sound trigger HAL", __func__);
2317 ret = -EIO;
2318 goto error_open;
2319 }
2320 pcm_device->pcm = NULL;
2321 pcm_device->sound_trigger_handle = adev->sound_trigger_open_for_streaming();
2322 if (pcm_device->sound_trigger_handle <= 0) {
2323 ALOGE("%s: Failed to open DSP for streaming", __func__);
2324 ret = -EIO;
2325 goto error_open;
2326 }
2327 ALOGV("Opened DSP successfully");
2328 } else {
2329 pcm_device->sound_trigger_handle = 0;
2330 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2331 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2332
2333 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2334 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2335 pcm_close(pcm_device->pcm);
2336 pcm_device->pcm = NULL;
2337 ret = -EIO;
2338 goto error_open;
2339 }
2340 }
2341
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002342skip_pcm_handling:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002343 /* force read and proc buffer reallocation in case of frame size or
2344 * channel count change */
2345 in->proc_buf_frames = 0;
2346 in->proc_buf_size = 0;
2347 in->read_buf_size = 0;
2348 in->read_buf_frames = 0;
2349
2350 /* if no supported sample rate is available, use the resampler */
2351 if (in->resampler) {
2352 in->resampler->reset(in->resampler);
2353 }
2354
2355 ALOGV("%s: exit", __func__);
2356 return ret;
2357
2358error_open:
2359 if (in->resampler) {
2360 release_resampler(in->resampler);
2361 in->resampler = NULL;
2362 }
2363 stop_input_stream(in);
2364
2365error_config:
2366 ALOGV("%s: exit: status(%d)", __func__, ret);
2367 adev->active_input = NULL;
2368 return ret;
2369}
2370
2371void lock_input_stream(struct stream_in *in)
2372{
2373 pthread_mutex_lock(&in->pre_lock);
2374 pthread_mutex_lock(&in->lock);
2375 pthread_mutex_unlock(&in->pre_lock);
2376}
2377
2378void lock_output_stream(struct stream_out *out)
2379{
2380 pthread_mutex_lock(&out->pre_lock);
2381 pthread_mutex_lock(&out->lock);
2382 pthread_mutex_unlock(&out->pre_lock);
2383}
2384
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002385static int uc_release_pcm_devices(struct audio_usecase *usecase)
2386{
2387 struct stream_out *out = (struct stream_out *)usecase->stream;
2388 struct pcm_device *pcm_device;
2389 struct listnode *node;
2390 struct listnode *next;
2391
2392 list_for_each_safe(node, next, &out->pcm_dev_list) {
2393 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2394 list_remove(node);
2395 free(pcm_device);
2396 }
2397 list_init(&usecase->mixer_list);
2398
2399 return 0;
2400}
2401
2402static int uc_select_pcm_devices(struct audio_usecase *usecase)
2403
2404{
2405 struct stream_out *out = (struct stream_out *)usecase->stream;
2406 struct pcm_device *pcm_device;
2407 struct pcm_device_profile *pcm_profile;
2408 struct mixer_card *mixer_card;
2409 audio_devices_t devices = usecase->devices;
2410
2411 list_init(&usecase->mixer_list);
2412 list_init(&out->pcm_dev_list);
2413
2414 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2415 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002416 if (pcm_device == NULL) {
2417 return -ENOMEM;
2418 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002419 pcm_device->pcm_profile = pcm_profile;
2420 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2421 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2422 if (mixer_card == NULL) {
2423 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2424 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2425 }
2426 devices &= ~pcm_profile->devices;
2427 }
2428
2429 return 0;
2430}
2431
2432static int out_close_pcm_devices(struct stream_out *out)
2433{
2434 struct pcm_device *pcm_device;
2435 struct listnode *node;
2436 struct audio_device *adev = out->dev;
2437
2438 list_for_each(node, &out->pcm_dev_list) {
2439 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2440 if (pcm_device->sound_trigger_handle > 0) {
2441 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
2442 pcm_device->sound_trigger_handle = 0;
2443 }
2444 if (pcm_device->pcm) {
2445 pcm_close(pcm_device->pcm);
2446 pcm_device->pcm = NULL;
2447 }
2448 if (pcm_device->resampler) {
2449 release_resampler(pcm_device->resampler);
2450 pcm_device->resampler = NULL;
2451 }
2452 if (pcm_device->res_buffer) {
2453 free(pcm_device->res_buffer);
2454 pcm_device->res_buffer = NULL;
2455 }
2456 }
2457
2458 return 0;
2459}
2460
2461static int out_open_pcm_devices(struct stream_out *out)
2462{
2463 struct pcm_device *pcm_device;
2464 struct listnode *node;
2465 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002466 int pcm_device_card;
2467 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002468
2469 list_for_each(node, &out->pcm_dev_list) {
2470 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002471 pcm_device_card = pcm_device->pcm_profile->card;
2472 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002473
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002474 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2475 pcm_device_id = pcm_device_deep_buffer.id;
2476
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002477 if (out->dev->voice.in_call) {
2478 ALOGV("%s: in_call, not opening PCMs", __func__);
2479 return ret;
2480 }
2481
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002482 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2483 __func__, pcm_device_card, pcm_device_id);
2484
2485 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002486 PCM_OUT | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2487
2488 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2489 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2490 pcm_device->pcm = NULL;
2491 ret = -EIO;
2492 goto error_open;
2493 }
2494 /*
2495 * If the stream rate differs from the PCM rate, we need to
2496 * create a resampler.
2497 */
2498 if (out->sample_rate != pcm_device->pcm_profile->config.rate) {
2499 ALOGV("%s: create_resampler(), pcm_device_card(%d), pcm_device_id(%d), \
2500 out_rate(%d), device_rate(%d)",__func__,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002501 pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002502 out->sample_rate, pcm_device->pcm_profile->config.rate);
2503 ret = create_resampler(out->sample_rate,
2504 pcm_device->pcm_profile->config.rate,
2505 audio_channel_count_from_out_mask(out->channel_mask),
2506 RESAMPLER_QUALITY_DEFAULT,
2507 NULL,
2508 &pcm_device->resampler);
2509 pcm_device->res_byte_count = 0;
2510 pcm_device->res_buffer = NULL;
2511 }
2512 }
2513 return ret;
2514
2515error_open:
2516 out_close_pcm_devices(out);
2517 return ret;
2518}
2519
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002520int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002521{
2522 struct audio_device *adev = out->dev;
2523 struct audio_usecase *uc_info;
2524
2525 uc_info = get_usecase_from_id(adev, out->usecase);
2526 if (uc_info == NULL) {
2527 ALOGE("%s: Could not find the usecase (%d) in the list",
2528 __func__, out->usecase);
2529 return -EINVAL;
2530 }
2531 disable_snd_device(adev, uc_info, uc_info->out_snd_device, true);
2532 uc_release_pcm_devices(uc_info);
2533 list_remove(&uc_info->adev_list_node);
2534 free(uc_info);
2535
2536 return 0;
2537}
2538
Andreas Schneider56204f62017-01-31 08:17:32 +01002539int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002540{
2541 struct audio_device *adev = out->dev;
2542 struct audio_usecase *uc_info;
2543
2544 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002545 if (uc_info == NULL) {
2546 return -ENOMEM;
2547 }
2548
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002549 uc_info->id = out->usecase;
2550 uc_info->type = PCM_PLAYBACK;
2551 uc_info->stream = (struct audio_stream *)out;
2552 uc_info->devices = out->devices;
2553 uc_info->in_snd_device = SND_DEVICE_NONE;
2554 uc_info->out_snd_device = SND_DEVICE_NONE;
2555 uc_select_pcm_devices(uc_info);
2556
2557 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2558 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002559
2560 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002561}
2562
2563static int stop_output_stream(struct stream_out *out)
2564{
2565 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002566 bool do_disable = true;
2567
2568 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2569 out->usecase, use_case_table[out->usecase]);
2570
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002571 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002572
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002573 if (do_disable)
2574 ret = disable_output_path_l(out);
2575
2576 ALOGV("%s: exit: status(%d)", __func__, ret);
2577 return ret;
2578}
2579
2580static int start_output_stream(struct stream_out *out)
2581{
2582 int ret = 0;
2583 struct audio_device *adev = out->dev;
2584
2585 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2586 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2587
Andreas Schneider56204f62017-01-31 08:17:32 +01002588 ret = enable_output_path_l(out);
2589 if (ret != 0) {
2590 goto error_config;
2591 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002592
2593 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2594 out->compr = NULL;
2595 ret = out_open_pcm_devices(out);
2596 if (ret != 0)
2597 goto error_open;
2598#ifdef PREPROCESSING_ENABLED
2599 out->echo_reference = NULL;
2600 out->echo_reference_generation = adev->echo_reference_generation;
2601 if (adev->echo_reference != NULL)
2602 out->echo_reference = adev->echo_reference;
2603#endif
2604 } else {
2605 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2606 COMPRESS_IN, &out->compr_config);
2607 if (out->compr && !is_compress_ready(out->compr)) {
2608 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2609 compress_close(out->compr);
2610 out->compr = NULL;
2611 ret = -EIO;
2612 goto error_open;
2613 }
2614 if (out->offload_callback)
2615 compress_nonblock(out->compr, out->non_blocking);
2616
2617 if (adev->offload_fx_start_output != NULL)
2618 adev->offload_fx_start_output(out->handle);
2619 }
2620 ALOGV("%s: exit", __func__);
2621 return 0;
2622error_open:
2623 stop_output_stream(out);
2624error_config:
2625 return ret;
2626}
2627
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002628int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002629{
2630 struct audio_usecase *uc_info;
2631
2632 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002633 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002634
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002635 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002636
2637 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2638 if (uc_info == NULL) {
2639 ALOGE("%s: Could not find the usecase (%d) in the list",
2640 __func__, USECASE_VOICE_CALL);
2641 return -EINVAL;
2642 }
2643
2644 disable_snd_device(adev, uc_info, uc_info->out_snd_device, false);
2645 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2646
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002647 list_remove(&uc_info->adev_list_node);
2648 free(uc_info);
2649
2650 ALOGV("%s: exit", __func__);
2651 return 0;
2652}
2653
2654/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002655int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002656{
2657 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002658 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002659
2660 ALOGV("%s: enter", __func__);
2661
2662 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002663 if (uc_info == NULL) {
2664 ret = -ENOMEM;
2665 goto exit;
2666 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002667 /*
2668 * We set this early so that functions called after this is being set
2669 * can use it. It is e.g. needed in select_devices() to inform the RILD
2670 * which output device we use.
2671 */
2672 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002673
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002674 uc_info->id = USECASE_VOICE_CALL;
2675 uc_info->type = VOICE_CALL;
2676 uc_info->stream = (struct audio_stream *)adev->primary_output;
2677 uc_info->devices = adev->primary_output->devices;
2678 uc_info->in_snd_device = SND_DEVICE_NONE;
2679 uc_info->out_snd_device = SND_DEVICE_NONE;
2680
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002681 list_init(&uc_info->mixer_list);
2682 list_add_tail(&uc_info->mixer_list,
2683 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002684
2685 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2686
2687 select_devices(adev, USECASE_VOICE_CALL);
2688
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002689 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002690
2691 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002692 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002693
Andreas Schneider56204f62017-01-31 08:17:32 +01002694exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002695 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002696 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002697}
2698
2699static int check_input_parameters(uint32_t sample_rate,
2700 audio_format_t format,
2701 int channel_count)
2702{
2703 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2704
2705 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2706
2707 switch (sample_rate) {
2708 case 8000:
2709 case 11025:
2710 case 12000:
2711 case 16000:
2712 case 22050:
2713 case 24000:
2714 case 32000:
2715 case 44100:
2716 case 48000:
2717 break;
2718 default:
2719 return -EINVAL;
2720 }
2721
2722 return 0;
2723}
2724
2725static size_t get_input_buffer_size(uint32_t sample_rate,
2726 audio_format_t format,
2727 int channel_count,
2728 usecase_type_t usecase_type,
2729 audio_devices_t devices)
2730{
2731 size_t size = 0;
2732 struct pcm_device_profile *pcm_profile;
2733
2734 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2735 return 0;
2736
2737 pcm_profile = get_pcm_device(usecase_type, devices);
2738 if (pcm_profile == NULL)
2739 return 0;
2740
2741 /*
2742 * take resampling into account and return the closest majoring
2743 * multiple of 16 frames, as audioflinger expects audio buffers to
2744 * be a multiple of 16 frames
2745 */
2746 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2747 size = ((size + 15) / 16) * 16;
2748
2749 return (size * channel_count * audio_bytes_per_sample(format));
2750
2751}
2752
2753static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2754{
2755 struct stream_out *out = (struct stream_out *)stream;
2756
2757 return out->sample_rate;
2758}
2759
2760static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2761{
2762 (void)stream;
2763 (void)rate;
2764 return -ENOSYS;
2765}
2766
2767static size_t out_get_buffer_size(const struct audio_stream *stream)
2768{
2769 struct stream_out *out = (struct stream_out *)stream;
2770
2771 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2772 return out->compr_config.fragment_size;
2773 }
2774
2775 return out->config.period_size *
2776 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2777}
2778
2779static uint32_t out_get_channels(const struct audio_stream *stream)
2780{
2781 struct stream_out *out = (struct stream_out *)stream;
2782
2783 return out->channel_mask;
2784}
2785
2786static audio_format_t out_get_format(const struct audio_stream *stream)
2787{
2788 struct stream_out *out = (struct stream_out *)stream;
2789
2790 return out->format;
2791}
2792
2793static int out_set_format(struct audio_stream *stream, audio_format_t format)
2794{
2795 (void)stream;
2796 (void)format;
2797 return -ENOSYS;
2798}
2799
2800static int do_out_standby_l(struct stream_out *out)
2801{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002802 int status = 0;
2803
2804 out->standby = true;
2805 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2806 out_close_pcm_devices(out);
2807#ifdef PREPROCESSING_ENABLED
2808 /* stop writing to echo reference */
2809 if (out->echo_reference != NULL) {
2810 out->echo_reference->write(out->echo_reference, NULL);
2811 if (out->echo_reference_generation != adev->echo_reference_generation) {
2812 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2813 release_echo_reference(out->echo_reference);
2814 out->echo_reference_generation = adev->echo_reference_generation;
2815 }
2816 out->echo_reference = NULL;
2817 }
2818#endif
2819 } else {
2820 stop_compressed_output_l(out);
2821 out->gapless_mdata.encoder_delay = 0;
2822 out->gapless_mdata.encoder_padding = 0;
2823 if (out->compr != NULL) {
2824 compress_close(out->compr);
2825 out->compr = NULL;
2826 }
2827 }
2828 status = stop_output_stream(out);
2829
2830 return status;
2831}
2832
2833static int out_standby(struct audio_stream *stream)
2834{
2835 struct stream_out *out = (struct stream_out *)stream;
2836 struct audio_device *adev = out->dev;
2837
2838 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2839 out->usecase, use_case_table[out->usecase]);
2840 lock_output_stream(out);
2841 if (!out->standby) {
2842 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002843 amplifier_output_stream_standby((struct audio_stream_out *) stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002844 do_out_standby_l(out);
2845 pthread_mutex_unlock(&adev->lock);
2846 }
2847 pthread_mutex_unlock(&out->lock);
2848 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002849
2850 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2851
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002852 return 0;
2853}
2854
2855static int out_dump(const struct audio_stream *stream, int fd)
2856{
2857 (void)stream;
2858 (void)fd;
2859
2860 return 0;
2861}
2862
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002863static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2864{
2865 struct stream_out *out = (struct stream_out *)stream;
2866 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002867 struct listnode *node;
2868 struct str_parms *parms;
2869 char value[32];
2870 int ret, val = 0;
2871 struct audio_usecase *uc_info;
2872 bool do_standby = false;
2873 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002874#ifdef PREPROCESSING_ENABLED
2875 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2876#endif
2877
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002878 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%#x) "
2879 "adev->mode(%#x)",
2880 __func__, out->usecase, use_case_table[out->usecase], kvpairs,
2881 out->devices, adev->mode);
2882
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002883 parms = str_parms_create_str(kvpairs);
2884 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2885 if (ret >= 0) {
2886 val = atoi(value);
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002887
2888 ALOGV("%s: routing: usecase(%d: %s) devices=(%#x) adev->mode(%#x)",
2889 __func__, out->usecase, use_case_table[out->usecase], val,
2890 adev->mode);
2891
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002892 pthread_mutex_lock(&adev->lock_inputs);
2893 lock_output_stream(out);
2894 pthread_mutex_lock(&adev->lock);
2895#ifdef PREPROCESSING_ENABLED
2896 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2897 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2898 /* reset active input:
2899 * - to attach the echo reference
2900 * - because a change in output device may change mic settings */
2901 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2902 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2903 in = adev->active_input;
2904 }
2905 }
2906#endif
Christopher N. Hesse33affb82017-11-16 17:01:37 +01002907 if (val != SND_DEVICE_NONE) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002908 bool bt_sco_active = false;
2909
2910 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2911 bt_sco_active = true;
2912 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002913 out->devices = val;
2914
2915 if (!out->standby) {
2916 uc_info = get_usecase_from_id(adev, out->usecase);
2917 if (uc_info == NULL) {
2918 ALOGE("%s: Could not find the usecase (%d) in the list",
2919 __func__, out->usecase);
2920 } else {
2921 list_for_each(node, &out->pcm_dev_list) {
2922 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2923 if ((pcm_device->pcm_profile->devices & val) == 0)
2924 do_standby = true;
2925 val &= ~pcm_device->pcm_profile->devices;
2926 }
2927 if (val != 0)
2928 do_standby = true;
2929 }
2930 if (do_standby)
2931 do_out_standby_l(out);
2932 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002933 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2934 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002935 select_devices(adev, out->usecase);
2936 }
2937 }
2938
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002939 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002940 (out == adev->primary_output)) {
2941 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002942 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2943 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002944 (out == adev->primary_output)) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002945 /* Turn on bluetooth if needed */
2946 if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002947 select_devices(adev, USECASE_VOICE_CALL);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002948 start_voice_session_bt_sco(adev->voice.session);
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002949 } else {
2950 /*
2951 * When we select different devices we need to restart the
2952 * voice call. The modem closes the stream on its end and
2953 * we do not get any output.
2954 */
2955 stop_voice_call(adev);
2956 start_voice_call(adev);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002957 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002958 }
2959 }
2960
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002961 pthread_mutex_unlock(&adev->lock);
2962 pthread_mutex_unlock(&out->lock);
2963#ifdef PREPROCESSING_ENABLED
2964 if (in) {
2965 /* The lock on adev->lock_inputs prevents input stream from being closed */
2966 lock_input_stream(in);
2967 pthread_mutex_lock(&adev->lock);
2968 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2969 do_in_standby_l(in);
2970 pthread_mutex_unlock(&adev->lock);
2971 pthread_mutex_unlock(&in->lock);
2972 }
2973#endif
2974 pthread_mutex_unlock(&adev->lock_inputs);
2975 }
2976
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002977 amplifier_set_parameters(parms);
2978
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002979 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2980 parse_compress_metadata(out, parms);
2981 }
2982
2983 str_parms_destroy(parms);
2984
2985 if (ret > 0)
2986 ret = 0;
2987 ALOGV("%s: exit: code(%d)", __func__, ret);
2988 return ret;
2989}
2990
2991static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2992{
2993 struct stream_out *out = (struct stream_out *)stream;
2994 struct str_parms *query = str_parms_create_str(keys);
2995 char *str;
2996 char value[256];
2997 struct str_parms *reply = str_parms_create();
2998 size_t i, j;
2999 int ret;
3000 bool first = true;
3001 ALOGV("%s: enter: keys - %s", __func__, keys);
3002 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
3003 if (ret >= 0) {
3004 value[0] = '\0';
3005 i = 0;
3006 while (out->supported_channel_masks[i] != 0) {
3007 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
3008 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
3009 if (!first) {
3010 strcat(value, "|");
3011 }
3012 strcat(value, out_channels_name_to_enum_table[j].name);
3013 first = false;
3014 break;
3015 }
3016 }
3017 i++;
3018 }
3019 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
3020 str = str_parms_to_str(reply);
3021 } else {
3022 str = strdup(keys);
3023 }
3024 str_parms_destroy(query);
3025 str_parms_destroy(reply);
3026 ALOGV("%s: exit: returns - %s", __func__, str);
3027 return str;
3028}
3029
3030static uint32_t out_get_latency(const struct audio_stream_out *stream)
3031{
3032 struct stream_out *out = (struct stream_out *)stream;
3033
3034 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3035 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
3036
3037 return (out->config.period_count * out->config.period_size * 1000) /
3038 (out->config.rate);
3039}
3040
3041static int out_set_volume(struct audio_stream_out *stream, float left,
3042 float right)
3043{
3044 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003045
3046 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
3047 /* only take left channel into account: the API is for stereo anyway */
3048 out->muted = (left == 0.0f);
3049 return 0;
3050 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003051 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003052 }
3053
3054 return -ENOSYS;
3055}
3056
Andreas Schneider3b643832017-01-31 11:48:22 +01003057#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003058static int fast_set_affinity(pid_t tid) {
3059 cpu_set_t cpu_set;
3060 int cpu_num;
3061 const char *irq_procfs = "/proc/asound/irq_affinity";
3062 FILE *fp;
3063
3064 if ((fp = fopen(irq_procfs, "r")) == NULL) {
3065 ALOGW("Procfs node %s not found", irq_procfs);
3066 return -1;
3067 }
3068
3069 if (fscanf(fp, "%d", &cpu_num) != 1) {
3070 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
3071 fclose(fp);
3072 return -1;
3073 }
3074 fclose(fp);
3075
3076 CPU_ZERO(&cpu_set);
3077 CPU_SET(cpu_num, &cpu_set);
3078 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
3079}
Andreas Schneider3b643832017-01-31 11:48:22 +01003080#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003081
3082static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3083 size_t bytes)
3084{
3085 struct stream_out *out = (struct stream_out *)stream;
3086 struct audio_device *adev = out->dev;
3087 ssize_t ret = 0;
3088 struct pcm_device *pcm_device;
3089 struct listnode *node;
3090 size_t frame_size = audio_stream_out_frame_size(stream);
3091 size_t frames_wr = 0, frames_rq = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003092#ifdef PREPROCESSING_ENABLED
3093 size_t in_frames = bytes / frame_size;
3094 size_t out_frames = in_frames;
3095 struct stream_in *in = NULL;
3096#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003097
3098 lock_output_stream(out);
3099
Andreas Schneider3b643832017-01-31 11:48:22 +01003100#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003101 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003102 pid_t tid = gettid();
3103 int err;
3104
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003105 err = fast_set_affinity(tid);
3106 if (err < 0) {
3107 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3108 }
3109 out->is_fastmixer_affinity_set = true;
3110 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003111#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003112
3113 if (out->standby) {
3114#ifdef PREPROCESSING_ENABLED
3115 pthread_mutex_unlock(&out->lock);
3116 /* Prevent input stream from being closed */
3117 pthread_mutex_lock(&adev->lock_inputs);
3118 lock_output_stream(out);
3119 if (!out->standby) {
3120 pthread_mutex_unlock(&adev->lock_inputs);
3121 goto false_alarm;
3122 }
3123#endif
3124 pthread_mutex_lock(&adev->lock);
3125 ret = start_output_stream(out);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003126 if (ret == 0) {
3127 amplifier_output_stream_start(stream, out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD);
3128 }
3129
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003130 /* ToDo: If use case is compress offload should return 0 */
3131 if (ret != 0) {
3132 pthread_mutex_unlock(&adev->lock);
3133#ifdef PREPROCESSING_ENABLED
3134 pthread_mutex_unlock(&adev->lock_inputs);
3135#endif
3136 goto exit;
3137 }
3138 out->standby = false;
3139
3140#ifdef PREPROCESSING_ENABLED
3141 /* A change in output device may change the microphone selection */
3142 if (adev->active_input &&
3143 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3144 adev->active_input->source == AUDIO_SOURCE_MIC)) {
3145 in = adev->active_input;
3146 ALOGV("%s: enter:) force_input_standby true", __func__);
3147 }
3148#endif
3149 pthread_mutex_unlock(&adev->lock);
3150#ifdef PREPROCESSING_ENABLED
3151 if (!in) {
3152 /* Leave mutex locked iff in != NULL */
3153 pthread_mutex_unlock(&adev->lock_inputs);
3154 }
3155#endif
3156 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003157#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003158false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003159#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003160
3161 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003162 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003163 return ret;
3164 } else {
3165#ifdef PREPROCESSING_ENABLED
3166 if (android_atomic_acquire_load(&adev->echo_reference_generation)
3167 != out->echo_reference_generation) {
3168 pthread_mutex_lock(&adev->lock);
3169 if (out->echo_reference != NULL) {
3170 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
3171 release_echo_reference(out->echo_reference);
3172 }
3173 // note that adev->echo_reference_generation here can be different from the one
3174 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
3175 // with what has been set by get_echo_reference() or put_echo_reference()
3176 out->echo_reference_generation = adev->echo_reference_generation;
3177 out->echo_reference = adev->echo_reference;
3178 ALOGV("%s: update echo reference generation %d", __func__,
3179 out->echo_reference_generation);
3180 pthread_mutex_unlock(&adev->lock);
3181 }
3182#endif
3183
3184 if (out->muted)
3185 memset((void *)buffer, 0, bytes);
3186 list_for_each(node, &out->pcm_dev_list) {
3187 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3188 if (pcm_device->resampler) {
3189 if (bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size
3190 > pcm_device->res_byte_count) {
3191 pcm_device->res_byte_count =
3192 bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size;
3193 pcm_device->res_buffer =
3194 realloc(pcm_device->res_buffer, pcm_device->res_byte_count);
3195 ALOGV("%s: resampler res_byte_count = %zu", __func__,
3196 pcm_device->res_byte_count);
3197 }
3198 frames_rq = bytes / frame_size;
3199 frames_wr = pcm_device->res_byte_count / frame_size;
3200 ALOGVV("%s: resampler request frames = %d frame_size = %d",
3201 __func__, frames_rq, frame_size);
3202 pcm_device->resampler->resample_from_input(pcm_device->resampler,
3203 (int16_t *)buffer, &frames_rq, (int16_t *)pcm_device->res_buffer, &frames_wr);
3204 ALOGVV("%s: resampler output frames_= %d", __func__, frames_wr);
3205 }
3206 if (pcm_device->pcm) {
3207#ifdef PREPROCESSING_ENABLED
3208 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
3209 struct echo_reference_buffer b;
3210 b.raw = (void *)buffer;
3211 b.frame_count = in_frames;
3212
3213 get_playback_delay(out, out_frames, &b);
3214 out->echo_reference->write(out->echo_reference, &b);
3215 }
3216#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003217 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
3218 if (pcm_device->resampler && pcm_device->res_buffer)
3219 pcm_device->status =
3220 pcm_write(pcm_device->pcm, (void *)pcm_device->res_buffer,
3221 frames_wr * frame_size);
3222 else
3223 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
3224 if (pcm_device->status != 0)
3225 ret = pcm_device->status;
3226 }
3227 }
3228 if (ret == 0)
3229 out->written += bytes / (out->config.channels * sizeof(short));
3230 }
3231
3232exit:
3233 pthread_mutex_unlock(&out->lock);
3234
3235 if (ret != 0) {
3236 list_for_each(node, &out->pcm_dev_list) {
3237 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3238 if (pcm_device->pcm && pcm_device->status != 0)
3239 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
3240 }
3241 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003242 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3243 clock_gettime(CLOCK_MONOTONIC, &t);
3244 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3245 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
3246 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
3247 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
3248 if (sleep_time > 0) {
3249 usleep(sleep_time);
3250 } else {
3251 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
3252 sleep_time = 0;
3253 }
3254 out->last_write_time_us = now + sleep_time;
3255 // last_write_time_us is an approximation of when the (simulated) alsa
3256 // buffer is believed completely full. The usleep above waits for more space
3257 // in the buffer, but by the end of the sleep the buffer is considered
3258 // topped-off.
3259 //
3260 // On the subsequent out_write(), we measure the elapsed time spent in
3261 // the mixer. This is subtracted from the sleep estimate based on frames,
3262 // thereby accounting for drain in the alsa buffer during mixing.
3263 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003264 }
3265
3266#ifdef PREPROCESSING_ENABLED
3267 if (in) {
3268 /* The lock on adev->lock_inputs prevents input stream from being closed */
3269 lock_input_stream(in);
3270 pthread_mutex_lock(&adev->lock);
3271 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3272 do_in_standby_l(in);
3273 pthread_mutex_unlock(&adev->lock);
3274 pthread_mutex_unlock(&in->lock);
3275 /* This mutex was left locked iff in != NULL */
3276 pthread_mutex_unlock(&adev->lock_inputs);
3277 }
3278#endif
3279
3280 return bytes;
3281}
3282
3283static int out_get_render_position(const struct audio_stream_out *stream,
3284 uint32_t *dsp_frames)
3285{
3286 struct stream_out *out = (struct stream_out *)stream;
3287 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003288 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3289 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003290 } else
3291 return -EINVAL;
3292}
3293
3294static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3295{
3296 (void)stream;
3297 (void)effect;
3298 return 0;
3299}
3300
3301static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3302{
3303 (void)stream;
3304 (void)effect;
3305 return 0;
3306}
3307
3308static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3309 int64_t *timestamp)
3310{
3311 (void)stream;
3312 (void)timestamp;
3313 return -EINVAL;
3314}
3315
3316static int out_get_presentation_position(const struct audio_stream_out *stream,
3317 uint64_t *frames, struct timespec *timestamp)
3318{
3319 struct stream_out *out = (struct stream_out *)stream;
3320 int ret = -1;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003321
3322 lock_output_stream(out);
3323
3324 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003325 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003326 } else {
Andreas Schneider97fa7f12017-02-11 14:21:56 +01003327 if (out->dev->voice.in_call) {
3328 ALOGVV("%s: in_call, do not handle PCMs", __func__);
3329 ret = 0;
3330 goto done;
3331 }
3332
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003333 /* FIXME: which device to read from? */
3334 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003335 struct pcm_device *pcm_device;
3336 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003337 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003338
Andreas Schneiderd6359182017-02-08 16:58:22 +01003339 list_for_each(node, &out->pcm_dev_list) {
3340 pcm_device = node_to_item(node,
3341 struct pcm_device,
3342 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003343
Andreas Schneiderd6359182017-02-08 16:58:22 +01003344 if (pcm_device->pcm != NULL) {
3345 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3346 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3347 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3348 /* This adjustment accounts for buffering after app processor.
3349 It is based on estimated DSP latency per use case, rather than exact. */
3350 signed_frames -=
3351 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3352
3353 /* It would be unusual for this value to be negative, but check just in case ... */
3354 if (signed_frames >= 0) {
3355 *frames = signed_frames;
3356 ret = 0;
3357 goto done;
3358 }
3359 ret = -1;
3360 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003361 }
3362 }
3363 }
3364 }
3365
Andreas Schneiderd6359182017-02-08 16:58:22 +01003366done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003367 pthread_mutex_unlock(&out->lock);
3368
3369 return ret;
3370}
3371
3372static int out_set_callback(struct audio_stream_out *stream,
3373 stream_callback_t callback, void *cookie)
3374{
3375 struct stream_out *out = (struct stream_out *)stream;
3376
3377 ALOGV("%s", __func__);
3378 lock_output_stream(out);
3379 out->offload_callback = callback;
3380 out->offload_cookie = cookie;
3381 pthread_mutex_unlock(&out->lock);
3382 return 0;
3383}
3384
3385static int out_pause(struct audio_stream_out* stream)
3386{
3387 struct stream_out *out = (struct stream_out *)stream;
3388 int status = -ENOSYS;
3389 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003390 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3391 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003392 return status;
3393}
3394
3395static int out_resume(struct audio_stream_out* stream)
3396{
3397 struct stream_out *out = (struct stream_out *)stream;
3398 int status = -ENOSYS;
3399 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003400 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3401 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003402 return status;
3403}
3404
3405static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3406{
3407 struct stream_out *out = (struct stream_out *)stream;
3408 int status = -ENOSYS;
3409 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003410 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3411 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003412 return status;
3413}
3414
3415static int out_flush(struct audio_stream_out* stream)
3416{
3417 struct stream_out *out = (struct stream_out *)stream;
3418 ALOGV("%s", __func__);
3419 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003420 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003421 }
3422 return -ENOSYS;
3423}
3424
3425/** audio_stream_in implementation **/
3426static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3427{
3428 struct stream_in *in = (struct stream_in *)stream;
3429
3430 return in->requested_rate;
3431}
3432
3433static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3434{
3435 (void)stream;
3436 (void)rate;
3437 return -ENOSYS;
3438}
3439
3440static uint32_t in_get_channels(const struct audio_stream *stream)
3441{
3442 struct stream_in *in = (struct stream_in *)stream;
3443
3444 return in->main_channels;
3445}
3446
3447static audio_format_t in_get_format(const struct audio_stream *stream)
3448{
3449 (void)stream;
3450 return AUDIO_FORMAT_PCM_16_BIT;
3451}
3452
3453static int in_set_format(struct audio_stream *stream, audio_format_t format)
3454{
3455 (void)stream;
3456 (void)format;
3457
3458 return -ENOSYS;
3459}
3460
3461static size_t in_get_buffer_size(const struct audio_stream *stream)
3462{
3463 struct stream_in *in = (struct stream_in *)stream;
3464
3465 return get_input_buffer_size(in->requested_rate,
3466 in_get_format(stream),
3467 audio_channel_count_from_in_mask(in->main_channels),
3468 in->usecase_type,
3469 in->devices);
3470}
3471
3472static int in_close_pcm_devices(struct stream_in *in)
3473{
3474 struct pcm_device *pcm_device;
3475 struct listnode *node;
3476 struct audio_device *adev = in->dev;
3477
3478 list_for_each(node, &in->pcm_dev_list) {
3479 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3480 if (pcm_device) {
3481 if (pcm_device->pcm)
3482 pcm_close(pcm_device->pcm);
3483 pcm_device->pcm = NULL;
3484 if (pcm_device->sound_trigger_handle > 0)
3485 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
3486 pcm_device->sound_trigger_handle = 0;
3487 }
3488 }
3489 return 0;
3490}
3491
3492
3493/* must be called with stream and hw device mutex locked */
3494static int do_in_standby_l(struct stream_in *in)
3495{
3496 int status = 0;
3497
3498#ifdef PREPROCESSING_ENABLED
3499 struct audio_device *adev = in->dev;
3500#endif
3501 if (!in->standby) {
3502
3503 in_close_pcm_devices(in);
3504
3505#ifdef PREPROCESSING_ENABLED
3506 if (in->echo_reference != NULL) {
3507 /* stop reading from echo reference */
3508 in->echo_reference->read(in->echo_reference, NULL);
3509 put_echo_reference(adev, in->echo_reference);
3510 in->echo_reference = NULL;
3511 }
3512#ifdef HW_AEC_LOOPBACK
3513 if (in->hw_echo_reference)
3514 {
3515 if (in->hw_ref_buf) {
3516 free(in->hw_ref_buf);
3517 in->hw_ref_buf = NULL;
3518 }
3519 }
3520#endif // HW_AEC_LOOPBACK
3521#endif // PREPROCESSING_ENABLED
3522
3523 status = stop_input_stream(in);
3524
3525 if (in->read_buf) {
3526 free(in->read_buf);
3527 in->read_buf = NULL;
3528 }
3529
3530 in->standby = 1;
3531 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003532
3533 in->last_read_time_us = 0;
3534
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003535 return 0;
3536}
3537
3538// called with adev->lock_inputs locked
3539static int in_standby_l(struct stream_in *in)
3540{
3541 struct audio_device *adev = in->dev;
3542 int status = 0;
3543 lock_input_stream(in);
3544 if (!in->standby) {
3545 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003546 amplifier_input_stream_standby((struct audio_stream_in *) in);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003547 status = do_in_standby_l(in);
3548 pthread_mutex_unlock(&adev->lock);
3549 }
3550 pthread_mutex_unlock(&in->lock);
3551 return status;
3552}
3553
3554static int in_standby(struct audio_stream *stream)
3555{
3556 struct stream_in *in = (struct stream_in *)stream;
3557 struct audio_device *adev = in->dev;
3558 int status;
3559 ALOGV("%s: enter", __func__);
3560 pthread_mutex_lock(&adev->lock_inputs);
3561 status = in_standby_l(in);
3562 pthread_mutex_unlock(&adev->lock_inputs);
3563 ALOGV("%s: exit: status(%d)", __func__, status);
3564 return status;
3565}
3566
3567static int in_dump(const struct audio_stream *stream, int fd)
3568{
3569 (void)stream;
3570 (void)fd;
3571
3572 return 0;
3573}
3574
3575static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3576{
3577 struct stream_in *in = (struct stream_in *)stream;
3578 struct audio_device *adev = in->dev;
3579 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003580 char value[32];
3581 int ret, val = 0;
3582 struct audio_usecase *uc_info;
3583 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003584 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003585
3586 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3587 parms = str_parms_create_str(kvpairs);
3588
3589 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3590
3591 pthread_mutex_lock(&adev->lock_inputs);
3592 lock_input_stream(in);
3593 pthread_mutex_lock(&adev->lock);
3594 if (ret >= 0) {
3595 val = atoi(value);
3596 /* no audio source uses val == 0 */
3597 if (((int)in->source != val) && (val != 0)) {
3598 in->source = val;
3599 }
3600 }
3601
3602 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3603 if (ret >= 0) {
3604 val = atoi(value);
3605 if (((int)in->devices != val) && (val != 0)) {
3606 in->devices = val;
3607 /* If recording is in progress, change the tx device to new device */
3608 if (!in->standby) {
3609 uc_info = get_usecase_from_id(adev, in->usecase);
3610 if (uc_info == NULL) {
3611 ALOGE("%s: Could not find the usecase (%d) in the list",
3612 __func__, in->usecase);
3613 } else {
3614 if (list_empty(&in->pcm_dev_list))
3615 ALOGE("%s: pcm device list empty", __func__);
3616 else {
3617 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3618 struct pcm_device, stream_list_node);
3619 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3620 do_standby = true;
3621 }
3622 }
3623 }
3624 if (do_standby) {
3625 ret = do_in_standby_l(in);
3626 } else
3627 ret = select_devices(adev, in->usecase);
3628 }
3629 }
3630 }
3631 pthread_mutex_unlock(&adev->lock);
3632 pthread_mutex_unlock(&in->lock);
3633 pthread_mutex_unlock(&adev->lock_inputs);
3634 str_parms_destroy(parms);
3635
3636 if (ret > 0)
3637 ret = 0;
3638
3639 ALOGV("%s: exit: status(%d)", __func__, ret);
3640 return ret;
3641}
3642
3643static char* in_get_parameters(const struct audio_stream *stream,
3644 const char *keys)
3645{
3646 (void)stream;
3647 (void)keys;
3648
3649 return strdup("");
3650}
3651
3652static int in_set_gain(struct audio_stream_in *stream, float gain)
3653{
3654 (void)stream;
3655 (void)gain;
3656
3657 return 0;
3658}
3659
3660static ssize_t read_bytes_from_dsp(struct stream_in *in, void* buffer,
3661 size_t bytes)
3662{
3663 struct pcm_device *pcm_device;
3664 struct audio_device *adev = in->dev;
3665
3666 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3667 struct pcm_device, stream_list_node);
3668
3669 if (pcm_device->sound_trigger_handle > 0)
3670 return adev->sound_trigger_read_samples(pcm_device->sound_trigger_handle, buffer, bytes);
3671 else
3672 return 0;
3673}
3674
3675static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3676 size_t bytes)
3677{
3678 struct stream_in *in = (struct stream_in *)stream;
3679 struct audio_device *adev = in->dev;
3680 ssize_t frames = -1;
3681 int ret = -1;
3682 int read_and_process_successful = false;
3683
3684 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003685
3686 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3687 lock_input_stream(in);
3688
Andreas Schneider3b643832017-01-31 11:48:22 +01003689#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003690 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003691 pid_t tid = gettid();
3692 int err;
3693
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003694 err = fast_set_affinity(tid);
3695 if (err < 0) {
3696 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3697 }
3698 in->is_fastcapture_affinity_set = true;
3699 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003700#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003701
3702 if (in->standby) {
3703 pthread_mutex_unlock(&in->lock);
3704 pthread_mutex_lock(&adev->lock_inputs);
3705 lock_input_stream(in);
3706 if (!in->standby) {
3707 pthread_mutex_unlock(&adev->lock_inputs);
3708 goto false_alarm;
3709 }
3710 pthread_mutex_lock(&adev->lock);
3711 ret = start_input_stream(in);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003712 if (ret == 0) {
3713 amplifier_input_stream_start(stream);
3714 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003715 pthread_mutex_unlock(&adev->lock);
3716 pthread_mutex_unlock(&adev->lock_inputs);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003717
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003718 if (ret != 0) {
3719 goto exit;
3720 }
3721 in->standby = 0;
3722 }
3723false_alarm:
3724
3725 if (!list_empty(&in->pcm_dev_list)) {
3726 if (in->usecase == USECASE_AUDIO_CAPTURE_HOTWORD) {
3727 bytes = read_bytes_from_dsp(in, buffer, bytes);
3728 if (bytes > 0)
3729 read_and_process_successful = true;
3730 } else {
3731 /*
3732 * Read PCM and:
3733 * - resample if needed
3734 * - process if pre-processors are attached
3735 * - discard unwanted channels
3736 */
3737 frames = read_and_process_frames(in, buffer, frames_rq);
3738 if (frames >= 0)
3739 read_and_process_successful = true;
3740 }
3741 }
3742
3743 /*
3744 * Instead of writing zeroes here, we could trust the hardware
3745 * to always provide zeroes when muted.
3746 */
3747 if (read_and_process_successful == true && adev->mic_mute)
3748 memset(buffer, 0, bytes);
3749
3750exit:
3751 pthread_mutex_unlock(&in->lock);
3752
3753 if (read_and_process_successful == false) {
3754 in_standby(&in->stream.common);
3755 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003756 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3757 clock_gettime(CLOCK_MONOTONIC, &t);
3758 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3759
3760 // we do a full sleep when exiting standby.
3761 const bool standby = in->last_read_time_us == 0;
3762 const int64_t elapsed_time_since_last_read = standby ?
3763 0 : now - in->last_read_time_us;
3764 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3765 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3766 if (sleep_time > 0) {
3767 usleep(sleep_time);
3768 } else {
3769 sleep_time = 0;
3770 }
3771 in->last_read_time_us = now + sleep_time;
3772 // last_read_time_us is an approximation of when the (simulated) alsa
3773 // buffer is drained by the read, and is empty.
3774 //
3775 // On the subsequent in_read(), we measure the elapsed time spent in
3776 // the recording thread. This is subtracted from the sleep estimate based on frames,
3777 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003778 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003779 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003780
3781 if (bytes > 0) {
3782 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3783 }
3784
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003785 return bytes;
3786}
3787
3788static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3789{
3790 (void)stream;
3791
3792 return 0;
3793}
3794
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003795static int in_get_capture_position(const struct audio_stream_in *stream,
3796 int64_t *frames, int64_t *time)
3797{
3798 if (stream == NULL || frames == NULL || time == NULL) {
3799 return -EINVAL;
3800 }
3801
3802 struct stream_in *in = (struct stream_in *)stream;
3803 struct pcm_device *pcm_device;
3804 int ret = -ENOSYS;
3805
3806 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3807 struct pcm_device, stream_list_node);
3808
3809 pthread_mutex_lock(&in->lock);
3810 if (pcm_device->pcm) {
3811 struct timespec timestamp;
3812 unsigned int avail;
3813 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3814 *frames = in->frames_read + avail;
3815 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3816 ret = 0;
3817 }
3818 }
3819
3820 pthread_mutex_unlock(&in->lock);
3821 return ret;
3822}
3823
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003824static int add_remove_audio_effect(const struct audio_stream *stream,
3825 effect_handle_t effect,
3826 bool enable)
3827{
3828 struct stream_in *in = (struct stream_in *)stream;
3829 struct audio_device *adev = in->dev;
3830 int status = 0;
3831 effect_descriptor_t desc;
3832#ifdef PREPROCESSING_ENABLED
3833 int i;
3834#endif
3835 status = (*effect)->get_descriptor(effect, &desc);
3836 if (status != 0)
3837 return status;
3838
3839 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3840
3841 pthread_mutex_lock(&adev->lock_inputs);
3842 lock_input_stream(in);
3843 pthread_mutex_lock(&in->dev->lock);
3844#ifndef PREPROCESSING_ENABLED
3845 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3846 in->enable_aec != enable &&
3847 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3848 in->enable_aec = enable;
3849 if (!in->standby)
3850 select_devices(in->dev, in->usecase);
3851 }
3852#else
3853 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3854 status = -ENOSYS;
3855 goto exit;
3856 }
3857 if ( enable == true ) {
3858 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3859 /* add the supported channel of the effect in the channel_configs */
3860 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3861 in->num_preprocessors ++;
3862 /* check compatibility between main channel supported and possible auxiliary channels */
3863 in_update_aux_channels(in, effect);//wesley crash
3864 in->aux_channels_changed = true;
3865 } else {
3866 /* if ( enable == false ) */
3867 if (in->num_preprocessors <= 0) {
3868 status = -ENOSYS;
3869 goto exit;
3870 }
3871 status = -EINVAL;
3872 for (i=0; i < in->num_preprocessors; i++) {
3873 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3874 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3875 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3876 in->preprocessors[i - 1].num_channel_configs =
3877 in->preprocessors[i].num_channel_configs;
3878 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3879 continue;
3880 }
3881 if ( in->preprocessors[i].effect_itfe == effect ) {
3882 ALOGV("add_remove_audio_effect found fx at index %d", i);
3883 free(in->preprocessors[i].channel_configs);
3884 status = 0;
3885 }
3886 }
3887 if (status != 0)
3888 goto exit;
3889 in->num_preprocessors--;
3890 /* if we remove one effect, at least the last proproc should be reset */
3891 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3892 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3893 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3894 in->aux_channels_changed = false;
3895 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3896 }
3897 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3898
3899 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3900 in->enable_aec = enable;
3901 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3902 if (!in->standby) {
3903 select_devices(in->dev, in->usecase);
3904 do_in_standby_l(in);
3905 }
3906 if (in->enable_aec == true) {
3907 in_configure_reverse(in);
3908 }
3909 }
3910exit:
3911#endif
3912 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3913 pthread_mutex_unlock(&in->dev->lock);
3914 pthread_mutex_unlock(&in->lock);
3915 pthread_mutex_unlock(&adev->lock_inputs);
3916 return status;
3917}
3918
3919static int in_add_audio_effect(const struct audio_stream *stream,
3920 effect_handle_t effect)
3921{
3922 ALOGV("%s: effect %p", __func__, effect);
3923 return add_remove_audio_effect(stream, effect, true);
3924}
3925
3926static int in_remove_audio_effect(const struct audio_stream *stream,
3927 effect_handle_t effect)
3928{
3929 ALOGV("%s: effect %p", __func__, effect);
3930 return add_remove_audio_effect(stream, effect, false);
3931}
3932
3933static int adev_open_output_stream(struct audio_hw_device *dev,
3934 audio_io_handle_t handle,
3935 audio_devices_t devices,
3936 audio_output_flags_t flags,
3937 struct audio_config *config,
3938 struct audio_stream_out **stream_out,
3939 const char *address __unused)
3940{
3941 struct audio_device *adev = (struct audio_device *)dev;
3942 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003943 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003944 struct pcm_device_profile *pcm_profile;
3945
3946 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3947 __func__, config->sample_rate, config->channel_mask, devices, flags);
3948 *stream_out = NULL;
3949 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003950 if (out == NULL) {
3951 ret = -ENOMEM;
3952 goto error_config;
3953 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003954
3955 if (devices == AUDIO_DEVICE_NONE)
3956 devices = AUDIO_DEVICE_OUT_SPEAKER;
3957
3958 out->flags = flags;
3959 out->devices = devices;
3960 out->dev = adev;
3961 out->format = config->format;
3962 out->sample_rate = config->sample_rate;
3963 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3964 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3965 out->handle = handle;
3966
3967 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3968 if (pcm_profile == NULL) {
3969 ret = -EINVAL;
3970 goto error_open;
3971 }
3972 out->config = pcm_profile->config;
3973
3974 /* Init use case and pcm_config */
3975 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3976 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3977 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3978 ALOGE("%s: Unsupported Offload information", __func__);
3979 ret = -EINVAL;
3980 goto error_open;
3981 }
3982 if (!is_supported_format(config->offload_info.format)) {
3983 ALOGE("%s: Unsupported audio format", __func__);
3984 ret = -EINVAL;
3985 goto error_open;
3986 }
3987
3988 out->compr_config.codec = (struct snd_codec *)
3989 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003990 if (out->compr_config.codec == NULL) {
3991 ret = -ENOMEM;
3992 goto error_open;
3993 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003994
3995 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3996 if (config->offload_info.channel_mask)
3997 out->channel_mask = config->offload_info.channel_mask;
3998 else if (config->channel_mask)
3999 out->channel_mask = config->channel_mask;
4000 out->format = config->offload_info.format;
4001 out->sample_rate = config->offload_info.sample_rate;
4002
4003 out->stream.set_callback = out_set_callback;
4004 out->stream.pause = out_pause;
4005 out->stream.resume = out_resume;
4006 out->stream.drain = out_drain;
4007 out->stream.flush = out_flush;
4008
4009 out->compr_config.codec->id =
4010 get_snd_codec_id(config->offload_info.format);
4011 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4012 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4013 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
4014 out->compr_config.codec->bit_rate =
4015 config->offload_info.bit_rate;
4016 out->compr_config.codec->ch_in =
4017 audio_channel_count_from_out_mask(config->channel_mask);
4018 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4019
4020 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4021 out->non_blocking = 1;
4022
4023 out->send_new_metadata = 1;
4024 create_offload_callback_thread(out);
4025 out->offload_state = OFFLOAD_STATE_IDLE;
4026
4027 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4028 __func__, config->offload_info.version,
4029 config->offload_info.bit_rate);
4030 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
4031 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01004032 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004033 out->sample_rate = out->config.rate;
4034 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
4035 } else {
4036 out->usecase = USECASE_AUDIO_PLAYBACK;
4037 out->sample_rate = out->config.rate;
4038 }
4039
4040 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
4041 if (adev->primary_output == NULL)
4042 adev->primary_output = out;
4043 else {
4044 ALOGE("%s: Primary output is already opened", __func__);
4045 ret = -EEXIST;
4046 goto error_open;
4047 }
4048 }
4049
4050 /* Check if this usecase is already existing */
4051 pthread_mutex_lock(&adev->lock);
4052 if (get_usecase_from_id(adev, out->usecase) != NULL) {
4053 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
4054 pthread_mutex_unlock(&adev->lock);
4055 ret = -EEXIST;
4056 goto error_open;
4057 }
4058 pthread_mutex_unlock(&adev->lock);
4059
4060 out->stream.common.get_sample_rate = out_get_sample_rate;
4061 out->stream.common.set_sample_rate = out_set_sample_rate;
4062 out->stream.common.get_buffer_size = out_get_buffer_size;
4063 out->stream.common.get_channels = out_get_channels;
4064 out->stream.common.get_format = out_get_format;
4065 out->stream.common.set_format = out_set_format;
4066 out->stream.common.standby = out_standby;
4067 out->stream.common.dump = out_dump;
4068 out->stream.common.set_parameters = out_set_parameters;
4069 out->stream.common.get_parameters = out_get_parameters;
4070 out->stream.common.add_audio_effect = out_add_audio_effect;
4071 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4072 out->stream.get_latency = out_get_latency;
4073 out->stream.set_volume = out_set_volume;
4074 out->stream.write = out_write;
4075 out->stream.get_render_position = out_get_render_position;
4076 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
4077 out->stream.get_presentation_position = out_get_presentation_position;
4078
4079 out->standby = 1;
4080 /* out->muted = false; by calloc() */
4081 /* out->written = 0; by calloc() */
4082
4083 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
4084 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
4085 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4086
4087 config->format = out->stream.common.get_format(&out->stream.common);
4088 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4089 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4090
4091 out->is_fastmixer_affinity_set = false;
4092
4093 *stream_out = &out->stream;
4094 ALOGV("%s: exit", __func__);
4095 return 0;
4096
4097error_open:
4098 free(out);
4099 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01004100error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004101 ALOGV("%s: exit: ret %d", __func__, ret);
4102 return ret;
4103}
4104
4105static void adev_close_output_stream(struct audio_hw_device *dev,
4106 struct audio_stream_out *stream)
4107{
4108 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004109 (void)dev;
4110
4111 ALOGV("%s: enter", __func__);
4112 out_standby(&stream->common);
4113 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4114 destroy_offload_callback_thread(out);
4115
4116 if (out->compr_config.codec != NULL)
4117 free(out->compr_config.codec);
4118 }
4119 pthread_cond_destroy(&out->cond);
4120 pthread_mutex_destroy(&out->lock);
4121 free(stream);
4122 ALOGV("%s: exit", __func__);
4123}
4124
4125static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4126{
4127 struct audio_device *adev = (struct audio_device *)dev;
4128 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004129 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01004130#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004131 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01004132#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004133 int ret;
4134
4135 ALOGV("%s: enter: %s", __func__, kvpairs);
4136
4137 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004138
Andreas Schneider05bc1882017-02-09 14:03:11 +01004139 /******************************************************
4140 *** BT SCO
4141 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004142 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4143 if (ret >= 0) {
4144 /* When set to false, HAL should disable EC and NS
4145 * But it is currently not supported.
4146 */
4147 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004148 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004149 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004150 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004151 }
4152
Andreas Schneider05bc1882017-02-09 14:03:11 +01004153 ret = str_parms_get_str(parms,
4154 AUDIO_PARAMETER_KEY_BT_SCO_WB,
4155 value,
4156 sizeof(value));
4157 if (ret >= 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01004158 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
4159 adev->voice.bluetooth_wb = true;
Andreas Schneider05bc1882017-02-09 14:03:11 +01004160 } else {
4161 adev->voice.bluetooth_wb = false;
4162 }
4163 }
4164
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01004165 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4166 if (ret >= 0) {
4167 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4168 adev->screen_off = false;
4169 else
4170 adev->screen_off = true;
4171 }
4172
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004173#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004174 ret = str_parms_get_int(parms, "rotation", &val);
4175 if (ret >= 0) {
4176 bool reverse_speakers = false;
4177 switch(val) {
4178 /* FIXME: note that the code below assumes that the speakers are in the correct placement
4179 relative to the user when the device is rotated 90deg from its default rotation. This
4180 assumption is device-specific, not platform-specific like this code. */
4181 case 270:
4182 reverse_speakers = true;
4183 break;
4184 case 0:
4185 case 90:
4186 case 180:
4187 break;
4188 default:
4189 ALOGE("%s: unexpected rotation of %d", __func__, val);
4190 }
4191 pthread_mutex_lock(&adev->lock);
4192 if (adev->speaker_lr_swap != reverse_speakers) {
4193 adev->speaker_lr_swap = reverse_speakers;
4194 /* only update the selected device if there is active pcm playback */
4195 struct audio_usecase *usecase;
4196 struct listnode *node;
4197 list_for_each(node, &adev->usecase_list) {
4198 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
4199 if (usecase->type == PCM_PLAYBACK) {
4200 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004201 break;
4202 }
4203 }
4204 }
4205 pthread_mutex_unlock(&adev->lock);
4206 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004207#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004208
4209 str_parms_destroy(parms);
4210
4211 if (ret > 0)
4212 ret = 0;
4213
4214 ALOGV("%s: exit with code(%d)", __func__, ret);
4215 return ret;
4216}
4217
4218static char* adev_get_parameters(const struct audio_hw_device *dev,
4219 const char *keys)
4220{
4221 (void)dev;
4222 (void)keys;
4223
4224 return strdup("");
4225}
4226
4227static int adev_init_check(const struct audio_hw_device *dev)
4228{
4229 (void)dev;
4230
4231 return 0;
4232}
4233
4234static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4235{
4236 int ret = 0;
4237 struct audio_device *adev = (struct audio_device *)dev;
4238 pthread_mutex_lock(&adev->lock);
4239 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004240 adev->voice.volume = volume;
4241 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004242 pthread_mutex_unlock(&adev->lock);
4243 return ret;
4244}
4245
4246static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
4247{
4248 (void)dev;
4249 (void)volume;
4250
4251 return -ENOSYS;
4252}
4253
4254static int adev_get_master_volume(struct audio_hw_device *dev,
4255 float *volume)
4256{
4257 (void)dev;
4258 (void)volume;
4259
4260 return -ENOSYS;
4261}
4262
4263static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
4264{
4265 (void)dev;
4266 (void)muted;
4267
4268 return -ENOSYS;
4269}
4270
4271static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
4272{
4273 (void)dev;
4274 (void)muted;
4275
4276 return -ENOSYS;
4277}
4278
4279static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4280{
4281 struct audio_device *adev = (struct audio_device *)dev;
4282
4283 pthread_mutex_lock(&adev->lock);
4284 if (adev->mode != mode) {
4285 ALOGI("%s mode = %d", __func__, mode);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004286 if (amplifier_set_mode(mode) != 0) {
4287 ALOGE("Failed setting amplifier mode");
4288 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004289 adev->mode = mode;
Christopher N. Hesse6c0020c2017-11-17 20:41:11 +01004290
4291 if ((mode == AUDIO_MODE_NORMAL) && adev->voice.in_call) {
4292 stop_voice_call(adev);
4293 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004294 }
4295 pthread_mutex_unlock(&adev->lock);
4296 return 0;
4297}
4298
4299static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4300{
4301 struct audio_device *adev = (struct audio_device *)dev;
4302 int err = 0;
4303
4304 pthread_mutex_lock(&adev->lock);
4305 adev->mic_mute = state;
4306
4307 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004308 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004309 }
4310
4311 pthread_mutex_unlock(&adev->lock);
4312 return err;
4313}
4314
4315static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4316{
4317 struct audio_device *adev = (struct audio_device *)dev;
4318
4319 *state = adev->mic_mute;
4320
4321 return 0;
4322}
4323
4324static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4325 const struct audio_config *config)
4326{
4327 (void)dev;
4328
4329 /* NOTE: we default to built in mic which may cause a mismatch between what we
4330 * report here and the actual buffer size
4331 */
4332 return get_input_buffer_size(config->sample_rate,
4333 config->format,
4334 audio_channel_count_from_in_mask(config->channel_mask),
4335 PCM_CAPTURE /* usecase_type */,
4336 AUDIO_DEVICE_IN_BUILTIN_MIC);
4337}
4338
4339static int adev_open_input_stream(struct audio_hw_device *dev,
4340 audio_io_handle_t handle __unused,
4341 audio_devices_t devices,
4342 struct audio_config *config,
4343 struct audio_stream_in **stream_in,
4344 audio_input_flags_t flags,
4345 const char *address __unused,
4346 audio_source_t source)
4347{
4348 struct audio_device *adev = (struct audio_device *)dev;
4349 struct stream_in *in;
4350 struct pcm_device_profile *pcm_profile;
4351
4352 ALOGV("%s: enter", __func__);
4353
4354 *stream_in = NULL;
4355 if (check_input_parameters(config->sample_rate, config->format,
4356 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4357 return -EINVAL;
4358
4359 usecase_type_t usecase_type = source == AUDIO_SOURCE_HOTWORD ?
4360 PCM_HOTWORD_STREAMING : flags & AUDIO_INPUT_FLAG_FAST ?
4361 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4362 pcm_profile = get_pcm_device(usecase_type, devices);
4363 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4364 // a low latency profile may not exist for that device, fall back
4365 // to regular capture. the MixerThread automatically changes
4366 // to non-fast capture based on the buffer size.
4367 flags &= ~AUDIO_INPUT_FLAG_FAST;
4368 usecase_type = PCM_CAPTURE;
4369 pcm_profile = get_pcm_device(usecase_type, devices);
4370 }
4371 if (pcm_profile == NULL)
4372 return -EINVAL;
4373
4374 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004375 if (in == NULL) {
4376 return -ENOMEM;
4377 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004378
4379 in->stream.common.get_sample_rate = in_get_sample_rate;
4380 in->stream.common.set_sample_rate = in_set_sample_rate;
4381 in->stream.common.get_buffer_size = in_get_buffer_size;
4382 in->stream.common.get_channels = in_get_channels;
4383 in->stream.common.get_format = in_get_format;
4384 in->stream.common.set_format = in_set_format;
4385 in->stream.common.standby = in_standby;
4386 in->stream.common.dump = in_dump;
4387 in->stream.common.set_parameters = in_set_parameters;
4388 in->stream.common.get_parameters = in_get_parameters;
4389 in->stream.common.add_audio_effect = in_add_audio_effect;
4390 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4391 in->stream.set_gain = in_set_gain;
4392 in->stream.read = in_read;
4393 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004394 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004395
4396 in->devices = devices;
4397 in->source = source;
4398 in->dev = adev;
4399 in->standby = 1;
4400 in->main_channels = config->channel_mask;
4401 in->requested_rate = config->sample_rate;
4402 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4403 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4404 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004405 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004406 /* HW codec is limited to default channels. No need to update with
4407 * requested channels */
4408 in->config = pcm_profile->config;
4409
4410 /* Update config params with the requested sample rate and channels */
4411 if (source == AUDIO_SOURCE_HOTWORD) {
4412 in->usecase = USECASE_AUDIO_CAPTURE_HOTWORD;
4413 } else {
4414 in->usecase = USECASE_AUDIO_CAPTURE;
4415 }
4416 in->usecase_type = usecase_type;
4417
4418 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4419 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4420
4421 in->is_fastcapture_affinity_set = false;
4422
4423 *stream_in = &in->stream;
4424 ALOGV("%s: exit", __func__);
4425 return 0;
4426}
4427
4428static void adev_close_input_stream(struct audio_hw_device *dev,
4429 struct audio_stream_in *stream)
4430{
4431 struct audio_device *adev = (struct audio_device *)dev;
4432 struct stream_in *in = (struct stream_in*)stream;
4433 ALOGV("%s", __func__);
4434
4435 /* prevent concurrent out_set_parameters, or out_write from standby */
4436 pthread_mutex_lock(&adev->lock_inputs);
4437
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004438 if (in->read_buf) {
4439 free(in->read_buf);
4440 in->read_buf = NULL;
4441 }
4442
4443 if (in->resampler) {
4444 release_resampler(in->resampler);
4445 in->resampler = NULL;
4446 }
4447
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004448#ifdef PREPROCESSING_ENABLED
4449 int i;
4450
4451 for (i=0; i<in->num_preprocessors; i++) {
4452 free(in->preprocessors[i].channel_configs);
4453 }
4454
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004455 if (in->proc_buf_in) {
4456 free(in->proc_buf_in);
4457 in->proc_buf_in = NULL;
4458 }
4459
4460 if (in->proc_buf_out) {
4461 free(in->proc_buf_out);
4462 in->proc_buf_out = NULL;
4463 }
4464
4465 if (in->ref_buf) {
4466 free(in->ref_buf);
4467 in->ref_buf = NULL;
4468 }
4469
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004470#endif
4471
4472 in_standby_l(in);
4473 free(stream);
4474
4475 pthread_mutex_unlock(&adev->lock_inputs);
4476
4477 return;
4478}
4479
4480static int adev_dump(const audio_hw_device_t *device, int fd)
4481{
4482 (void)device;
4483 (void)fd;
4484
4485 return 0;
4486}
4487
4488static int adev_close(hw_device_t *device)
4489{
4490 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004491 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004492 audio_device_ref_count--;
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004493 if (audio_device_ref_count == 0) {
4494 if (amplifier_close() != 0) {
4495 ALOGE("Amplifier close failed");
4496 }
4497 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004498 free(adev->snd_dev_ref_cnt);
4499 free_mixer_list(adev);
4500 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004501
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004502 adev = NULL;
4503
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004504 return 0;
4505}
4506
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004507/* This returns true if the input parameter looks at all plausible as a low latency period size,
4508 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4509 * just that it _might_ work.
4510 */
4511static bool period_size_is_plausible_for_low_latency(int period_size)
4512{
4513 switch (period_size) {
4514 case 64:
4515 case 96:
4516 case 128:
4517 case 192:
4518 case 256:
4519 return true;
4520 default:
4521 return false;
4522 }
4523}
4524
4525static int adev_open(const hw_module_t *module, const char *name,
4526 hw_device_t **device)
4527{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004528 ALOGV("%s: enter", __func__);
4529 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4530
Andreas Schneider56204f62017-01-31 08:17:32 +01004531 *device = NULL;
4532
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004533 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004534 if (adev == NULL) {
4535 return -ENOMEM;
4536 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004537
4538 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4539 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4540 adev->device.common.module = (struct hw_module_t *)module;
4541 adev->device.common.close = adev_close;
4542
4543 adev->device.init_check = adev_init_check;
4544 adev->device.set_voice_volume = adev_set_voice_volume;
4545 adev->device.set_master_volume = adev_set_master_volume;
4546 adev->device.get_master_volume = adev_get_master_volume;
4547 adev->device.set_master_mute = adev_set_master_mute;
4548 adev->device.get_master_mute = adev_get_master_mute;
4549 adev->device.set_mode = adev_set_mode;
4550 adev->device.set_mic_mute = adev_set_mic_mute;
4551 adev->device.get_mic_mute = adev_get_mic_mute;
4552 adev->device.set_parameters = adev_set_parameters;
4553 adev->device.get_parameters = adev_get_parameters;
4554 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4555 adev->device.open_output_stream = adev_open_output_stream;
4556 adev->device.close_output_stream = adev_close_output_stream;
4557 adev->device.open_input_stream = adev_open_input_stream;
4558 adev->device.close_input_stream = adev_close_input_stream;
4559 adev->device.dump = adev_dump;
4560
4561 /* Set the default route before the PCM stream is opened */
4562 adev->mode = AUDIO_MODE_NORMAL;
4563 adev->active_input = NULL;
4564 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004565
4566 adev->voice.volume = 1.0f;
4567 adev->voice.bluetooth_nrec = true;
4568 adev->voice.in_call = false;
Christopher N. Hessee4a1c592018-01-16 18:33:38 +01004569 adev->voice.bluetooth_wb = false;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004570
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004571 /* adev->cur_hdmi_channels = 0; by calloc() */
4572 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004573 if (adev->snd_dev_ref_cnt == NULL) {
4574 free(adev);
4575 return -ENOMEM;
4576 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004577
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004578 adev->ns_in_voice_rec = false;
4579
4580 list_init(&adev->usecase_list);
4581
4582 if (mixer_init(adev) != 0) {
4583 free(adev->snd_dev_ref_cnt);
4584 free(adev);
4585 ALOGE("%s: Failed to init, aborting.", __func__);
4586 *device = NULL;
4587 return -EINVAL;
4588 }
4589
4590 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4591 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4592 if (adev->offload_fx_lib == NULL) {
4593 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4594 } else {
4595 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4596 adev->offload_fx_start_output =
4597 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4598 "visualizer_hal_start_output");
4599 adev->offload_fx_stop_output =
4600 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4601 "visualizer_hal_stop_output");
4602 }
4603 }
4604
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004605 if (access(SOUND_TRIGGER_HAL_LIBRARY_PATH, R_OK) == 0) {
4606 adev->sound_trigger_lib = dlopen(SOUND_TRIGGER_HAL_LIBRARY_PATH, RTLD_NOW);
4607 if (adev->sound_trigger_lib == NULL) {
4608 ALOGE("%s: DLOPEN failed for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4609 } else {
4610 ALOGV("%s: DLOPEN successful for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4611 adev->sound_trigger_open_for_streaming =
4612 (int (*)(void))dlsym(adev->sound_trigger_lib,
4613 "sound_trigger_open_for_streaming");
4614 adev->sound_trigger_read_samples =
4615 (size_t (*)(int, void *, size_t))dlsym(adev->sound_trigger_lib,
4616 "sound_trigger_read_samples");
4617 adev->sound_trigger_close_for_streaming =
4618 (int (*)(int))dlsym(adev->sound_trigger_lib,
4619 "sound_trigger_close_for_streaming");
4620 if (!adev->sound_trigger_open_for_streaming ||
4621 !adev->sound_trigger_read_samples ||
4622 !adev->sound_trigger_close_for_streaming) {
4623
4624 ALOGE("%s: Error grabbing functions in %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4625 adev->sound_trigger_open_for_streaming = 0;
4626 adev->sound_trigger_read_samples = 0;
4627 adev->sound_trigger_close_for_streaming = 0;
4628 }
4629 }
4630 }
4631
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004632 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004633 if (adev->voice.session == NULL) {
4634 ALOGE("%s: Failed to initialize voice session data", __func__);
4635
4636 free(adev->snd_dev_ref_cnt);
4637 free(adev);
4638
4639 *device = NULL;
4640 return -EINVAL;
4641 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004642
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004643 if (amplifier_open() != 0) {
4644 ALOGE("Amplifier initialization failed");
4645 }
4646
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004647 *device = &adev->device.common;
4648
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004649 audio_device_ref_count++;
4650
4651 char value[PROPERTY_VALUE_MAX];
4652 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4653 int trial = atoi(value);
4654 if (period_size_is_plausible_for_low_latency(trial)) {
4655
4656 pcm_device_playback.config.period_size = trial;
4657 pcm_device_playback.config.start_threshold =
4658 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4659 pcm_device_playback.config.stop_threshold =
4660 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4661
4662 pcm_device_capture_low_latency.config.period_size = trial;
4663 }
4664 }
4665
4666 ALOGV("%s: exit", __func__);
4667 return 0;
4668}
4669
4670static struct hw_module_methods_t hal_module_methods = {
4671 .open = adev_open,
4672};
4673
4674struct audio_module HAL_MODULE_INFO_SYM = {
4675 .common = {
4676 .tag = HARDWARE_MODULE_TAG,
4677 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4678 .hal_api_version = HARDWARE_HAL_API_VERSION,
4679 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004680 .name = "Samsung Audio HAL",
4681 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004682 .methods = &hal_module_methods,
4683 },
4684};