blob: 712d3f801b67d374a7b67affba1c69c4d91e6960 [file] [log] [blame]
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Christopher N. Hesse2f6f8582017-01-28 12:46:15 +01003 * Copyright (C) 2017 Christopher N. Hesse <raymanfx@gmail.com>
Andreas Schneider759368f2017-02-02 16:11:14 +01004 * Copyright (C) 2017 Andreas Schneider <asn@cryptomilk.org>
stenkinevgeniy44335362018-05-07 18:00:13 +00005 * Copyright (C) 2018 The LineageOS Project
Christopher N. Hesse297a6362017-01-28 12:40:45 +01006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
21/*#define LOG_NDEBUG 0*/
22/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
28
29#define _GNU_SOURCE
30#include <errno.h>
31#include <pthread.h>
32#include <stdint.h>
33#include <sys/time.h>
34#include <stdlib.h>
35#include <math.h>
36#include <dlfcn.h>
Christopher N. Hesse297a6362017-01-28 12:40:45 +010037
38#include <cutils/log.h>
39#include <cutils/str_parms.h>
40#include <cutils/atomic.h>
41#include <cutils/sched_policy.h>
42#include <cutils/properties.h>
43
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010044#include <samsung_audio.h>
45
Christopher N. Hesse297a6362017-01-28 12:40:45 +010046#include <hardware/audio_effect.h>
47#include <system/thread_defs.h>
48#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
50#include "audio_hw.h"
Christopher N. Hesse757ac412017-01-28 14:42:48 +010051#include "compress_offload.h"
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +010052#include "voice.h"
Christopher N. Hesse297a6362017-01-28 12:40:45 +010053
54#include "sound/compress_params.h"
55
Christopher N. Hesse297a6362017-01-28 12:40:45 +010056
57/* TODO: the following PCM device profiles could be read from a config file */
58static struct pcm_device_profile pcm_device_playback = {
59 .config = {
60 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
61 .rate = PLAYBACK_DEFAULT_SAMPLING_RATE,
62 .period_size = PLAYBACK_PERIOD_SIZE,
63 .period_count = PLAYBACK_PERIOD_COUNT,
64 .format = PCM_FORMAT_S16_LE,
65 .start_threshold = PLAYBACK_START_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
66 .stop_threshold = PLAYBACK_STOP_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
67 .silence_threshold = 0,
68 .silence_size = UINT_MAX,
69 .avail_min = PLAYBACK_AVAILABLE_MIN,
70 },
71 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010072 .id = SOUND_PLAYBACK_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010073 .type = PCM_PLAYBACK,
74 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
stenkinevgeniy53929f72018-07-09 11:20:36 +000075 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010076};
77
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010078static struct pcm_device_profile pcm_device_deep_buffer = {
79 .config = {
80 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
81 .rate = DEEP_BUFFER_OUTPUT_SAMPLING_RATE,
82 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
83 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
84 .format = PCM_FORMAT_S16_LE,
85 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
86 .stop_threshold = INT_MAX,
87 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
88 },
89 .card = SOUND_CARD,
90 .id = SOUND_DEEP_BUFFER_DEVICE,
91 .type = PCM_PLAYBACK,
92 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
stenkinevgeniy53929f72018-07-09 11:20:36 +000093 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010094};
95
Christopher N. Hesse297a6362017-01-28 12:40:45 +010096static struct pcm_device_profile pcm_device_capture = {
97 .config = {
98 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
99 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
100 .period_size = CAPTURE_PERIOD_SIZE,
101 .period_count = CAPTURE_PERIOD_COUNT,
102 .format = PCM_FORMAT_S16_LE,
103 .start_threshold = CAPTURE_START_THRESHOLD,
104 .stop_threshold = 0,
105 .silence_threshold = 0,
106 .avail_min = 0,
107 },
108 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100109 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100110 .type = PCM_CAPTURE,
stenkinevgeniy53929f72018-07-09 11:20:36 +0000111 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100112};
113
114static struct pcm_device_profile pcm_device_capture_low_latency = {
115 .config = {
116 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
117 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
118 .period_size = CAPTURE_PERIOD_SIZE_LOW_LATENCY,
119 .period_count = CAPTURE_PERIOD_COUNT_LOW_LATENCY,
120 .format = PCM_FORMAT_S16_LE,
121 .start_threshold = CAPTURE_START_THRESHOLD,
122 .stop_threshold = 0,
123 .silence_threshold = 0,
124 .avail_min = 0,
125 },
126 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100127 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100128 .type = PCM_CAPTURE_LOW_LATENCY,
stenkinevgeniy53929f72018-07-09 11:20:36 +0000129 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100130};
131
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100132static struct pcm_device_profile * const pcm_devices[] = {
133 &pcm_device_playback,
134 &pcm_device_capture,
135 &pcm_device_capture_low_latency,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100136 NULL,
137};
138
139static const char * const use_case_table[AUDIO_USECASE_MAX] = {
140 [USECASE_AUDIO_PLAYBACK] = "playback",
141 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "playback multi-channel",
142 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Andreas Schneiderdf6fc8a2017-02-14 11:38:41 +0100143 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "playback deep-buffer",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100144 [USECASE_AUDIO_CAPTURE] = "capture",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100145 [USECASE_VOICE_CALL] = "voice-call",
146};
147
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100148#define STRING_TO_ENUM(string) { #string, string }
149
150static unsigned int audio_device_ref_count;
151
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100152struct string_to_enum {
153 const char *name;
154 uint32_t value;
155};
156
157static const struct string_to_enum out_channels_name_to_enum_table[] = {
158 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
159 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
160 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
161};
162
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200163static struct audio_device *adev = NULL;
164
165static amplifier_device_t * get_amplifier_device(void)
166{
167 if (adev)
168 return adev->amp;
169
170 return NULL;
171}
172
173static int amplifier_open(void)
174{
175 int rc;
176 amplifier_module_t *module;
177
178 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
179 (const hw_module_t **) &module);
180 if (rc) {
Christopher N. Hessec487bbe2018-07-12 13:51:43 +0200181 if (rc == -ENOENT) {
182 // no amplifier HAL present
183 return -ENOENT;
184 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200185 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
186 __func__, strerror(-rc));
187 return -ENODEV;
188 }
189
190 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
191 if (rc) {
192 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
193 __func__, strerror(-rc));
194 return -ENODEV;
195 }
196
197 return 0;
198}
199
200static int amplifier_set_input_devices(uint32_t devices)
201{
202 amplifier_device_t *amp = get_amplifier_device();
203 if (amp && amp->set_input_devices)
204 return amp->set_input_devices(amp, devices);
205
206 return 0;
207}
208
209static int amplifier_set_output_devices(uint32_t devices)
210{
211 amplifier_device_t *amp = get_amplifier_device();
212 if (amp && amp->set_output_devices)
213 return amp->set_output_devices(amp, devices);
214
215 return 0;
216}
217
218static int amplifier_enable_devices(uint32_t devices, bool enable)
219{
220 amplifier_device_t *amp = get_amplifier_device();
221 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
222 devices < SND_DEVICE_OUT_END;
223
224 if (amp && amp->enable_output_devices && is_output)
225 return amp->enable_output_devices(amp, devices, enable);
226
227 if (amp && amp->enable_input_devices && !is_output)
228 return amp->enable_input_devices(amp, devices, enable);
229
230 return 0;
231}
232
233static int amplifier_set_mode(audio_mode_t mode)
234{
235 amplifier_device_t *amp = get_amplifier_device();
236 if (amp && amp->set_mode)
237 return amp->set_mode(amp, mode);
238
239 return 0;
240}
241
242static int amplifier_output_stream_start(struct audio_stream_out *stream,
243 bool offload)
244{
245 amplifier_device_t *amp = get_amplifier_device();
246 if (amp && amp->output_stream_start)
247 return amp->output_stream_start(amp, stream, offload);
248
249 return 0;
250}
251
252static int amplifier_input_stream_start(struct audio_stream_in *stream)
253{
254 amplifier_device_t *amp = get_amplifier_device();
255 if (amp && amp->input_stream_start)
256 return amp->input_stream_start(amp, stream);
257
258 return 0;
259}
260
261static int amplifier_output_stream_standby(struct audio_stream_out *stream)
262{
263 amplifier_device_t *amp = get_amplifier_device();
264 if (amp && amp->output_stream_standby)
265 return amp->output_stream_standby(amp, stream);
266
267 return 0;
268}
269
270static int amplifier_input_stream_standby(struct audio_stream_in *stream)
271{
272 amplifier_device_t *amp = get_amplifier_device();
273 if (amp && amp->input_stream_standby)
274 return amp->input_stream_standby(amp, stream);
275
276 return 0;
277}
278
279static int amplifier_set_parameters(struct str_parms *parms)
280{
281 amplifier_device_t *amp = get_amplifier_device();
282 if (amp && amp->set_parameters)
283 return amp->set_parameters(amp, parms);
284
285 return 0;
286}
287
288static int amplifier_close(void)
289{
290 amplifier_device_t *amp = get_amplifier_device();
291 if (amp)
292 amplifier_device_close(amp);
293
294 return 0;
295}
296
Andreas Schneider759368f2017-02-02 16:11:14 +0100297struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
298 struct timespec ret;
299 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100300
301 if (time0.tv_nsec > time1.tv_nsec) {
302 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
303 time0.tv_nsec -= (long int) (1E9 * xsec);
304 time0.tv_sec += xsec;
305 }
306
307 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
308 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
309 time0.tv_nsec += (long int) (1E9 * xsec);
310 time0.tv_sec -= xsec;
311 }
312
Paul Keithf114e2e2017-02-14 20:41:33 -0600313 ret.tv_sec = labs(time1.tv_sec - time0.tv_sec);
314 ret.tv_nsec = labs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100315
316 return ret;
317}
318
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100319static bool is_supported_format(audio_format_t format)
320{
321 if (format == AUDIO_FORMAT_MP3 ||
322 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
323 return true;
324
325 return false;
326}
327
328static int get_snd_codec_id(audio_format_t format)
329{
330 int id = 0;
331
332 switch (format & AUDIO_FORMAT_MAIN_MASK) {
333 case AUDIO_FORMAT_MP3:
334 id = SND_AUDIOCODEC_MP3;
335 break;
336 case AUDIO_FORMAT_AAC:
337 id = SND_AUDIOCODEC_AAC;
338 break;
339 default:
340 ALOGE("%s: Unsupported audio format", __func__);
341 }
342
343 return id;
344}
345
346/* Array to store sound devices */
347static const char * const device_table[SND_DEVICE_MAX] = {
348 [SND_DEVICE_NONE] = "none",
349 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100350 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100351 [SND_DEVICE_OUT_SPEAKER] = "speaker",
352 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
353 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100354 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100355 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100356 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100357 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100358 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100359 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100360 [SND_DEVICE_OUT_VOICE_BT_SCO] = "voice-bt-sco-headset",
361 [SND_DEVICE_OUT_VOICE_BT_SCO_WB] = "voice-bt-sco-headset-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100362 [SND_DEVICE_OUT_HDMI] = "hdmi",
363 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
364 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100365
366 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100367 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100368 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
369 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100370 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100371 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
372 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100373 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
374 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100375 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100376 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100377 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100378 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100379 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100380 [SND_DEVICE_IN_VOICE_BT_SCO_MIC] = "voice-bt-sco-mic",
381 [SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB] = "voice-bt-sco-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100382 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
383 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
384 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100385 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
386 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100387};
388
389static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
390{
391 struct mixer_card *mixer_card;
392 struct listnode *node;
393
394 list_for_each(node, &adev->mixer_list) {
395 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
396 if (mixer_card->card == card)
397 return mixer_card;
398 }
399 return NULL;
400}
401
402static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
403{
404 struct mixer_card *mixer_card;
405 struct listnode *node;
406
407 list_for_each(node, &usecase->mixer_list) {
408 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
409 if (mixer_card->card == card)
410 return mixer_card;
411 }
412 return NULL;
413}
414
415static void free_mixer_list(struct audio_device *adev)
416{
417 struct mixer_card *mixer_card;
418 struct listnode *node;
419 struct listnode *next;
420
421 list_for_each_safe(node, next, &adev->mixer_list) {
422 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
423 list_remove(node);
424 audio_route_free(mixer_card->audio_route);
425 free(mixer_card);
426 }
427}
428
429static int mixer_init(struct audio_device *adev)
430{
431 int i;
432 int card;
433 int retry_num;
434 struct mixer *mixer;
435 struct audio_route *audio_route;
436 char mixer_path[PATH_MAX];
437 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100438 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100439
440 list_init(&adev->mixer_list);
441
442 for (i = 0; pcm_devices[i] != NULL; i++) {
443 card = pcm_devices[i]->card;
444 if (adev_get_mixer_for_card(adev, card) == NULL) {
445 retry_num = 0;
446 do {
447 mixer = mixer_open(card);
448 if (mixer == NULL) {
449 if (++retry_num > RETRY_NUMBER) {
450 ALOGE("%s unable to open the mixer for--card %d, aborting.",
451 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100452 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100453 goto error;
454 }
455 usleep(RETRY_US);
456 }
457 } while (mixer == NULL);
458
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100459 sprintf(mixer_path, "/vendor/etc/mixer_paths_%d.xml", card);
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100460 if (access(mixer_path, F_OK) == -1) {
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100461 ALOGW("%s: Failed to open mixer paths from %s, retrying with legacy location",
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100462 __func__, mixer_path);
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100463 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
464 if (access(mixer_path, F_OK) == -1) {
465 ALOGE("%s: Failed to load a mixer paths configuration, your system will crash",
466 __func__);
467 }
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100468 }
469
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100470 audio_route = audio_route_init(card, mixer_path);
471 if (!audio_route) {
472 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
473 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100474 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100475 goto error;
476 }
477 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100478 if (mixer_card == NULL) {
479 ret = -ENOMEM;
480 goto error;
481 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100482 mixer_card->card = card;
483 mixer_card->mixer = mixer;
484 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100485
486 /* Do not sleep on first enable_snd_device() */
487 mixer_card->dsp_poweroff_time.tv_sec = 1;
488 mixer_card->dsp_poweroff_time.tv_nsec = 0;
489
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100490 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
491 }
492 }
493
494 return 0;
495
496error:
497 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100498 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100499}
500
501static const char *get_snd_device_name(snd_device_t snd_device)
502{
503 const char *name = NULL;
504
Andreas Schneideradb788d2017-02-13 15:19:36 +0100505 if (snd_device == SND_DEVICE_NONE ||
Andreas Schneiderdde54c02017-02-15 14:10:58 +0100506 (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100507 name = device_table[snd_device];
508
509 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
510
511 return name;
512}
513
514static const char *get_snd_device_display_name(snd_device_t snd_device)
515{
516 const char *name = get_snd_device_name(snd_device);
517
518 if (name == NULL)
519 name = "SND DEVICE NOT FOUND";
520
521 return name;
522}
523
524static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
525{
526 int i;
527
528 devices &= ~AUDIO_DEVICE_BIT_IN;
529 for (i = 0; pcm_devices[i] != NULL; i++) {
530 if ((pcm_devices[i]->type == uc_type) &&
531 (devices & pcm_devices[i]->devices))
532 break;
533 }
534 return pcm_devices[i];
535}
536
537static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
538 audio_usecase_t uc_id)
539{
540 struct audio_usecase *usecase;
541 struct listnode *node;
542
543 list_for_each(node, &adev->usecase_list) {
544 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
545 if (usecase->id == uc_id)
546 return usecase;
547 }
548 return NULL;
549}
550
551static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
552 usecase_type_t type)
553{
554 struct audio_usecase *usecase;
555 struct listnode *node;
556
557 list_for_each(node, &adev->usecase_list) {
558 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
559 if (usecase->type & type)
560 return usecase;
561 }
562 return NULL;
563}
564
565/* always called with adev lock held */
566static int set_voice_volume_l(struct audio_device *adev, float volume)
567{
568 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100569
570 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100571 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100572 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100573
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100574 return err;
575}
576
577
578static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
579{
580
581 audio_mode_t mode = adev->mode;
582 snd_device_t snd_device = SND_DEVICE_NONE;
583
584 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
585 if (devices == AUDIO_DEVICE_NONE ||
586 devices & AUDIO_DEVICE_BIT_IN) {
587 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
588 goto exit;
589 }
590
591 if (mode == AUDIO_MODE_IN_CALL) {
592 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
593 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100594 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Fevax51bd12c2017-03-15 10:56:39 -0300595 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100596 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100597 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
598 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
599 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100600 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100601 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100602
603 if (voice_session_uses_wideband(adev->voice.session)) {
604 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
605 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
606 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300607 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100608 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO_WB;
Andreas Schneider59486fa2017-02-06 09:16:39 +0100609 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
610 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
611 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
612 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
613 }
614 }
615
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100616 if (snd_device != SND_DEVICE_NONE) {
617 goto exit;
618 }
619 }
620
621 if (popcount(devices) == 2) {
622 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
623 AUDIO_DEVICE_OUT_SPEAKER)) {
624 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
625 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
626 AUDIO_DEVICE_OUT_SPEAKER)) {
627 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
628 } else {
629 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
630 goto exit;
631 }
632 if (snd_device != SND_DEVICE_NONE) {
633 goto exit;
634 }
635 }
636
637 if (popcount(devices) != 1) {
638 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
639 goto exit;
640 }
641
642 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
643 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
644 snd_device = SND_DEVICE_OUT_HEADPHONES;
645 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
646 snd_device = SND_DEVICE_OUT_SPEAKER;
647 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
648 snd_device = SND_DEVICE_OUT_BT_SCO;
649 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100650 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100651 } else {
652 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
653 }
654exit:
655 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
656 return snd_device;
657}
658
659static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
660{
661 audio_source_t source;
662 audio_mode_t mode = adev->mode;
663 audio_devices_t in_device;
664 audio_channel_mask_t channel_mask;
665 snd_device_t snd_device = SND_DEVICE_NONE;
666 struct stream_in *active_input = NULL;
667 struct audio_usecase *usecase;
668
669 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
670 if (usecase != NULL) {
671 active_input = (struct stream_in *)usecase->stream;
672 }
673 source = (active_input == NULL) ?
674 AUDIO_SOURCE_DEFAULT : active_input->source;
675
Andreas Schneider757e2d82017-02-10 19:28:35 +0100676 in_device = (active_input == NULL) ?
677 AUDIO_DEVICE_NONE :
678 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100679 channel_mask = (active_input == NULL) ?
680 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
681
682 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
683 __func__, out_device, in_device);
684 if (mode == AUDIO_MODE_IN_CALL) {
685 if (out_device == AUDIO_DEVICE_NONE) {
686 ALOGE("%s: No output device set for voice call", __func__);
687 goto exit;
688 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100689
Andreas Schneider82f32482017-02-06 09:00:48 +0100690 snd_device = SND_DEVICE_IN_VOICE_MIC;
691 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100692 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100693 }
694
695 if (voice_session_uses_twomic(adev->voice.session)) {
696 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
697 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
698 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
699 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
700 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
701 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100702 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100703
704 if (voice_session_uses_wideband(adev->voice.session)) {
705 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
706 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
707 }
708
709 if (voice_session_uses_twomic(adev->voice.session)) {
710 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
711 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
712 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
713 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
714 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
715 }
716 }
717 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100718
719 /* BT SCO */
720 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Andreas Schneider05bc1882017-02-09 14:03:11 +0100721
stenkinevgeniy097e2942018-05-22 18:06:48 +0000722 if (voice_session_uses_wideband(adev->voice.session)) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100723 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB;
stenkinevgeniy097e2942018-05-22 18:06:48 +0000724 } else {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100725 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC;
Andreas Schneider05bc1882017-02-09 14:03:11 +0100726 }
727 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100728 } else if (source == AUDIO_SOURCE_CAMCORDER) {
729 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
730 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
731 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
732 }
733 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
734 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100735 if (snd_device == SND_DEVICE_NONE) {
736 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
737 }
738 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
739 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
740 }
741 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
742 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
743 in_device = AUDIO_DEVICE_IN_BACK_MIC;
744 if (active_input) {
745 if (active_input->enable_aec) {
746 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
747 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
748 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
749 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
750 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
751 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100752 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100753 }
754 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
755 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
756 }
757 }
758 /* TODO: set echo reference */
759 }
760 } else if (source == AUDIO_SOURCE_DEFAULT) {
761 goto exit;
762 }
763
764
765 if (snd_device != SND_DEVICE_NONE) {
766 goto exit;
767 }
768
769 if (in_device != AUDIO_DEVICE_NONE &&
770 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
771 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
772 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100773 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100774 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
775 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
776 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
777 snd_device = SND_DEVICE_IN_HEADSET_MIC;
778 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
779 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
780 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
781 snd_device = SND_DEVICE_IN_HDMI_MIC;
782 } else {
783 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100784 ALOGW("%s: Using default earpiece-mic", __func__);
785 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100786 }
787 } else {
788 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100789 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100790 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
791 snd_device = SND_DEVICE_IN_HEADSET_MIC;
792 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
793 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
794 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100795 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100796 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
797 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
798 } else {
799 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100800 ALOGW("%s: Using default earpiece-mic", __func__);
801 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100802 }
803 }
804exit:
805 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
806 return snd_device;
807}
808
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100809#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100810static int set_hdmi_channels(struct audio_device *adev, int channel_count)
811{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100812 (void)adev;
813 (void)channel_count;
814 /* TODO */
815
816 return 0;
817}
818
819static int edid_get_max_channels(struct audio_device *adev)
820{
821 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100822 (void)adev;
823
824 /* TODO */
825 return max_channels;
826}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100827#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100828
829/* Delay in Us */
830static int64_t render_latency(audio_usecase_t usecase)
831{
832 (void)usecase;
833 /* TODO */
834 return 0;
835}
836
837static int enable_snd_device(struct audio_device *adev,
838 struct audio_usecase *uc_info,
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100839 snd_device_t snd_device)
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100840{
841 struct mixer_card *mixer_card;
842 struct listnode *node;
843 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100844#ifdef DSP_POWEROFF_DELAY
845 struct timespec activation_time;
846 struct timespec elapsed_time;
847#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100848
849 if (snd_device_name == NULL)
850 return -EINVAL;
851
852 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
853 ALOGV("Request to enable combo device: enable individual devices\n");
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100854 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER);
855 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100856 return 0;
857 }
858 adev->snd_dev_ref_cnt[snd_device]++;
859 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
860 ALOGV("%s: snd_device(%d: %s) is already active",
861 __func__, snd_device, snd_device_name);
862 return 0;
863 }
864
865 ALOGV("%s: snd_device(%d: %s)", __func__,
866 snd_device, snd_device_name);
867
868 list_for_each(node, &uc_info->mixer_list) {
869 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100870
871#ifdef DSP_POWEROFF_DELAY
872 clock_gettime(CLOCK_MONOTONIC, &activation_time);
873
Andreas Schneider58735a92017-02-13 16:48:17 +0100874 elapsed_time = time_spec_diff(activation_time,
875 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100876 if (elapsed_time.tv_sec == 0) {
877 long elapsed_usec = elapsed_time.tv_nsec / 1000;
878
879 if (elapsed_usec < DSP_POWEROFF_DELAY) {
880 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
881 }
882 }
Andreas Schneider759368f2017-02-02 16:11:14 +0100883#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200884
885 amplifier_enable_devices(snd_device, true);
886
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100887 audio_route_apply_and_update_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100888 }
889
890 return 0;
891}
892
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100893int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100894 struct audio_usecase *uc_info,
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100895 snd_device_t snd_device)
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100896{
897 struct mixer_card *mixer_card;
898 struct listnode *node;
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100899 struct audio_usecase *out_uc_info = get_usecase_from_type(adev, PCM_PLAYBACK);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100900 const char *snd_device_name = get_snd_device_name(snd_device);
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100901 const char *out_snd_device_name = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100902
903 if (snd_device_name == NULL)
904 return -EINVAL;
905
906 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
907 ALOGV("Request to disable combo device: disable individual devices\n");
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100908 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER);
909 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100910 return 0;
911 }
912
913 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
914 ALOGE("%s: device ref cnt is already 0", __func__);
915 return -EINVAL;
916 }
917 adev->snd_dev_ref_cnt[snd_device]--;
918 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
919 ALOGV("%s: snd_device(%d: %s)", __func__,
920 snd_device, snd_device_name);
921 list_for_each(node, &uc_info->mixer_list) {
922 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100923 audio_route_reset_and_update_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse719630a2018-02-12 01:47:48 +0100924 if (snd_device > SND_DEVICE_IN_BEGIN && out_uc_info != NULL) {
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100925 /*
926 * Cycle the rx device to eliminate routing conflicts.
927 * This prevents issues when an input route shares mixer controls with an output
928 * route.
929 */
930 out_snd_device_name = get_snd_device_name(out_uc_info->out_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100931 audio_route_apply_and_update_path(mixer_card->audio_route, out_snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100932 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200933
934 amplifier_enable_devices(snd_device, false);
Andreas Schneider759368f2017-02-02 16:11:14 +0100935#ifdef DSP_POWEROFF_DELAY
936 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
937#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100938 }
939 }
940 return 0;
941}
942
stenkinevgeniyb81e05f2018-05-08 12:02:35 +0000943static void check_and_route_usecases(struct audio_device *adev,
944 struct audio_usecase *uc_info,
945 usecase_type_t type,
946 snd_device_t snd_device)
947{
948 struct listnode *node;
949 struct audio_usecase *usecase;
950 bool switch_device[AUDIO_USECASE_MAX], need_switch = false;
951 snd_device_t usecase_snd_device = SND_DEVICE_NONE;
952 int i;
953
954 /*
955 * This function is to make sure that all the usecases that are active on
956 * the hardware codec backend are always routed to any one device that is
957 * handled by the hardware codec.
958 * For example, if low-latency and deep-buffer usecases are currently active
959 * on speaker and out_set_parameters(headset) is received on low-latency
960 * output, then we have to make sure deep-buffer is also switched to headset or
961 * if audio-record and voice-call usecases are currently
962 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
963 * is received for voice call then we have to make sure that audio-record
964 * usecase is also switched to earpiece i.e.
965 * because of the limitation that both the devices cannot be enabled
966 * at the same time as they share the same backend.
967 */
968 /* Disable all the usecases on the shared backend other than the
969 specified usecase */
970 for (i = 0; i < AUDIO_USECASE_MAX; i++)
971 switch_device[i] = false;
972
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
975 if (usecase->type != type || usecase == uc_info)
976 continue;
977 usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device :
978 usecase->in_snd_device;
979 if (usecase_snd_device != snd_device) {
980 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
981 __func__, use_case_table[usecase->id],
982 get_snd_device_name(usecase_snd_device));
983 switch_device[usecase->id] = true;
984 need_switch = true;
985 }
986 }
987 if (need_switch) {
988 list_for_each(node, &adev->usecase_list) {
989 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
990 usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device :
991 usecase->in_snd_device;
992 if (switch_device[usecase->id]) {
993 disable_snd_device(adev, usecase, usecase_snd_device);
994 enable_snd_device(adev, usecase, snd_device);
995 if (type == PCM_PLAYBACK)
996 usecase->out_snd_device = snd_device;
997 else
998 usecase->in_snd_device = snd_device;
999 }
1000 }
1001 }
1002}
1003
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001004static int select_devices(struct audio_device *adev,
1005 audio_usecase_t uc_id)
1006{
1007 snd_device_t out_snd_device = SND_DEVICE_NONE;
1008 snd_device_t in_snd_device = SND_DEVICE_NONE;
1009 struct audio_usecase *usecase = NULL;
1010 struct audio_usecase *vc_usecase = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001011 struct stream_in *active_input = NULL;
1012 struct stream_out *active_out;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001013
1014 ALOGV("%s: usecase(%d)", __func__, uc_id);
1015
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001016 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
1017 if (usecase != NULL) {
1018 active_input = (struct stream_in *)usecase->stream;
1019 }
1020
1021 usecase = get_usecase_from_id(adev, uc_id);
1022 if (usecase == NULL) {
1023 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1024 return -EINVAL;
1025 }
1026 active_out = (struct stream_out *)usecase->stream;
1027
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001028
1029 /*
1030 * If the voice call is active, use the sound devices of voice call usecase
1031 * so that it would not result any device switch. All the usecases will
1032 * be switched to new device when select_devices() is called for voice call
1033 * usecase.
1034 */
1035 if (usecase->type != VOICE_CALL && adev->voice.in_call) {
1036 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
1037 if (vc_usecase == NULL) {
1038 ALOGE("%s: Could not find the voice call usecase", __func__);
1039 } else {
stenkinevgeniy5ca267a2018-05-30 15:43:14 +00001040 in_snd_device = vc_usecase->in_snd_device;
1041 out_snd_device = vc_usecase->out_snd_device;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001042 }
1043 }
1044
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001045 if (usecase->type == VOICE_CALL) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001046 usecase->devices = active_out->devices;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001047 prepare_voice_session(adev->voice.session, active_out->devices);
1048 out_snd_device = get_output_snd_device(adev, active_out->devices);
1049 in_snd_device = get_input_snd_device(adev, active_out->devices);
1050 } else if (usecase->type == PCM_PLAYBACK) {
1051 usecase->devices = active_out->devices;
1052 in_snd_device = SND_DEVICE_NONE;
1053 if (out_snd_device == SND_DEVICE_NONE) {
1054 out_snd_device = get_output_snd_device(adev, active_out->devices);
1055 if (active_out == adev->primary_output &&
1056 active_input &&
1057 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1058 select_devices(adev, active_input->usecase);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001059 }
1060 }
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001061 } else if (usecase->type == PCM_CAPTURE) {
1062 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
1063 out_snd_device = SND_DEVICE_NONE;
1064 if (in_snd_device == SND_DEVICE_NONE) {
1065 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
1066 adev->primary_output && !adev->primary_output->standby) {
1067 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
1068 } else {
1069 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001070 }
1071 }
1072 }
1073
1074 if (out_snd_device == usecase->out_snd_device &&
1075 in_snd_device == usecase->in_snd_device) {
1076 return 0;
1077 }
1078
1079 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
1080 out_snd_device, get_snd_device_display_name(out_snd_device),
1081 in_snd_device, get_snd_device_display_name(in_snd_device));
1082
1083
1084 /* Disable current sound devices */
1085 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001086 disable_snd_device(adev, usecase, usecase->out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001087 }
1088
1089 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001090 disable_snd_device(adev, usecase, usecase->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001091 }
1092
1093 /* Enable new sound devices */
1094 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +01001095 /* We need to update the audio path if we switch the out devices */
1096 if (adev->voice.in_call) {
1097 set_voice_session_audio_path(adev->voice.session);
1098 }
1099
stenkinevgeniyb81e05f2018-05-08 12:02:35 +00001100 check_and_route_usecases(adev, usecase, PCM_PLAYBACK, out_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001101 enable_snd_device(adev, usecase, out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001102 }
1103
1104 if (in_snd_device != SND_DEVICE_NONE) {
stenkinevgeniyb81e05f2018-05-08 12:02:35 +00001105 check_and_route_usecases(adev, usecase, PCM_CAPTURE, in_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001106 enable_snd_device(adev, usecase, in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001107 }
1108
1109 usecase->in_snd_device = in_snd_device;
1110 usecase->out_snd_device = out_snd_device;
1111
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02001112 /* Rely on amplifier_set_devices to distinguish between in/out devices */
1113 amplifier_set_input_devices(in_snd_device);
1114 amplifier_set_output_devices(out_snd_device);
1115
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001116 return 0;
1117}
1118
1119
1120static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
1121static int do_in_standby_l(struct stream_in *in);
1122
1123#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001124static void get_capture_delay(struct stream_in *in,
1125 size_t frames __unused,
1126 struct echo_reference_buffer *buffer)
1127{
1128 ALOGVV("%s: enter:)", __func__);
1129 /* read frames available in kernel driver buffer */
1130 unsigned int kernel_frames;
1131 struct timespec tstamp;
1132 long buf_delay;
1133 long rsmp_delay;
1134 long kernel_delay;
1135 long delay_ns;
1136 struct pcm_device *pcm_device;
1137
1138 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1139 struct pcm_device, stream_list_node);
1140
1141 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1142 buffer->time_stamp.tv_sec = 0;
1143 buffer->time_stamp.tv_nsec = 0;
1144 buffer->delay_ns = 0;
1145 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1146 return;
1147 }
1148
1149 /* read frames available in audio HAL input buffer
1150 * add number of frames being read as we want the capture time of first sample
1151 * in current buffer */
1152 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1153 * at requested sampling rate */
1154 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1155 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1156
1157 /* add delay introduced by resampler */
1158 rsmp_delay = 0;
1159 if (in->resampler) {
1160 rsmp_delay = in->resampler->delay_ns(in->resampler);
1161 }
1162
1163 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1164
1165 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1166
1167 buffer->time_stamp = tstamp;
1168 buffer->delay_ns = delay_ns;
1169 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1170 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1171 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1172 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1173 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1174 in->read_buf_frames, in->proc_buf_frames, frames);
1175}
1176
1177static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1178{
1179 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1180 struct echo_reference_buffer b;
1181 b.delay_ns = 0;
1182 struct pcm_device *pcm_device;
1183
Vasyl Gellod758a172018-07-01 10:57:35 +03001184 if (list_empty(&in->pcm_dev_list)) {
1185 ALOGW("%s: pcm device list empty", __func__);
1186 return b.delay_ns;
1187 }
1188
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001189 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1190 struct pcm_device, stream_list_node);
1191
1192 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1193 "b.frame_count = [%zd]",
1194 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1195 if (in->ref_buf_frames < frames) {
1196 if (in->ref_buf_size < frames) {
1197 in->ref_buf_size = frames;
1198 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1199 ALOG_ASSERT((in->ref_buf != NULL),
1200 "update_echo_reference() failed to reallocate ref_buf");
1201 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1202 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1203 }
1204 b.frame_count = frames - in->ref_buf_frames;
1205 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1206
1207 get_capture_delay(in, frames, &b);
1208
1209 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1210 {
1211 in->ref_buf_frames += b.frame_count;
1212 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1213 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1214 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1215 }
1216 } else
1217 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1218 return b.delay_ns;
1219}
1220
1221static int set_preprocessor_param(effect_handle_t handle,
1222 effect_param_t *param)
1223{
1224 uint32_t size = sizeof(int);
Basil Gelloefdfdba2018-05-21 18:29:12 +03001225 uint32_t bufsize = sizeof(effect_param_t) +
1226 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1227 param->vsize;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001228
1229 int status = (*handle)->command(handle,
1230 EFFECT_CMD_SET_PARAM,
Basil Gelloefdfdba2018-05-21 18:29:12 +03001231 bufsize,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001232 param,
1233 &size,
1234 &param->status);
1235 if (status == 0)
1236 status = param->status;
1237
1238 return status;
1239}
1240
1241static int set_preprocessor_echo_delay(effect_handle_t handle,
1242 int32_t delay_us)
1243{
Basil Gelloefdfdba2018-05-21 18:29:12 +03001244 const uint32_t param_size = sizeof(uint32_t);
1245 const uint32_t value_size = sizeof(uint32_t);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001246
Basil Gelloefdfdba2018-05-21 18:29:12 +03001247 const uint32_t param_padded_size =
1248 ((param_size - 1) / sizeof(int) + 1) * sizeof(int);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001249
Basil Gelloefdfdba2018-05-21 18:29:12 +03001250 const uint32_t bufsize = sizeof(effect_param_t) +
1251 param_padded_size + value_size;
1252
1253 uint8_t buf[bufsize];
1254 memset(&buf, 0, bufsize);
1255
1256 effect_param_t *effect_param = (effect_param_t *)&buf;
1257
1258 effect_param->psize = param_size;
1259 effect_param->vsize = value_size;
1260
1261 *(uint32_t *)&buf[sizeof(effect_param_t)] = AEC_PARAM_ECHO_DELAY;
1262 *(int32_t *)&buf[sizeof(effect_param_t) + param_padded_size] = delay_us;
1263
1264 return set_preprocessor_param(handle, effect_param);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001265}
1266
1267static void push_echo_reference(struct stream_in *in, size_t frames)
1268{
1269 ALOGVV("%s: enter:)", __func__);
1270 /* read frames from echo reference buffer and update echo delay
1271 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1272
1273 int32_t delay_us = update_echo_reference(in, frames)/1000;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001274 int i;
1275 audio_buffer_t buf;
1276
1277 if (in->ref_buf_frames < frames)
1278 frames = in->ref_buf_frames;
1279
1280 buf.frameCount = frames;
1281 buf.raw = in->ref_buf;
1282
1283 for (i = 0; i < in->num_preprocessors; i++) {
1284 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1285 continue;
1286 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1287 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1288 &buf,
1289 NULL);
1290 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1291 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1292 }
1293
1294 in->ref_buf_frames -= buf.frameCount;
1295 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1296 __func__, in->ref_buf_frames, in->config.channels);
1297 if (in->ref_buf_frames) {
1298 memcpy(in->ref_buf,
1299 in->ref_buf + buf.frameCount * in->config.channels,
1300 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1301 }
1302}
1303
1304static void put_echo_reference(struct audio_device *adev,
1305 struct echo_reference_itfe *reference)
1306{
1307 ALOGV("%s: enter:)", __func__);
1308 int32_t prev_generation = adev->echo_reference_generation;
1309 struct stream_out *out = adev->primary_output;
1310
1311 if (adev->echo_reference != NULL &&
1312 reference == adev->echo_reference) {
1313 /* echo reference is taken from the low latency output stream used
1314 * for voice use cases */
1315 adev->echo_reference = NULL;
1316 android_atomic_inc(&adev->echo_reference_generation);
1317 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1318 // if the primary output is in standby or did not pick the echo reference yet
1319 // we can safely get rid of it here.
1320 // otherwise, out_write() or out_standby() will detect the change in echo reference
1321 // generation and release the echo reference owned by the stream.
1322 if ((out->echo_reference_generation != prev_generation) || out->standby)
1323 release_echo_reference(reference);
1324 } else {
1325 release_echo_reference(reference);
1326 }
1327 ALOGV("release_echo_reference");
1328 }
1329}
1330
1331static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1332 audio_format_t format __unused,
1333 uint32_t channel_count,
1334 uint32_t sampling_rate)
1335{
1336 ALOGV("%s: enter:)", __func__);
1337 put_echo_reference(adev, adev->echo_reference);
1338 /* echo reference is taken from the low latency output stream used
1339 * for voice use cases */
1340 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1341 !adev->primary_output->standby) {
1342 struct audio_stream *stream =
1343 &adev->primary_output->stream.common;
1344 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1345 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1346 ALOGV("Calling create_echo_reference");
1347 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1348 channel_count,
1349 sampling_rate,
1350 AUDIO_FORMAT_PCM_16_BIT,
1351 wr_channel_count,
1352 wr_sampling_rate,
1353 &adev->echo_reference);
1354 if (status == 0)
1355 android_atomic_inc(&adev->echo_reference_generation);
1356 }
1357 return adev->echo_reference;
1358}
1359
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001360static int get_playback_delay(struct stream_out *out,
1361 size_t frames,
1362 struct echo_reference_buffer *buffer)
1363{
1364 unsigned int kernel_frames;
1365 int status;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001366 struct pcm_device *pcm_device;
1367
1368 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1369 struct pcm_device, stream_list_node);
1370
1371 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1372 if (status < 0) {
1373 buffer->time_stamp.tv_sec = 0;
1374 buffer->time_stamp.tv_nsec = 0;
1375 buffer->delay_ns = 0;
1376 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1377 "setting playbackTimestamp to 0");
1378 return status;
1379 }
1380
1381 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1382
1383 /* adjust render time stamp with delay added by current driver buffer.
1384 * Add the duration of current frame as we want the render time of the last
1385 * sample being written. */
1386 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1387 out->config.rate);
1388 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1389 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1390
1391 return 0;
1392}
1393
1394#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1395 do { \
1396 if (fct_status != 0) \
1397 status = fct_status; \
1398 else if (cmd_status != 0) \
1399 status = cmd_status; \
1400 } while(0)
1401
1402static int in_configure_reverse(struct stream_in *in)
1403{
1404 int32_t cmd_status;
1405 uint32_t size = sizeof(int);
1406 effect_config_t config;
1407 int32_t status = 0;
1408 int32_t fct_status = 0;
1409 int i;
1410 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1411 if (in->num_preprocessors > 0) {
1412 config.inputCfg.channels = in->main_channels;
1413 config.outputCfg.channels = in->main_channels;
1414 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1415 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1416 config.inputCfg.samplingRate = in->requested_rate;
1417 config.outputCfg.samplingRate = in->requested_rate;
1418 config.inputCfg.mask =
1419 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1420 config.outputCfg.mask =
1421 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1422
1423 for (i = 0; i < in->num_preprocessors; i++)
1424 {
1425 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1426 continue;
1427 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1428 in->preprocessors[i].effect_itfe,
1429 EFFECT_CMD_SET_CONFIG_REVERSE,
1430 sizeof(effect_config_t),
1431 &config,
1432 &size,
1433 &cmd_status);
1434 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1435 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1436 }
1437 }
1438 return status;
1439}
1440
1441#define MAX_NUM_CHANNEL_CONFIGS 10
1442
1443static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1444 struct effect_info_s *effect_info)
1445{
1446 /* size and format of the cmd are defined in hardware/audio_effect.h */
1447 effect_handle_t effect = effect_info->effect_itfe;
1448 uint32_t cmd_size = 2 * sizeof(uint32_t);
1449 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1450 /* reply = status + number of configs (n) + n x channel_config_t */
1451 uint32_t reply_size =
1452 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1453 int32_t reply[reply_size];
1454 int32_t cmd_status;
1455
1456 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1457 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1458 ALOG_ASSERT((effect_info->channel_configs == NULL),
1459 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1460
1461 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1462 * This error will be interpreted as if the effect supports the main_channels but does not
1463 * support any aux_channels */
1464 cmd_status = (*effect)->command(effect,
1465 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1466 cmd_size,
1467 (void*)&cmd,
1468 &reply_size,
1469 (void*)&reply);
1470
1471 if (cmd_status != 0) {
1472 ALOGV("in_read_audio_effect_channel_configs(): "
1473 "fx->command returned %d", cmd_status);
1474 return;
1475 }
1476
1477 if (reply[0] != 0) {
1478 ALOGW("in_read_audio_effect_channel_configs(): "
1479 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1480 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1481 return;
1482 }
1483
1484 /* the feature is not supported */
1485 ALOGV("in_read_audio_effect_channel_configs()(): "
1486 "Feature supported and adding %d channel configs to the list", reply[1]);
1487 effect_info->num_channel_configs = reply[1];
1488 effect_info->channel_configs =
1489 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1490 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1491}
1492
1493
1494#define NUM_IN_AUX_CNL_CONFIGS 2
1495static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1496 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1497 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1498};
1499static uint32_t in_get_aux_channels(struct stream_in *in)
1500{
1501 int i;
1502 channel_config_t new_chcfg = {0, 0};
1503
1504 if (in->num_preprocessors == 0)
1505 return 0;
1506
1507 /* do not enable dual mic configurations when capturing from other microphones than
1508 * main or sub */
1509 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1510 return 0;
1511
1512 /* retain most complex aux channels configuration compatible with requested main channels and
1513 * supported by audio driver and all pre processors */
1514 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1515 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1516 if (cur_chcfg->main_channels == in->main_channels) {
1517 size_t match_cnt;
1518 size_t idx_preproc;
1519 for (idx_preproc = 0, match_cnt = 0;
1520 /* no need to continue if at least one preprocessor doesn't match */
1521 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1522 idx_preproc++) {
1523 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1524 size_t idx_chcfg;
1525
1526 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1527 if (memcmp(effect_info->channel_configs + idx_chcfg,
1528 cur_chcfg,
1529 sizeof(channel_config_t)) == 0) {
1530 match_cnt++;
1531 break;
1532 }
1533 }
1534 }
1535 /* if all preprocessors match, we have a candidate */
1536 if (match_cnt == (size_t)in->num_preprocessors) {
1537 /* retain most complex aux channels configuration */
1538 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1539 new_chcfg = *cur_chcfg;
1540 }
1541 }
1542 }
1543 }
1544
1545 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1546
1547 return new_chcfg.aux_channels;
1548}
1549
1550static int in_configure_effect_channels(effect_handle_t effect,
1551 channel_config_t *channel_config)
1552{
1553 int status = 0;
1554 int fct_status;
1555 int32_t cmd_status;
1556 uint32_t reply_size;
1557 effect_config_t config;
1558 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1559
1560 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1561 channel_config->main_channels,
1562 channel_config->aux_channels);
1563
1564 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1565 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1566 reply_size = sizeof(effect_config_t);
1567 fct_status = (*effect)->command(effect,
1568 EFFECT_CMD_GET_CONFIG,
1569 0,
1570 NULL,
1571 &reply_size,
1572 &config);
1573 if (fct_status != 0) {
1574 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1575 return fct_status;
1576 }
1577
1578 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1579 config.outputCfg.channels = config.inputCfg.channels;
1580 reply_size = sizeof(uint32_t);
1581 fct_status = (*effect)->command(effect,
1582 EFFECT_CMD_SET_CONFIG,
1583 sizeof(effect_config_t),
1584 &config,
1585 &reply_size,
1586 &cmd_status);
1587 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1588
1589 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1590 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1591 reply_size = sizeof(uint32_t);
1592 fct_status = (*effect)->command(effect,
1593 EFFECT_CMD_SET_FEATURE_CONFIG,
1594 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1595 cmd,
1596 &reply_size,
1597 &cmd_status);
1598 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1599
1600 /* some implementations need to be re-enabled after a config change */
1601 reply_size = sizeof(uint32_t);
1602 fct_status = (*effect)->command(effect,
1603 EFFECT_CMD_ENABLE,
1604 0,
1605 NULL,
1606 &reply_size,
1607 &cmd_status);
1608 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1609
1610 return status;
1611}
1612
1613static int in_reconfigure_channels(struct stream_in *in,
1614 effect_handle_t effect,
1615 channel_config_t *channel_config,
1616 bool config_changed) {
1617
1618 int status = 0;
1619
1620 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1621 config_changed, effect);
1622
1623 /* if config changed, reconfigure all previously added effects */
1624 if (config_changed) {
1625 int i;
1626 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1627 for (i = 0; i < in->num_preprocessors; i++)
1628 {
1629 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1630 channel_config);
1631 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1632 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1633 if (cur_status != 0) {
1634 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1635 "%d with channels: [%04x][%04x]",
1636 cur_status,
1637 i,
1638 channel_config->main_channels,
1639 channel_config->aux_channels);
1640 status = cur_status;
1641 }
1642 }
1643 } else if (effect != NULL && channel_config->aux_channels) {
1644 /* if aux channels config did not change but aux channels are present,
1645 * we still need to configure the effect being added */
1646 status = in_configure_effect_channels(effect, channel_config);
1647 }
1648 return status;
1649}
1650
1651static void in_update_aux_channels(struct stream_in *in,
1652 effect_handle_t effect)
1653{
1654 uint32_t aux_channels;
1655 channel_config_t channel_config;
1656 int status;
1657
1658 aux_channels = in_get_aux_channels(in);
1659
1660 channel_config.main_channels = in->main_channels;
1661 channel_config.aux_channels = aux_channels;
1662 status = in_reconfigure_channels(in,
1663 effect,
1664 &channel_config,
1665 (aux_channels != in->aux_channels));
1666
1667 if (status != 0) {
1668 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1669 /* resetting aux channels configuration */
1670 aux_channels = 0;
1671 channel_config.aux_channels = 0;
1672 in_reconfigure_channels(in, effect, &channel_config, true);
1673 }
1674 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1675 if (in->aux_channels != aux_channels) {
1676 in->aux_channels_changed = true;
1677 in->aux_channels = aux_channels;
1678 do_in_standby_l(in);
1679 }
1680}
1681#endif
1682
1683/* This function reads PCM data and:
1684 * - resample if needed
1685 * - process if pre-processors are attached
1686 * - discard unwanted channels
1687 */
1688static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1689{
1690 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001691 size_t src_channels = in->config.channels;
1692 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1693 int i;
1694 void *proc_buf_out;
1695 struct pcm_device *pcm_device;
1696 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1697#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001698 audio_buffer_t in_buf;
1699 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001700 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1701#endif
1702
1703 /* Additional channels might be added on top of main_channels:
1704 * - aux_channels (by processing effects)
1705 * - extra channels due to HW limitations
1706 * In case of additional channels, we cannot work inplace
1707 */
1708 if (has_additional_channels)
1709 proc_buf_out = in->proc_buf_out;
1710 else
1711 proc_buf_out = buffer;
1712
1713 if (list_empty(&in->pcm_dev_list)) {
1714 ALOGE("%s: pcm device list empty", __func__);
1715 return -EINVAL;
1716 }
1717
1718 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1719 struct pcm_device, stream_list_node);
1720
1721#ifdef PREPROCESSING_ENABLED
1722 if (has_processing) {
1723 /* since all the processing below is done in frames and using the config.channels
1724 * as the number of channels, no changes is required in case aux_channels are present */
1725 while (frames_wr < frames) {
1726 /* first reload enough frames at the end of process input buffer */
1727 if (in->proc_buf_frames < (size_t)frames) {
1728 ssize_t frames_rd;
1729 if (in->proc_buf_size < (size_t)frames) {
1730 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1731 in->proc_buf_size = (size_t)frames;
1732 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1733 ALOG_ASSERT((in->proc_buf_in != NULL),
1734 "process_frames() failed to reallocate proc_buf_in");
1735 if (has_additional_channels) {
1736 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1737 ALOG_ASSERT((in->proc_buf_out != NULL),
1738 "process_frames() failed to reallocate proc_buf_out");
1739 proc_buf_out = in->proc_buf_out;
1740 }
1741 }
1742 frames_rd = read_frames(in,
1743 in->proc_buf_in +
1744 in->proc_buf_frames * in->config.channels,
1745 frames - in->proc_buf_frames);
1746 if (frames_rd < 0) {
1747 /* Return error code */
1748 frames_wr = frames_rd;
1749 break;
1750 }
1751 in->proc_buf_frames += frames_rd;
1752 }
1753
1754 if (in->echo_reference != NULL) {
1755 push_echo_reference(in, in->proc_buf_frames);
1756 }
1757
1758 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1759 * the maximum number of frames to be consumed and produced by process() */
1760 in_buf.frameCount = in->proc_buf_frames;
1761 in_buf.s16 = in->proc_buf_in;
1762 out_buf.frameCount = frames - frames_wr;
1763 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1764
1765 /* FIXME: this works because of current pre processing library implementation that
1766 * does the actual process only when the last enabled effect process is called.
1767 * The generic solution is to have an output buffer for each effect and pass it as
1768 * input to the next.
1769 */
1770 for (i = 0; i < in->num_preprocessors; i++) {
1771 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1772 &in_buf,
1773 &out_buf);
1774 }
1775
1776 /* process() has updated the number of frames consumed and produced in
1777 * in_buf.frameCount and out_buf.frameCount respectively
1778 * move remaining frames to the beginning of in->proc_buf_in */
1779 in->proc_buf_frames -= in_buf.frameCount;
1780
1781 if (in->proc_buf_frames) {
1782 memcpy(in->proc_buf_in,
1783 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1784 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1785 }
1786
1787 /* if not enough frames were passed to process(), read more and retry. */
1788 if (out_buf.frameCount == 0) {
1789 ALOGW("No frames produced by preproc");
1790 continue;
1791 }
1792
1793 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1794 frames_wr += out_buf.frameCount;
1795 } else {
1796 /* The effect does not comply to the API. In theory, we should never end up here! */
1797 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1798 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1799 frames_wr = frames;
1800 }
1801 }
1802 }
1803 else
1804#endif //PREPROCESSING_ENABLED
1805 {
1806 /* No processing effects attached */
1807 if (has_additional_channels) {
1808 /* With additional channels, we cannot use original buffer */
1809 if (in->proc_buf_size < (size_t)frames) {
1810 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1811 in->proc_buf_size = (size_t)frames;
1812 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1813 ALOG_ASSERT((in->proc_buf_out != NULL),
1814 "process_frames() failed to reallocate proc_buf_out");
1815 proc_buf_out = in->proc_buf_out;
1816 }
1817 }
1818 frames_wr = read_frames(in, proc_buf_out, frames);
1819 }
1820
1821 /* Remove all additional channels that have been added on top of main_channels:
1822 * - aux_channels
1823 * - extra channels from HW due to HW limitations
1824 * Assumption is made that the channels are interleaved and that the main
1825 * channels are first. */
1826
1827 if (has_additional_channels)
1828 {
1829 int16_t* src_buffer = (int16_t *)proc_buf_out;
1830 int16_t* dst_buffer = (int16_t *)buffer;
1831
1832 if (dst_channels == 1) {
1833 for (i = frames_wr; i > 0; i--)
1834 {
1835 *dst_buffer++ = *src_buffer;
1836 src_buffer += src_channels;
1837 }
1838 } else {
1839 for (i = frames_wr; i > 0; i--)
1840 {
1841 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1842 dst_buffer += dst_channels;
1843 src_buffer += src_channels;
1844 }
1845 }
1846 }
1847
1848 return frames_wr;
1849}
1850
1851static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1852 struct resampler_buffer* buffer)
1853{
1854 struct stream_in *in;
1855 struct pcm_device *pcm_device;
1856
1857 if (buffer_provider == NULL || buffer == NULL)
1858 return -EINVAL;
1859
1860 in = (struct stream_in *)((char *)buffer_provider -
1861 offsetof(struct stream_in, buf_provider));
1862
1863 if (list_empty(&in->pcm_dev_list)) {
1864 buffer->raw = NULL;
1865 buffer->frame_count = 0;
1866 in->read_status = -ENODEV;
1867 return -ENODEV;
1868 }
1869
1870 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1871 struct pcm_device, stream_list_node);
1872
1873 if (in->read_buf_frames == 0) {
1874 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1875 if (in->read_buf_size < in->config.period_size) {
1876 in->read_buf_size = in->config.period_size;
1877 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
1878 ALOG_ASSERT((in->read_buf != NULL),
1879 "get_next_buffer() failed to reallocate read_buf");
1880 }
1881
1882 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
1883
1884 if (in->read_status != 0) {
1885 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1886 buffer->raw = NULL;
1887 buffer->frame_count = 0;
1888 return in->read_status;
1889 }
1890 in->read_buf_frames = in->config.period_size;
1891
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001892 }
1893
1894 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
1895 in->read_buf_frames : buffer->frame_count;
1896 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
1897 in->config.channels;
1898 return in->read_status;
1899}
1900
1901static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1902 struct resampler_buffer* buffer)
1903{
1904 struct stream_in *in;
1905
1906 if (buffer_provider == NULL || buffer == NULL)
1907 return;
1908
1909 in = (struct stream_in *)((char *)buffer_provider -
1910 offsetof(struct stream_in, buf_provider));
1911
1912 in->read_buf_frames -= buffer->frame_count;
1913}
1914
1915/* read_frames() reads frames from kernel driver, down samples to capture rate
1916 * if necessary and output the number of frames requested to the buffer specified */
1917static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
1918{
1919 ssize_t frames_wr = 0;
1920
1921 struct pcm_device *pcm_device;
1922
1923 if (list_empty(&in->pcm_dev_list)) {
1924 ALOGE("%s: pcm device list empty", __func__);
1925 return -EINVAL;
1926 }
1927
1928 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1929 struct pcm_device, stream_list_node);
1930
1931 while (frames_wr < frames) {
1932 size_t frames_rd = frames - frames_wr;
1933 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
1934 __func__,frames_rd,frames_wr,in->config.channels);
1935 if (in->resampler != NULL) {
1936 in->resampler->resample_from_provider(in->resampler,
1937 (int16_t *)((char *)buffer +
1938 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
1939 &frames_rd);
1940 } else {
1941 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01001942 .raw = NULL,
1943 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001944 };
1945 get_next_buffer(&in->buf_provider, &buf);
1946 if (buf.raw != NULL) {
1947 memcpy((char *)buffer +
1948 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
1949 buf.raw,
1950 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
1951 frames_rd = buf.frame_count;
1952 }
1953 release_buffer(&in->buf_provider, &buf);
1954 }
1955 /* in->read_status is updated by getNextBuffer() also called by
1956 * in->resampler->resample_from_provider() */
1957 if (in->read_status != 0)
1958 return in->read_status;
1959
1960 frames_wr += frames_rd;
1961 }
1962 return frames_wr;
1963}
1964
1965static int in_release_pcm_devices(struct stream_in *in)
1966{
1967 struct pcm_device *pcm_device;
1968 struct listnode *node;
1969 struct listnode *next;
1970
1971 list_for_each_safe(node, next, &in->pcm_dev_list) {
1972 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
1973 list_remove(node);
1974 free(pcm_device);
1975 }
1976
1977 return 0;
1978}
1979
1980static int stop_input_stream(struct stream_in *in)
1981{
1982 struct audio_usecase *uc_info;
1983 struct audio_device *adev = in->dev;
1984
1985 adev->active_input = NULL;
1986 ALOGV("%s: enter: usecase(%d: %s)", __func__,
1987 in->usecase, use_case_table[in->usecase]);
1988 uc_info = get_usecase_from_id(adev, in->usecase);
1989 if (uc_info == NULL) {
1990 ALOGE("%s: Could not find the usecase (%d) in the list",
1991 __func__, in->usecase);
1992 return -EINVAL;
1993 }
1994
1995 /* Disable the tx device */
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001996 disable_snd_device(adev, uc_info, uc_info->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001997
1998 list_remove(&uc_info->adev_list_node);
1999 free(uc_info);
2000
2001 if (list_empty(&in->pcm_dev_list)) {
2002 ALOGE("%s: pcm device list empty", __func__);
2003 return -EINVAL;
2004 }
2005
2006 in_release_pcm_devices(in);
2007 list_init(&in->pcm_dev_list);
2008
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002009 ALOGV("%s: exit", __func__);
2010 return 0;
2011}
2012
2013static int start_input_stream(struct stream_in *in)
2014{
2015 /* Enable output device and stream routing controls */
2016 int ret = 0;
2017 bool recreate_resampler = false;
2018 struct audio_usecase *uc_info;
2019 struct audio_device *adev = in->dev;
2020 struct pcm_device_profile *pcm_profile;
2021 struct pcm_device *pcm_device;
2022
2023 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2024 adev->active_input = in;
2025 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2026 if (pcm_profile == NULL) {
2027 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2028 __func__, in->usecase);
2029 ret = -EINVAL;
2030 goto error_config;
2031 }
2032
2033 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002034 if (uc_info == NULL) {
2035 ret = -ENOMEM;
2036 goto error_config;
2037 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002038 uc_info->id = in->usecase;
2039 uc_info->type = PCM_CAPTURE;
2040 uc_info->stream = (struct audio_stream *)in;
2041 uc_info->devices = in->devices;
2042 uc_info->in_snd_device = SND_DEVICE_NONE;
2043 uc_info->out_snd_device = SND_DEVICE_NONE;
2044
2045 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002046 if (pcm_device == NULL) {
2047 free(uc_info);
2048 ret = -ENOMEM;
2049 goto error_config;
2050 }
2051
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002052 pcm_device->pcm_profile = pcm_profile;
2053 list_init(&in->pcm_dev_list);
2054 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2055
2056 list_init(&uc_info->mixer_list);
2057 list_add_tail(&uc_info->mixer_list,
2058 &adev_get_mixer_for_card(adev,
2059 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2060
2061 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2062
2063 select_devices(adev, in->usecase);
2064
2065 /* Config should be updated as profile can be changed between different calls
2066 * to this function:
2067 * - Trigger resampler creation
2068 * - Config needs to be updated */
2069 if (in->config.rate != pcm_profile->config.rate) {
2070 recreate_resampler = true;
2071 }
2072 in->config = pcm_profile->config;
2073
2074#ifdef PREPROCESSING_ENABLED
2075 if (in->aux_channels_changed) {
2076 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2077 recreate_resampler = true;
2078 }
2079#endif
2080
2081 if (in->requested_rate != in->config.rate) {
2082 recreate_resampler = true;
2083 }
2084
2085 if (recreate_resampler) {
2086 if (in->resampler) {
2087 release_resampler(in->resampler);
2088 in->resampler = NULL;
2089 }
2090 in->buf_provider.get_next_buffer = get_next_buffer;
2091 in->buf_provider.release_buffer = release_buffer;
2092 ret = create_resampler(in->config.rate,
2093 in->requested_rate,
2094 in->config.channels,
2095 RESAMPLER_QUALITY_DEFAULT,
2096 &in->buf_provider,
2097 &in->resampler);
2098 }
2099
2100#ifdef PREPROCESSING_ENABLED
2101 if (in->enable_aec && in->echo_reference == NULL) {
2102 in->echo_reference = get_echo_reference(adev,
2103 AUDIO_FORMAT_PCM_16_BIT,
2104 audio_channel_count_from_in_mask(in->main_channels),
2105 in->requested_rate
2106 );
2107 }
2108
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002109#endif
2110
2111 /* Open the PCM device.
2112 * The HW is limited to support only the default pcm_profile settings.
2113 * As such a change in aux_channels will not have an effect.
2114 */
2115 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2116 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2117 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2118 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2119
stenkinevgeniy44335362018-05-07 18:00:13 +00002120 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002121 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2122
stenkinevgeniy44335362018-05-07 18:00:13 +00002123 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2124 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2125 pcm_close(pcm_device->pcm);
2126 pcm_device->pcm = NULL;
2127 ret = -EIO;
2128 goto error_open;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002129 }
2130
2131 /* force read and proc buffer reallocation in case of frame size or
2132 * channel count change */
2133 in->proc_buf_frames = 0;
2134 in->proc_buf_size = 0;
2135 in->read_buf_size = 0;
2136 in->read_buf_frames = 0;
2137
2138 /* if no supported sample rate is available, use the resampler */
2139 if (in->resampler) {
2140 in->resampler->reset(in->resampler);
2141 }
2142
2143 ALOGV("%s: exit", __func__);
2144 return ret;
2145
2146error_open:
2147 if (in->resampler) {
2148 release_resampler(in->resampler);
2149 in->resampler = NULL;
2150 }
2151 stop_input_stream(in);
2152
2153error_config:
2154 ALOGV("%s: exit: status(%d)", __func__, ret);
2155 adev->active_input = NULL;
2156 return ret;
2157}
2158
2159void lock_input_stream(struct stream_in *in)
2160{
2161 pthread_mutex_lock(&in->pre_lock);
2162 pthread_mutex_lock(&in->lock);
2163 pthread_mutex_unlock(&in->pre_lock);
2164}
2165
2166void lock_output_stream(struct stream_out *out)
2167{
2168 pthread_mutex_lock(&out->pre_lock);
2169 pthread_mutex_lock(&out->lock);
2170 pthread_mutex_unlock(&out->pre_lock);
2171}
2172
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002173static int uc_release_pcm_devices(struct audio_usecase *usecase)
2174{
2175 struct stream_out *out = (struct stream_out *)usecase->stream;
2176 struct pcm_device *pcm_device;
2177 struct listnode *node;
2178 struct listnode *next;
2179
2180 list_for_each_safe(node, next, &out->pcm_dev_list) {
2181 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2182 list_remove(node);
2183 free(pcm_device);
2184 }
2185 list_init(&usecase->mixer_list);
2186
2187 return 0;
2188}
2189
2190static int uc_select_pcm_devices(struct audio_usecase *usecase)
2191
2192{
2193 struct stream_out *out = (struct stream_out *)usecase->stream;
2194 struct pcm_device *pcm_device;
2195 struct pcm_device_profile *pcm_profile;
2196 struct mixer_card *mixer_card;
2197 audio_devices_t devices = usecase->devices;
2198
2199 list_init(&usecase->mixer_list);
2200 list_init(&out->pcm_dev_list);
2201
2202 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2203 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002204 if (pcm_device == NULL) {
2205 return -ENOMEM;
2206 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002207 pcm_device->pcm_profile = pcm_profile;
2208 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2209 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2210 if (mixer_card == NULL) {
2211 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2212 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2213 }
2214 devices &= ~pcm_profile->devices;
2215 }
2216
2217 return 0;
2218}
2219
2220static int out_close_pcm_devices(struct stream_out *out)
2221{
2222 struct pcm_device *pcm_device;
2223 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002224
2225 list_for_each(node, &out->pcm_dev_list) {
2226 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002227 if (pcm_device->pcm) {
2228 pcm_close(pcm_device->pcm);
2229 pcm_device->pcm = NULL;
2230 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002231 }
2232
2233 return 0;
2234}
2235
2236static int out_open_pcm_devices(struct stream_out *out)
2237{
2238 struct pcm_device *pcm_device;
2239 struct listnode *node;
2240 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002241 int pcm_device_card;
2242 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002243
2244 list_for_each(node, &out->pcm_dev_list) {
2245 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002246 pcm_device_card = pcm_device->pcm_profile->card;
2247 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002248
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002249 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2250 pcm_device_id = pcm_device_deep_buffer.id;
2251
2252 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2253 __func__, pcm_device_card, pcm_device_id);
2254
2255 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
stenkinevgeniy2ef158a2018-05-08 06:52:05 +00002256 PCM_OUT | PCM_MONOTONIC, &out->config);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002257
2258 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2259 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2260 pcm_device->pcm = NULL;
2261 ret = -EIO;
2262 goto error_open;
2263 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002264 }
2265 return ret;
2266
2267error_open:
2268 out_close_pcm_devices(out);
2269 return ret;
2270}
2271
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002272int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002273{
2274 struct audio_device *adev = out->dev;
2275 struct audio_usecase *uc_info;
2276
2277 uc_info = get_usecase_from_id(adev, out->usecase);
2278 if (uc_info == NULL) {
2279 ALOGE("%s: Could not find the usecase (%d) in the list",
2280 __func__, out->usecase);
2281 return -EINVAL;
2282 }
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002283 disable_snd_device(adev, uc_info, uc_info->out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002284 uc_release_pcm_devices(uc_info);
2285 list_remove(&uc_info->adev_list_node);
2286 free(uc_info);
2287
2288 return 0;
2289}
2290
Andreas Schneider56204f62017-01-31 08:17:32 +01002291int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002292{
2293 struct audio_device *adev = out->dev;
2294 struct audio_usecase *uc_info;
2295
2296 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002297 if (uc_info == NULL) {
2298 return -ENOMEM;
2299 }
2300
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002301 uc_info->id = out->usecase;
2302 uc_info->type = PCM_PLAYBACK;
2303 uc_info->stream = (struct audio_stream *)out;
2304 uc_info->devices = out->devices;
2305 uc_info->in_snd_device = SND_DEVICE_NONE;
2306 uc_info->out_snd_device = SND_DEVICE_NONE;
2307 uc_select_pcm_devices(uc_info);
2308
2309 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2310 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002311
2312 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002313}
2314
2315static int stop_output_stream(struct stream_out *out)
2316{
2317 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002318 bool do_disable = true;
2319
2320 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2321 out->usecase, use_case_table[out->usecase]);
2322
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002323 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002324
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002325 if (do_disable)
2326 ret = disable_output_path_l(out);
2327
2328 ALOGV("%s: exit: status(%d)", __func__, ret);
2329 return ret;
2330}
2331
2332static int start_output_stream(struct stream_out *out)
2333{
2334 int ret = 0;
2335 struct audio_device *adev = out->dev;
2336
2337 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2338 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2339
Andreas Schneider56204f62017-01-31 08:17:32 +01002340 ret = enable_output_path_l(out);
2341 if (ret != 0) {
2342 goto error_config;
2343 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002344
2345 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2346 out->compr = NULL;
2347 ret = out_open_pcm_devices(out);
2348 if (ret != 0)
2349 goto error_open;
2350#ifdef PREPROCESSING_ENABLED
2351 out->echo_reference = NULL;
2352 out->echo_reference_generation = adev->echo_reference_generation;
2353 if (adev->echo_reference != NULL)
2354 out->echo_reference = adev->echo_reference;
2355#endif
2356 } else {
2357 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2358 COMPRESS_IN, &out->compr_config);
2359 if (out->compr && !is_compress_ready(out->compr)) {
2360 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2361 compress_close(out->compr);
2362 out->compr = NULL;
2363 ret = -EIO;
2364 goto error_open;
2365 }
2366 if (out->offload_callback)
2367 compress_nonblock(out->compr, out->non_blocking);
2368
2369 if (adev->offload_fx_start_output != NULL)
2370 adev->offload_fx_start_output(out->handle);
2371 }
2372 ALOGV("%s: exit", __func__);
2373 return 0;
2374error_open:
2375 stop_output_stream(out);
2376error_config:
2377 return ret;
2378}
2379
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002380int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002381{
2382 struct audio_usecase *uc_info;
2383
2384 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002385 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002386
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002387 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002388
2389 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2390 if (uc_info == NULL) {
2391 ALOGE("%s: Could not find the usecase (%d) in the list",
2392 __func__, USECASE_VOICE_CALL);
2393 return -EINVAL;
2394 }
2395
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002396 disable_snd_device(adev, uc_info, uc_info->out_snd_device);
2397 disable_snd_device(adev, uc_info, uc_info->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002398
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002399 list_remove(&uc_info->adev_list_node);
2400 free(uc_info);
2401
2402 ALOGV("%s: exit", __func__);
2403 return 0;
2404}
2405
2406/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002407int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002408{
2409 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002410 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002411
2412 ALOGV("%s: enter", __func__);
2413
2414 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002415 if (uc_info == NULL) {
2416 ret = -ENOMEM;
2417 goto exit;
2418 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002419 /*
2420 * We set this early so that functions called after this is being set
2421 * can use it. It is e.g. needed in select_devices() to inform the RILD
2422 * which output device we use.
2423 */
2424 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002425
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002426 uc_info->id = USECASE_VOICE_CALL;
2427 uc_info->type = VOICE_CALL;
2428 uc_info->stream = (struct audio_stream *)adev->primary_output;
2429 uc_info->devices = adev->primary_output->devices;
2430 uc_info->in_snd_device = SND_DEVICE_NONE;
2431 uc_info->out_snd_device = SND_DEVICE_NONE;
2432
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002433 list_init(&uc_info->mixer_list);
2434 list_add_tail(&uc_info->mixer_list,
2435 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002436
2437 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2438
2439 select_devices(adev, USECASE_VOICE_CALL);
2440
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002441 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002442
2443 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002444 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002445
Andreas Schneider56204f62017-01-31 08:17:32 +01002446exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002447 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002448 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002449}
2450
2451static int check_input_parameters(uint32_t sample_rate,
2452 audio_format_t format,
2453 int channel_count)
2454{
2455 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2456
2457 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2458
2459 switch (sample_rate) {
2460 case 8000:
2461 case 11025:
2462 case 12000:
2463 case 16000:
2464 case 22050:
2465 case 24000:
2466 case 32000:
2467 case 44100:
2468 case 48000:
2469 break;
2470 default:
2471 return -EINVAL;
2472 }
2473
2474 return 0;
2475}
2476
2477static size_t get_input_buffer_size(uint32_t sample_rate,
2478 audio_format_t format,
2479 int channel_count,
2480 usecase_type_t usecase_type,
2481 audio_devices_t devices)
2482{
2483 size_t size = 0;
2484 struct pcm_device_profile *pcm_profile;
2485
2486 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2487 return 0;
2488
2489 pcm_profile = get_pcm_device(usecase_type, devices);
2490 if (pcm_profile == NULL)
2491 return 0;
2492
2493 /*
2494 * take resampling into account and return the closest majoring
2495 * multiple of 16 frames, as audioflinger expects audio buffers to
2496 * be a multiple of 16 frames
2497 */
2498 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2499 size = ((size + 15) / 16) * 16;
2500
2501 return (size * channel_count * audio_bytes_per_sample(format));
2502
2503}
2504
2505static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2506{
2507 struct stream_out *out = (struct stream_out *)stream;
2508
2509 return out->sample_rate;
2510}
2511
2512static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2513{
2514 (void)stream;
2515 (void)rate;
2516 return -ENOSYS;
2517}
2518
2519static size_t out_get_buffer_size(const struct audio_stream *stream)
2520{
2521 struct stream_out *out = (struct stream_out *)stream;
2522
2523 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2524 return out->compr_config.fragment_size;
2525 }
2526
2527 return out->config.period_size *
2528 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2529}
2530
2531static uint32_t out_get_channels(const struct audio_stream *stream)
2532{
2533 struct stream_out *out = (struct stream_out *)stream;
2534
2535 return out->channel_mask;
2536}
2537
2538static audio_format_t out_get_format(const struct audio_stream *stream)
2539{
2540 struct stream_out *out = (struct stream_out *)stream;
2541
2542 return out->format;
2543}
2544
2545static int out_set_format(struct audio_stream *stream, audio_format_t format)
2546{
2547 (void)stream;
2548 (void)format;
2549 return -ENOSYS;
2550}
2551
2552static int do_out_standby_l(struct stream_out *out)
2553{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002554 int status = 0;
2555
2556 out->standby = true;
2557 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2558 out_close_pcm_devices(out);
2559#ifdef PREPROCESSING_ENABLED
2560 /* stop writing to echo reference */
2561 if (out->echo_reference != NULL) {
2562 out->echo_reference->write(out->echo_reference, NULL);
2563 if (out->echo_reference_generation != adev->echo_reference_generation) {
2564 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2565 release_echo_reference(out->echo_reference);
2566 out->echo_reference_generation = adev->echo_reference_generation;
2567 }
2568 out->echo_reference = NULL;
2569 }
2570#endif
2571 } else {
2572 stop_compressed_output_l(out);
2573 out->gapless_mdata.encoder_delay = 0;
2574 out->gapless_mdata.encoder_padding = 0;
2575 if (out->compr != NULL) {
2576 compress_close(out->compr);
2577 out->compr = NULL;
2578 }
2579 }
2580 status = stop_output_stream(out);
2581
2582 return status;
2583}
2584
2585static int out_standby(struct audio_stream *stream)
2586{
2587 struct stream_out *out = (struct stream_out *)stream;
2588 struct audio_device *adev = out->dev;
2589
2590 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2591 out->usecase, use_case_table[out->usecase]);
2592 lock_output_stream(out);
2593 if (!out->standby) {
2594 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002595 amplifier_output_stream_standby((struct audio_stream_out *) stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002596 do_out_standby_l(out);
2597 pthread_mutex_unlock(&adev->lock);
2598 }
2599 pthread_mutex_unlock(&out->lock);
2600 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002601
2602 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2603
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002604 return 0;
2605}
2606
2607static int out_dump(const struct audio_stream *stream, int fd)
2608{
2609 (void)stream;
2610 (void)fd;
2611
2612 return 0;
2613}
2614
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002615static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2616{
2617 struct stream_out *out = (struct stream_out *)stream;
2618 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002619 struct listnode *node;
2620 struct str_parms *parms;
2621 char value[32];
2622 int ret, val = 0;
2623 struct audio_usecase *uc_info;
2624 bool do_standby = false;
2625 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002626#ifdef PREPROCESSING_ENABLED
2627 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2628#endif
2629
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002630 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%#x) "
2631 "adev->mode(%#x)",
2632 __func__, out->usecase, use_case_table[out->usecase], kvpairs,
2633 out->devices, adev->mode);
2634
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002635 parms = str_parms_create_str(kvpairs);
2636 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2637 if (ret >= 0) {
2638 val = atoi(value);
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002639
2640 ALOGV("%s: routing: usecase(%d: %s) devices=(%#x) adev->mode(%#x)",
2641 __func__, out->usecase, use_case_table[out->usecase], val,
2642 adev->mode);
2643
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002644 pthread_mutex_lock(&adev->lock_inputs);
2645 lock_output_stream(out);
2646 pthread_mutex_lock(&adev->lock);
2647#ifdef PREPROCESSING_ENABLED
2648 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2649 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2650 /* reset active input:
2651 * - to attach the echo reference
2652 * - because a change in output device may change mic settings */
2653 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2654 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2655 in = adev->active_input;
2656 }
2657 }
2658#endif
Christopher N. Hesse33affb82017-11-16 17:01:37 +01002659 if (val != SND_DEVICE_NONE) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002660 out->devices = val;
2661
2662 if (!out->standby) {
2663 uc_info = get_usecase_from_id(adev, out->usecase);
2664 if (uc_info == NULL) {
2665 ALOGE("%s: Could not find the usecase (%d) in the list",
2666 __func__, out->usecase);
2667 } else {
2668 list_for_each(node, &out->pcm_dev_list) {
2669 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2670 if ((pcm_device->pcm_profile->devices & val) == 0)
2671 do_standby = true;
2672 val &= ~pcm_device->pcm_profile->devices;
2673 }
2674 if (val != 0)
2675 do_standby = true;
2676 }
2677 if (do_standby)
2678 do_out_standby_l(out);
2679 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002680 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2681 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002682 select_devices(adev, out->usecase);
2683 }
2684 }
2685
stenkinevgeniy53929f72018-07-09 11:20:36 +00002686 /* Turn on bluetooth sco if needed */
2687 if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION || adev->mode == AUDIO_MODE_IN_CALL) &&
2688 (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !adev->bt_sco_active) {
2689 adev->bt_sco_active = true;
2690 start_voice_session_bt_sco(adev);
2691 }
2692 else if (!(out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && adev->bt_sco_active) {
2693 adev->bt_sco_active = false;
2694 stop_voice_session_bt_sco(adev);
2695 }
2696
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002697 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002698 (out == adev->primary_output)) {
2699 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002700 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2701 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002702 (out == adev->primary_output)) {
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002703 /*
2704 * When we select different devices we need to restart the
2705 * voice call. The modem closes the stream on its end and
2706 * we do not get any output.
2707 */
2708 stop_voice_call(adev);
2709 start_voice_call(adev);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002710 }
2711 }
2712
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002713 pthread_mutex_unlock(&adev->lock);
2714 pthread_mutex_unlock(&out->lock);
2715#ifdef PREPROCESSING_ENABLED
2716 if (in) {
2717 /* The lock on adev->lock_inputs prevents input stream from being closed */
2718 lock_input_stream(in);
2719 pthread_mutex_lock(&adev->lock);
2720 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2721 do_in_standby_l(in);
2722 pthread_mutex_unlock(&adev->lock);
2723 pthread_mutex_unlock(&in->lock);
2724 }
2725#endif
2726 pthread_mutex_unlock(&adev->lock_inputs);
2727 }
2728
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002729 amplifier_set_parameters(parms);
2730
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002731 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2732 parse_compress_metadata(out, parms);
2733 }
2734
2735 str_parms_destroy(parms);
2736
2737 if (ret > 0)
2738 ret = 0;
2739 ALOGV("%s: exit: code(%d)", __func__, ret);
2740 return ret;
2741}
2742
2743static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2744{
2745 struct stream_out *out = (struct stream_out *)stream;
2746 struct str_parms *query = str_parms_create_str(keys);
2747 char *str;
2748 char value[256];
2749 struct str_parms *reply = str_parms_create();
2750 size_t i, j;
2751 int ret;
2752 bool first = true;
2753 ALOGV("%s: enter: keys - %s", __func__, keys);
2754 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2755 if (ret >= 0) {
2756 value[0] = '\0';
2757 i = 0;
2758 while (out->supported_channel_masks[i] != 0) {
2759 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2760 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2761 if (!first) {
2762 strcat(value, "|");
2763 }
2764 strcat(value, out_channels_name_to_enum_table[j].name);
2765 first = false;
2766 break;
2767 }
2768 }
2769 i++;
2770 }
2771 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2772 str = str_parms_to_str(reply);
2773 } else {
2774 str = strdup(keys);
2775 }
2776 str_parms_destroy(query);
2777 str_parms_destroy(reply);
2778 ALOGV("%s: exit: returns - %s", __func__, str);
2779 return str;
2780}
2781
2782static uint32_t out_get_latency(const struct audio_stream_out *stream)
2783{
2784 struct stream_out *out = (struct stream_out *)stream;
2785
2786 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2787 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2788
2789 return (out->config.period_count * out->config.period_size * 1000) /
2790 (out->config.rate);
2791}
2792
2793static int out_set_volume(struct audio_stream_out *stream, float left,
2794 float right)
2795{
2796 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002797
2798 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2799 /* only take left channel into account: the API is for stereo anyway */
2800 out->muted = (left == 0.0f);
2801 return 0;
2802 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002803 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002804 }
2805
2806 return -ENOSYS;
2807}
2808
Andreas Schneider3b643832017-01-31 11:48:22 +01002809#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002810static int fast_set_affinity(pid_t tid) {
2811 cpu_set_t cpu_set;
2812 int cpu_num;
2813 const char *irq_procfs = "/proc/asound/irq_affinity";
2814 FILE *fp;
2815
2816 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2817 ALOGW("Procfs node %s not found", irq_procfs);
2818 return -1;
2819 }
2820
2821 if (fscanf(fp, "%d", &cpu_num) != 1) {
2822 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2823 fclose(fp);
2824 return -1;
2825 }
2826 fclose(fp);
2827
2828 CPU_ZERO(&cpu_set);
2829 CPU_SET(cpu_num, &cpu_set);
2830 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2831}
Andreas Schneider3b643832017-01-31 11:48:22 +01002832#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002833
2834static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2835 size_t bytes)
2836{
2837 struct stream_out *out = (struct stream_out *)stream;
2838 struct audio_device *adev = out->dev;
2839 ssize_t ret = 0;
2840 struct pcm_device *pcm_device;
2841 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002842#ifdef PREPROCESSING_ENABLED
stenkinevgeniyd0a02c02018-05-08 07:17:53 +00002843 size_t frame_size = audio_stream_out_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002844 size_t in_frames = bytes / frame_size;
2845 size_t out_frames = in_frames;
2846 struct stream_in *in = NULL;
2847#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002848
2849 lock_output_stream(out);
2850
Andreas Schneider3b643832017-01-31 11:48:22 +01002851#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002852 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002853 pid_t tid = gettid();
2854 int err;
2855
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002856 err = fast_set_affinity(tid);
2857 if (err < 0) {
2858 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2859 }
2860 out->is_fastmixer_affinity_set = true;
2861 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002862#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002863
2864 if (out->standby) {
2865#ifdef PREPROCESSING_ENABLED
2866 pthread_mutex_unlock(&out->lock);
2867 /* Prevent input stream from being closed */
2868 pthread_mutex_lock(&adev->lock_inputs);
2869 lock_output_stream(out);
2870 if (!out->standby) {
2871 pthread_mutex_unlock(&adev->lock_inputs);
2872 goto false_alarm;
2873 }
2874#endif
2875 pthread_mutex_lock(&adev->lock);
2876 ret = start_output_stream(out);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002877 if (ret == 0) {
2878 amplifier_output_stream_start(stream, out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD);
2879 }
2880
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002881 /* ToDo: If use case is compress offload should return 0 */
2882 if (ret != 0) {
2883 pthread_mutex_unlock(&adev->lock);
2884#ifdef PREPROCESSING_ENABLED
2885 pthread_mutex_unlock(&adev->lock_inputs);
2886#endif
2887 goto exit;
2888 }
2889 out->standby = false;
2890
2891#ifdef PREPROCESSING_ENABLED
2892 /* A change in output device may change the microphone selection */
2893 if (adev->active_input &&
2894 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2895 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2896 in = adev->active_input;
2897 ALOGV("%s: enter:) force_input_standby true", __func__);
2898 }
2899#endif
2900 pthread_mutex_unlock(&adev->lock);
2901#ifdef PREPROCESSING_ENABLED
2902 if (!in) {
2903 /* Leave mutex locked iff in != NULL */
2904 pthread_mutex_unlock(&adev->lock_inputs);
2905 }
2906#endif
2907 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002908#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002909false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002910#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002911
2912 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002913 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002914 return ret;
2915 } else {
2916#ifdef PREPROCESSING_ENABLED
2917 if (android_atomic_acquire_load(&adev->echo_reference_generation)
2918 != out->echo_reference_generation) {
2919 pthread_mutex_lock(&adev->lock);
2920 if (out->echo_reference != NULL) {
2921 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2922 release_echo_reference(out->echo_reference);
2923 }
2924 // note that adev->echo_reference_generation here can be different from the one
2925 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
2926 // with what has been set by get_echo_reference() or put_echo_reference()
2927 out->echo_reference_generation = adev->echo_reference_generation;
2928 out->echo_reference = adev->echo_reference;
2929 ALOGV("%s: update echo reference generation %d", __func__,
2930 out->echo_reference_generation);
2931 pthread_mutex_unlock(&adev->lock);
2932 }
2933#endif
2934
2935 if (out->muted)
2936 memset((void *)buffer, 0, bytes);
2937 list_for_each(node, &out->pcm_dev_list) {
2938 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002939 if (pcm_device->pcm) {
2940#ifdef PREPROCESSING_ENABLED
2941 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
2942 struct echo_reference_buffer b;
2943 b.raw = (void *)buffer;
2944 b.frame_count = in_frames;
2945
2946 get_playback_delay(out, out_frames, &b);
2947 out->echo_reference->write(out->echo_reference, &b);
2948 }
2949#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002950 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
stenkinevgeniyd0a02c02018-05-08 07:17:53 +00002951 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002952 if (pcm_device->status != 0)
2953 ret = pcm_device->status;
2954 }
2955 }
2956 if (ret == 0)
2957 out->written += bytes / (out->config.channels * sizeof(short));
2958 }
2959
2960exit:
2961 pthread_mutex_unlock(&out->lock);
2962
2963 if (ret != 0) {
2964 list_for_each(node, &out->pcm_dev_list) {
2965 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2966 if (pcm_device->pcm && pcm_device->status != 0)
2967 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
2968 }
2969 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002970 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
2971 clock_gettime(CLOCK_MONOTONIC, &t);
2972 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
2973 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
2974 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2975 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
2976 if (sleep_time > 0) {
2977 usleep(sleep_time);
2978 } else {
2979 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
2980 sleep_time = 0;
2981 }
2982 out->last_write_time_us = now + sleep_time;
2983 // last_write_time_us is an approximation of when the (simulated) alsa
2984 // buffer is believed completely full. The usleep above waits for more space
2985 // in the buffer, but by the end of the sleep the buffer is considered
2986 // topped-off.
2987 //
2988 // On the subsequent out_write(), we measure the elapsed time spent in
2989 // the mixer. This is subtracted from the sleep estimate based on frames,
2990 // thereby accounting for drain in the alsa buffer during mixing.
2991 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002992 }
2993
2994#ifdef PREPROCESSING_ENABLED
2995 if (in) {
2996 /* The lock on adev->lock_inputs prevents input stream from being closed */
2997 lock_input_stream(in);
2998 pthread_mutex_lock(&adev->lock);
2999 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3000 do_in_standby_l(in);
3001 pthread_mutex_unlock(&adev->lock);
3002 pthread_mutex_unlock(&in->lock);
3003 /* This mutex was left locked iff in != NULL */
3004 pthread_mutex_unlock(&adev->lock_inputs);
3005 }
3006#endif
3007
3008 return bytes;
3009}
3010
3011static int out_get_render_position(const struct audio_stream_out *stream,
3012 uint32_t *dsp_frames)
3013{
3014 struct stream_out *out = (struct stream_out *)stream;
3015 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003016 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3017 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003018 } else
3019 return -EINVAL;
3020}
3021
3022static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3023{
3024 (void)stream;
3025 (void)effect;
3026 return 0;
3027}
3028
3029static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3030{
3031 (void)stream;
3032 (void)effect;
3033 return 0;
3034}
3035
3036static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3037 int64_t *timestamp)
3038{
3039 (void)stream;
3040 (void)timestamp;
3041 return -EINVAL;
3042}
3043
3044static int out_get_presentation_position(const struct audio_stream_out *stream,
3045 uint64_t *frames, struct timespec *timestamp)
3046{
3047 struct stream_out *out = (struct stream_out *)stream;
Victor Lourme5869cd32018-03-26 19:36:07 +02003048 int ret = -EINVAL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003049
3050 lock_output_stream(out);
3051
3052 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003053 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003054 } else {
3055 /* FIXME: which device to read from? */
3056 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003057 struct pcm_device *pcm_device;
3058 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003059 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003060
Andreas Schneiderd6359182017-02-08 16:58:22 +01003061 list_for_each(node, &out->pcm_dev_list) {
3062 pcm_device = node_to_item(node,
3063 struct pcm_device,
3064 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003065
Andreas Schneiderd6359182017-02-08 16:58:22 +01003066 if (pcm_device->pcm != NULL) {
3067 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3068 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3069 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3070 /* This adjustment accounts for buffering after app processor.
3071 It is based on estimated DSP latency per use case, rather than exact. */
3072 signed_frames -=
3073 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3074
3075 /* It would be unusual for this value to be negative, but check just in case ... */
3076 if (signed_frames >= 0) {
3077 *frames = signed_frames;
3078 ret = 0;
3079 goto done;
3080 }
Andreas Schneiderd6359182017-02-08 16:58:22 +01003081 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003082 }
3083 }
3084 }
3085 }
3086
Andreas Schneiderd6359182017-02-08 16:58:22 +01003087done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003088 pthread_mutex_unlock(&out->lock);
3089
3090 return ret;
3091}
3092
3093static int out_set_callback(struct audio_stream_out *stream,
3094 stream_callback_t callback, void *cookie)
3095{
3096 struct stream_out *out = (struct stream_out *)stream;
3097
3098 ALOGV("%s", __func__);
3099 lock_output_stream(out);
3100 out->offload_callback = callback;
3101 out->offload_cookie = cookie;
3102 pthread_mutex_unlock(&out->lock);
3103 return 0;
3104}
3105
3106static int out_pause(struct audio_stream_out* stream)
3107{
3108 struct stream_out *out = (struct stream_out *)stream;
3109 int status = -ENOSYS;
3110 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003111 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3112 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003113 return status;
3114}
3115
3116static int out_resume(struct audio_stream_out* stream)
3117{
3118 struct stream_out *out = (struct stream_out *)stream;
3119 int status = -ENOSYS;
3120 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003121 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3122 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003123 return status;
3124}
3125
3126static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3127{
3128 struct stream_out *out = (struct stream_out *)stream;
3129 int status = -ENOSYS;
3130 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003131 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3132 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003133 return status;
3134}
3135
3136static int out_flush(struct audio_stream_out* stream)
3137{
3138 struct stream_out *out = (struct stream_out *)stream;
3139 ALOGV("%s", __func__);
3140 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003141 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003142 }
3143 return -ENOSYS;
3144}
3145
3146/** audio_stream_in implementation **/
3147static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3148{
3149 struct stream_in *in = (struct stream_in *)stream;
3150
3151 return in->requested_rate;
3152}
3153
3154static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3155{
3156 (void)stream;
3157 (void)rate;
3158 return -ENOSYS;
3159}
3160
3161static uint32_t in_get_channels(const struct audio_stream *stream)
3162{
3163 struct stream_in *in = (struct stream_in *)stream;
3164
3165 return in->main_channels;
3166}
3167
3168static audio_format_t in_get_format(const struct audio_stream *stream)
3169{
3170 (void)stream;
3171 return AUDIO_FORMAT_PCM_16_BIT;
3172}
3173
3174static int in_set_format(struct audio_stream *stream, audio_format_t format)
3175{
3176 (void)stream;
3177 (void)format;
3178
3179 return -ENOSYS;
3180}
3181
3182static size_t in_get_buffer_size(const struct audio_stream *stream)
3183{
3184 struct stream_in *in = (struct stream_in *)stream;
3185
3186 return get_input_buffer_size(in->requested_rate,
3187 in_get_format(stream),
3188 audio_channel_count_from_in_mask(in->main_channels),
3189 in->usecase_type,
3190 in->devices);
3191}
3192
3193static int in_close_pcm_devices(struct stream_in *in)
3194{
3195 struct pcm_device *pcm_device;
3196 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003197
3198 list_for_each(node, &in->pcm_dev_list) {
3199 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3200 if (pcm_device) {
3201 if (pcm_device->pcm)
3202 pcm_close(pcm_device->pcm);
3203 pcm_device->pcm = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003204 }
3205 }
3206 return 0;
3207}
3208
3209
3210/* must be called with stream and hw device mutex locked */
3211static int do_in_standby_l(struct stream_in *in)
3212{
3213 int status = 0;
3214
3215#ifdef PREPROCESSING_ENABLED
3216 struct audio_device *adev = in->dev;
3217#endif
3218 if (!in->standby) {
3219
3220 in_close_pcm_devices(in);
3221
3222#ifdef PREPROCESSING_ENABLED
3223 if (in->echo_reference != NULL) {
3224 /* stop reading from echo reference */
3225 in->echo_reference->read(in->echo_reference, NULL);
3226 put_echo_reference(adev, in->echo_reference);
3227 in->echo_reference = NULL;
3228 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003229#endif // PREPROCESSING_ENABLED
3230
3231 status = stop_input_stream(in);
3232
3233 if (in->read_buf) {
3234 free(in->read_buf);
3235 in->read_buf = NULL;
3236 }
3237
3238 in->standby = 1;
3239 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003240
3241 in->last_read_time_us = 0;
3242
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003243 return 0;
3244}
3245
3246// called with adev->lock_inputs locked
3247static int in_standby_l(struct stream_in *in)
3248{
3249 struct audio_device *adev = in->dev;
3250 int status = 0;
3251 lock_input_stream(in);
3252 if (!in->standby) {
3253 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003254 amplifier_input_stream_standby((struct audio_stream_in *) in);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003255 status = do_in_standby_l(in);
3256 pthread_mutex_unlock(&adev->lock);
3257 }
3258 pthread_mutex_unlock(&in->lock);
3259 return status;
3260}
3261
3262static int in_standby(struct audio_stream *stream)
3263{
3264 struct stream_in *in = (struct stream_in *)stream;
3265 struct audio_device *adev = in->dev;
3266 int status;
3267 ALOGV("%s: enter", __func__);
3268 pthread_mutex_lock(&adev->lock_inputs);
3269 status = in_standby_l(in);
3270 pthread_mutex_unlock(&adev->lock_inputs);
3271 ALOGV("%s: exit: status(%d)", __func__, status);
3272 return status;
3273}
3274
3275static int in_dump(const struct audio_stream *stream, int fd)
3276{
3277 (void)stream;
3278 (void)fd;
3279
3280 return 0;
3281}
3282
3283static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3284{
3285 struct stream_in *in = (struct stream_in *)stream;
3286 struct audio_device *adev = in->dev;
3287 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003288 char value[32];
3289 int ret, val = 0;
3290 struct audio_usecase *uc_info;
3291 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003292 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003293
3294 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3295 parms = str_parms_create_str(kvpairs);
3296
3297 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3298
3299 pthread_mutex_lock(&adev->lock_inputs);
3300 lock_input_stream(in);
3301 pthread_mutex_lock(&adev->lock);
3302 if (ret >= 0) {
3303 val = atoi(value);
3304 /* no audio source uses val == 0 */
3305 if (((int)in->source != val) && (val != 0)) {
3306 in->source = val;
3307 }
3308 }
3309
3310 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3311 if (ret >= 0) {
3312 val = atoi(value);
3313 if (((int)in->devices != val) && (val != 0)) {
3314 in->devices = val;
3315 /* If recording is in progress, change the tx device to new device */
3316 if (!in->standby) {
3317 uc_info = get_usecase_from_id(adev, in->usecase);
3318 if (uc_info == NULL) {
3319 ALOGE("%s: Could not find the usecase (%d) in the list",
3320 __func__, in->usecase);
3321 } else {
3322 if (list_empty(&in->pcm_dev_list))
3323 ALOGE("%s: pcm device list empty", __func__);
3324 else {
3325 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3326 struct pcm_device, stream_list_node);
3327 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3328 do_standby = true;
3329 }
3330 }
3331 }
3332 if (do_standby) {
3333 ret = do_in_standby_l(in);
3334 } else
3335 ret = select_devices(adev, in->usecase);
3336 }
3337 }
3338 }
3339 pthread_mutex_unlock(&adev->lock);
3340 pthread_mutex_unlock(&in->lock);
3341 pthread_mutex_unlock(&adev->lock_inputs);
3342 str_parms_destroy(parms);
3343
3344 if (ret > 0)
3345 ret = 0;
3346
3347 ALOGV("%s: exit: status(%d)", __func__, ret);
3348 return ret;
3349}
3350
3351static char* in_get_parameters(const struct audio_stream *stream,
3352 const char *keys)
3353{
3354 (void)stream;
3355 (void)keys;
3356
3357 return strdup("");
3358}
3359
3360static int in_set_gain(struct audio_stream_in *stream, float gain)
3361{
3362 (void)stream;
3363 (void)gain;
3364
3365 return 0;
3366}
3367
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003368static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3369 size_t bytes)
3370{
3371 struct stream_in *in = (struct stream_in *)stream;
3372 struct audio_device *adev = in->dev;
3373 ssize_t frames = -1;
3374 int ret = -1;
3375 int read_and_process_successful = false;
3376
3377 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003378
3379 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3380 lock_input_stream(in);
3381
Andreas Schneider3b643832017-01-31 11:48:22 +01003382#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003383 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003384 pid_t tid = gettid();
3385 int err;
3386
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003387 err = fast_set_affinity(tid);
3388 if (err < 0) {
3389 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3390 }
3391 in->is_fastcapture_affinity_set = true;
3392 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003393#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003394
3395 if (in->standby) {
3396 pthread_mutex_unlock(&in->lock);
3397 pthread_mutex_lock(&adev->lock_inputs);
3398 lock_input_stream(in);
3399 if (!in->standby) {
3400 pthread_mutex_unlock(&adev->lock_inputs);
3401 goto false_alarm;
3402 }
3403 pthread_mutex_lock(&adev->lock);
3404 ret = start_input_stream(in);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003405 if (ret == 0) {
3406 amplifier_input_stream_start(stream);
3407 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003408 pthread_mutex_unlock(&adev->lock);
3409 pthread_mutex_unlock(&adev->lock_inputs);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003410
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003411 if (ret != 0) {
3412 goto exit;
3413 }
3414 in->standby = 0;
3415 }
3416false_alarm:
3417
3418 if (!list_empty(&in->pcm_dev_list)) {
stenkinevgeniy44335362018-05-07 18:00:13 +00003419 /*
3420 * Read PCM and:
3421 * - resample if needed
3422 * - process if pre-processors are attached
3423 * - discard unwanted channels
3424 */
3425 frames = read_and_process_frames(in, buffer, frames_rq);
3426 if (frames >= 0)
3427 read_and_process_successful = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003428 }
3429
3430 /*
3431 * Instead of writing zeroes here, we could trust the hardware
3432 * to always provide zeroes when muted.
3433 */
3434 if (read_and_process_successful == true && adev->mic_mute)
3435 memset(buffer, 0, bytes);
3436
3437exit:
3438 pthread_mutex_unlock(&in->lock);
3439
3440 if (read_and_process_successful == false) {
3441 in_standby(&in->stream.common);
3442 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003443 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3444 clock_gettime(CLOCK_MONOTONIC, &t);
3445 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3446
3447 // we do a full sleep when exiting standby.
3448 const bool standby = in->last_read_time_us == 0;
3449 const int64_t elapsed_time_since_last_read = standby ?
3450 0 : now - in->last_read_time_us;
3451 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3452 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3453 if (sleep_time > 0) {
3454 usleep(sleep_time);
3455 } else {
3456 sleep_time = 0;
3457 }
3458 in->last_read_time_us = now + sleep_time;
3459 // last_read_time_us is an approximation of when the (simulated) alsa
3460 // buffer is drained by the read, and is empty.
3461 //
3462 // On the subsequent in_read(), we measure the elapsed time spent in
3463 // the recording thread. This is subtracted from the sleep estimate based on frames,
3464 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003465 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003466 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003467
3468 if (bytes > 0) {
3469 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3470 }
3471
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003472 return bytes;
3473}
3474
3475static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3476{
3477 (void)stream;
3478
3479 return 0;
3480}
3481
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003482static int in_get_capture_position(const struct audio_stream_in *stream,
3483 int64_t *frames, int64_t *time)
3484{
3485 if (stream == NULL || frames == NULL || time == NULL) {
3486 return -EINVAL;
3487 }
3488
3489 struct stream_in *in = (struct stream_in *)stream;
3490 struct pcm_device *pcm_device;
3491 int ret = -ENOSYS;
3492
Vasyl Gellod758a172018-07-01 10:57:35 +03003493 if (list_empty(&in->pcm_dev_list)) {
3494 ALOGW("%s: pcm device list empty", __func__);
3495 return -ENODEV;
3496 }
3497
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003498 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3499 struct pcm_device, stream_list_node);
3500
3501 pthread_mutex_lock(&in->lock);
3502 if (pcm_device->pcm) {
3503 struct timespec timestamp;
3504 unsigned int avail;
3505 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3506 *frames = in->frames_read + avail;
3507 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3508 ret = 0;
3509 }
3510 }
3511
3512 pthread_mutex_unlock(&in->lock);
3513 return ret;
3514}
3515
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003516static int add_remove_audio_effect(const struct audio_stream *stream,
3517 effect_handle_t effect,
3518 bool enable)
3519{
3520 struct stream_in *in = (struct stream_in *)stream;
3521 struct audio_device *adev = in->dev;
3522 int status = 0;
3523 effect_descriptor_t desc;
3524#ifdef PREPROCESSING_ENABLED
3525 int i;
3526#endif
3527 status = (*effect)->get_descriptor(effect, &desc);
3528 if (status != 0)
3529 return status;
3530
3531 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3532
3533 pthread_mutex_lock(&adev->lock_inputs);
3534 lock_input_stream(in);
3535 pthread_mutex_lock(&in->dev->lock);
3536#ifndef PREPROCESSING_ENABLED
3537 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3538 in->enable_aec != enable &&
3539 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3540 in->enable_aec = enable;
3541 if (!in->standby)
3542 select_devices(in->dev, in->usecase);
3543 }
3544#else
3545 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3546 status = -ENOSYS;
3547 goto exit;
3548 }
3549 if ( enable == true ) {
3550 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3551 /* add the supported channel of the effect in the channel_configs */
3552 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3553 in->num_preprocessors ++;
3554 /* check compatibility between main channel supported and possible auxiliary channels */
3555 in_update_aux_channels(in, effect);//wesley crash
3556 in->aux_channels_changed = true;
3557 } else {
3558 /* if ( enable == false ) */
3559 if (in->num_preprocessors <= 0) {
3560 status = -ENOSYS;
3561 goto exit;
3562 }
3563 status = -EINVAL;
3564 for (i=0; i < in->num_preprocessors; i++) {
3565 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3566 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3567 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3568 in->preprocessors[i - 1].num_channel_configs =
3569 in->preprocessors[i].num_channel_configs;
3570 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3571 continue;
3572 }
3573 if ( in->preprocessors[i].effect_itfe == effect ) {
3574 ALOGV("add_remove_audio_effect found fx at index %d", i);
3575 free(in->preprocessors[i].channel_configs);
3576 status = 0;
3577 }
3578 }
3579 if (status != 0)
3580 goto exit;
3581 in->num_preprocessors--;
3582 /* if we remove one effect, at least the last proproc should be reset */
3583 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3584 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3585 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3586 in->aux_channels_changed = false;
3587 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3588 }
3589 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3590
3591 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3592 in->enable_aec = enable;
3593 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3594 if (!in->standby) {
3595 select_devices(in->dev, in->usecase);
3596 do_in_standby_l(in);
3597 }
3598 if (in->enable_aec == true) {
3599 in_configure_reverse(in);
3600 }
3601 }
3602exit:
3603#endif
3604 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3605 pthread_mutex_unlock(&in->dev->lock);
3606 pthread_mutex_unlock(&in->lock);
3607 pthread_mutex_unlock(&adev->lock_inputs);
3608 return status;
3609}
3610
3611static int in_add_audio_effect(const struct audio_stream *stream,
3612 effect_handle_t effect)
3613{
3614 ALOGV("%s: effect %p", __func__, effect);
3615 return add_remove_audio_effect(stream, effect, true);
3616}
3617
3618static int in_remove_audio_effect(const struct audio_stream *stream,
3619 effect_handle_t effect)
3620{
3621 ALOGV("%s: effect %p", __func__, effect);
3622 return add_remove_audio_effect(stream, effect, false);
3623}
3624
3625static int adev_open_output_stream(struct audio_hw_device *dev,
3626 audio_io_handle_t handle,
3627 audio_devices_t devices,
3628 audio_output_flags_t flags,
3629 struct audio_config *config,
3630 struct audio_stream_out **stream_out,
3631 const char *address __unused)
3632{
3633 struct audio_device *adev = (struct audio_device *)dev;
3634 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003635 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003636 struct pcm_device_profile *pcm_profile;
3637
3638 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3639 __func__, config->sample_rate, config->channel_mask, devices, flags);
3640 *stream_out = NULL;
3641 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003642 if (out == NULL) {
3643 ret = -ENOMEM;
3644 goto error_config;
3645 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003646
3647 if (devices == AUDIO_DEVICE_NONE)
3648 devices = AUDIO_DEVICE_OUT_SPEAKER;
3649
3650 out->flags = flags;
3651 out->devices = devices;
3652 out->dev = adev;
3653 out->format = config->format;
3654 out->sample_rate = config->sample_rate;
3655 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3656 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3657 out->handle = handle;
3658
3659 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3660 if (pcm_profile == NULL) {
3661 ret = -EINVAL;
3662 goto error_open;
3663 }
3664 out->config = pcm_profile->config;
3665
3666 /* Init use case and pcm_config */
3667 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3668 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3669 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3670 ALOGE("%s: Unsupported Offload information", __func__);
3671 ret = -EINVAL;
3672 goto error_open;
3673 }
3674 if (!is_supported_format(config->offload_info.format)) {
3675 ALOGE("%s: Unsupported audio format", __func__);
3676 ret = -EINVAL;
3677 goto error_open;
3678 }
3679
3680 out->compr_config.codec = (struct snd_codec *)
3681 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003682 if (out->compr_config.codec == NULL) {
3683 ret = -ENOMEM;
3684 goto error_open;
3685 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003686
3687 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3688 if (config->offload_info.channel_mask)
3689 out->channel_mask = config->offload_info.channel_mask;
3690 else if (config->channel_mask)
3691 out->channel_mask = config->channel_mask;
3692 out->format = config->offload_info.format;
3693 out->sample_rate = config->offload_info.sample_rate;
3694
3695 out->stream.set_callback = out_set_callback;
3696 out->stream.pause = out_pause;
3697 out->stream.resume = out_resume;
3698 out->stream.drain = out_drain;
3699 out->stream.flush = out_flush;
3700
3701 out->compr_config.codec->id =
3702 get_snd_codec_id(config->offload_info.format);
3703 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3704 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3705 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3706 out->compr_config.codec->bit_rate =
3707 config->offload_info.bit_rate;
3708 out->compr_config.codec->ch_in =
3709 audio_channel_count_from_out_mask(config->channel_mask);
3710 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3711
3712 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3713 out->non_blocking = 1;
3714
3715 out->send_new_metadata = 1;
3716 create_offload_callback_thread(out);
3717 out->offload_state = OFFLOAD_STATE_IDLE;
3718
3719 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3720 __func__, config->offload_info.version,
3721 config->offload_info.bit_rate);
3722 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3723 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003724 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003725 out->sample_rate = out->config.rate;
3726 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3727 } else {
3728 out->usecase = USECASE_AUDIO_PLAYBACK;
3729 out->sample_rate = out->config.rate;
3730 }
3731
3732 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3733 if (adev->primary_output == NULL)
3734 adev->primary_output = out;
3735 else {
3736 ALOGE("%s: Primary output is already opened", __func__);
3737 ret = -EEXIST;
3738 goto error_open;
3739 }
3740 }
3741
3742 /* Check if this usecase is already existing */
3743 pthread_mutex_lock(&adev->lock);
3744 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3745 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3746 pthread_mutex_unlock(&adev->lock);
3747 ret = -EEXIST;
3748 goto error_open;
3749 }
3750 pthread_mutex_unlock(&adev->lock);
3751
3752 out->stream.common.get_sample_rate = out_get_sample_rate;
3753 out->stream.common.set_sample_rate = out_set_sample_rate;
3754 out->stream.common.get_buffer_size = out_get_buffer_size;
3755 out->stream.common.get_channels = out_get_channels;
3756 out->stream.common.get_format = out_get_format;
3757 out->stream.common.set_format = out_set_format;
3758 out->stream.common.standby = out_standby;
3759 out->stream.common.dump = out_dump;
3760 out->stream.common.set_parameters = out_set_parameters;
3761 out->stream.common.get_parameters = out_get_parameters;
3762 out->stream.common.add_audio_effect = out_add_audio_effect;
3763 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3764 out->stream.get_latency = out_get_latency;
3765 out->stream.set_volume = out_set_volume;
3766 out->stream.write = out_write;
3767 out->stream.get_render_position = out_get_render_position;
3768 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3769 out->stream.get_presentation_position = out_get_presentation_position;
3770
3771 out->standby = 1;
3772 /* out->muted = false; by calloc() */
3773 /* out->written = 0; by calloc() */
3774
3775 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3776 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3777 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3778
3779 config->format = out->stream.common.get_format(&out->stream.common);
3780 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3781 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3782
3783 out->is_fastmixer_affinity_set = false;
3784
3785 *stream_out = &out->stream;
3786 ALOGV("%s: exit", __func__);
3787 return 0;
3788
3789error_open:
3790 free(out);
3791 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003792error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003793 ALOGV("%s: exit: ret %d", __func__, ret);
3794 return ret;
3795}
3796
3797static void adev_close_output_stream(struct audio_hw_device *dev,
3798 struct audio_stream_out *stream)
3799{
3800 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003801 (void)dev;
3802
3803 ALOGV("%s: enter", __func__);
3804 out_standby(&stream->common);
3805 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3806 destroy_offload_callback_thread(out);
3807
3808 if (out->compr_config.codec != NULL)
3809 free(out->compr_config.codec);
3810 }
3811 pthread_cond_destroy(&out->cond);
3812 pthread_mutex_destroy(&out->lock);
3813 free(stream);
3814 ALOGV("%s: exit", __func__);
3815}
3816
3817static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3818{
3819 struct audio_device *adev = (struct audio_device *)dev;
3820 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003821 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003822#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003823 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003824#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003825 int ret;
3826
3827 ALOGV("%s: enter: %s", __func__, kvpairs);
3828
3829 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003830
Andreas Schneider05bc1882017-02-09 14:03:11 +01003831 /******************************************************
3832 *** BT SCO
3833 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003834 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3835 if (ret >= 0) {
3836 /* When set to false, HAL should disable EC and NS
3837 * But it is currently not supported.
3838 */
3839 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003840 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003841 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003842 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003843 }
3844
Andreas Schneider05bc1882017-02-09 14:03:11 +01003845 ret = str_parms_get_str(parms,
3846 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3847 value,
3848 sizeof(value));
3849 if (ret >= 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01003850 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3851 adev->voice.bluetooth_wb = true;
Andreas Schneider05bc1882017-02-09 14:03:11 +01003852 } else {
3853 adev->voice.bluetooth_wb = false;
3854 }
3855 }
3856
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003857 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3858 if (ret >= 0) {
3859 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3860 adev->screen_off = false;
3861 else
3862 adev->screen_off = true;
3863 }
3864
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003865#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003866 ret = str_parms_get_int(parms, "rotation", &val);
3867 if (ret >= 0) {
3868 bool reverse_speakers = false;
3869 switch(val) {
3870 /* FIXME: note that the code below assumes that the speakers are in the correct placement
3871 relative to the user when the device is rotated 90deg from its default rotation. This
3872 assumption is device-specific, not platform-specific like this code. */
3873 case 270:
3874 reverse_speakers = true;
3875 break;
3876 case 0:
3877 case 90:
3878 case 180:
3879 break;
3880 default:
3881 ALOGE("%s: unexpected rotation of %d", __func__, val);
3882 }
3883 pthread_mutex_lock(&adev->lock);
3884 if (adev->speaker_lr_swap != reverse_speakers) {
3885 adev->speaker_lr_swap = reverse_speakers;
3886 /* only update the selected device if there is active pcm playback */
3887 struct audio_usecase *usecase;
3888 struct listnode *node;
3889 list_for_each(node, &adev->usecase_list) {
3890 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
3891 if (usecase->type == PCM_PLAYBACK) {
3892 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003893 break;
3894 }
3895 }
3896 }
3897 pthread_mutex_unlock(&adev->lock);
3898 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003899#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003900
3901 str_parms_destroy(parms);
3902
3903 if (ret > 0)
3904 ret = 0;
3905
3906 ALOGV("%s: exit with code(%d)", __func__, ret);
3907 return ret;
3908}
3909
3910static char* adev_get_parameters(const struct audio_hw_device *dev,
3911 const char *keys)
3912{
3913 (void)dev;
3914 (void)keys;
3915
3916 return strdup("");
3917}
3918
3919static int adev_init_check(const struct audio_hw_device *dev)
3920{
3921 (void)dev;
3922
3923 return 0;
3924}
3925
3926static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3927{
3928 int ret = 0;
3929 struct audio_device *adev = (struct audio_device *)dev;
3930 pthread_mutex_lock(&adev->lock);
3931 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003932 adev->voice.volume = volume;
3933 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003934 pthread_mutex_unlock(&adev->lock);
3935 return ret;
3936}
3937
3938static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
3939{
3940 (void)dev;
3941 (void)volume;
3942
3943 return -ENOSYS;
3944}
3945
3946static int adev_get_master_volume(struct audio_hw_device *dev,
3947 float *volume)
3948{
3949 (void)dev;
3950 (void)volume;
3951
3952 return -ENOSYS;
3953}
3954
3955static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
3956{
3957 (void)dev;
3958 (void)muted;
3959
3960 return -ENOSYS;
3961}
3962
3963static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
3964{
3965 (void)dev;
3966 (void)muted;
3967
3968 return -ENOSYS;
3969}
3970
3971static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3972{
3973 struct audio_device *adev = (struct audio_device *)dev;
3974
3975 pthread_mutex_lock(&adev->lock);
3976 if (adev->mode != mode) {
3977 ALOGI("%s mode = %d", __func__, mode);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003978 if (amplifier_set_mode(mode) != 0) {
3979 ALOGE("Failed setting amplifier mode");
3980 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003981 adev->mode = mode;
Christopher N. Hesse6c0020c2017-11-17 20:41:11 +01003982
3983 if ((mode == AUDIO_MODE_NORMAL) && adev->voice.in_call) {
3984 stop_voice_call(adev);
3985 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003986 }
3987 pthread_mutex_unlock(&adev->lock);
3988 return 0;
3989}
3990
3991static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3992{
3993 struct audio_device *adev = (struct audio_device *)dev;
3994 int err = 0;
3995
3996 pthread_mutex_lock(&adev->lock);
3997 adev->mic_mute = state;
3998
3999 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004000 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004001 }
4002
4003 pthread_mutex_unlock(&adev->lock);
4004 return err;
4005}
4006
4007static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4008{
4009 struct audio_device *adev = (struct audio_device *)dev;
4010
4011 *state = adev->mic_mute;
4012
4013 return 0;
4014}
4015
4016static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4017 const struct audio_config *config)
4018{
4019 (void)dev;
4020
4021 /* NOTE: we default to built in mic which may cause a mismatch between what we
4022 * report here and the actual buffer size
4023 */
4024 return get_input_buffer_size(config->sample_rate,
4025 config->format,
4026 audio_channel_count_from_in_mask(config->channel_mask),
4027 PCM_CAPTURE /* usecase_type */,
4028 AUDIO_DEVICE_IN_BUILTIN_MIC);
4029}
4030
4031static int adev_open_input_stream(struct audio_hw_device *dev,
4032 audio_io_handle_t handle __unused,
4033 audio_devices_t devices,
4034 struct audio_config *config,
4035 struct audio_stream_in **stream_in,
4036 audio_input_flags_t flags,
4037 const char *address __unused,
4038 audio_source_t source)
4039{
4040 struct audio_device *adev = (struct audio_device *)dev;
4041 struct stream_in *in;
4042 struct pcm_device_profile *pcm_profile;
4043
4044 ALOGV("%s: enter", __func__);
4045
4046 *stream_in = NULL;
4047 if (check_input_parameters(config->sample_rate, config->format,
4048 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4049 return -EINVAL;
4050
stenkinevgeniy44335362018-05-07 18:00:13 +00004051 usecase_type_t usecase_type = flags & AUDIO_INPUT_FLAG_FAST ?
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004052 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4053 pcm_profile = get_pcm_device(usecase_type, devices);
4054 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4055 // a low latency profile may not exist for that device, fall back
4056 // to regular capture. the MixerThread automatically changes
4057 // to non-fast capture based on the buffer size.
4058 flags &= ~AUDIO_INPUT_FLAG_FAST;
4059 usecase_type = PCM_CAPTURE;
4060 pcm_profile = get_pcm_device(usecase_type, devices);
4061 }
4062 if (pcm_profile == NULL)
4063 return -EINVAL;
4064
4065 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004066 if (in == NULL) {
4067 return -ENOMEM;
4068 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004069
4070 in->stream.common.get_sample_rate = in_get_sample_rate;
4071 in->stream.common.set_sample_rate = in_set_sample_rate;
4072 in->stream.common.get_buffer_size = in_get_buffer_size;
4073 in->stream.common.get_channels = in_get_channels;
4074 in->stream.common.get_format = in_get_format;
4075 in->stream.common.set_format = in_set_format;
4076 in->stream.common.standby = in_standby;
4077 in->stream.common.dump = in_dump;
4078 in->stream.common.set_parameters = in_set_parameters;
4079 in->stream.common.get_parameters = in_get_parameters;
4080 in->stream.common.add_audio_effect = in_add_audio_effect;
4081 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4082 in->stream.set_gain = in_set_gain;
4083 in->stream.read = in_read;
4084 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004085 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004086
4087 in->devices = devices;
4088 in->source = source;
4089 in->dev = adev;
4090 in->standby = 1;
4091 in->main_channels = config->channel_mask;
4092 in->requested_rate = config->sample_rate;
4093 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4094 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4095 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004096 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004097 /* HW codec is limited to default channels. No need to update with
4098 * requested channels */
4099 in->config = pcm_profile->config;
4100
4101 /* Update config params with the requested sample rate and channels */
stenkinevgeniy44335362018-05-07 18:00:13 +00004102 in->usecase = USECASE_AUDIO_CAPTURE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004103 in->usecase_type = usecase_type;
4104
4105 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4106 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4107
4108 in->is_fastcapture_affinity_set = false;
4109
4110 *stream_in = &in->stream;
4111 ALOGV("%s: exit", __func__);
4112 return 0;
4113}
4114
4115static void adev_close_input_stream(struct audio_hw_device *dev,
4116 struct audio_stream_in *stream)
4117{
4118 struct audio_device *adev = (struct audio_device *)dev;
4119 struct stream_in *in = (struct stream_in*)stream;
4120 ALOGV("%s", __func__);
4121
4122 /* prevent concurrent out_set_parameters, or out_write from standby */
4123 pthread_mutex_lock(&adev->lock_inputs);
4124
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004125 if (in->read_buf) {
4126 free(in->read_buf);
4127 in->read_buf = NULL;
4128 }
4129
4130 if (in->resampler) {
4131 release_resampler(in->resampler);
4132 in->resampler = NULL;
4133 }
4134
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004135#ifdef PREPROCESSING_ENABLED
4136 int i;
4137
4138 for (i=0; i<in->num_preprocessors; i++) {
4139 free(in->preprocessors[i].channel_configs);
4140 }
4141
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004142 if (in->proc_buf_in) {
4143 free(in->proc_buf_in);
4144 in->proc_buf_in = NULL;
4145 }
4146
4147 if (in->proc_buf_out) {
4148 free(in->proc_buf_out);
4149 in->proc_buf_out = NULL;
4150 }
4151
4152 if (in->ref_buf) {
4153 free(in->ref_buf);
4154 in->ref_buf = NULL;
4155 }
4156
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004157#endif
4158
4159 in_standby_l(in);
4160 free(stream);
4161
4162 pthread_mutex_unlock(&adev->lock_inputs);
4163
4164 return;
4165}
4166
4167static int adev_dump(const audio_hw_device_t *device, int fd)
4168{
4169 (void)device;
4170 (void)fd;
4171
4172 return 0;
4173}
4174
4175static int adev_close(hw_device_t *device)
4176{
4177 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004178 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004179 audio_device_ref_count--;
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004180 if (audio_device_ref_count == 0) {
4181 if (amplifier_close() != 0) {
4182 ALOGE("Amplifier close failed");
4183 }
4184 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004185 free(adev->snd_dev_ref_cnt);
4186 free_mixer_list(adev);
4187 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004188
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004189 adev = NULL;
4190
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004191 return 0;
4192}
4193
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004194/* This returns true if the input parameter looks at all plausible as a low latency period size,
4195 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4196 * just that it _might_ work.
4197 */
4198static bool period_size_is_plausible_for_low_latency(int period_size)
4199{
4200 switch (period_size) {
4201 case 64:
4202 case 96:
4203 case 128:
4204 case 192:
4205 case 256:
4206 return true;
4207 default:
4208 return false;
4209 }
4210}
4211
4212static int adev_open(const hw_module_t *module, const char *name,
4213 hw_device_t **device)
4214{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004215 ALOGV("%s: enter", __func__);
4216 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4217
Andreas Schneider56204f62017-01-31 08:17:32 +01004218 *device = NULL;
4219
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004220 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004221 if (adev == NULL) {
4222 return -ENOMEM;
4223 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004224
4225 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4226 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4227 adev->device.common.module = (struct hw_module_t *)module;
4228 adev->device.common.close = adev_close;
4229
4230 adev->device.init_check = adev_init_check;
4231 adev->device.set_voice_volume = adev_set_voice_volume;
4232 adev->device.set_master_volume = adev_set_master_volume;
4233 adev->device.get_master_volume = adev_get_master_volume;
4234 adev->device.set_master_mute = adev_set_master_mute;
4235 adev->device.get_master_mute = adev_get_master_mute;
4236 adev->device.set_mode = adev_set_mode;
4237 adev->device.set_mic_mute = adev_set_mic_mute;
4238 adev->device.get_mic_mute = adev_get_mic_mute;
4239 adev->device.set_parameters = adev_set_parameters;
4240 adev->device.get_parameters = adev_get_parameters;
4241 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4242 adev->device.open_output_stream = adev_open_output_stream;
4243 adev->device.close_output_stream = adev_close_output_stream;
4244 adev->device.open_input_stream = adev_open_input_stream;
4245 adev->device.close_input_stream = adev_close_input_stream;
4246 adev->device.dump = adev_dump;
4247
4248 /* Set the default route before the PCM stream is opened */
4249 adev->mode = AUDIO_MODE_NORMAL;
4250 adev->active_input = NULL;
4251 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004252
4253 adev->voice.volume = 1.0f;
4254 adev->voice.bluetooth_nrec = true;
4255 adev->voice.in_call = false;
Christopher N. Hessee4a1c592018-01-16 18:33:38 +01004256 adev->voice.bluetooth_wb = false;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004257
stenkinevgeniy53929f72018-07-09 11:20:36 +00004258 adev->bt_sco_active = false;
4259
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004260 /* adev->cur_hdmi_channels = 0; by calloc() */
4261 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004262 if (adev->snd_dev_ref_cnt == NULL) {
4263 free(adev);
4264 return -ENOMEM;
4265 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004266
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004267 adev->ns_in_voice_rec = false;
4268
4269 list_init(&adev->usecase_list);
4270
4271 if (mixer_init(adev) != 0) {
4272 free(adev->snd_dev_ref_cnt);
4273 free(adev);
4274 ALOGE("%s: Failed to init, aborting.", __func__);
4275 *device = NULL;
4276 return -EINVAL;
4277 }
4278
4279 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4280 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4281 if (adev->offload_fx_lib == NULL) {
4282 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4283 } else {
4284 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4285 adev->offload_fx_start_output =
4286 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4287 "visualizer_hal_start_output");
4288 adev->offload_fx_stop_output =
4289 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4290 "visualizer_hal_stop_output");
4291 }
4292 }
4293
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004294 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004295 if (adev->voice.session == NULL) {
4296 ALOGE("%s: Failed to initialize voice session data", __func__);
4297
4298 free(adev->snd_dev_ref_cnt);
4299 free(adev);
4300
4301 *device = NULL;
4302 return -EINVAL;
4303 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004304
Christopher N. Hessec487bbe2018-07-12 13:51:43 +02004305 if (amplifier_open() != -ENOENT) {
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004306 ALOGE("Amplifier initialization failed");
4307 }
4308
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004309 *device = &adev->device.common;
4310
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004311 audio_device_ref_count++;
4312
4313 char value[PROPERTY_VALUE_MAX];
4314 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4315 int trial = atoi(value);
4316 if (period_size_is_plausible_for_low_latency(trial)) {
4317
4318 pcm_device_playback.config.period_size = trial;
4319 pcm_device_playback.config.start_threshold =
4320 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4321 pcm_device_playback.config.stop_threshold =
4322 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4323
4324 pcm_device_capture_low_latency.config.period_size = trial;
4325 }
4326 }
4327
4328 ALOGV("%s: exit", __func__);
4329 return 0;
4330}
4331
4332static struct hw_module_methods_t hal_module_methods = {
4333 .open = adev_open,
4334};
4335
4336struct audio_module HAL_MODULE_INFO_SYM = {
4337 .common = {
4338 .tag = HARDWARE_MODULE_TAG,
4339 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4340 .hal_api_version = HARDWARE_HAL_API_VERSION,
4341 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004342 .name = "Samsung Audio HAL",
4343 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004344 .methods = &hal_module_methods,
4345 },
4346};