blob: 076a469226c5359cfc9ebc73f74e909b0b28bb75 [file] [log] [blame]
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Christopher N. Hesse2f6f8582017-01-28 12:46:15 +01003 * Copyright (C) 2017 Christopher N. Hesse <raymanfx@gmail.com>
Andreas Schneider759368f2017-02-02 16:11:14 +01004 * Copyright (C) 2017 Andreas Schneider <asn@cryptomilk.org>
Christopher N. Hesse297a6362017-01-28 12:40:45 +01005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#define LOG_TAG "audio_hw_primary"
20/*#define LOG_NDEBUG 0*/
21/*#define VERY_VERY_VERBOSE_LOGGING*/
22#ifdef VERY_VERY_VERBOSE_LOGGING
23#define ALOGVV ALOGV
24#else
25#define ALOGVV(a...) do { } while(0)
26#endif
27
28#define _GNU_SOURCE
29#include <errno.h>
30#include <pthread.h>
31#include <stdint.h>
32#include <sys/time.h>
33#include <stdlib.h>
34#include <math.h>
35#include <dlfcn.h>
Christopher N. Hesse297a6362017-01-28 12:40:45 +010036
37#include <cutils/log.h>
38#include <cutils/str_parms.h>
39#include <cutils/atomic.h>
40#include <cutils/sched_policy.h>
41#include <cutils/properties.h>
42
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010043#include <samsung_audio.h>
44
Christopher N. Hesse297a6362017-01-28 12:40:45 +010045#include <hardware/audio_effect.h>
46#include <system/thread_defs.h>
47#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
49#include "audio_hw.h"
Christopher N. Hesse757ac412017-01-28 14:42:48 +010050#include "compress_offload.h"
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +010051#include "voice.h"
Christopher N. Hesse297a6362017-01-28 12:40:45 +010052
53#include "sound/compress_params.h"
54
Christopher N. Hesse297a6362017-01-28 12:40:45 +010055
56/* TODO: the following PCM device profiles could be read from a config file */
57static struct pcm_device_profile pcm_device_playback = {
58 .config = {
59 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
60 .rate = PLAYBACK_DEFAULT_SAMPLING_RATE,
61 .period_size = PLAYBACK_PERIOD_SIZE,
62 .period_count = PLAYBACK_PERIOD_COUNT,
63 .format = PCM_FORMAT_S16_LE,
64 .start_threshold = PLAYBACK_START_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
65 .stop_threshold = PLAYBACK_STOP_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
66 .silence_threshold = 0,
67 .silence_size = UINT_MAX,
68 .avail_min = PLAYBACK_AVAILABLE_MIN,
69 },
70 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010071 .id = SOUND_PLAYBACK_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010072 .type = PCM_PLAYBACK,
73 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
Fevax86ac2342017-02-08 09:52:12 +010074 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010075};
76
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010077static struct pcm_device_profile pcm_device_deep_buffer = {
78 .config = {
79 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
80 .rate = DEEP_BUFFER_OUTPUT_SAMPLING_RATE,
81 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
82 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
83 .format = PCM_FORMAT_S16_LE,
84 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
85 .stop_threshold = INT_MAX,
86 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
87 },
88 .card = SOUND_CARD,
89 .id = SOUND_DEEP_BUFFER_DEVICE,
90 .type = PCM_PLAYBACK,
91 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
Fevax86ac2342017-02-08 09:52:12 +010092 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010093};
94
Christopher N. Hesse297a6362017-01-28 12:40:45 +010095static struct pcm_device_profile pcm_device_capture = {
96 .config = {
97 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
98 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
99 .period_size = CAPTURE_PERIOD_SIZE,
100 .period_count = CAPTURE_PERIOD_COUNT,
101 .format = PCM_FORMAT_S16_LE,
102 .start_threshold = CAPTURE_START_THRESHOLD,
103 .stop_threshold = 0,
104 .silence_threshold = 0,
105 .avail_min = 0,
106 },
107 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100108 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100109 .type = PCM_CAPTURE,
110 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
111};
112
113static struct pcm_device_profile pcm_device_capture_low_latency = {
114 .config = {
115 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
116 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
117 .period_size = CAPTURE_PERIOD_SIZE_LOW_LATENCY,
118 .period_count = CAPTURE_PERIOD_COUNT_LOW_LATENCY,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = CAPTURE_START_THRESHOLD,
121 .stop_threshold = 0,
122 .silence_threshold = 0,
123 .avail_min = 0,
124 },
125 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100126 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100127 .type = PCM_CAPTURE_LOW_LATENCY,
128 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
129};
130
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100131#ifdef SOUND_CAPTURE_LOOPBACK_AEC_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100132static struct pcm_device_profile pcm_device_capture_loopback_aec = {
133 .config = {
134 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
135 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
136 .period_size = CAPTURE_PERIOD_SIZE,
137 .period_count = CAPTURE_PERIOD_COUNT,
138 .format = PCM_FORMAT_S16_LE,
139 .start_threshold = CAPTURE_START_THRESHOLD,
140 .stop_threshold = 0,
141 .silence_threshold = 0,
142 .avail_min = 0,
143 },
144 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100145 .id = SOUND_CAPTURE_LOOPBACK_AEC_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100146 .type = PCM_CAPTURE,
147 .devices = SND_DEVICE_IN_LOOPBACK_AEC,
148};
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100149#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100150
151static struct pcm_device_profile pcm_device_playback_sco = {
152 .config = {
153 .channels = SCO_DEFAULT_CHANNEL_COUNT,
154 .rate = SCO_DEFAULT_SAMPLING_RATE,
155 .period_size = SCO_PERIOD_SIZE,
156 .period_count = SCO_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158 .start_threshold = SCO_START_THRESHOLD,
159 .stop_threshold = SCO_STOP_THRESHOLD,
160 .silence_threshold = 0,
161 .avail_min = SCO_AVAILABLE_MIN,
162 },
163 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100164 .id = SOUND_PLAYBACK_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100165 .type = PCM_PLAYBACK,
166 .devices =
167 AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
168 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
169};
170
171static struct pcm_device_profile pcm_device_capture_sco = {
172 .config = {
173 .channels = SCO_DEFAULT_CHANNEL_COUNT,
174 .rate = SCO_DEFAULT_SAMPLING_RATE,
175 .period_size = SCO_PERIOD_SIZE,
176 .period_count = SCO_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = CAPTURE_START_THRESHOLD,
179 .stop_threshold = 0,
180 .silence_threshold = 0,
181 .avail_min = 0,
182 },
183 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100184 .id = SOUND_CAPTURE_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100185 .type = PCM_CAPTURE,
186 .devices = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
187};
188
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100189#ifdef SOUND_CAPTURE_HOTWORD_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100190static struct pcm_device_profile pcm_device_hotword_streaming = {
191 .config = {
192 .channels = 1,
193 .rate = 16000,
194 .period_size = CAPTURE_PERIOD_SIZE,
195 .period_count = CAPTURE_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = CAPTURE_START_THRESHOLD,
198 .stop_threshold = 0,
199 .silence_threshold = 0,
200 .avail_min = 0,
201 },
202 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100203 .id = SOUND_CAPTURE_HOTWORD_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100204 .type = PCM_HOTWORD_STREAMING,
205 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC
206};
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100207#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100208
209static struct pcm_device_profile * const pcm_devices[] = {
210 &pcm_device_playback,
211 &pcm_device_capture,
212 &pcm_device_capture_low_latency,
213 &pcm_device_playback_sco,
214 &pcm_device_capture_sco,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100215#ifdef SOUND_CAPTURE_LOOPBACK_AEC_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100216 &pcm_device_capture_loopback_aec,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100217#endif
218#ifdef SOUND_CAPTURE_HOTWORD_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100219 &pcm_device_hotword_streaming,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100220#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100221 NULL,
222};
223
224static const char * const use_case_table[AUDIO_USECASE_MAX] = {
225 [USECASE_AUDIO_PLAYBACK] = "playback",
226 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "playback multi-channel",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Andreas Schneiderdf6fc8a2017-02-14 11:38:41 +0100228 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "playback deep-buffer",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100229 [USECASE_AUDIO_CAPTURE] = "capture",
230 [USECASE_AUDIO_CAPTURE_HOTWORD] = "capture-hotword",
231 [USECASE_VOICE_CALL] = "voice-call",
232};
233
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100234#define STRING_TO_ENUM(string) { #string, string }
235
236static unsigned int audio_device_ref_count;
237
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100238struct string_to_enum {
239 const char *name;
240 uint32_t value;
241};
242
243static const struct string_to_enum out_channels_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
245 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
246 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
247};
248
Andreas Schneider759368f2017-02-02 16:11:14 +0100249struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
250 struct timespec ret;
251 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100252
253 if (time0.tv_nsec > time1.tv_nsec) {
254 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
255 time0.tv_nsec -= (long int) (1E9 * xsec);
256 time0.tv_sec += xsec;
257 }
258
259 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
260 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
261 time0.tv_nsec += (long int) (1E9 * xsec);
262 time0.tv_sec -= xsec;
263 }
264
Paul Keithf114e2e2017-02-14 20:41:33 -0600265 ret.tv_sec = labs(time1.tv_sec - time0.tv_sec);
266 ret.tv_nsec = labs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100267
268 return ret;
269}
270
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100271static bool is_supported_format(audio_format_t format)
272{
273 if (format == AUDIO_FORMAT_MP3 ||
274 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
275 return true;
276
277 return false;
278}
279
280static int get_snd_codec_id(audio_format_t format)
281{
282 int id = 0;
283
284 switch (format & AUDIO_FORMAT_MAIN_MASK) {
285 case AUDIO_FORMAT_MP3:
286 id = SND_AUDIOCODEC_MP3;
287 break;
288 case AUDIO_FORMAT_AAC:
289 id = SND_AUDIOCODEC_AAC;
290 break;
291 default:
292 ALOGE("%s: Unsupported audio format", __func__);
293 }
294
295 return id;
296}
297
298/* Array to store sound devices */
299static const char * const device_table[SND_DEVICE_MAX] = {
300 [SND_DEVICE_NONE] = "none",
301 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100302 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100303 [SND_DEVICE_OUT_SPEAKER] = "speaker",
304 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
305 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100306 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100307 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100308 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100309 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100310 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100311 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100312 [SND_DEVICE_OUT_HDMI] = "hdmi",
313 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
314 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100315
316 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100317 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100318 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
319 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100320 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100321 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
322 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100323 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
324 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100325 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100326 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100327 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100328 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100329 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100330 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
331 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
332 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100333 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
334 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100335 [SND_DEVICE_IN_LOOPBACK_AEC] = "loopback-aec",
336};
337
338static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
339{
340 struct mixer_card *mixer_card;
341 struct listnode *node;
342
343 list_for_each(node, &adev->mixer_list) {
344 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
345 if (mixer_card->card == card)
346 return mixer_card;
347 }
348 return NULL;
349}
350
351static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
352{
353 struct mixer_card *mixer_card;
354 struct listnode *node;
355
356 list_for_each(node, &usecase->mixer_list) {
357 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
358 if (mixer_card->card == card)
359 return mixer_card;
360 }
361 return NULL;
362}
363
364static void free_mixer_list(struct audio_device *adev)
365{
366 struct mixer_card *mixer_card;
367 struct listnode *node;
368 struct listnode *next;
369
370 list_for_each_safe(node, next, &adev->mixer_list) {
371 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
372 list_remove(node);
373 audio_route_free(mixer_card->audio_route);
374 free(mixer_card);
375 }
376}
377
378static int mixer_init(struct audio_device *adev)
379{
380 int i;
381 int card;
382 int retry_num;
383 struct mixer *mixer;
384 struct audio_route *audio_route;
385 char mixer_path[PATH_MAX];
386 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100387 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100388
389 list_init(&adev->mixer_list);
390
391 for (i = 0; pcm_devices[i] != NULL; i++) {
392 card = pcm_devices[i]->card;
393 if (adev_get_mixer_for_card(adev, card) == NULL) {
394 retry_num = 0;
395 do {
396 mixer = mixer_open(card);
397 if (mixer == NULL) {
398 if (++retry_num > RETRY_NUMBER) {
399 ALOGE("%s unable to open the mixer for--card %d, aborting.",
400 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100401 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100402 goto error;
403 }
404 usleep(RETRY_US);
405 }
406 } while (mixer == NULL);
407
408 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
409 audio_route = audio_route_init(card, mixer_path);
410 if (!audio_route) {
411 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
412 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100413 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100414 goto error;
415 }
416 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100417 if (mixer_card == NULL) {
418 ret = -ENOMEM;
419 goto error;
420 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100421 mixer_card->card = card;
422 mixer_card->mixer = mixer;
423 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100424
425 /* Do not sleep on first enable_snd_device() */
426 mixer_card->dsp_poweroff_time.tv_sec = 1;
427 mixer_card->dsp_poweroff_time.tv_nsec = 0;
428
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100429 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
430 }
431 }
432
433 return 0;
434
435error:
436 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100437 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100438}
439
440static const char *get_snd_device_name(snd_device_t snd_device)
441{
442 const char *name = NULL;
443
Andreas Schneideradb788d2017-02-13 15:19:36 +0100444 if (snd_device == SND_DEVICE_NONE ||
Andreas Schneiderdde54c02017-02-15 14:10:58 +0100445 (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100446 name = device_table[snd_device];
447
448 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
449
450 return name;
451}
452
453static const char *get_snd_device_display_name(snd_device_t snd_device)
454{
455 const char *name = get_snd_device_name(snd_device);
456
457 if (name == NULL)
458 name = "SND DEVICE NOT FOUND";
459
460 return name;
461}
462
463static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
464{
465 int i;
466
467 devices &= ~AUDIO_DEVICE_BIT_IN;
468 for (i = 0; pcm_devices[i] != NULL; i++) {
469 if ((pcm_devices[i]->type == uc_type) &&
470 (devices & pcm_devices[i]->devices))
471 break;
472 }
473 return pcm_devices[i];
474}
475
476static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
477 audio_usecase_t uc_id)
478{
479 struct audio_usecase *usecase;
480 struct listnode *node;
481
482 list_for_each(node, &adev->usecase_list) {
483 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
484 if (usecase->id == uc_id)
485 return usecase;
486 }
487 return NULL;
488}
489
490static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
491 usecase_type_t type)
492{
493 struct audio_usecase *usecase;
494 struct listnode *node;
495
496 list_for_each(node, &adev->usecase_list) {
497 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
498 if (usecase->type & type)
499 return usecase;
500 }
501 return NULL;
502}
503
504/* always called with adev lock held */
505static int set_voice_volume_l(struct audio_device *adev, float volume)
506{
507 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100508
509 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100510 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100511 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100512
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100513 return err;
514}
515
516
517static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
518{
519
520 audio_mode_t mode = adev->mode;
521 snd_device_t snd_device = SND_DEVICE_NONE;
522
523 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
524 if (devices == AUDIO_DEVICE_NONE ||
525 devices & AUDIO_DEVICE_BIT_IN) {
526 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
527 goto exit;
528 }
529
530 if (mode == AUDIO_MODE_IN_CALL) {
531 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
532 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100533 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100534 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
535 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
536 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100537 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100538 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100539
540 if (voice_session_uses_wideband(adev->voice.session)) {
541 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
542 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
543 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
544 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
545 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
546 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
547 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
548 }
549 }
550
551 if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
552 snd_device = SND_DEVICE_OUT_BT_SCO;
553 }
554
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100555 if (snd_device != SND_DEVICE_NONE) {
556 goto exit;
557 }
558 }
559
560 if (popcount(devices) == 2) {
561 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
562 AUDIO_DEVICE_OUT_SPEAKER)) {
563 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
564 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
565 AUDIO_DEVICE_OUT_SPEAKER)) {
566 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
567 } else {
568 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
569 goto exit;
570 }
571 if (snd_device != SND_DEVICE_NONE) {
572 goto exit;
573 }
574 }
575
576 if (popcount(devices) != 1) {
577 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
578 goto exit;
579 }
580
581 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
582 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
583 snd_device = SND_DEVICE_OUT_HEADPHONES;
584 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
585 snd_device = SND_DEVICE_OUT_SPEAKER;
586 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
587 snd_device = SND_DEVICE_OUT_BT_SCO;
588 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100589 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100590 } else {
591 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
592 }
593exit:
594 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
595 return snd_device;
596}
597
598static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
599{
600 audio_source_t source;
601 audio_mode_t mode = adev->mode;
602 audio_devices_t in_device;
603 audio_channel_mask_t channel_mask;
604 snd_device_t snd_device = SND_DEVICE_NONE;
605 struct stream_in *active_input = NULL;
606 struct audio_usecase *usecase;
607
608 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
609 if (usecase != NULL) {
610 active_input = (struct stream_in *)usecase->stream;
611 }
612 source = (active_input == NULL) ?
613 AUDIO_SOURCE_DEFAULT : active_input->source;
614
Andreas Schneider757e2d82017-02-10 19:28:35 +0100615 in_device = (active_input == NULL) ?
616 AUDIO_DEVICE_NONE :
617 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100618 channel_mask = (active_input == NULL) ?
619 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
620
621 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
622 __func__, out_device, in_device);
623 if (mode == AUDIO_MODE_IN_CALL) {
624 if (out_device == AUDIO_DEVICE_NONE) {
625 ALOGE("%s: No output device set for voice call", __func__);
626 goto exit;
627 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100628
Andreas Schneider82f32482017-02-06 09:00:48 +0100629 snd_device = SND_DEVICE_IN_VOICE_MIC;
630 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100631 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100632 }
633
634 if (voice_session_uses_twomic(adev->voice.session)) {
635 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
636 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
637 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
638 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
639 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
640 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100641 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100642
643 if (voice_session_uses_wideband(adev->voice.session)) {
644 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
645 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
646 }
647
648 if (voice_session_uses_twomic(adev->voice.session)) {
649 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
650 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
651 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
652 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
653 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
654 }
655 }
656 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100657
658 /* BT SCO */
659 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
660 snd_device = SND_DEVICE_IN_VOICE_MIC;
661
662 if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
663 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
664 } else if (voice_session_uses_twomic(adev->voice.session)) {
665 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
666 }
667 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100668 } else if (source == AUDIO_SOURCE_CAMCORDER) {
669 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
670 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
671 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
672 }
673 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
674 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100675 if (snd_device == SND_DEVICE_NONE) {
676 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
677 }
678 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
679 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
680 }
681 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
682 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
683 in_device = AUDIO_DEVICE_IN_BACK_MIC;
684 if (active_input) {
685 if (active_input->enable_aec) {
686 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
687 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
688 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
689 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
690 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
691 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100692 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100693 }
694 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
695 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
696 }
697 }
698 /* TODO: set echo reference */
699 }
700 } else if (source == AUDIO_SOURCE_DEFAULT) {
701 goto exit;
702 }
703
704
705 if (snd_device != SND_DEVICE_NONE) {
706 goto exit;
707 }
708
709 if (in_device != AUDIO_DEVICE_NONE &&
710 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
711 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
712 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100713 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100714 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
715 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
716 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
717 snd_device = SND_DEVICE_IN_HEADSET_MIC;
718 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
719 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
720 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
721 snd_device = SND_DEVICE_IN_HDMI_MIC;
722 } else {
723 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100724 ALOGW("%s: Using default earpiece-mic", __func__);
725 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100726 }
727 } else {
728 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100729 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100730 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
731 snd_device = SND_DEVICE_IN_HEADSET_MIC;
732 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
733 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
734 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100735 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100736 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
737 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
738 } else {
739 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100740 ALOGW("%s: Using default earpiece-mic", __func__);
741 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100742 }
743 }
744exit:
745 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
746 return snd_device;
747}
748
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100749#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100750static int set_hdmi_channels(struct audio_device *adev, int channel_count)
751{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100752 (void)adev;
753 (void)channel_count;
754 /* TODO */
755
756 return 0;
757}
758
759static int edid_get_max_channels(struct audio_device *adev)
760{
761 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100762 (void)adev;
763
764 /* TODO */
765 return max_channels;
766}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100767#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100768
769/* Delay in Us */
770static int64_t render_latency(audio_usecase_t usecase)
771{
772 (void)usecase;
773 /* TODO */
774 return 0;
775}
776
777static int enable_snd_device(struct audio_device *adev,
778 struct audio_usecase *uc_info,
779 snd_device_t snd_device,
780 bool update_mixer)
781{
782 struct mixer_card *mixer_card;
783 struct listnode *node;
784 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100785#ifdef DSP_POWEROFF_DELAY
786 struct timespec activation_time;
787 struct timespec elapsed_time;
788#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100789
790 if (snd_device_name == NULL)
791 return -EINVAL;
792
793 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
794 ALOGV("Request to enable combo device: enable individual devices\n");
795 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
796 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
797 return 0;
798 }
799 adev->snd_dev_ref_cnt[snd_device]++;
800 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
801 ALOGV("%s: snd_device(%d: %s) is already active",
802 __func__, snd_device, snd_device_name);
803 return 0;
804 }
805
806 ALOGV("%s: snd_device(%d: %s)", __func__,
807 snd_device, snd_device_name);
808
809 list_for_each(node, &uc_info->mixer_list) {
810 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100811
812#ifdef DSP_POWEROFF_DELAY
813 clock_gettime(CLOCK_MONOTONIC, &activation_time);
814
Andreas Schneider58735a92017-02-13 16:48:17 +0100815 elapsed_time = time_spec_diff(activation_time,
816 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100817 if (elapsed_time.tv_sec == 0) {
818 long elapsed_usec = elapsed_time.tv_nsec / 1000;
819
820 if (elapsed_usec < DSP_POWEROFF_DELAY) {
821 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
822 }
823 }
824 update_mixer = true;
825#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100826 audio_route_apply_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100827 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100828 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100829 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100830 }
831
832 return 0;
833}
834
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100835int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100836 struct audio_usecase *uc_info,
837 snd_device_t snd_device,
838 bool update_mixer)
839{
840 struct mixer_card *mixer_card;
841 struct listnode *node;
842 const char *snd_device_name = get_snd_device_name(snd_device);
843
844 if (snd_device_name == NULL)
845 return -EINVAL;
846
847 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
848 ALOGV("Request to disable combo device: disable individual devices\n");
849 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
850 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
851 return 0;
852 }
853
854 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
855 ALOGE("%s: device ref cnt is already 0", __func__);
856 return -EINVAL;
857 }
858 adev->snd_dev_ref_cnt[snd_device]--;
859 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
860 ALOGV("%s: snd_device(%d: %s)", __func__,
861 snd_device, snd_device_name);
862 list_for_each(node, &uc_info->mixer_list) {
863 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100864#ifdef DSP_POWEROFF_DELAY
865 update_mixer = true;
866#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100867 audio_route_reset_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100868 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100869 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100870 }
871#ifdef DSP_POWEROFF_DELAY
872 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
873#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100874 }
875 }
876 return 0;
877}
878
879static int select_devices(struct audio_device *adev,
880 audio_usecase_t uc_id)
881{
882 snd_device_t out_snd_device = SND_DEVICE_NONE;
883 snd_device_t in_snd_device = SND_DEVICE_NONE;
884 struct audio_usecase *usecase = NULL;
885 struct audio_usecase *vc_usecase = NULL;
886 struct listnode *node;
887 struct stream_in *active_input = NULL;
888 struct stream_out *active_out;
889 struct mixer_card *mixer_card;
890
891 ALOGV("%s: usecase(%d)", __func__, uc_id);
892
893 if (uc_id == USECASE_AUDIO_CAPTURE_HOTWORD)
894 return 0;
895
896 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
897 if (usecase != NULL) {
898 active_input = (struct stream_in *)usecase->stream;
899 }
900
901 usecase = get_usecase_from_id(adev, uc_id);
902 if (usecase == NULL) {
903 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
904 return -EINVAL;
905 }
906 active_out = (struct stream_out *)usecase->stream;
907
Christopher N. Hesse130da9f2017-02-15 12:18:41 +0100908
909 /*
910 * If the voice call is active, use the sound devices of voice call usecase
911 * so that it would not result any device switch. All the usecases will
912 * be switched to new device when select_devices() is called for voice call
913 * usecase.
914 */
915 if (usecase->type != VOICE_CALL && adev->voice.in_call) {
916 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
917 if (vc_usecase == NULL) {
918 ALOGE("%s: Could not find the voice call usecase", __func__);
919 } else {
920 in_snd_device = vc_usecase->in_snd_device;
921 out_snd_device = vc_usecase->out_snd_device;
922 }
923 }
924
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100925 if (usecase->type == VOICE_CALL) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100926 usecase->devices = active_out->devices;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +0100927 prepare_voice_session(adev->voice.session, active_out->devices);
928 out_snd_device = get_output_snd_device(adev, active_out->devices);
929 in_snd_device = get_input_snd_device(adev, active_out->devices);
930 } else if (usecase->type == PCM_PLAYBACK) {
931 usecase->devices = active_out->devices;
932 in_snd_device = SND_DEVICE_NONE;
933 if (out_snd_device == SND_DEVICE_NONE) {
934 out_snd_device = get_output_snd_device(adev, active_out->devices);
935 if (active_out == adev->primary_output &&
936 active_input &&
937 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
938 select_devices(adev, active_input->usecase);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100939 }
940 }
Christopher N. Hesse130da9f2017-02-15 12:18:41 +0100941 } else if (usecase->type == PCM_CAPTURE) {
942 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
943 out_snd_device = SND_DEVICE_NONE;
944 if (in_snd_device == SND_DEVICE_NONE) {
945 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
946 adev->primary_output && !adev->primary_output->standby) {
947 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
948 } else {
949 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100950 }
951 }
952 }
953
954 if (out_snd_device == usecase->out_snd_device &&
955 in_snd_device == usecase->in_snd_device) {
956 return 0;
957 }
958
959 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
960 out_snd_device, get_snd_device_display_name(out_snd_device),
961 in_snd_device, get_snd_device_display_name(in_snd_device));
962
963
964 /* Disable current sound devices */
965 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100966 disable_snd_device(adev, usecase, usecase->out_snd_device, false);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100967 }
968
969 if (usecase->in_snd_device != SND_DEVICE_NONE) {
970 disable_snd_device(adev, usecase, usecase->in_snd_device, false);
971 }
972
973 /* Enable new sound devices */
974 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100975 /* We need to update the audio path if we switch the out devices */
976 if (adev->voice.in_call) {
977 set_voice_session_audio_path(adev->voice.session);
978 }
979
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100980 enable_snd_device(adev, usecase, out_snd_device, false);
981 }
982
983 if (in_snd_device != SND_DEVICE_NONE) {
984 enable_snd_device(adev, usecase, in_snd_device, false);
985 }
986
987 list_for_each(node, &usecase->mixer_list) {
988 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
989 audio_route_update_mixer(mixer_card->audio_route);
990 }
991
992 usecase->in_snd_device = in_snd_device;
993 usecase->out_snd_device = out_snd_device;
994
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100995 return 0;
996}
997
998
999static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
1000static int do_in_standby_l(struct stream_in *in);
1001
1002#ifdef PREPROCESSING_ENABLED
1003static void get_capture_reference_delay(struct stream_in *in,
1004 size_t frames __unused,
1005 struct echo_reference_buffer *buffer)
1006{
1007 ALOGVV("%s: enter:)", __func__);
1008
1009 /* read frames available in kernel driver buffer */
1010 unsigned int kernel_frames;
1011 struct timespec tstamp;
1012 long buf_delay;
1013 long kernel_delay;
1014 long delay_ns;
1015 struct pcm_device *ref_device;
1016 long rsmp_delay = 0;
1017
1018 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1019 struct pcm_device, stream_list_node);
1020
1021 if (pcm_get_htimestamp(ref_device->pcm, &kernel_frames, &tstamp) < 0) {
1022 buffer->time_stamp.tv_sec = 0;
1023 buffer->time_stamp.tv_nsec = 0;
1024 buffer->delay_ns = 0;
1025 ALOGW("read get_capture_reference_delay(): pcm_htimestamp error");
1026 return;
1027 }
1028
1029 /* adjust render time stamp with delay added by current driver buffer.
1030 * Add the duration of current frame as we want the render time of the last
1031 * sample being written. */
1032
1033 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / ref_device->pcm_profile->config.rate);
1034
1035 buffer->time_stamp = tstamp;
1036 buffer->delay_ns = kernel_delay;
1037
1038 ALOGVV("get_capture_reference_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5d],"
1039 " delay_ns: [%d] , frames:[%zd]",
1040 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns, frames);
1041}
1042
1043static void get_capture_delay(struct stream_in *in,
1044 size_t frames __unused,
1045 struct echo_reference_buffer *buffer)
1046{
1047 ALOGVV("%s: enter:)", __func__);
1048 /* read frames available in kernel driver buffer */
1049 unsigned int kernel_frames;
1050 struct timespec tstamp;
1051 long buf_delay;
1052 long rsmp_delay;
1053 long kernel_delay;
1054 long delay_ns;
1055 struct pcm_device *pcm_device;
1056
1057 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1058 struct pcm_device, stream_list_node);
1059
1060 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1061 buffer->time_stamp.tv_sec = 0;
1062 buffer->time_stamp.tv_nsec = 0;
1063 buffer->delay_ns = 0;
1064 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1065 return;
1066 }
1067
1068 /* read frames available in audio HAL input buffer
1069 * add number of frames being read as we want the capture time of first sample
1070 * in current buffer */
1071 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1072 * at requested sampling rate */
1073 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1074 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1075
1076 /* add delay introduced by resampler */
1077 rsmp_delay = 0;
1078 if (in->resampler) {
1079 rsmp_delay = in->resampler->delay_ns(in->resampler);
1080 }
1081
1082 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1083
1084 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1085
1086 buffer->time_stamp = tstamp;
1087 buffer->delay_ns = delay_ns;
1088 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1089 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1090 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1091 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1092 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1093 in->read_buf_frames, in->proc_buf_frames, frames);
1094}
1095
1096static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1097{
1098 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1099 struct echo_reference_buffer b;
1100 b.delay_ns = 0;
1101 struct pcm_device *pcm_device;
1102
1103 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1104 struct pcm_device, stream_list_node);
1105
1106 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1107 "b.frame_count = [%zd]",
1108 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1109 if (in->ref_buf_frames < frames) {
1110 if (in->ref_buf_size < frames) {
1111 in->ref_buf_size = frames;
1112 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1113 ALOG_ASSERT((in->ref_buf != NULL),
1114 "update_echo_reference() failed to reallocate ref_buf");
1115 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1116 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1117 }
1118 b.frame_count = frames - in->ref_buf_frames;
1119 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1120
1121 get_capture_delay(in, frames, &b);
1122
1123 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1124 {
1125 in->ref_buf_frames += b.frame_count;
1126 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1127 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1128 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1129 }
1130 } else
1131 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1132 return b.delay_ns;
1133}
1134
1135static int set_preprocessor_param(effect_handle_t handle,
1136 effect_param_t *param)
1137{
1138 uint32_t size = sizeof(int);
1139 uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1140 param->vsize;
1141
1142 int status = (*handle)->command(handle,
1143 EFFECT_CMD_SET_PARAM,
1144 sizeof (effect_param_t) + psize,
1145 param,
1146 &size,
1147 &param->status);
1148 if (status == 0)
1149 status = param->status;
1150
1151 return status;
1152}
1153
1154static int set_preprocessor_echo_delay(effect_handle_t handle,
1155 int32_t delay_us)
1156{
1157 struct {
1158 effect_param_t param;
1159 uint32_t data_0;
1160 int32_t data_1;
1161 } buf;
1162 memset(&buf, 0, sizeof(buf));
1163
1164 buf.param.psize = sizeof(uint32_t);
1165 buf.param.vsize = sizeof(uint32_t);
1166 buf.data_0 = AEC_PARAM_ECHO_DELAY;
1167 buf.data_1 = delay_us;
1168
1169 return set_preprocessor_param(handle, &buf.param);
1170}
1171
1172static void push_echo_reference(struct stream_in *in, size_t frames)
1173{
1174 ALOGVV("%s: enter:)", __func__);
1175 /* read frames from echo reference buffer and update echo delay
1176 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1177
1178 int32_t delay_us = update_echo_reference(in, frames)/1000;
1179 int32_t size_in_bytes = 0;
1180 int i;
1181 audio_buffer_t buf;
1182
1183 if (in->ref_buf_frames < frames)
1184 frames = in->ref_buf_frames;
1185
1186 buf.frameCount = frames;
1187 buf.raw = in->ref_buf;
1188
1189 for (i = 0; i < in->num_preprocessors; i++) {
1190 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1191 continue;
1192 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1193 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1194 &buf,
1195 NULL);
1196 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1197 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1198 }
1199
1200 in->ref_buf_frames -= buf.frameCount;
1201 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1202 __func__, in->ref_buf_frames, in->config.channels);
1203 if (in->ref_buf_frames) {
1204 memcpy(in->ref_buf,
1205 in->ref_buf + buf.frameCount * in->config.channels,
1206 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1207 }
1208}
1209
1210static void put_echo_reference(struct audio_device *adev,
1211 struct echo_reference_itfe *reference)
1212{
1213 ALOGV("%s: enter:)", __func__);
1214 int32_t prev_generation = adev->echo_reference_generation;
1215 struct stream_out *out = adev->primary_output;
1216
1217 if (adev->echo_reference != NULL &&
1218 reference == adev->echo_reference) {
1219 /* echo reference is taken from the low latency output stream used
1220 * for voice use cases */
1221 adev->echo_reference = NULL;
1222 android_atomic_inc(&adev->echo_reference_generation);
1223 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1224 // if the primary output is in standby or did not pick the echo reference yet
1225 // we can safely get rid of it here.
1226 // otherwise, out_write() or out_standby() will detect the change in echo reference
1227 // generation and release the echo reference owned by the stream.
1228 if ((out->echo_reference_generation != prev_generation) || out->standby)
1229 release_echo_reference(reference);
1230 } else {
1231 release_echo_reference(reference);
1232 }
1233 ALOGV("release_echo_reference");
1234 }
1235}
1236
1237static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1238 audio_format_t format __unused,
1239 uint32_t channel_count,
1240 uint32_t sampling_rate)
1241{
1242 ALOGV("%s: enter:)", __func__);
1243 put_echo_reference(adev, adev->echo_reference);
1244 /* echo reference is taken from the low latency output stream used
1245 * for voice use cases */
1246 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1247 !adev->primary_output->standby) {
1248 struct audio_stream *stream =
1249 &adev->primary_output->stream.common;
1250 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1251 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1252 ALOGV("Calling create_echo_reference");
1253 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1254 channel_count,
1255 sampling_rate,
1256 AUDIO_FORMAT_PCM_16_BIT,
1257 wr_channel_count,
1258 wr_sampling_rate,
1259 &adev->echo_reference);
1260 if (status == 0)
1261 android_atomic_inc(&adev->echo_reference_generation);
1262 }
1263 return adev->echo_reference;
1264}
1265
1266#ifdef HW_AEC_LOOPBACK
1267static int get_hw_echo_reference(struct stream_in *in)
1268{
1269 struct pcm_device_profile *ref_pcm_profile;
1270 struct pcm_device *ref_device;
1271 struct audio_device *adev = in->dev;
1272
1273 in->hw_echo_reference = false;
1274
1275 if (adev->primary_output!= NULL &&
1276 !adev->primary_output->standby &&
1277 adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1278 adev->primary_output->devices == AUDIO_DEVICE_OUT_SPEAKER) {
1279 struct audio_stream *stream = &adev->primary_output->stream.common;
1280
1281 // TODO: currently there is no low latency mode for aec reference.
1282 ref_pcm_profile = get_pcm_device(PCM_CAPTURE, pcm_device_capture_loopback_aec.devices);
1283 if (ref_pcm_profile == NULL) {
1284 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1285 __func__, pcm_device_capture_loopback_aec.devices);
1286 return -EINVAL;
1287 }
1288
1289 ref_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01001290 if (ref_device == NULL) {
1291 return -ENOMEM;
1292 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001293 ref_device->pcm_profile = ref_pcm_profile;
1294
1295 ALOGV("%s: ref_device rate:%d, ch:%d", __func__, ref_pcm_profile->config.rate, ref_pcm_profile->config.channels);
1296 ref_device->pcm = pcm_open(ref_device->pcm_profile->card, ref_device->pcm_profile->id, PCM_IN | PCM_MONOTONIC, &ref_device->pcm_profile->config);
1297
1298 if (ref_device->pcm && !pcm_is_ready(ref_device->pcm)) {
1299 ALOGE("%s: %s", __func__, pcm_get_error(ref_device->pcm));
1300 pcm_close(ref_device->pcm);
1301 ref_device->pcm = NULL;
1302 return -EIO;
1303 }
1304 list_add_tail(&in->pcm_dev_list, &ref_device->stream_list_node);
1305
1306 in->hw_echo_reference = true;
1307
1308 ALOGV("%s: hw_echo_reference is true", __func__);
1309 }
1310
1311 return 0;
1312}
1313#endif
1314
1315static int get_playback_delay(struct stream_out *out,
1316 size_t frames,
1317 struct echo_reference_buffer *buffer)
1318{
1319 unsigned int kernel_frames;
1320 int status;
1321 int primary_pcm = 0;
1322 struct pcm_device *pcm_device;
1323
1324 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1325 struct pcm_device, stream_list_node);
1326
1327 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1328 if (status < 0) {
1329 buffer->time_stamp.tv_sec = 0;
1330 buffer->time_stamp.tv_nsec = 0;
1331 buffer->delay_ns = 0;
1332 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1333 "setting playbackTimestamp to 0");
1334 return status;
1335 }
1336
1337 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1338
1339 /* adjust render time stamp with delay added by current driver buffer.
1340 * Add the duration of current frame as we want the render time of the last
1341 * sample being written. */
1342 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1343 out->config.rate);
1344 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1345 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1346
1347 return 0;
1348}
1349
1350#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1351 do { \
1352 if (fct_status != 0) \
1353 status = fct_status; \
1354 else if (cmd_status != 0) \
1355 status = cmd_status; \
1356 } while(0)
1357
1358static int in_configure_reverse(struct stream_in *in)
1359{
1360 int32_t cmd_status;
1361 uint32_t size = sizeof(int);
1362 effect_config_t config;
1363 int32_t status = 0;
1364 int32_t fct_status = 0;
1365 int i;
1366 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1367 if (in->num_preprocessors > 0) {
1368 config.inputCfg.channels = in->main_channels;
1369 config.outputCfg.channels = in->main_channels;
1370 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1371 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1372 config.inputCfg.samplingRate = in->requested_rate;
1373 config.outputCfg.samplingRate = in->requested_rate;
1374 config.inputCfg.mask =
1375 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1376 config.outputCfg.mask =
1377 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1378
1379 for (i = 0; i < in->num_preprocessors; i++)
1380 {
1381 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1382 continue;
1383 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1384 in->preprocessors[i].effect_itfe,
1385 EFFECT_CMD_SET_CONFIG_REVERSE,
1386 sizeof(effect_config_t),
1387 &config,
1388 &size,
1389 &cmd_status);
1390 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1391 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1392 }
1393 }
1394 return status;
1395}
1396
1397#define MAX_NUM_CHANNEL_CONFIGS 10
1398
1399static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1400 struct effect_info_s *effect_info)
1401{
1402 /* size and format of the cmd are defined in hardware/audio_effect.h */
1403 effect_handle_t effect = effect_info->effect_itfe;
1404 uint32_t cmd_size = 2 * sizeof(uint32_t);
1405 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1406 /* reply = status + number of configs (n) + n x channel_config_t */
1407 uint32_t reply_size =
1408 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1409 int32_t reply[reply_size];
1410 int32_t cmd_status;
1411
1412 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1413 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1414 ALOG_ASSERT((effect_info->channel_configs == NULL),
1415 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1416
1417 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1418 * This error will be interpreted as if the effect supports the main_channels but does not
1419 * support any aux_channels */
1420 cmd_status = (*effect)->command(effect,
1421 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1422 cmd_size,
1423 (void*)&cmd,
1424 &reply_size,
1425 (void*)&reply);
1426
1427 if (cmd_status != 0) {
1428 ALOGV("in_read_audio_effect_channel_configs(): "
1429 "fx->command returned %d", cmd_status);
1430 return;
1431 }
1432
1433 if (reply[0] != 0) {
1434 ALOGW("in_read_audio_effect_channel_configs(): "
1435 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1436 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1437 return;
1438 }
1439
1440 /* the feature is not supported */
1441 ALOGV("in_read_audio_effect_channel_configs()(): "
1442 "Feature supported and adding %d channel configs to the list", reply[1]);
1443 effect_info->num_channel_configs = reply[1];
1444 effect_info->channel_configs =
1445 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1446 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1447}
1448
1449
1450#define NUM_IN_AUX_CNL_CONFIGS 2
1451static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1452 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1453 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1454};
1455static uint32_t in_get_aux_channels(struct stream_in *in)
1456{
1457 int i;
1458 channel_config_t new_chcfg = {0, 0};
1459
1460 if (in->num_preprocessors == 0)
1461 return 0;
1462
1463 /* do not enable dual mic configurations when capturing from other microphones than
1464 * main or sub */
1465 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1466 return 0;
1467
1468 /* retain most complex aux channels configuration compatible with requested main channels and
1469 * supported by audio driver and all pre processors */
1470 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1471 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1472 if (cur_chcfg->main_channels == in->main_channels) {
1473 size_t match_cnt;
1474 size_t idx_preproc;
1475 for (idx_preproc = 0, match_cnt = 0;
1476 /* no need to continue if at least one preprocessor doesn't match */
1477 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1478 idx_preproc++) {
1479 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1480 size_t idx_chcfg;
1481
1482 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1483 if (memcmp(effect_info->channel_configs + idx_chcfg,
1484 cur_chcfg,
1485 sizeof(channel_config_t)) == 0) {
1486 match_cnt++;
1487 break;
1488 }
1489 }
1490 }
1491 /* if all preprocessors match, we have a candidate */
1492 if (match_cnt == (size_t)in->num_preprocessors) {
1493 /* retain most complex aux channels configuration */
1494 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1495 new_chcfg = *cur_chcfg;
1496 }
1497 }
1498 }
1499 }
1500
1501 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1502
1503 return new_chcfg.aux_channels;
1504}
1505
1506static int in_configure_effect_channels(effect_handle_t effect,
1507 channel_config_t *channel_config)
1508{
1509 int status = 0;
1510 int fct_status;
1511 int32_t cmd_status;
1512 uint32_t reply_size;
1513 effect_config_t config;
1514 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1515
1516 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1517 channel_config->main_channels,
1518 channel_config->aux_channels);
1519
1520 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1521 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1522 reply_size = sizeof(effect_config_t);
1523 fct_status = (*effect)->command(effect,
1524 EFFECT_CMD_GET_CONFIG,
1525 0,
1526 NULL,
1527 &reply_size,
1528 &config);
1529 if (fct_status != 0) {
1530 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1531 return fct_status;
1532 }
1533
1534 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1535 config.outputCfg.channels = config.inputCfg.channels;
1536 reply_size = sizeof(uint32_t);
1537 fct_status = (*effect)->command(effect,
1538 EFFECT_CMD_SET_CONFIG,
1539 sizeof(effect_config_t),
1540 &config,
1541 &reply_size,
1542 &cmd_status);
1543 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1544
1545 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1546 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1547 reply_size = sizeof(uint32_t);
1548 fct_status = (*effect)->command(effect,
1549 EFFECT_CMD_SET_FEATURE_CONFIG,
1550 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1551 cmd,
1552 &reply_size,
1553 &cmd_status);
1554 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1555
1556 /* some implementations need to be re-enabled after a config change */
1557 reply_size = sizeof(uint32_t);
1558 fct_status = (*effect)->command(effect,
1559 EFFECT_CMD_ENABLE,
1560 0,
1561 NULL,
1562 &reply_size,
1563 &cmd_status);
1564 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1565
1566 return status;
1567}
1568
1569static int in_reconfigure_channels(struct stream_in *in,
1570 effect_handle_t effect,
1571 channel_config_t *channel_config,
1572 bool config_changed) {
1573
1574 int status = 0;
1575
1576 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1577 config_changed, effect);
1578
1579 /* if config changed, reconfigure all previously added effects */
1580 if (config_changed) {
1581 int i;
1582 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1583 for (i = 0; i < in->num_preprocessors; i++)
1584 {
1585 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1586 channel_config);
1587 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1588 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1589 if (cur_status != 0) {
1590 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1591 "%d with channels: [%04x][%04x]",
1592 cur_status,
1593 i,
1594 channel_config->main_channels,
1595 channel_config->aux_channels);
1596 status = cur_status;
1597 }
1598 }
1599 } else if (effect != NULL && channel_config->aux_channels) {
1600 /* if aux channels config did not change but aux channels are present,
1601 * we still need to configure the effect being added */
1602 status = in_configure_effect_channels(effect, channel_config);
1603 }
1604 return status;
1605}
1606
1607static void in_update_aux_channels(struct stream_in *in,
1608 effect_handle_t effect)
1609{
1610 uint32_t aux_channels;
1611 channel_config_t channel_config;
1612 int status;
1613
1614 aux_channels = in_get_aux_channels(in);
1615
1616 channel_config.main_channels = in->main_channels;
1617 channel_config.aux_channels = aux_channels;
1618 status = in_reconfigure_channels(in,
1619 effect,
1620 &channel_config,
1621 (aux_channels != in->aux_channels));
1622
1623 if (status != 0) {
1624 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1625 /* resetting aux channels configuration */
1626 aux_channels = 0;
1627 channel_config.aux_channels = 0;
1628 in_reconfigure_channels(in, effect, &channel_config, true);
1629 }
1630 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1631 if (in->aux_channels != aux_channels) {
1632 in->aux_channels_changed = true;
1633 in->aux_channels = aux_channels;
1634 do_in_standby_l(in);
1635 }
1636}
1637#endif
1638
1639/* This function reads PCM data and:
1640 * - resample if needed
1641 * - process if pre-processors are attached
1642 * - discard unwanted channels
1643 */
1644static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1645{
1646 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001647 size_t src_channels = in->config.channels;
1648 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1649 int i;
1650 void *proc_buf_out;
1651 struct pcm_device *pcm_device;
1652 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1653#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001654 audio_buffer_t in_buf;
1655 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001656 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1657#endif
1658
1659 /* Additional channels might be added on top of main_channels:
1660 * - aux_channels (by processing effects)
1661 * - extra channels due to HW limitations
1662 * In case of additional channels, we cannot work inplace
1663 */
1664 if (has_additional_channels)
1665 proc_buf_out = in->proc_buf_out;
1666 else
1667 proc_buf_out = buffer;
1668
1669 if (list_empty(&in->pcm_dev_list)) {
1670 ALOGE("%s: pcm device list empty", __func__);
1671 return -EINVAL;
1672 }
1673
1674 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1675 struct pcm_device, stream_list_node);
1676
1677#ifdef PREPROCESSING_ENABLED
1678 if (has_processing) {
1679 /* since all the processing below is done in frames and using the config.channels
1680 * as the number of channels, no changes is required in case aux_channels are present */
1681 while (frames_wr < frames) {
1682 /* first reload enough frames at the end of process input buffer */
1683 if (in->proc_buf_frames < (size_t)frames) {
1684 ssize_t frames_rd;
1685 if (in->proc_buf_size < (size_t)frames) {
1686 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1687 in->proc_buf_size = (size_t)frames;
1688 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1689 ALOG_ASSERT((in->proc_buf_in != NULL),
1690 "process_frames() failed to reallocate proc_buf_in");
1691 if (has_additional_channels) {
1692 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1693 ALOG_ASSERT((in->proc_buf_out != NULL),
1694 "process_frames() failed to reallocate proc_buf_out");
1695 proc_buf_out = in->proc_buf_out;
1696 }
1697 }
1698 frames_rd = read_frames(in,
1699 in->proc_buf_in +
1700 in->proc_buf_frames * in->config.channels,
1701 frames - in->proc_buf_frames);
1702 if (frames_rd < 0) {
1703 /* Return error code */
1704 frames_wr = frames_rd;
1705 break;
1706 }
1707 in->proc_buf_frames += frames_rd;
1708 }
1709
1710 if (in->echo_reference != NULL) {
1711 push_echo_reference(in, in->proc_buf_frames);
1712 }
1713
1714 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1715 * the maximum number of frames to be consumed and produced by process() */
1716 in_buf.frameCount = in->proc_buf_frames;
1717 in_buf.s16 = in->proc_buf_in;
1718 out_buf.frameCount = frames - frames_wr;
1719 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1720
1721 /* FIXME: this works because of current pre processing library implementation that
1722 * does the actual process only when the last enabled effect process is called.
1723 * The generic solution is to have an output buffer for each effect and pass it as
1724 * input to the next.
1725 */
1726 for (i = 0; i < in->num_preprocessors; i++) {
1727 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1728 &in_buf,
1729 &out_buf);
1730 }
1731
1732 /* process() has updated the number of frames consumed and produced in
1733 * in_buf.frameCount and out_buf.frameCount respectively
1734 * move remaining frames to the beginning of in->proc_buf_in */
1735 in->proc_buf_frames -= in_buf.frameCount;
1736
1737 if (in->proc_buf_frames) {
1738 memcpy(in->proc_buf_in,
1739 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1740 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1741 }
1742
1743 /* if not enough frames were passed to process(), read more and retry. */
1744 if (out_buf.frameCount == 0) {
1745 ALOGW("No frames produced by preproc");
1746 continue;
1747 }
1748
1749 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1750 frames_wr += out_buf.frameCount;
1751 } else {
1752 /* The effect does not comply to the API. In theory, we should never end up here! */
1753 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1754 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1755 frames_wr = frames;
1756 }
1757 }
1758 }
1759 else
1760#endif //PREPROCESSING_ENABLED
1761 {
1762 /* No processing effects attached */
1763 if (has_additional_channels) {
1764 /* With additional channels, we cannot use original buffer */
1765 if (in->proc_buf_size < (size_t)frames) {
1766 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1767 in->proc_buf_size = (size_t)frames;
1768 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1769 ALOG_ASSERT((in->proc_buf_out != NULL),
1770 "process_frames() failed to reallocate proc_buf_out");
1771 proc_buf_out = in->proc_buf_out;
1772 }
1773 }
1774 frames_wr = read_frames(in, proc_buf_out, frames);
1775 }
1776
1777 /* Remove all additional channels that have been added on top of main_channels:
1778 * - aux_channels
1779 * - extra channels from HW due to HW limitations
1780 * Assumption is made that the channels are interleaved and that the main
1781 * channels are first. */
1782
1783 if (has_additional_channels)
1784 {
1785 int16_t* src_buffer = (int16_t *)proc_buf_out;
1786 int16_t* dst_buffer = (int16_t *)buffer;
1787
1788 if (dst_channels == 1) {
1789 for (i = frames_wr; i > 0; i--)
1790 {
1791 *dst_buffer++ = *src_buffer;
1792 src_buffer += src_channels;
1793 }
1794 } else {
1795 for (i = frames_wr; i > 0; i--)
1796 {
1797 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1798 dst_buffer += dst_channels;
1799 src_buffer += src_channels;
1800 }
1801 }
1802 }
1803
1804 return frames_wr;
1805}
1806
1807static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1808 struct resampler_buffer* buffer)
1809{
1810 struct stream_in *in;
1811 struct pcm_device *pcm_device;
1812
1813 if (buffer_provider == NULL || buffer == NULL)
1814 return -EINVAL;
1815
1816 in = (struct stream_in *)((char *)buffer_provider -
1817 offsetof(struct stream_in, buf_provider));
1818
1819 if (list_empty(&in->pcm_dev_list)) {
1820 buffer->raw = NULL;
1821 buffer->frame_count = 0;
1822 in->read_status = -ENODEV;
1823 return -ENODEV;
1824 }
1825
1826 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1827 struct pcm_device, stream_list_node);
1828
1829 if (in->read_buf_frames == 0) {
1830 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1831 if (in->read_buf_size < in->config.period_size) {
1832 in->read_buf_size = in->config.period_size;
1833 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
1834 ALOG_ASSERT((in->read_buf != NULL),
1835 "get_next_buffer() failed to reallocate read_buf");
1836 }
1837
1838 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
1839
1840 if (in->read_status != 0) {
1841 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1842 buffer->raw = NULL;
1843 buffer->frame_count = 0;
1844 return in->read_status;
1845 }
1846 in->read_buf_frames = in->config.period_size;
1847
1848#ifdef PREPROCESSING_ENABLED
1849#ifdef HW_AEC_LOOPBACK
1850 if (in->hw_echo_reference) {
1851 struct pcm_device *temp_device = NULL;
1852 struct pcm_device *ref_device = NULL;
1853 struct listnode *node = NULL;
1854 struct echo_reference_buffer b;
1855 size_t size_hw_ref_bytes;
1856 size_t size_hw_ref_frames;
1857 int read_status = 0;
1858
1859 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1860 struct pcm_device, stream_list_node);
1861 list_for_each(node, &in->pcm_dev_list) {
1862 temp_device = node_to_item(node, struct pcm_device, stream_list_node);
1863 if (temp_device->pcm_profile->id == 1) {
1864 ref_device = temp_device;
1865 break;
1866 }
1867 }
1868 if (ref_device) {
1869 size_hw_ref_bytes = pcm_frames_to_bytes(ref_device->pcm, ref_device->pcm_profile->config.period_size);
1870 size_hw_ref_frames = ref_device->pcm_profile->config.period_size;
1871 if (in->hw_ref_buf_size < size_hw_ref_frames) {
1872 in->hw_ref_buf_size = size_hw_ref_frames;
1873 in->hw_ref_buf = (int16_t *) realloc(in->hw_ref_buf, size_hw_ref_bytes);
1874 ALOG_ASSERT((in->hw_ref_buf != NULL),
1875 "get_next_buffer() failed to reallocate hw_ref_buf");
1876 ALOGV("get_next_buffer(): hw_ref_buf %p extended to %zd bytes",
1877 in->hw_ref_buf, size_hw_ref_bytes);
1878 }
1879
1880 read_status = pcm_read(ref_device->pcm, (void*)in->hw_ref_buf, size_hw_ref_bytes);
1881 if (read_status != 0) {
1882 ALOGE("process_frames() pcm_read error for HW reference %d", read_status);
1883 b.raw = NULL;
1884 b.frame_count = 0;
1885 }
1886 else {
1887 get_capture_reference_delay(in, size_hw_ref_frames, &b);
1888 b.raw = (void *)in->hw_ref_buf;
1889 b.frame_count = size_hw_ref_frames;
1890 if (b.delay_ns != 0)
1891 b.delay_ns = -b.delay_ns; // as this is capture delay, it needs to be subtracted from the microphone delay
1892 in->echo_reference->write(in->echo_reference, &b);
1893 }
1894 }
1895 }
1896#endif // HW_AEC_LOOPBACK
1897#endif // PREPROCESSING_ENABLED
1898 }
1899
1900 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
1901 in->read_buf_frames : buffer->frame_count;
1902 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
1903 in->config.channels;
1904 return in->read_status;
1905}
1906
1907static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1908 struct resampler_buffer* buffer)
1909{
1910 struct stream_in *in;
1911
1912 if (buffer_provider == NULL || buffer == NULL)
1913 return;
1914
1915 in = (struct stream_in *)((char *)buffer_provider -
1916 offsetof(struct stream_in, buf_provider));
1917
1918 in->read_buf_frames -= buffer->frame_count;
1919}
1920
1921/* read_frames() reads frames from kernel driver, down samples to capture rate
1922 * if necessary and output the number of frames requested to the buffer specified */
1923static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
1924{
1925 ssize_t frames_wr = 0;
1926
1927 struct pcm_device *pcm_device;
1928
1929 if (list_empty(&in->pcm_dev_list)) {
1930 ALOGE("%s: pcm device list empty", __func__);
1931 return -EINVAL;
1932 }
1933
1934 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1935 struct pcm_device, stream_list_node);
1936
1937 while (frames_wr < frames) {
1938 size_t frames_rd = frames - frames_wr;
1939 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
1940 __func__,frames_rd,frames_wr,in->config.channels);
1941 if (in->resampler != NULL) {
1942 in->resampler->resample_from_provider(in->resampler,
1943 (int16_t *)((char *)buffer +
1944 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
1945 &frames_rd);
1946 } else {
1947 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01001948 .raw = NULL,
1949 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001950 };
1951 get_next_buffer(&in->buf_provider, &buf);
1952 if (buf.raw != NULL) {
1953 memcpy((char *)buffer +
1954 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
1955 buf.raw,
1956 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
1957 frames_rd = buf.frame_count;
1958 }
1959 release_buffer(&in->buf_provider, &buf);
1960 }
1961 /* in->read_status is updated by getNextBuffer() also called by
1962 * in->resampler->resample_from_provider() */
1963 if (in->read_status != 0)
1964 return in->read_status;
1965
1966 frames_wr += frames_rd;
1967 }
1968 return frames_wr;
1969}
1970
1971static int in_release_pcm_devices(struct stream_in *in)
1972{
1973 struct pcm_device *pcm_device;
1974 struct listnode *node;
1975 struct listnode *next;
1976
1977 list_for_each_safe(node, next, &in->pcm_dev_list) {
1978 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
1979 list_remove(node);
1980 free(pcm_device);
1981 }
1982
1983 return 0;
1984}
1985
1986static int stop_input_stream(struct stream_in *in)
1987{
1988 struct audio_usecase *uc_info;
1989 struct audio_device *adev = in->dev;
1990
1991 adev->active_input = NULL;
1992 ALOGV("%s: enter: usecase(%d: %s)", __func__,
1993 in->usecase, use_case_table[in->usecase]);
1994 uc_info = get_usecase_from_id(adev, in->usecase);
1995 if (uc_info == NULL) {
1996 ALOGE("%s: Could not find the usecase (%d) in the list",
1997 __func__, in->usecase);
1998 return -EINVAL;
1999 }
2000
2001 /* Disable the tx device */
2002 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2003
2004 list_remove(&uc_info->adev_list_node);
2005 free(uc_info);
2006
2007 if (list_empty(&in->pcm_dev_list)) {
2008 ALOGE("%s: pcm device list empty", __func__);
2009 return -EINVAL;
2010 }
2011
2012 in_release_pcm_devices(in);
2013 list_init(&in->pcm_dev_list);
2014
2015#ifdef HW_AEC_LOOPBACK
2016 if (in->hw_echo_reference)
2017 {
2018 in->hw_echo_reference = false;
2019 }
2020#endif
2021
2022 ALOGV("%s: exit", __func__);
2023 return 0;
2024}
2025
2026static int start_input_stream(struct stream_in *in)
2027{
2028 /* Enable output device and stream routing controls */
2029 int ret = 0;
2030 bool recreate_resampler = false;
2031 struct audio_usecase *uc_info;
2032 struct audio_device *adev = in->dev;
2033 struct pcm_device_profile *pcm_profile;
2034 struct pcm_device *pcm_device;
2035
2036 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2037 adev->active_input = in;
2038 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2039 if (pcm_profile == NULL) {
2040 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2041 __func__, in->usecase);
2042 ret = -EINVAL;
2043 goto error_config;
2044 }
2045
2046 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002047 if (uc_info == NULL) {
2048 ret = -ENOMEM;
2049 goto error_config;
2050 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002051 uc_info->id = in->usecase;
2052 uc_info->type = PCM_CAPTURE;
2053 uc_info->stream = (struct audio_stream *)in;
2054 uc_info->devices = in->devices;
2055 uc_info->in_snd_device = SND_DEVICE_NONE;
2056 uc_info->out_snd_device = SND_DEVICE_NONE;
2057
2058 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002059 if (pcm_device == NULL) {
2060 free(uc_info);
2061 ret = -ENOMEM;
2062 goto error_config;
2063 }
2064
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002065 pcm_device->pcm_profile = pcm_profile;
2066 list_init(&in->pcm_dev_list);
2067 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2068
2069 list_init(&uc_info->mixer_list);
2070 list_add_tail(&uc_info->mixer_list,
2071 &adev_get_mixer_for_card(adev,
2072 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2073
2074 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2075
2076 select_devices(adev, in->usecase);
2077
2078 /* Config should be updated as profile can be changed between different calls
2079 * to this function:
2080 * - Trigger resampler creation
2081 * - Config needs to be updated */
2082 if (in->config.rate != pcm_profile->config.rate) {
2083 recreate_resampler = true;
2084 }
2085 in->config = pcm_profile->config;
2086
2087#ifdef PREPROCESSING_ENABLED
2088 if (in->aux_channels_changed) {
2089 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2090 recreate_resampler = true;
2091 }
2092#endif
2093
2094 if (in->requested_rate != in->config.rate) {
2095 recreate_resampler = true;
2096 }
2097
2098 if (recreate_resampler) {
2099 if (in->resampler) {
2100 release_resampler(in->resampler);
2101 in->resampler = NULL;
2102 }
2103 in->buf_provider.get_next_buffer = get_next_buffer;
2104 in->buf_provider.release_buffer = release_buffer;
2105 ret = create_resampler(in->config.rate,
2106 in->requested_rate,
2107 in->config.channels,
2108 RESAMPLER_QUALITY_DEFAULT,
2109 &in->buf_provider,
2110 &in->resampler);
2111 }
2112
2113#ifdef PREPROCESSING_ENABLED
2114 if (in->enable_aec && in->echo_reference == NULL) {
2115 in->echo_reference = get_echo_reference(adev,
2116 AUDIO_FORMAT_PCM_16_BIT,
2117 audio_channel_count_from_in_mask(in->main_channels),
2118 in->requested_rate
2119 );
2120 }
2121
2122#ifdef HW_AEC_LOOPBACK
2123 if (in->enable_aec) {
2124 ret = get_hw_echo_reference(in);
2125 if (ret!=0)
2126 goto error_open;
2127
2128 /* force ref buffer reallocation */
2129 in->hw_ref_buf_size = 0;
2130 }
2131#endif
2132#endif
2133
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002134 if (in->dev->voice.in_call) {
2135 ALOGV("%s: in_call, not handling PCMs", __func__);
2136 goto skip_pcm_handling;
2137 }
2138
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002139 /* Open the PCM device.
2140 * The HW is limited to support only the default pcm_profile settings.
2141 * As such a change in aux_channels will not have an effect.
2142 */
2143 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2144 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2145 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2146 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2147
2148 if (pcm_profile->type == PCM_HOTWORD_STREAMING) {
2149 if (!adev->sound_trigger_open_for_streaming) {
2150 ALOGE("%s: No handle to sound trigger HAL", __func__);
2151 ret = -EIO;
2152 goto error_open;
2153 }
2154 pcm_device->pcm = NULL;
2155 pcm_device->sound_trigger_handle = adev->sound_trigger_open_for_streaming();
2156 if (pcm_device->sound_trigger_handle <= 0) {
2157 ALOGE("%s: Failed to open DSP for streaming", __func__);
2158 ret = -EIO;
2159 goto error_open;
2160 }
2161 ALOGV("Opened DSP successfully");
2162 } else {
2163 pcm_device->sound_trigger_handle = 0;
2164 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2165 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2166
2167 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2168 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2169 pcm_close(pcm_device->pcm);
2170 pcm_device->pcm = NULL;
2171 ret = -EIO;
2172 goto error_open;
2173 }
2174 }
2175
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002176skip_pcm_handling:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002177 /* force read and proc buffer reallocation in case of frame size or
2178 * channel count change */
2179 in->proc_buf_frames = 0;
2180 in->proc_buf_size = 0;
2181 in->read_buf_size = 0;
2182 in->read_buf_frames = 0;
2183
2184 /* if no supported sample rate is available, use the resampler */
2185 if (in->resampler) {
2186 in->resampler->reset(in->resampler);
2187 }
2188
2189 ALOGV("%s: exit", __func__);
2190 return ret;
2191
2192error_open:
2193 if (in->resampler) {
2194 release_resampler(in->resampler);
2195 in->resampler = NULL;
2196 }
2197 stop_input_stream(in);
2198
2199error_config:
2200 ALOGV("%s: exit: status(%d)", __func__, ret);
2201 adev->active_input = NULL;
2202 return ret;
2203}
2204
2205void lock_input_stream(struct stream_in *in)
2206{
2207 pthread_mutex_lock(&in->pre_lock);
2208 pthread_mutex_lock(&in->lock);
2209 pthread_mutex_unlock(&in->pre_lock);
2210}
2211
2212void lock_output_stream(struct stream_out *out)
2213{
2214 pthread_mutex_lock(&out->pre_lock);
2215 pthread_mutex_lock(&out->lock);
2216 pthread_mutex_unlock(&out->pre_lock);
2217}
2218
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002219static int uc_release_pcm_devices(struct audio_usecase *usecase)
2220{
2221 struct stream_out *out = (struct stream_out *)usecase->stream;
2222 struct pcm_device *pcm_device;
2223 struct listnode *node;
2224 struct listnode *next;
2225
2226 list_for_each_safe(node, next, &out->pcm_dev_list) {
2227 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2228 list_remove(node);
2229 free(pcm_device);
2230 }
2231 list_init(&usecase->mixer_list);
2232
2233 return 0;
2234}
2235
2236static int uc_select_pcm_devices(struct audio_usecase *usecase)
2237
2238{
2239 struct stream_out *out = (struct stream_out *)usecase->stream;
2240 struct pcm_device *pcm_device;
2241 struct pcm_device_profile *pcm_profile;
2242 struct mixer_card *mixer_card;
2243 audio_devices_t devices = usecase->devices;
2244
2245 list_init(&usecase->mixer_list);
2246 list_init(&out->pcm_dev_list);
2247
2248 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2249 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002250 if (pcm_device == NULL) {
2251 return -ENOMEM;
2252 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002253 pcm_device->pcm_profile = pcm_profile;
2254 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2255 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2256 if (mixer_card == NULL) {
2257 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2258 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2259 }
2260 devices &= ~pcm_profile->devices;
2261 }
2262
2263 return 0;
2264}
2265
2266static int out_close_pcm_devices(struct stream_out *out)
2267{
2268 struct pcm_device *pcm_device;
2269 struct listnode *node;
2270 struct audio_device *adev = out->dev;
2271
2272 list_for_each(node, &out->pcm_dev_list) {
2273 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2274 if (pcm_device->sound_trigger_handle > 0) {
2275 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
2276 pcm_device->sound_trigger_handle = 0;
2277 }
2278 if (pcm_device->pcm) {
2279 pcm_close(pcm_device->pcm);
2280 pcm_device->pcm = NULL;
2281 }
2282 if (pcm_device->resampler) {
2283 release_resampler(pcm_device->resampler);
2284 pcm_device->resampler = NULL;
2285 }
2286 if (pcm_device->res_buffer) {
2287 free(pcm_device->res_buffer);
2288 pcm_device->res_buffer = NULL;
2289 }
2290 }
2291
2292 return 0;
2293}
2294
2295static int out_open_pcm_devices(struct stream_out *out)
2296{
2297 struct pcm_device *pcm_device;
2298 struct listnode *node;
2299 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002300 int pcm_device_card;
2301 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002302
2303 list_for_each(node, &out->pcm_dev_list) {
2304 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002305 pcm_device_card = pcm_device->pcm_profile->card;
2306 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002307
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002308 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2309 pcm_device_id = pcm_device_deep_buffer.id;
2310
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002311 if (out->dev->voice.in_call) {
2312 ALOGV("%s: in_call, not opening PCMs", __func__);
2313 return ret;
2314 }
2315
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002316 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2317 __func__, pcm_device_card, pcm_device_id);
2318
2319 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002320 PCM_OUT | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2321
2322 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2323 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2324 pcm_device->pcm = NULL;
2325 ret = -EIO;
2326 goto error_open;
2327 }
2328 /*
2329 * If the stream rate differs from the PCM rate, we need to
2330 * create a resampler.
2331 */
2332 if (out->sample_rate != pcm_device->pcm_profile->config.rate) {
2333 ALOGV("%s: create_resampler(), pcm_device_card(%d), pcm_device_id(%d), \
2334 out_rate(%d), device_rate(%d)",__func__,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002335 pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002336 out->sample_rate, pcm_device->pcm_profile->config.rate);
2337 ret = create_resampler(out->sample_rate,
2338 pcm_device->pcm_profile->config.rate,
2339 audio_channel_count_from_out_mask(out->channel_mask),
2340 RESAMPLER_QUALITY_DEFAULT,
2341 NULL,
2342 &pcm_device->resampler);
2343 pcm_device->res_byte_count = 0;
2344 pcm_device->res_buffer = NULL;
2345 }
2346 }
2347 return ret;
2348
2349error_open:
2350 out_close_pcm_devices(out);
2351 return ret;
2352}
2353
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002354int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002355{
2356 struct audio_device *adev = out->dev;
2357 struct audio_usecase *uc_info;
2358
2359 uc_info = get_usecase_from_id(adev, out->usecase);
2360 if (uc_info == NULL) {
2361 ALOGE("%s: Could not find the usecase (%d) in the list",
2362 __func__, out->usecase);
2363 return -EINVAL;
2364 }
2365 disable_snd_device(adev, uc_info, uc_info->out_snd_device, true);
2366 uc_release_pcm_devices(uc_info);
2367 list_remove(&uc_info->adev_list_node);
2368 free(uc_info);
2369
2370 return 0;
2371}
2372
Andreas Schneider56204f62017-01-31 08:17:32 +01002373int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002374{
2375 struct audio_device *adev = out->dev;
2376 struct audio_usecase *uc_info;
2377
2378 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002379 if (uc_info == NULL) {
2380 return -ENOMEM;
2381 }
2382
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002383 uc_info->id = out->usecase;
2384 uc_info->type = PCM_PLAYBACK;
2385 uc_info->stream = (struct audio_stream *)out;
2386 uc_info->devices = out->devices;
2387 uc_info->in_snd_device = SND_DEVICE_NONE;
2388 uc_info->out_snd_device = SND_DEVICE_NONE;
2389 uc_select_pcm_devices(uc_info);
2390
2391 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2392 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002393
2394 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002395}
2396
2397static int stop_output_stream(struct stream_out *out)
2398{
2399 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002400 bool do_disable = true;
2401
2402 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2403 out->usecase, use_case_table[out->usecase]);
2404
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002405 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002406
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002407 if (do_disable)
2408 ret = disable_output_path_l(out);
2409
2410 ALOGV("%s: exit: status(%d)", __func__, ret);
2411 return ret;
2412}
2413
2414static int start_output_stream(struct stream_out *out)
2415{
2416 int ret = 0;
2417 struct audio_device *adev = out->dev;
2418
2419 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2420 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2421
Andreas Schneider56204f62017-01-31 08:17:32 +01002422 ret = enable_output_path_l(out);
2423 if (ret != 0) {
2424 goto error_config;
2425 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002426
2427 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2428 out->compr = NULL;
2429 ret = out_open_pcm_devices(out);
2430 if (ret != 0)
2431 goto error_open;
2432#ifdef PREPROCESSING_ENABLED
2433 out->echo_reference = NULL;
2434 out->echo_reference_generation = adev->echo_reference_generation;
2435 if (adev->echo_reference != NULL)
2436 out->echo_reference = adev->echo_reference;
2437#endif
2438 } else {
2439 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2440 COMPRESS_IN, &out->compr_config);
2441 if (out->compr && !is_compress_ready(out->compr)) {
2442 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2443 compress_close(out->compr);
2444 out->compr = NULL;
2445 ret = -EIO;
2446 goto error_open;
2447 }
2448 if (out->offload_callback)
2449 compress_nonblock(out->compr, out->non_blocking);
2450
2451 if (adev->offload_fx_start_output != NULL)
2452 adev->offload_fx_start_output(out->handle);
2453 }
2454 ALOGV("%s: exit", __func__);
2455 return 0;
2456error_open:
2457 stop_output_stream(out);
2458error_config:
2459 return ret;
2460}
2461
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002462int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002463{
2464 struct audio_usecase *uc_info;
2465
2466 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002467 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002468
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002469 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002470
2471 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2472 if (uc_info == NULL) {
2473 ALOGE("%s: Could not find the usecase (%d) in the list",
2474 __func__, USECASE_VOICE_CALL);
2475 return -EINVAL;
2476 }
2477
2478 disable_snd_device(adev, uc_info, uc_info->out_snd_device, false);
2479 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2480
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002481 list_remove(&uc_info->adev_list_node);
2482 free(uc_info);
2483
2484 ALOGV("%s: exit", __func__);
2485 return 0;
2486}
2487
2488/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002489int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002490{
2491 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002492 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002493
2494 ALOGV("%s: enter", __func__);
2495
2496 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002497 if (uc_info == NULL) {
2498 ret = -ENOMEM;
2499 goto exit;
2500 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002501 /*
2502 * We set this early so that functions called after this is being set
2503 * can use it. It is e.g. needed in select_devices() to inform the RILD
2504 * which output device we use.
2505 */
2506 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002507
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002508 uc_info->id = USECASE_VOICE_CALL;
2509 uc_info->type = VOICE_CALL;
2510 uc_info->stream = (struct audio_stream *)adev->primary_output;
2511 uc_info->devices = adev->primary_output->devices;
2512 uc_info->in_snd_device = SND_DEVICE_NONE;
2513 uc_info->out_snd_device = SND_DEVICE_NONE;
2514
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002515 list_init(&uc_info->mixer_list);
2516 list_add_tail(&uc_info->mixer_list,
2517 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002518
2519 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2520
2521 select_devices(adev, USECASE_VOICE_CALL);
2522
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002523 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002524
2525 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002526 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002527
Andreas Schneider56204f62017-01-31 08:17:32 +01002528exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002529 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002530 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002531}
2532
2533static int check_input_parameters(uint32_t sample_rate,
2534 audio_format_t format,
2535 int channel_count)
2536{
2537 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2538
2539 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2540
2541 switch (sample_rate) {
2542 case 8000:
2543 case 11025:
2544 case 12000:
2545 case 16000:
2546 case 22050:
2547 case 24000:
2548 case 32000:
2549 case 44100:
2550 case 48000:
2551 break;
2552 default:
2553 return -EINVAL;
2554 }
2555
2556 return 0;
2557}
2558
2559static size_t get_input_buffer_size(uint32_t sample_rate,
2560 audio_format_t format,
2561 int channel_count,
2562 usecase_type_t usecase_type,
2563 audio_devices_t devices)
2564{
2565 size_t size = 0;
2566 struct pcm_device_profile *pcm_profile;
2567
2568 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2569 return 0;
2570
2571 pcm_profile = get_pcm_device(usecase_type, devices);
2572 if (pcm_profile == NULL)
2573 return 0;
2574
2575 /*
2576 * take resampling into account and return the closest majoring
2577 * multiple of 16 frames, as audioflinger expects audio buffers to
2578 * be a multiple of 16 frames
2579 */
2580 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2581 size = ((size + 15) / 16) * 16;
2582
2583 return (size * channel_count * audio_bytes_per_sample(format));
2584
2585}
2586
2587static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2588{
2589 struct stream_out *out = (struct stream_out *)stream;
2590
2591 return out->sample_rate;
2592}
2593
2594static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2595{
2596 (void)stream;
2597 (void)rate;
2598 return -ENOSYS;
2599}
2600
2601static size_t out_get_buffer_size(const struct audio_stream *stream)
2602{
2603 struct stream_out *out = (struct stream_out *)stream;
2604
2605 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2606 return out->compr_config.fragment_size;
2607 }
2608
2609 return out->config.period_size *
2610 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2611}
2612
2613static uint32_t out_get_channels(const struct audio_stream *stream)
2614{
2615 struct stream_out *out = (struct stream_out *)stream;
2616
2617 return out->channel_mask;
2618}
2619
2620static audio_format_t out_get_format(const struct audio_stream *stream)
2621{
2622 struct stream_out *out = (struct stream_out *)stream;
2623
2624 return out->format;
2625}
2626
2627static int out_set_format(struct audio_stream *stream, audio_format_t format)
2628{
2629 (void)stream;
2630 (void)format;
2631 return -ENOSYS;
2632}
2633
2634static int do_out_standby_l(struct stream_out *out)
2635{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002636 int status = 0;
2637
2638 out->standby = true;
2639 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2640 out_close_pcm_devices(out);
2641#ifdef PREPROCESSING_ENABLED
2642 /* stop writing to echo reference */
2643 if (out->echo_reference != NULL) {
2644 out->echo_reference->write(out->echo_reference, NULL);
2645 if (out->echo_reference_generation != adev->echo_reference_generation) {
2646 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2647 release_echo_reference(out->echo_reference);
2648 out->echo_reference_generation = adev->echo_reference_generation;
2649 }
2650 out->echo_reference = NULL;
2651 }
2652#endif
2653 } else {
2654 stop_compressed_output_l(out);
2655 out->gapless_mdata.encoder_delay = 0;
2656 out->gapless_mdata.encoder_padding = 0;
2657 if (out->compr != NULL) {
2658 compress_close(out->compr);
2659 out->compr = NULL;
2660 }
2661 }
2662 status = stop_output_stream(out);
2663
2664 return status;
2665}
2666
2667static int out_standby(struct audio_stream *stream)
2668{
2669 struct stream_out *out = (struct stream_out *)stream;
2670 struct audio_device *adev = out->dev;
2671
2672 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2673 out->usecase, use_case_table[out->usecase]);
2674 lock_output_stream(out);
2675 if (!out->standby) {
2676 pthread_mutex_lock(&adev->lock);
2677 do_out_standby_l(out);
2678 pthread_mutex_unlock(&adev->lock);
2679 }
2680 pthread_mutex_unlock(&out->lock);
2681 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002682
2683 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2684
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002685 return 0;
2686}
2687
2688static int out_dump(const struct audio_stream *stream, int fd)
2689{
2690 (void)stream;
2691 (void)fd;
2692
2693 return 0;
2694}
2695
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002696static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2697{
2698 struct stream_out *out = (struct stream_out *)stream;
2699 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002700 struct listnode *node;
2701 struct str_parms *parms;
2702 char value[32];
2703 int ret, val = 0;
2704 struct audio_usecase *uc_info;
2705 bool do_standby = false;
2706 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002707#ifdef PREPROCESSING_ENABLED
2708 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2709#endif
2710
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002711 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%#x) "
2712 "adev->mode(%#x)",
2713 __func__, out->usecase, use_case_table[out->usecase], kvpairs,
2714 out->devices, adev->mode);
2715
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002716 parms = str_parms_create_str(kvpairs);
2717 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2718 if (ret >= 0) {
2719 val = atoi(value);
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002720
2721 ALOGV("%s: routing: usecase(%d: %s) devices=(%#x) adev->mode(%#x)",
2722 __func__, out->usecase, use_case_table[out->usecase], val,
2723 adev->mode);
2724
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002725 pthread_mutex_lock(&adev->lock_inputs);
2726 lock_output_stream(out);
2727 pthread_mutex_lock(&adev->lock);
2728#ifdef PREPROCESSING_ENABLED
2729 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2730 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2731 /* reset active input:
2732 * - to attach the echo reference
2733 * - because a change in output device may change mic settings */
2734 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2735 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2736 in = adev->active_input;
2737 }
2738 }
2739#endif
2740 if (val != 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002741 bool bt_sco_active = false;
2742
2743 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2744 bt_sco_active = true;
2745 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002746 out->devices = val;
2747
2748 if (!out->standby) {
2749 uc_info = get_usecase_from_id(adev, out->usecase);
2750 if (uc_info == NULL) {
2751 ALOGE("%s: Could not find the usecase (%d) in the list",
2752 __func__, out->usecase);
2753 } else {
2754 list_for_each(node, &out->pcm_dev_list) {
2755 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2756 if ((pcm_device->pcm_profile->devices & val) == 0)
2757 do_standby = true;
2758 val &= ~pcm_device->pcm_profile->devices;
2759 }
2760 if (val != 0)
2761 do_standby = true;
2762 }
2763 if (do_standby)
2764 do_out_standby_l(out);
2765 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002766 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2767 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002768 select_devices(adev, out->usecase);
2769 }
2770 }
2771
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002772 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002773 (out == adev->primary_output)) {
2774 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002775 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2776 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002777 (out == adev->primary_output)) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002778 /* Turn on bluetooth if needed */
2779 if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002780 select_devices(adev, USECASE_VOICE_CALL);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002781 start_voice_session_bt_sco(adev->voice.session);
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002782 } else {
2783 /*
2784 * When we select different devices we need to restart the
2785 * voice call. The modem closes the stream on its end and
2786 * we do not get any output.
2787 */
2788 stop_voice_call(adev);
2789 start_voice_call(adev);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002790 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002791 }
2792 }
2793
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002794 if ((adev->mode == AUDIO_MODE_NORMAL) && adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002795 (out == adev->primary_output)) {
2796 stop_voice_call(adev);
2797 }
2798 pthread_mutex_unlock(&adev->lock);
2799 pthread_mutex_unlock(&out->lock);
2800#ifdef PREPROCESSING_ENABLED
2801 if (in) {
2802 /* The lock on adev->lock_inputs prevents input stream from being closed */
2803 lock_input_stream(in);
2804 pthread_mutex_lock(&adev->lock);
2805 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2806 do_in_standby_l(in);
2807 pthread_mutex_unlock(&adev->lock);
2808 pthread_mutex_unlock(&in->lock);
2809 }
2810#endif
2811 pthread_mutex_unlock(&adev->lock_inputs);
2812 }
2813
2814 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2815 parse_compress_metadata(out, parms);
2816 }
2817
2818 str_parms_destroy(parms);
2819
2820 if (ret > 0)
2821 ret = 0;
2822 ALOGV("%s: exit: code(%d)", __func__, ret);
2823 return ret;
2824}
2825
2826static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2827{
2828 struct stream_out *out = (struct stream_out *)stream;
2829 struct str_parms *query = str_parms_create_str(keys);
2830 char *str;
2831 char value[256];
2832 struct str_parms *reply = str_parms_create();
2833 size_t i, j;
2834 int ret;
2835 bool first = true;
2836 ALOGV("%s: enter: keys - %s", __func__, keys);
2837 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2838 if (ret >= 0) {
2839 value[0] = '\0';
2840 i = 0;
2841 while (out->supported_channel_masks[i] != 0) {
2842 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2843 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2844 if (!first) {
2845 strcat(value, "|");
2846 }
2847 strcat(value, out_channels_name_to_enum_table[j].name);
2848 first = false;
2849 break;
2850 }
2851 }
2852 i++;
2853 }
2854 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2855 str = str_parms_to_str(reply);
2856 } else {
2857 str = strdup(keys);
2858 }
2859 str_parms_destroy(query);
2860 str_parms_destroy(reply);
2861 ALOGV("%s: exit: returns - %s", __func__, str);
2862 return str;
2863}
2864
2865static uint32_t out_get_latency(const struct audio_stream_out *stream)
2866{
2867 struct stream_out *out = (struct stream_out *)stream;
2868
2869 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2870 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2871
2872 return (out->config.period_count * out->config.period_size * 1000) /
2873 (out->config.rate);
2874}
2875
2876static int out_set_volume(struct audio_stream_out *stream, float left,
2877 float right)
2878{
2879 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002880
2881 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2882 /* only take left channel into account: the API is for stereo anyway */
2883 out->muted = (left == 0.0f);
2884 return 0;
2885 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002886 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002887 }
2888
2889 return -ENOSYS;
2890}
2891
Andreas Schneider3b643832017-01-31 11:48:22 +01002892#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002893static int fast_set_affinity(pid_t tid) {
2894 cpu_set_t cpu_set;
2895 int cpu_num;
2896 const char *irq_procfs = "/proc/asound/irq_affinity";
2897 FILE *fp;
2898
2899 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2900 ALOGW("Procfs node %s not found", irq_procfs);
2901 return -1;
2902 }
2903
2904 if (fscanf(fp, "%d", &cpu_num) != 1) {
2905 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2906 fclose(fp);
2907 return -1;
2908 }
2909 fclose(fp);
2910
2911 CPU_ZERO(&cpu_set);
2912 CPU_SET(cpu_num, &cpu_set);
2913 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2914}
Andreas Schneider3b643832017-01-31 11:48:22 +01002915#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002916
2917static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2918 size_t bytes)
2919{
2920 struct stream_out *out = (struct stream_out *)stream;
2921 struct audio_device *adev = out->dev;
2922 ssize_t ret = 0;
2923 struct pcm_device *pcm_device;
2924 struct listnode *node;
2925 size_t frame_size = audio_stream_out_frame_size(stream);
2926 size_t frames_wr = 0, frames_rq = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002927#ifdef PREPROCESSING_ENABLED
2928 size_t in_frames = bytes / frame_size;
2929 size_t out_frames = in_frames;
2930 struct stream_in *in = NULL;
2931#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002932
2933 lock_output_stream(out);
2934
Andreas Schneider3b643832017-01-31 11:48:22 +01002935#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002936 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002937 pid_t tid = gettid();
2938 int err;
2939
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002940 err = fast_set_affinity(tid);
2941 if (err < 0) {
2942 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2943 }
2944 out->is_fastmixer_affinity_set = true;
2945 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002946#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002947
2948 if (out->standby) {
2949#ifdef PREPROCESSING_ENABLED
2950 pthread_mutex_unlock(&out->lock);
2951 /* Prevent input stream from being closed */
2952 pthread_mutex_lock(&adev->lock_inputs);
2953 lock_output_stream(out);
2954 if (!out->standby) {
2955 pthread_mutex_unlock(&adev->lock_inputs);
2956 goto false_alarm;
2957 }
2958#endif
2959 pthread_mutex_lock(&adev->lock);
2960 ret = start_output_stream(out);
2961 /* ToDo: If use case is compress offload should return 0 */
2962 if (ret != 0) {
2963 pthread_mutex_unlock(&adev->lock);
2964#ifdef PREPROCESSING_ENABLED
2965 pthread_mutex_unlock(&adev->lock_inputs);
2966#endif
2967 goto exit;
2968 }
2969 out->standby = false;
2970
2971#ifdef PREPROCESSING_ENABLED
2972 /* A change in output device may change the microphone selection */
2973 if (adev->active_input &&
2974 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2975 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2976 in = adev->active_input;
2977 ALOGV("%s: enter:) force_input_standby true", __func__);
2978 }
2979#endif
2980 pthread_mutex_unlock(&adev->lock);
2981#ifdef PREPROCESSING_ENABLED
2982 if (!in) {
2983 /* Leave mutex locked iff in != NULL */
2984 pthread_mutex_unlock(&adev->lock_inputs);
2985 }
2986#endif
2987 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002988#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002989false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002990#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002991
2992 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002993 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002994 return ret;
2995 } else {
2996#ifdef PREPROCESSING_ENABLED
2997 if (android_atomic_acquire_load(&adev->echo_reference_generation)
2998 != out->echo_reference_generation) {
2999 pthread_mutex_lock(&adev->lock);
3000 if (out->echo_reference != NULL) {
3001 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
3002 release_echo_reference(out->echo_reference);
3003 }
3004 // note that adev->echo_reference_generation here can be different from the one
3005 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
3006 // with what has been set by get_echo_reference() or put_echo_reference()
3007 out->echo_reference_generation = adev->echo_reference_generation;
3008 out->echo_reference = adev->echo_reference;
3009 ALOGV("%s: update echo reference generation %d", __func__,
3010 out->echo_reference_generation);
3011 pthread_mutex_unlock(&adev->lock);
3012 }
3013#endif
3014
3015 if (out->muted)
3016 memset((void *)buffer, 0, bytes);
3017 list_for_each(node, &out->pcm_dev_list) {
3018 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3019 if (pcm_device->resampler) {
3020 if (bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size
3021 > pcm_device->res_byte_count) {
3022 pcm_device->res_byte_count =
3023 bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size;
3024 pcm_device->res_buffer =
3025 realloc(pcm_device->res_buffer, pcm_device->res_byte_count);
3026 ALOGV("%s: resampler res_byte_count = %zu", __func__,
3027 pcm_device->res_byte_count);
3028 }
3029 frames_rq = bytes / frame_size;
3030 frames_wr = pcm_device->res_byte_count / frame_size;
3031 ALOGVV("%s: resampler request frames = %d frame_size = %d",
3032 __func__, frames_rq, frame_size);
3033 pcm_device->resampler->resample_from_input(pcm_device->resampler,
3034 (int16_t *)buffer, &frames_rq, (int16_t *)pcm_device->res_buffer, &frames_wr);
3035 ALOGVV("%s: resampler output frames_= %d", __func__, frames_wr);
3036 }
3037 if (pcm_device->pcm) {
3038#ifdef PREPROCESSING_ENABLED
3039 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
3040 struct echo_reference_buffer b;
3041 b.raw = (void *)buffer;
3042 b.frame_count = in_frames;
3043
3044 get_playback_delay(out, out_frames, &b);
3045 out->echo_reference->write(out->echo_reference, &b);
3046 }
3047#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003048 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
3049 if (pcm_device->resampler && pcm_device->res_buffer)
3050 pcm_device->status =
3051 pcm_write(pcm_device->pcm, (void *)pcm_device->res_buffer,
3052 frames_wr * frame_size);
3053 else
3054 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
3055 if (pcm_device->status != 0)
3056 ret = pcm_device->status;
3057 }
3058 }
3059 if (ret == 0)
3060 out->written += bytes / (out->config.channels * sizeof(short));
3061 }
3062
3063exit:
3064 pthread_mutex_unlock(&out->lock);
3065
3066 if (ret != 0) {
3067 list_for_each(node, &out->pcm_dev_list) {
3068 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3069 if (pcm_device->pcm && pcm_device->status != 0)
3070 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
3071 }
3072 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003073 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3074 clock_gettime(CLOCK_MONOTONIC, &t);
3075 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3076 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
3077 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
3078 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
3079 if (sleep_time > 0) {
3080 usleep(sleep_time);
3081 } else {
3082 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
3083 sleep_time = 0;
3084 }
3085 out->last_write_time_us = now + sleep_time;
3086 // last_write_time_us is an approximation of when the (simulated) alsa
3087 // buffer is believed completely full. The usleep above waits for more space
3088 // in the buffer, but by the end of the sleep the buffer is considered
3089 // topped-off.
3090 //
3091 // On the subsequent out_write(), we measure the elapsed time spent in
3092 // the mixer. This is subtracted from the sleep estimate based on frames,
3093 // thereby accounting for drain in the alsa buffer during mixing.
3094 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003095 }
3096
3097#ifdef PREPROCESSING_ENABLED
3098 if (in) {
3099 /* The lock on adev->lock_inputs prevents input stream from being closed */
3100 lock_input_stream(in);
3101 pthread_mutex_lock(&adev->lock);
3102 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3103 do_in_standby_l(in);
3104 pthread_mutex_unlock(&adev->lock);
3105 pthread_mutex_unlock(&in->lock);
3106 /* This mutex was left locked iff in != NULL */
3107 pthread_mutex_unlock(&adev->lock_inputs);
3108 }
3109#endif
3110
3111 return bytes;
3112}
3113
3114static int out_get_render_position(const struct audio_stream_out *stream,
3115 uint32_t *dsp_frames)
3116{
3117 struct stream_out *out = (struct stream_out *)stream;
3118 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003119 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3120 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003121 } else
3122 return -EINVAL;
3123}
3124
3125static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3126{
3127 (void)stream;
3128 (void)effect;
3129 return 0;
3130}
3131
3132static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3133{
3134 (void)stream;
3135 (void)effect;
3136 return 0;
3137}
3138
3139static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3140 int64_t *timestamp)
3141{
3142 (void)stream;
3143 (void)timestamp;
3144 return -EINVAL;
3145}
3146
3147static int out_get_presentation_position(const struct audio_stream_out *stream,
3148 uint64_t *frames, struct timespec *timestamp)
3149{
3150 struct stream_out *out = (struct stream_out *)stream;
3151 int ret = -1;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003152
3153 lock_output_stream(out);
3154
3155 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003156 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003157 } else {
Andreas Schneider97fa7f12017-02-11 14:21:56 +01003158 if (out->dev->voice.in_call) {
3159 ALOGVV("%s: in_call, do not handle PCMs", __func__);
3160 ret = 0;
3161 goto done;
3162 }
3163
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003164 /* FIXME: which device to read from? */
3165 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003166 struct pcm_device *pcm_device;
3167 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003168 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003169
Andreas Schneiderd6359182017-02-08 16:58:22 +01003170 list_for_each(node, &out->pcm_dev_list) {
3171 pcm_device = node_to_item(node,
3172 struct pcm_device,
3173 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003174
Andreas Schneiderd6359182017-02-08 16:58:22 +01003175 if (pcm_device->pcm != NULL) {
3176 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3177 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3178 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3179 /* This adjustment accounts for buffering after app processor.
3180 It is based on estimated DSP latency per use case, rather than exact. */
3181 signed_frames -=
3182 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3183
3184 /* It would be unusual for this value to be negative, but check just in case ... */
3185 if (signed_frames >= 0) {
3186 *frames = signed_frames;
3187 ret = 0;
3188 goto done;
3189 }
3190 ret = -1;
3191 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003192 }
3193 }
3194 }
3195 }
3196
Andreas Schneiderd6359182017-02-08 16:58:22 +01003197done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003198 pthread_mutex_unlock(&out->lock);
3199
3200 return ret;
3201}
3202
3203static int out_set_callback(struct audio_stream_out *stream,
3204 stream_callback_t callback, void *cookie)
3205{
3206 struct stream_out *out = (struct stream_out *)stream;
3207
3208 ALOGV("%s", __func__);
3209 lock_output_stream(out);
3210 out->offload_callback = callback;
3211 out->offload_cookie = cookie;
3212 pthread_mutex_unlock(&out->lock);
3213 return 0;
3214}
3215
3216static int out_pause(struct audio_stream_out* stream)
3217{
3218 struct stream_out *out = (struct stream_out *)stream;
3219 int status = -ENOSYS;
3220 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003221 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3222 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003223 return status;
3224}
3225
3226static int out_resume(struct audio_stream_out* stream)
3227{
3228 struct stream_out *out = (struct stream_out *)stream;
3229 int status = -ENOSYS;
3230 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003231 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3232 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003233 return status;
3234}
3235
3236static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3237{
3238 struct stream_out *out = (struct stream_out *)stream;
3239 int status = -ENOSYS;
3240 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003241 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3242 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003243 return status;
3244}
3245
3246static int out_flush(struct audio_stream_out* stream)
3247{
3248 struct stream_out *out = (struct stream_out *)stream;
3249 ALOGV("%s", __func__);
3250 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003251 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003252 }
3253 return -ENOSYS;
3254}
3255
3256/** audio_stream_in implementation **/
3257static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3258{
3259 struct stream_in *in = (struct stream_in *)stream;
3260
3261 return in->requested_rate;
3262}
3263
3264static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3265{
3266 (void)stream;
3267 (void)rate;
3268 return -ENOSYS;
3269}
3270
3271static uint32_t in_get_channels(const struct audio_stream *stream)
3272{
3273 struct stream_in *in = (struct stream_in *)stream;
3274
3275 return in->main_channels;
3276}
3277
3278static audio_format_t in_get_format(const struct audio_stream *stream)
3279{
3280 (void)stream;
3281 return AUDIO_FORMAT_PCM_16_BIT;
3282}
3283
3284static int in_set_format(struct audio_stream *stream, audio_format_t format)
3285{
3286 (void)stream;
3287 (void)format;
3288
3289 return -ENOSYS;
3290}
3291
3292static size_t in_get_buffer_size(const struct audio_stream *stream)
3293{
3294 struct stream_in *in = (struct stream_in *)stream;
3295
3296 return get_input_buffer_size(in->requested_rate,
3297 in_get_format(stream),
3298 audio_channel_count_from_in_mask(in->main_channels),
3299 in->usecase_type,
3300 in->devices);
3301}
3302
3303static int in_close_pcm_devices(struct stream_in *in)
3304{
3305 struct pcm_device *pcm_device;
3306 struct listnode *node;
3307 struct audio_device *adev = in->dev;
3308
3309 list_for_each(node, &in->pcm_dev_list) {
3310 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3311 if (pcm_device) {
3312 if (pcm_device->pcm)
3313 pcm_close(pcm_device->pcm);
3314 pcm_device->pcm = NULL;
3315 if (pcm_device->sound_trigger_handle > 0)
3316 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
3317 pcm_device->sound_trigger_handle = 0;
3318 }
3319 }
3320 return 0;
3321}
3322
3323
3324/* must be called with stream and hw device mutex locked */
3325static int do_in_standby_l(struct stream_in *in)
3326{
3327 int status = 0;
3328
3329#ifdef PREPROCESSING_ENABLED
3330 struct audio_device *adev = in->dev;
3331#endif
3332 if (!in->standby) {
3333
3334 in_close_pcm_devices(in);
3335
3336#ifdef PREPROCESSING_ENABLED
3337 if (in->echo_reference != NULL) {
3338 /* stop reading from echo reference */
3339 in->echo_reference->read(in->echo_reference, NULL);
3340 put_echo_reference(adev, in->echo_reference);
3341 in->echo_reference = NULL;
3342 }
3343#ifdef HW_AEC_LOOPBACK
3344 if (in->hw_echo_reference)
3345 {
3346 if (in->hw_ref_buf) {
3347 free(in->hw_ref_buf);
3348 in->hw_ref_buf = NULL;
3349 }
3350 }
3351#endif // HW_AEC_LOOPBACK
3352#endif // PREPROCESSING_ENABLED
3353
3354 status = stop_input_stream(in);
3355
3356 if (in->read_buf) {
3357 free(in->read_buf);
3358 in->read_buf = NULL;
3359 }
3360
3361 in->standby = 1;
3362 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003363
3364 in->last_read_time_us = 0;
3365
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003366 return 0;
3367}
3368
3369// called with adev->lock_inputs locked
3370static int in_standby_l(struct stream_in *in)
3371{
3372 struct audio_device *adev = in->dev;
3373 int status = 0;
3374 lock_input_stream(in);
3375 if (!in->standby) {
3376 pthread_mutex_lock(&adev->lock);
3377 status = do_in_standby_l(in);
3378 pthread_mutex_unlock(&adev->lock);
3379 }
3380 pthread_mutex_unlock(&in->lock);
3381 return status;
3382}
3383
3384static int in_standby(struct audio_stream *stream)
3385{
3386 struct stream_in *in = (struct stream_in *)stream;
3387 struct audio_device *adev = in->dev;
3388 int status;
3389 ALOGV("%s: enter", __func__);
3390 pthread_mutex_lock(&adev->lock_inputs);
3391 status = in_standby_l(in);
3392 pthread_mutex_unlock(&adev->lock_inputs);
3393 ALOGV("%s: exit: status(%d)", __func__, status);
3394 return status;
3395}
3396
3397static int in_dump(const struct audio_stream *stream, int fd)
3398{
3399 (void)stream;
3400 (void)fd;
3401
3402 return 0;
3403}
3404
3405static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3406{
3407 struct stream_in *in = (struct stream_in *)stream;
3408 struct audio_device *adev = in->dev;
3409 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003410 char value[32];
3411 int ret, val = 0;
3412 struct audio_usecase *uc_info;
3413 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003414 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003415
3416 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3417 parms = str_parms_create_str(kvpairs);
3418
3419 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3420
3421 pthread_mutex_lock(&adev->lock_inputs);
3422 lock_input_stream(in);
3423 pthread_mutex_lock(&adev->lock);
3424 if (ret >= 0) {
3425 val = atoi(value);
3426 /* no audio source uses val == 0 */
3427 if (((int)in->source != val) && (val != 0)) {
3428 in->source = val;
3429 }
3430 }
3431
3432 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3433 if (ret >= 0) {
3434 val = atoi(value);
3435 if (((int)in->devices != val) && (val != 0)) {
3436 in->devices = val;
3437 /* If recording is in progress, change the tx device to new device */
3438 if (!in->standby) {
3439 uc_info = get_usecase_from_id(adev, in->usecase);
3440 if (uc_info == NULL) {
3441 ALOGE("%s: Could not find the usecase (%d) in the list",
3442 __func__, in->usecase);
3443 } else {
3444 if (list_empty(&in->pcm_dev_list))
3445 ALOGE("%s: pcm device list empty", __func__);
3446 else {
3447 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3448 struct pcm_device, stream_list_node);
3449 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3450 do_standby = true;
3451 }
3452 }
3453 }
3454 if (do_standby) {
3455 ret = do_in_standby_l(in);
3456 } else
3457 ret = select_devices(adev, in->usecase);
3458 }
3459 }
3460 }
3461 pthread_mutex_unlock(&adev->lock);
3462 pthread_mutex_unlock(&in->lock);
3463 pthread_mutex_unlock(&adev->lock_inputs);
3464 str_parms_destroy(parms);
3465
3466 if (ret > 0)
3467 ret = 0;
3468
3469 ALOGV("%s: exit: status(%d)", __func__, ret);
3470 return ret;
3471}
3472
3473static char* in_get_parameters(const struct audio_stream *stream,
3474 const char *keys)
3475{
3476 (void)stream;
3477 (void)keys;
3478
3479 return strdup("");
3480}
3481
3482static int in_set_gain(struct audio_stream_in *stream, float gain)
3483{
3484 (void)stream;
3485 (void)gain;
3486
3487 return 0;
3488}
3489
3490static ssize_t read_bytes_from_dsp(struct stream_in *in, void* buffer,
3491 size_t bytes)
3492{
3493 struct pcm_device *pcm_device;
3494 struct audio_device *adev = in->dev;
3495
3496 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3497 struct pcm_device, stream_list_node);
3498
3499 if (pcm_device->sound_trigger_handle > 0)
3500 return adev->sound_trigger_read_samples(pcm_device->sound_trigger_handle, buffer, bytes);
3501 else
3502 return 0;
3503}
3504
3505static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3506 size_t bytes)
3507{
3508 struct stream_in *in = (struct stream_in *)stream;
3509 struct audio_device *adev = in->dev;
3510 ssize_t frames = -1;
3511 int ret = -1;
3512 int read_and_process_successful = false;
3513
3514 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003515
3516 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3517 lock_input_stream(in);
3518
Andreas Schneider3b643832017-01-31 11:48:22 +01003519#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003520 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003521 pid_t tid = gettid();
3522 int err;
3523
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003524 err = fast_set_affinity(tid);
3525 if (err < 0) {
3526 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3527 }
3528 in->is_fastcapture_affinity_set = true;
3529 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003530#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003531
3532 if (in->standby) {
3533 pthread_mutex_unlock(&in->lock);
3534 pthread_mutex_lock(&adev->lock_inputs);
3535 lock_input_stream(in);
3536 if (!in->standby) {
3537 pthread_mutex_unlock(&adev->lock_inputs);
3538 goto false_alarm;
3539 }
3540 pthread_mutex_lock(&adev->lock);
3541 ret = start_input_stream(in);
3542 pthread_mutex_unlock(&adev->lock);
3543 pthread_mutex_unlock(&adev->lock_inputs);
3544 if (ret != 0) {
3545 goto exit;
3546 }
3547 in->standby = 0;
3548 }
3549false_alarm:
3550
3551 if (!list_empty(&in->pcm_dev_list)) {
3552 if (in->usecase == USECASE_AUDIO_CAPTURE_HOTWORD) {
3553 bytes = read_bytes_from_dsp(in, buffer, bytes);
3554 if (bytes > 0)
3555 read_and_process_successful = true;
3556 } else {
3557 /*
3558 * Read PCM and:
3559 * - resample if needed
3560 * - process if pre-processors are attached
3561 * - discard unwanted channels
3562 */
3563 frames = read_and_process_frames(in, buffer, frames_rq);
3564 if (frames >= 0)
3565 read_and_process_successful = true;
3566 }
3567 }
3568
3569 /*
3570 * Instead of writing zeroes here, we could trust the hardware
3571 * to always provide zeroes when muted.
3572 */
3573 if (read_and_process_successful == true && adev->mic_mute)
3574 memset(buffer, 0, bytes);
3575
3576exit:
3577 pthread_mutex_unlock(&in->lock);
3578
3579 if (read_and_process_successful == false) {
3580 in_standby(&in->stream.common);
3581 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003582 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3583 clock_gettime(CLOCK_MONOTONIC, &t);
3584 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3585
3586 // we do a full sleep when exiting standby.
3587 const bool standby = in->last_read_time_us == 0;
3588 const int64_t elapsed_time_since_last_read = standby ?
3589 0 : now - in->last_read_time_us;
3590 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3591 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3592 if (sleep_time > 0) {
3593 usleep(sleep_time);
3594 } else {
3595 sleep_time = 0;
3596 }
3597 in->last_read_time_us = now + sleep_time;
3598 // last_read_time_us is an approximation of when the (simulated) alsa
3599 // buffer is drained by the read, and is empty.
3600 //
3601 // On the subsequent in_read(), we measure the elapsed time spent in
3602 // the recording thread. This is subtracted from the sleep estimate based on frames,
3603 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003604 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003605 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003606
3607 if (bytes > 0) {
3608 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3609 }
3610
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003611 return bytes;
3612}
3613
3614static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3615{
3616 (void)stream;
3617
3618 return 0;
3619}
3620
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003621static int in_get_capture_position(const struct audio_stream_in *stream,
3622 int64_t *frames, int64_t *time)
3623{
3624 if (stream == NULL || frames == NULL || time == NULL) {
3625 return -EINVAL;
3626 }
3627
3628 struct stream_in *in = (struct stream_in *)stream;
3629 struct pcm_device *pcm_device;
3630 int ret = -ENOSYS;
3631
3632 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3633 struct pcm_device, stream_list_node);
3634
3635 pthread_mutex_lock(&in->lock);
3636 if (pcm_device->pcm) {
3637 struct timespec timestamp;
3638 unsigned int avail;
3639 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3640 *frames = in->frames_read + avail;
3641 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3642 ret = 0;
3643 }
3644 }
3645
3646 pthread_mutex_unlock(&in->lock);
3647 return ret;
3648}
3649
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003650static int add_remove_audio_effect(const struct audio_stream *stream,
3651 effect_handle_t effect,
3652 bool enable)
3653{
3654 struct stream_in *in = (struct stream_in *)stream;
3655 struct audio_device *adev = in->dev;
3656 int status = 0;
3657 effect_descriptor_t desc;
3658#ifdef PREPROCESSING_ENABLED
3659 int i;
3660#endif
3661 status = (*effect)->get_descriptor(effect, &desc);
3662 if (status != 0)
3663 return status;
3664
3665 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3666
3667 pthread_mutex_lock(&adev->lock_inputs);
3668 lock_input_stream(in);
3669 pthread_mutex_lock(&in->dev->lock);
3670#ifndef PREPROCESSING_ENABLED
3671 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3672 in->enable_aec != enable &&
3673 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3674 in->enable_aec = enable;
3675 if (!in->standby)
3676 select_devices(in->dev, in->usecase);
3677 }
3678#else
3679 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3680 status = -ENOSYS;
3681 goto exit;
3682 }
3683 if ( enable == true ) {
3684 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3685 /* add the supported channel of the effect in the channel_configs */
3686 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3687 in->num_preprocessors ++;
3688 /* check compatibility between main channel supported and possible auxiliary channels */
3689 in_update_aux_channels(in, effect);//wesley crash
3690 in->aux_channels_changed = true;
3691 } else {
3692 /* if ( enable == false ) */
3693 if (in->num_preprocessors <= 0) {
3694 status = -ENOSYS;
3695 goto exit;
3696 }
3697 status = -EINVAL;
3698 for (i=0; i < in->num_preprocessors; i++) {
3699 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3700 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3701 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3702 in->preprocessors[i - 1].num_channel_configs =
3703 in->preprocessors[i].num_channel_configs;
3704 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3705 continue;
3706 }
3707 if ( in->preprocessors[i].effect_itfe == effect ) {
3708 ALOGV("add_remove_audio_effect found fx at index %d", i);
3709 free(in->preprocessors[i].channel_configs);
3710 status = 0;
3711 }
3712 }
3713 if (status != 0)
3714 goto exit;
3715 in->num_preprocessors--;
3716 /* if we remove one effect, at least the last proproc should be reset */
3717 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3718 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3719 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3720 in->aux_channels_changed = false;
3721 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3722 }
3723 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3724
3725 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3726 in->enable_aec = enable;
3727 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3728 if (!in->standby) {
3729 select_devices(in->dev, in->usecase);
3730 do_in_standby_l(in);
3731 }
3732 if (in->enable_aec == true) {
3733 in_configure_reverse(in);
3734 }
3735 }
3736exit:
3737#endif
3738 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3739 pthread_mutex_unlock(&in->dev->lock);
3740 pthread_mutex_unlock(&in->lock);
3741 pthread_mutex_unlock(&adev->lock_inputs);
3742 return status;
3743}
3744
3745static int in_add_audio_effect(const struct audio_stream *stream,
3746 effect_handle_t effect)
3747{
3748 ALOGV("%s: effect %p", __func__, effect);
3749 return add_remove_audio_effect(stream, effect, true);
3750}
3751
3752static int in_remove_audio_effect(const struct audio_stream *stream,
3753 effect_handle_t effect)
3754{
3755 ALOGV("%s: effect %p", __func__, effect);
3756 return add_remove_audio_effect(stream, effect, false);
3757}
3758
3759static int adev_open_output_stream(struct audio_hw_device *dev,
3760 audio_io_handle_t handle,
3761 audio_devices_t devices,
3762 audio_output_flags_t flags,
3763 struct audio_config *config,
3764 struct audio_stream_out **stream_out,
3765 const char *address __unused)
3766{
3767 struct audio_device *adev = (struct audio_device *)dev;
3768 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003769 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003770 struct pcm_device_profile *pcm_profile;
3771
3772 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3773 __func__, config->sample_rate, config->channel_mask, devices, flags);
3774 *stream_out = NULL;
3775 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003776 if (out == NULL) {
3777 ret = -ENOMEM;
3778 goto error_config;
3779 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003780
3781 if (devices == AUDIO_DEVICE_NONE)
3782 devices = AUDIO_DEVICE_OUT_SPEAKER;
3783
3784 out->flags = flags;
3785 out->devices = devices;
3786 out->dev = adev;
3787 out->format = config->format;
3788 out->sample_rate = config->sample_rate;
3789 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3790 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3791 out->handle = handle;
3792
3793 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3794 if (pcm_profile == NULL) {
3795 ret = -EINVAL;
3796 goto error_open;
3797 }
3798 out->config = pcm_profile->config;
3799
3800 /* Init use case and pcm_config */
3801 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3802 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3803 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3804 ALOGE("%s: Unsupported Offload information", __func__);
3805 ret = -EINVAL;
3806 goto error_open;
3807 }
3808 if (!is_supported_format(config->offload_info.format)) {
3809 ALOGE("%s: Unsupported audio format", __func__);
3810 ret = -EINVAL;
3811 goto error_open;
3812 }
3813
3814 out->compr_config.codec = (struct snd_codec *)
3815 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003816 if (out->compr_config.codec == NULL) {
3817 ret = -ENOMEM;
3818 goto error_open;
3819 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003820
3821 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3822 if (config->offload_info.channel_mask)
3823 out->channel_mask = config->offload_info.channel_mask;
3824 else if (config->channel_mask)
3825 out->channel_mask = config->channel_mask;
3826 out->format = config->offload_info.format;
3827 out->sample_rate = config->offload_info.sample_rate;
3828
3829 out->stream.set_callback = out_set_callback;
3830 out->stream.pause = out_pause;
3831 out->stream.resume = out_resume;
3832 out->stream.drain = out_drain;
3833 out->stream.flush = out_flush;
3834
3835 out->compr_config.codec->id =
3836 get_snd_codec_id(config->offload_info.format);
3837 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3838 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3839 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3840 out->compr_config.codec->bit_rate =
3841 config->offload_info.bit_rate;
3842 out->compr_config.codec->ch_in =
3843 audio_channel_count_from_out_mask(config->channel_mask);
3844 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3845
3846 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3847 out->non_blocking = 1;
3848
3849 out->send_new_metadata = 1;
3850 create_offload_callback_thread(out);
3851 out->offload_state = OFFLOAD_STATE_IDLE;
3852
3853 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3854 __func__, config->offload_info.version,
3855 config->offload_info.bit_rate);
3856 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3857 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003858 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003859 out->sample_rate = out->config.rate;
3860 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3861 } else {
3862 out->usecase = USECASE_AUDIO_PLAYBACK;
3863 out->sample_rate = out->config.rate;
3864 }
3865
3866 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3867 if (adev->primary_output == NULL)
3868 adev->primary_output = out;
3869 else {
3870 ALOGE("%s: Primary output is already opened", __func__);
3871 ret = -EEXIST;
3872 goto error_open;
3873 }
3874 }
3875
3876 /* Check if this usecase is already existing */
3877 pthread_mutex_lock(&adev->lock);
3878 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3879 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3880 pthread_mutex_unlock(&adev->lock);
3881 ret = -EEXIST;
3882 goto error_open;
3883 }
3884 pthread_mutex_unlock(&adev->lock);
3885
3886 out->stream.common.get_sample_rate = out_get_sample_rate;
3887 out->stream.common.set_sample_rate = out_set_sample_rate;
3888 out->stream.common.get_buffer_size = out_get_buffer_size;
3889 out->stream.common.get_channels = out_get_channels;
3890 out->stream.common.get_format = out_get_format;
3891 out->stream.common.set_format = out_set_format;
3892 out->stream.common.standby = out_standby;
3893 out->stream.common.dump = out_dump;
3894 out->stream.common.set_parameters = out_set_parameters;
3895 out->stream.common.get_parameters = out_get_parameters;
3896 out->stream.common.add_audio_effect = out_add_audio_effect;
3897 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3898 out->stream.get_latency = out_get_latency;
3899 out->stream.set_volume = out_set_volume;
3900 out->stream.write = out_write;
3901 out->stream.get_render_position = out_get_render_position;
3902 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3903 out->stream.get_presentation_position = out_get_presentation_position;
3904
3905 out->standby = 1;
3906 /* out->muted = false; by calloc() */
3907 /* out->written = 0; by calloc() */
3908
3909 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3910 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3911 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3912
3913 config->format = out->stream.common.get_format(&out->stream.common);
3914 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3915 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3916
3917 out->is_fastmixer_affinity_set = false;
3918
3919 *stream_out = &out->stream;
3920 ALOGV("%s: exit", __func__);
3921 return 0;
3922
3923error_open:
3924 free(out);
3925 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003926error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003927 ALOGV("%s: exit: ret %d", __func__, ret);
3928 return ret;
3929}
3930
3931static void adev_close_output_stream(struct audio_hw_device *dev,
3932 struct audio_stream_out *stream)
3933{
3934 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003935 (void)dev;
3936
3937 ALOGV("%s: enter", __func__);
3938 out_standby(&stream->common);
3939 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3940 destroy_offload_callback_thread(out);
3941
3942 if (out->compr_config.codec != NULL)
3943 free(out->compr_config.codec);
3944 }
3945 pthread_cond_destroy(&out->cond);
3946 pthread_mutex_destroy(&out->lock);
3947 free(stream);
3948 ALOGV("%s: exit", __func__);
3949}
3950
3951static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3952{
3953 struct audio_device *adev = (struct audio_device *)dev;
3954 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003955 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003956#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003957 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003958#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003959 int ret;
3960
3961 ALOGV("%s: enter: %s", __func__, kvpairs);
3962
3963 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003964
Andreas Schneider05bc1882017-02-09 14:03:11 +01003965 /******************************************************
3966 *** BT SCO
3967 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003968 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3969 if (ret >= 0) {
3970 /* When set to false, HAL should disable EC and NS
3971 * But it is currently not supported.
3972 */
3973 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003974 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003975 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003976 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003977 }
3978
Andreas Schneider05bc1882017-02-09 14:03:11 +01003979 ret = str_parms_get_str(parms,
3980 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3981 value,
3982 sizeof(value));
3983 if (ret >= 0) {
3984 /* TODO: Add support in voice calls */
3985 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3986 adev->voice.bluetooth_wb = true;
3987 ALOGI("%s: Implement support for BT SCO wideband calls!!!",
3988 __func__);
3989 } else {
3990 adev->voice.bluetooth_wb = false;
3991 }
3992 }
3993
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003994 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3995 if (ret >= 0) {
3996 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3997 adev->screen_off = false;
3998 else
3999 adev->screen_off = true;
4000 }
4001
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004002#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004003 ret = str_parms_get_int(parms, "rotation", &val);
4004 if (ret >= 0) {
4005 bool reverse_speakers = false;
4006 switch(val) {
4007 /* FIXME: note that the code below assumes that the speakers are in the correct placement
4008 relative to the user when the device is rotated 90deg from its default rotation. This
4009 assumption is device-specific, not platform-specific like this code. */
4010 case 270:
4011 reverse_speakers = true;
4012 break;
4013 case 0:
4014 case 90:
4015 case 180:
4016 break;
4017 default:
4018 ALOGE("%s: unexpected rotation of %d", __func__, val);
4019 }
4020 pthread_mutex_lock(&adev->lock);
4021 if (adev->speaker_lr_swap != reverse_speakers) {
4022 adev->speaker_lr_swap = reverse_speakers;
4023 /* only update the selected device if there is active pcm playback */
4024 struct audio_usecase *usecase;
4025 struct listnode *node;
4026 list_for_each(node, &adev->usecase_list) {
4027 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
4028 if (usecase->type == PCM_PLAYBACK) {
4029 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004030 break;
4031 }
4032 }
4033 }
4034 pthread_mutex_unlock(&adev->lock);
4035 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004036#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004037
4038 str_parms_destroy(parms);
4039
4040 if (ret > 0)
4041 ret = 0;
4042
4043 ALOGV("%s: exit with code(%d)", __func__, ret);
4044 return ret;
4045}
4046
4047static char* adev_get_parameters(const struct audio_hw_device *dev,
4048 const char *keys)
4049{
4050 (void)dev;
4051 (void)keys;
4052
4053 return strdup("");
4054}
4055
4056static int adev_init_check(const struct audio_hw_device *dev)
4057{
4058 (void)dev;
4059
4060 return 0;
4061}
4062
4063static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4064{
4065 int ret = 0;
4066 struct audio_device *adev = (struct audio_device *)dev;
4067 pthread_mutex_lock(&adev->lock);
4068 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004069 adev->voice.volume = volume;
4070 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004071 pthread_mutex_unlock(&adev->lock);
4072 return ret;
4073}
4074
4075static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
4076{
4077 (void)dev;
4078 (void)volume;
4079
4080 return -ENOSYS;
4081}
4082
4083static int adev_get_master_volume(struct audio_hw_device *dev,
4084 float *volume)
4085{
4086 (void)dev;
4087 (void)volume;
4088
4089 return -ENOSYS;
4090}
4091
4092static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
4093{
4094 (void)dev;
4095 (void)muted;
4096
4097 return -ENOSYS;
4098}
4099
4100static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
4101{
4102 (void)dev;
4103 (void)muted;
4104
4105 return -ENOSYS;
4106}
4107
4108static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4109{
4110 struct audio_device *adev = (struct audio_device *)dev;
4111
4112 pthread_mutex_lock(&adev->lock);
4113 if (adev->mode != mode) {
4114 ALOGI("%s mode = %d", __func__, mode);
4115 adev->mode = mode;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004116 }
4117 pthread_mutex_unlock(&adev->lock);
4118 return 0;
4119}
4120
4121static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4122{
4123 struct audio_device *adev = (struct audio_device *)dev;
4124 int err = 0;
4125
4126 pthread_mutex_lock(&adev->lock);
4127 adev->mic_mute = state;
4128
4129 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004130 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004131 }
4132
4133 pthread_mutex_unlock(&adev->lock);
4134 return err;
4135}
4136
4137static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4138{
4139 struct audio_device *adev = (struct audio_device *)dev;
4140
4141 *state = adev->mic_mute;
4142
4143 return 0;
4144}
4145
4146static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4147 const struct audio_config *config)
4148{
4149 (void)dev;
4150
4151 /* NOTE: we default to built in mic which may cause a mismatch between what we
4152 * report here and the actual buffer size
4153 */
4154 return get_input_buffer_size(config->sample_rate,
4155 config->format,
4156 audio_channel_count_from_in_mask(config->channel_mask),
4157 PCM_CAPTURE /* usecase_type */,
4158 AUDIO_DEVICE_IN_BUILTIN_MIC);
4159}
4160
4161static int adev_open_input_stream(struct audio_hw_device *dev,
4162 audio_io_handle_t handle __unused,
4163 audio_devices_t devices,
4164 struct audio_config *config,
4165 struct audio_stream_in **stream_in,
4166 audio_input_flags_t flags,
4167 const char *address __unused,
4168 audio_source_t source)
4169{
4170 struct audio_device *adev = (struct audio_device *)dev;
4171 struct stream_in *in;
4172 struct pcm_device_profile *pcm_profile;
4173
4174 ALOGV("%s: enter", __func__);
4175
4176 *stream_in = NULL;
4177 if (check_input_parameters(config->sample_rate, config->format,
4178 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4179 return -EINVAL;
4180
4181 usecase_type_t usecase_type = source == AUDIO_SOURCE_HOTWORD ?
4182 PCM_HOTWORD_STREAMING : flags & AUDIO_INPUT_FLAG_FAST ?
4183 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4184 pcm_profile = get_pcm_device(usecase_type, devices);
4185 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4186 // a low latency profile may not exist for that device, fall back
4187 // to regular capture. the MixerThread automatically changes
4188 // to non-fast capture based on the buffer size.
4189 flags &= ~AUDIO_INPUT_FLAG_FAST;
4190 usecase_type = PCM_CAPTURE;
4191 pcm_profile = get_pcm_device(usecase_type, devices);
4192 }
4193 if (pcm_profile == NULL)
4194 return -EINVAL;
4195
4196 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004197 if (in == NULL) {
4198 return -ENOMEM;
4199 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004200
4201 in->stream.common.get_sample_rate = in_get_sample_rate;
4202 in->stream.common.set_sample_rate = in_set_sample_rate;
4203 in->stream.common.get_buffer_size = in_get_buffer_size;
4204 in->stream.common.get_channels = in_get_channels;
4205 in->stream.common.get_format = in_get_format;
4206 in->stream.common.set_format = in_set_format;
4207 in->stream.common.standby = in_standby;
4208 in->stream.common.dump = in_dump;
4209 in->stream.common.set_parameters = in_set_parameters;
4210 in->stream.common.get_parameters = in_get_parameters;
4211 in->stream.common.add_audio_effect = in_add_audio_effect;
4212 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4213 in->stream.set_gain = in_set_gain;
4214 in->stream.read = in_read;
4215 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004216 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004217
4218 in->devices = devices;
4219 in->source = source;
4220 in->dev = adev;
4221 in->standby = 1;
4222 in->main_channels = config->channel_mask;
4223 in->requested_rate = config->sample_rate;
4224 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4225 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4226 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004227 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004228 /* HW codec is limited to default channels. No need to update with
4229 * requested channels */
4230 in->config = pcm_profile->config;
4231
4232 /* Update config params with the requested sample rate and channels */
4233 if (source == AUDIO_SOURCE_HOTWORD) {
4234 in->usecase = USECASE_AUDIO_CAPTURE_HOTWORD;
4235 } else {
4236 in->usecase = USECASE_AUDIO_CAPTURE;
4237 }
4238 in->usecase_type = usecase_type;
4239
4240 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4241 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4242
4243 in->is_fastcapture_affinity_set = false;
4244
4245 *stream_in = &in->stream;
4246 ALOGV("%s: exit", __func__);
4247 return 0;
4248}
4249
4250static void adev_close_input_stream(struct audio_hw_device *dev,
4251 struct audio_stream_in *stream)
4252{
4253 struct audio_device *adev = (struct audio_device *)dev;
4254 struct stream_in *in = (struct stream_in*)stream;
4255 ALOGV("%s", __func__);
4256
4257 /* prevent concurrent out_set_parameters, or out_write from standby */
4258 pthread_mutex_lock(&adev->lock_inputs);
4259
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004260 if (in->read_buf) {
4261 free(in->read_buf);
4262 in->read_buf = NULL;
4263 }
4264
4265 if (in->resampler) {
4266 release_resampler(in->resampler);
4267 in->resampler = NULL;
4268 }
4269
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004270#ifdef PREPROCESSING_ENABLED
4271 int i;
4272
4273 for (i=0; i<in->num_preprocessors; i++) {
4274 free(in->preprocessors[i].channel_configs);
4275 }
4276
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004277 if (in->proc_buf_in) {
4278 free(in->proc_buf_in);
4279 in->proc_buf_in = NULL;
4280 }
4281
4282 if (in->proc_buf_out) {
4283 free(in->proc_buf_out);
4284 in->proc_buf_out = NULL;
4285 }
4286
4287 if (in->ref_buf) {
4288 free(in->ref_buf);
4289 in->ref_buf = NULL;
4290 }
4291
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004292#endif
4293
4294 in_standby_l(in);
4295 free(stream);
4296
4297 pthread_mutex_unlock(&adev->lock_inputs);
4298
4299 return;
4300}
4301
4302static int adev_dump(const audio_hw_device_t *device, int fd)
4303{
4304 (void)device;
4305 (void)fd;
4306
4307 return 0;
4308}
4309
4310static int adev_close(hw_device_t *device)
4311{
4312 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004313 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004314 audio_device_ref_count--;
4315 free(adev->snd_dev_ref_cnt);
4316 free_mixer_list(adev);
4317 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004318
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004319 return 0;
4320}
4321
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004322/* This returns true if the input parameter looks at all plausible as a low latency period size,
4323 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4324 * just that it _might_ work.
4325 */
4326static bool period_size_is_plausible_for_low_latency(int period_size)
4327{
4328 switch (period_size) {
4329 case 64:
4330 case 96:
4331 case 128:
4332 case 192:
4333 case 256:
4334 return true;
4335 default:
4336 return false;
4337 }
4338}
4339
4340static int adev_open(const hw_module_t *module, const char *name,
4341 hw_device_t **device)
4342{
4343 struct audio_device *adev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004344
4345 ALOGV("%s: enter", __func__);
4346 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4347
Andreas Schneider56204f62017-01-31 08:17:32 +01004348 *device = NULL;
4349
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004350 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004351 if (adev == NULL) {
4352 return -ENOMEM;
4353 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004354
4355 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4356 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4357 adev->device.common.module = (struct hw_module_t *)module;
4358 adev->device.common.close = adev_close;
4359
4360 adev->device.init_check = adev_init_check;
4361 adev->device.set_voice_volume = adev_set_voice_volume;
4362 adev->device.set_master_volume = adev_set_master_volume;
4363 adev->device.get_master_volume = adev_get_master_volume;
4364 adev->device.set_master_mute = adev_set_master_mute;
4365 adev->device.get_master_mute = adev_get_master_mute;
4366 adev->device.set_mode = adev_set_mode;
4367 adev->device.set_mic_mute = adev_set_mic_mute;
4368 adev->device.get_mic_mute = adev_get_mic_mute;
4369 adev->device.set_parameters = adev_set_parameters;
4370 adev->device.get_parameters = adev_get_parameters;
4371 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4372 adev->device.open_output_stream = adev_open_output_stream;
4373 adev->device.close_output_stream = adev_close_output_stream;
4374 adev->device.open_input_stream = adev_open_input_stream;
4375 adev->device.close_input_stream = adev_close_input_stream;
4376 adev->device.dump = adev_dump;
4377
4378 /* Set the default route before the PCM stream is opened */
4379 adev->mode = AUDIO_MODE_NORMAL;
4380 adev->active_input = NULL;
4381 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004382
4383 adev->voice.volume = 1.0f;
4384 adev->voice.bluetooth_nrec = true;
4385 adev->voice.in_call = false;
4386
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004387 /* adev->cur_hdmi_channels = 0; by calloc() */
4388 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004389 if (adev->snd_dev_ref_cnt == NULL) {
4390 free(adev);
4391 return -ENOMEM;
4392 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004393
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004394 adev->ns_in_voice_rec = false;
4395
4396 list_init(&adev->usecase_list);
4397
4398 if (mixer_init(adev) != 0) {
4399 free(adev->snd_dev_ref_cnt);
4400 free(adev);
4401 ALOGE("%s: Failed to init, aborting.", __func__);
4402 *device = NULL;
4403 return -EINVAL;
4404 }
4405
4406 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4407 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4408 if (adev->offload_fx_lib == NULL) {
4409 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4410 } else {
4411 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4412 adev->offload_fx_start_output =
4413 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4414 "visualizer_hal_start_output");
4415 adev->offload_fx_stop_output =
4416 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4417 "visualizer_hal_stop_output");
4418 }
4419 }
4420
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004421 if (access(SOUND_TRIGGER_HAL_LIBRARY_PATH, R_OK) == 0) {
4422 adev->sound_trigger_lib = dlopen(SOUND_TRIGGER_HAL_LIBRARY_PATH, RTLD_NOW);
4423 if (adev->sound_trigger_lib == NULL) {
4424 ALOGE("%s: DLOPEN failed for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4425 } else {
4426 ALOGV("%s: DLOPEN successful for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4427 adev->sound_trigger_open_for_streaming =
4428 (int (*)(void))dlsym(adev->sound_trigger_lib,
4429 "sound_trigger_open_for_streaming");
4430 adev->sound_trigger_read_samples =
4431 (size_t (*)(int, void *, size_t))dlsym(adev->sound_trigger_lib,
4432 "sound_trigger_read_samples");
4433 adev->sound_trigger_close_for_streaming =
4434 (int (*)(int))dlsym(adev->sound_trigger_lib,
4435 "sound_trigger_close_for_streaming");
4436 if (!adev->sound_trigger_open_for_streaming ||
4437 !adev->sound_trigger_read_samples ||
4438 !adev->sound_trigger_close_for_streaming) {
4439
4440 ALOGE("%s: Error grabbing functions in %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4441 adev->sound_trigger_open_for_streaming = 0;
4442 adev->sound_trigger_read_samples = 0;
4443 adev->sound_trigger_close_for_streaming = 0;
4444 }
4445 }
4446 }
4447
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004448 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004449 if (adev->voice.session == NULL) {
4450 ALOGE("%s: Failed to initialize voice session data", __func__);
4451
4452 free(adev->snd_dev_ref_cnt);
4453 free(adev);
4454
4455 *device = NULL;
4456 return -EINVAL;
4457 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004458
4459 *device = &adev->device.common;
4460
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004461 audio_device_ref_count++;
4462
4463 char value[PROPERTY_VALUE_MAX];
4464 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4465 int trial = atoi(value);
4466 if (period_size_is_plausible_for_low_latency(trial)) {
4467
4468 pcm_device_playback.config.period_size = trial;
4469 pcm_device_playback.config.start_threshold =
4470 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4471 pcm_device_playback.config.stop_threshold =
4472 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4473
4474 pcm_device_capture_low_latency.config.period_size = trial;
4475 }
4476 }
4477
4478 ALOGV("%s: exit", __func__);
4479 return 0;
4480}
4481
4482static struct hw_module_methods_t hal_module_methods = {
4483 .open = adev_open,
4484};
4485
4486struct audio_module HAL_MODULE_INFO_SYM = {
4487 .common = {
4488 .tag = HARDWARE_MODULE_TAG,
4489 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4490 .hal_api_version = HARDWARE_HAL_API_VERSION,
4491 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004492 .name = "Samsung Audio HAL",
4493 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004494 .methods = &hal_module_methods,
4495 },
4496};