blob: f0bfff07e33c66a1cb190868bf61746e6cf97f18 [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 ||
445 (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
2711 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%d) adev->mode(%d)",
2712 __func__, out->usecase, use_case_table[out->usecase], kvpairs, out->devices, adev->mode);
2713 parms = str_parms_create_str(kvpairs);
2714 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2715 if (ret >= 0) {
2716 val = atoi(value);
2717 pthread_mutex_lock(&adev->lock_inputs);
2718 lock_output_stream(out);
2719 pthread_mutex_lock(&adev->lock);
2720#ifdef PREPROCESSING_ENABLED
2721 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2722 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2723 /* reset active input:
2724 * - to attach the echo reference
2725 * - because a change in output device may change mic settings */
2726 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2727 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2728 in = adev->active_input;
2729 }
2730 }
2731#endif
2732 if (val != 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002733 bool bt_sco_active = false;
2734
2735 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2736 bt_sco_active = true;
2737 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002738 out->devices = val;
2739
2740 if (!out->standby) {
2741 uc_info = get_usecase_from_id(adev, out->usecase);
2742 if (uc_info == NULL) {
2743 ALOGE("%s: Could not find the usecase (%d) in the list",
2744 __func__, out->usecase);
2745 } else {
2746 list_for_each(node, &out->pcm_dev_list) {
2747 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2748 if ((pcm_device->pcm_profile->devices & val) == 0)
2749 do_standby = true;
2750 val &= ~pcm_device->pcm_profile->devices;
2751 }
2752 if (val != 0)
2753 do_standby = true;
2754 }
2755 if (do_standby)
2756 do_out_standby_l(out);
2757 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002758 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2759 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002760 select_devices(adev, out->usecase);
2761 }
2762 }
2763
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002764 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002765 (out == adev->primary_output)) {
2766 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002767 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2768 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002769 (out == adev->primary_output)) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002770 /* Turn on bluetooth if needed */
2771 if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
2772 start_voice_session_bt_sco(adev->voice.session);
2773 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002774 select_devices(adev, USECASE_VOICE_CALL);
2775 }
2776 }
2777
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002778 if ((adev->mode == AUDIO_MODE_NORMAL) && adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002779 (out == adev->primary_output)) {
2780 stop_voice_call(adev);
2781 }
2782 pthread_mutex_unlock(&adev->lock);
2783 pthread_mutex_unlock(&out->lock);
2784#ifdef PREPROCESSING_ENABLED
2785 if (in) {
2786 /* The lock on adev->lock_inputs prevents input stream from being closed */
2787 lock_input_stream(in);
2788 pthread_mutex_lock(&adev->lock);
2789 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2790 do_in_standby_l(in);
2791 pthread_mutex_unlock(&adev->lock);
2792 pthread_mutex_unlock(&in->lock);
2793 }
2794#endif
2795 pthread_mutex_unlock(&adev->lock_inputs);
2796 }
2797
2798 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2799 parse_compress_metadata(out, parms);
2800 }
2801
2802 str_parms_destroy(parms);
2803
2804 if (ret > 0)
2805 ret = 0;
2806 ALOGV("%s: exit: code(%d)", __func__, ret);
2807 return ret;
2808}
2809
2810static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2811{
2812 struct stream_out *out = (struct stream_out *)stream;
2813 struct str_parms *query = str_parms_create_str(keys);
2814 char *str;
2815 char value[256];
2816 struct str_parms *reply = str_parms_create();
2817 size_t i, j;
2818 int ret;
2819 bool first = true;
2820 ALOGV("%s: enter: keys - %s", __func__, keys);
2821 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2822 if (ret >= 0) {
2823 value[0] = '\0';
2824 i = 0;
2825 while (out->supported_channel_masks[i] != 0) {
2826 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2827 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2828 if (!first) {
2829 strcat(value, "|");
2830 }
2831 strcat(value, out_channels_name_to_enum_table[j].name);
2832 first = false;
2833 break;
2834 }
2835 }
2836 i++;
2837 }
2838 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2839 str = str_parms_to_str(reply);
2840 } else {
2841 str = strdup(keys);
2842 }
2843 str_parms_destroy(query);
2844 str_parms_destroy(reply);
2845 ALOGV("%s: exit: returns - %s", __func__, str);
2846 return str;
2847}
2848
2849static uint32_t out_get_latency(const struct audio_stream_out *stream)
2850{
2851 struct stream_out *out = (struct stream_out *)stream;
2852
2853 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2854 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2855
2856 return (out->config.period_count * out->config.period_size * 1000) /
2857 (out->config.rate);
2858}
2859
2860static int out_set_volume(struct audio_stream_out *stream, float left,
2861 float right)
2862{
2863 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002864
2865 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2866 /* only take left channel into account: the API is for stereo anyway */
2867 out->muted = (left == 0.0f);
2868 return 0;
2869 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002870 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002871 }
2872
2873 return -ENOSYS;
2874}
2875
Andreas Schneider3b643832017-01-31 11:48:22 +01002876#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002877static int fast_set_affinity(pid_t tid) {
2878 cpu_set_t cpu_set;
2879 int cpu_num;
2880 const char *irq_procfs = "/proc/asound/irq_affinity";
2881 FILE *fp;
2882
2883 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2884 ALOGW("Procfs node %s not found", irq_procfs);
2885 return -1;
2886 }
2887
2888 if (fscanf(fp, "%d", &cpu_num) != 1) {
2889 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2890 fclose(fp);
2891 return -1;
2892 }
2893 fclose(fp);
2894
2895 CPU_ZERO(&cpu_set);
2896 CPU_SET(cpu_num, &cpu_set);
2897 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2898}
Andreas Schneider3b643832017-01-31 11:48:22 +01002899#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002900
2901static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2902 size_t bytes)
2903{
2904 struct stream_out *out = (struct stream_out *)stream;
2905 struct audio_device *adev = out->dev;
2906 ssize_t ret = 0;
2907 struct pcm_device *pcm_device;
2908 struct listnode *node;
2909 size_t frame_size = audio_stream_out_frame_size(stream);
2910 size_t frames_wr = 0, frames_rq = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002911#ifdef PREPROCESSING_ENABLED
2912 size_t in_frames = bytes / frame_size;
2913 size_t out_frames = in_frames;
2914 struct stream_in *in = NULL;
2915#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002916
2917 lock_output_stream(out);
2918
Andreas Schneider3b643832017-01-31 11:48:22 +01002919#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002920 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002921 pid_t tid = gettid();
2922 int err;
2923
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002924 err = fast_set_affinity(tid);
2925 if (err < 0) {
2926 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2927 }
2928 out->is_fastmixer_affinity_set = true;
2929 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002930#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002931
2932 if (out->standby) {
2933#ifdef PREPROCESSING_ENABLED
2934 pthread_mutex_unlock(&out->lock);
2935 /* Prevent input stream from being closed */
2936 pthread_mutex_lock(&adev->lock_inputs);
2937 lock_output_stream(out);
2938 if (!out->standby) {
2939 pthread_mutex_unlock(&adev->lock_inputs);
2940 goto false_alarm;
2941 }
2942#endif
2943 pthread_mutex_lock(&adev->lock);
2944 ret = start_output_stream(out);
2945 /* ToDo: If use case is compress offload should return 0 */
2946 if (ret != 0) {
2947 pthread_mutex_unlock(&adev->lock);
2948#ifdef PREPROCESSING_ENABLED
2949 pthread_mutex_unlock(&adev->lock_inputs);
2950#endif
2951 goto exit;
2952 }
2953 out->standby = false;
2954
2955#ifdef PREPROCESSING_ENABLED
2956 /* A change in output device may change the microphone selection */
2957 if (adev->active_input &&
2958 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2959 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2960 in = adev->active_input;
2961 ALOGV("%s: enter:) force_input_standby true", __func__);
2962 }
2963#endif
2964 pthread_mutex_unlock(&adev->lock);
2965#ifdef PREPROCESSING_ENABLED
2966 if (!in) {
2967 /* Leave mutex locked iff in != NULL */
2968 pthread_mutex_unlock(&adev->lock_inputs);
2969 }
2970#endif
2971 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002972#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002973false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002974#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002975
2976 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002977 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002978 return ret;
2979 } else {
2980#ifdef PREPROCESSING_ENABLED
2981 if (android_atomic_acquire_load(&adev->echo_reference_generation)
2982 != out->echo_reference_generation) {
2983 pthread_mutex_lock(&adev->lock);
2984 if (out->echo_reference != NULL) {
2985 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2986 release_echo_reference(out->echo_reference);
2987 }
2988 // note that adev->echo_reference_generation here can be different from the one
2989 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
2990 // with what has been set by get_echo_reference() or put_echo_reference()
2991 out->echo_reference_generation = adev->echo_reference_generation;
2992 out->echo_reference = adev->echo_reference;
2993 ALOGV("%s: update echo reference generation %d", __func__,
2994 out->echo_reference_generation);
2995 pthread_mutex_unlock(&adev->lock);
2996 }
2997#endif
2998
2999 if (out->muted)
3000 memset((void *)buffer, 0, bytes);
3001 list_for_each(node, &out->pcm_dev_list) {
3002 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3003 if (pcm_device->resampler) {
3004 if (bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size
3005 > pcm_device->res_byte_count) {
3006 pcm_device->res_byte_count =
3007 bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size;
3008 pcm_device->res_buffer =
3009 realloc(pcm_device->res_buffer, pcm_device->res_byte_count);
3010 ALOGV("%s: resampler res_byte_count = %zu", __func__,
3011 pcm_device->res_byte_count);
3012 }
3013 frames_rq = bytes / frame_size;
3014 frames_wr = pcm_device->res_byte_count / frame_size;
3015 ALOGVV("%s: resampler request frames = %d frame_size = %d",
3016 __func__, frames_rq, frame_size);
3017 pcm_device->resampler->resample_from_input(pcm_device->resampler,
3018 (int16_t *)buffer, &frames_rq, (int16_t *)pcm_device->res_buffer, &frames_wr);
3019 ALOGVV("%s: resampler output frames_= %d", __func__, frames_wr);
3020 }
3021 if (pcm_device->pcm) {
3022#ifdef PREPROCESSING_ENABLED
3023 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
3024 struct echo_reference_buffer b;
3025 b.raw = (void *)buffer;
3026 b.frame_count = in_frames;
3027
3028 get_playback_delay(out, out_frames, &b);
3029 out->echo_reference->write(out->echo_reference, &b);
3030 }
3031#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003032 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
3033 if (pcm_device->resampler && pcm_device->res_buffer)
3034 pcm_device->status =
3035 pcm_write(pcm_device->pcm, (void *)pcm_device->res_buffer,
3036 frames_wr * frame_size);
3037 else
3038 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
3039 if (pcm_device->status != 0)
3040 ret = pcm_device->status;
3041 }
3042 }
3043 if (ret == 0)
3044 out->written += bytes / (out->config.channels * sizeof(short));
3045 }
3046
3047exit:
3048 pthread_mutex_unlock(&out->lock);
3049
3050 if (ret != 0) {
3051 list_for_each(node, &out->pcm_dev_list) {
3052 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3053 if (pcm_device->pcm && pcm_device->status != 0)
3054 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
3055 }
3056 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003057 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3058 clock_gettime(CLOCK_MONOTONIC, &t);
3059 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3060 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
3061 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
3062 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
3063 if (sleep_time > 0) {
3064 usleep(sleep_time);
3065 } else {
3066 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
3067 sleep_time = 0;
3068 }
3069 out->last_write_time_us = now + sleep_time;
3070 // last_write_time_us is an approximation of when the (simulated) alsa
3071 // buffer is believed completely full. The usleep above waits for more space
3072 // in the buffer, but by the end of the sleep the buffer is considered
3073 // topped-off.
3074 //
3075 // On the subsequent out_write(), we measure the elapsed time spent in
3076 // the mixer. This is subtracted from the sleep estimate based on frames,
3077 // thereby accounting for drain in the alsa buffer during mixing.
3078 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003079 }
3080
3081#ifdef PREPROCESSING_ENABLED
3082 if (in) {
3083 /* The lock on adev->lock_inputs prevents input stream from being closed */
3084 lock_input_stream(in);
3085 pthread_mutex_lock(&adev->lock);
3086 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3087 do_in_standby_l(in);
3088 pthread_mutex_unlock(&adev->lock);
3089 pthread_mutex_unlock(&in->lock);
3090 /* This mutex was left locked iff in != NULL */
3091 pthread_mutex_unlock(&adev->lock_inputs);
3092 }
3093#endif
3094
3095 return bytes;
3096}
3097
3098static int out_get_render_position(const struct audio_stream_out *stream,
3099 uint32_t *dsp_frames)
3100{
3101 struct stream_out *out = (struct stream_out *)stream;
3102 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003103 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3104 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003105 } else
3106 return -EINVAL;
3107}
3108
3109static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3110{
3111 (void)stream;
3112 (void)effect;
3113 return 0;
3114}
3115
3116static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3117{
3118 (void)stream;
3119 (void)effect;
3120 return 0;
3121}
3122
3123static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3124 int64_t *timestamp)
3125{
3126 (void)stream;
3127 (void)timestamp;
3128 return -EINVAL;
3129}
3130
3131static int out_get_presentation_position(const struct audio_stream_out *stream,
3132 uint64_t *frames, struct timespec *timestamp)
3133{
3134 struct stream_out *out = (struct stream_out *)stream;
3135 int ret = -1;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003136
3137 lock_output_stream(out);
3138
3139 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003140 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003141 } else {
Andreas Schneider97fa7f12017-02-11 14:21:56 +01003142 if (out->dev->voice.in_call) {
3143 ALOGVV("%s: in_call, do not handle PCMs", __func__);
3144 ret = 0;
3145 goto done;
3146 }
3147
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003148 /* FIXME: which device to read from? */
3149 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003150 struct pcm_device *pcm_device;
3151 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003152 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003153
Andreas Schneiderd6359182017-02-08 16:58:22 +01003154 list_for_each(node, &out->pcm_dev_list) {
3155 pcm_device = node_to_item(node,
3156 struct pcm_device,
3157 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003158
Andreas Schneiderd6359182017-02-08 16:58:22 +01003159 if (pcm_device->pcm != NULL) {
3160 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3161 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3162 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3163 /* This adjustment accounts for buffering after app processor.
3164 It is based on estimated DSP latency per use case, rather than exact. */
3165 signed_frames -=
3166 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3167
3168 /* It would be unusual for this value to be negative, but check just in case ... */
3169 if (signed_frames >= 0) {
3170 *frames = signed_frames;
3171 ret = 0;
3172 goto done;
3173 }
3174 ret = -1;
3175 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003176 }
3177 }
3178 }
3179 }
3180
Andreas Schneiderd6359182017-02-08 16:58:22 +01003181done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003182 pthread_mutex_unlock(&out->lock);
3183
3184 return ret;
3185}
3186
3187static int out_set_callback(struct audio_stream_out *stream,
3188 stream_callback_t callback, void *cookie)
3189{
3190 struct stream_out *out = (struct stream_out *)stream;
3191
3192 ALOGV("%s", __func__);
3193 lock_output_stream(out);
3194 out->offload_callback = callback;
3195 out->offload_cookie = cookie;
3196 pthread_mutex_unlock(&out->lock);
3197 return 0;
3198}
3199
3200static int out_pause(struct audio_stream_out* stream)
3201{
3202 struct stream_out *out = (struct stream_out *)stream;
3203 int status = -ENOSYS;
3204 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003205 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3206 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003207 return status;
3208}
3209
3210static int out_resume(struct audio_stream_out* stream)
3211{
3212 struct stream_out *out = (struct stream_out *)stream;
3213 int status = -ENOSYS;
3214 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003215 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3216 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003217 return status;
3218}
3219
3220static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3221{
3222 struct stream_out *out = (struct stream_out *)stream;
3223 int status = -ENOSYS;
3224 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003225 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3226 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003227 return status;
3228}
3229
3230static int out_flush(struct audio_stream_out* stream)
3231{
3232 struct stream_out *out = (struct stream_out *)stream;
3233 ALOGV("%s", __func__);
3234 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003235 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003236 }
3237 return -ENOSYS;
3238}
3239
3240/** audio_stream_in implementation **/
3241static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3242{
3243 struct stream_in *in = (struct stream_in *)stream;
3244
3245 return in->requested_rate;
3246}
3247
3248static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3249{
3250 (void)stream;
3251 (void)rate;
3252 return -ENOSYS;
3253}
3254
3255static uint32_t in_get_channels(const struct audio_stream *stream)
3256{
3257 struct stream_in *in = (struct stream_in *)stream;
3258
3259 return in->main_channels;
3260}
3261
3262static audio_format_t in_get_format(const struct audio_stream *stream)
3263{
3264 (void)stream;
3265 return AUDIO_FORMAT_PCM_16_BIT;
3266}
3267
3268static int in_set_format(struct audio_stream *stream, audio_format_t format)
3269{
3270 (void)stream;
3271 (void)format;
3272
3273 return -ENOSYS;
3274}
3275
3276static size_t in_get_buffer_size(const struct audio_stream *stream)
3277{
3278 struct stream_in *in = (struct stream_in *)stream;
3279
3280 return get_input_buffer_size(in->requested_rate,
3281 in_get_format(stream),
3282 audio_channel_count_from_in_mask(in->main_channels),
3283 in->usecase_type,
3284 in->devices);
3285}
3286
3287static int in_close_pcm_devices(struct stream_in *in)
3288{
3289 struct pcm_device *pcm_device;
3290 struct listnode *node;
3291 struct audio_device *adev = in->dev;
3292
3293 list_for_each(node, &in->pcm_dev_list) {
3294 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3295 if (pcm_device) {
3296 if (pcm_device->pcm)
3297 pcm_close(pcm_device->pcm);
3298 pcm_device->pcm = NULL;
3299 if (pcm_device->sound_trigger_handle > 0)
3300 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
3301 pcm_device->sound_trigger_handle = 0;
3302 }
3303 }
3304 return 0;
3305}
3306
3307
3308/* must be called with stream and hw device mutex locked */
3309static int do_in_standby_l(struct stream_in *in)
3310{
3311 int status = 0;
3312
3313#ifdef PREPROCESSING_ENABLED
3314 struct audio_device *adev = in->dev;
3315#endif
3316 if (!in->standby) {
3317
3318 in_close_pcm_devices(in);
3319
3320#ifdef PREPROCESSING_ENABLED
3321 if (in->echo_reference != NULL) {
3322 /* stop reading from echo reference */
3323 in->echo_reference->read(in->echo_reference, NULL);
3324 put_echo_reference(adev, in->echo_reference);
3325 in->echo_reference = NULL;
3326 }
3327#ifdef HW_AEC_LOOPBACK
3328 if (in->hw_echo_reference)
3329 {
3330 if (in->hw_ref_buf) {
3331 free(in->hw_ref_buf);
3332 in->hw_ref_buf = NULL;
3333 }
3334 }
3335#endif // HW_AEC_LOOPBACK
3336#endif // PREPROCESSING_ENABLED
3337
3338 status = stop_input_stream(in);
3339
3340 if (in->read_buf) {
3341 free(in->read_buf);
3342 in->read_buf = NULL;
3343 }
3344
3345 in->standby = 1;
3346 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003347
3348 in->last_read_time_us = 0;
3349
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003350 return 0;
3351}
3352
3353// called with adev->lock_inputs locked
3354static int in_standby_l(struct stream_in *in)
3355{
3356 struct audio_device *adev = in->dev;
3357 int status = 0;
3358 lock_input_stream(in);
3359 if (!in->standby) {
3360 pthread_mutex_lock(&adev->lock);
3361 status = do_in_standby_l(in);
3362 pthread_mutex_unlock(&adev->lock);
3363 }
3364 pthread_mutex_unlock(&in->lock);
3365 return status;
3366}
3367
3368static int in_standby(struct audio_stream *stream)
3369{
3370 struct stream_in *in = (struct stream_in *)stream;
3371 struct audio_device *adev = in->dev;
3372 int status;
3373 ALOGV("%s: enter", __func__);
3374 pthread_mutex_lock(&adev->lock_inputs);
3375 status = in_standby_l(in);
3376 pthread_mutex_unlock(&adev->lock_inputs);
3377 ALOGV("%s: exit: status(%d)", __func__, status);
3378 return status;
3379}
3380
3381static int in_dump(const struct audio_stream *stream, int fd)
3382{
3383 (void)stream;
3384 (void)fd;
3385
3386 return 0;
3387}
3388
3389static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3390{
3391 struct stream_in *in = (struct stream_in *)stream;
3392 struct audio_device *adev = in->dev;
3393 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003394 char value[32];
3395 int ret, val = 0;
3396 struct audio_usecase *uc_info;
3397 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003398 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003399
3400 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3401 parms = str_parms_create_str(kvpairs);
3402
3403 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3404
3405 pthread_mutex_lock(&adev->lock_inputs);
3406 lock_input_stream(in);
3407 pthread_mutex_lock(&adev->lock);
3408 if (ret >= 0) {
3409 val = atoi(value);
3410 /* no audio source uses val == 0 */
3411 if (((int)in->source != val) && (val != 0)) {
3412 in->source = val;
3413 }
3414 }
3415
3416 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3417 if (ret >= 0) {
3418 val = atoi(value);
3419 if (((int)in->devices != val) && (val != 0)) {
3420 in->devices = val;
3421 /* If recording is in progress, change the tx device to new device */
3422 if (!in->standby) {
3423 uc_info = get_usecase_from_id(adev, in->usecase);
3424 if (uc_info == NULL) {
3425 ALOGE("%s: Could not find the usecase (%d) in the list",
3426 __func__, in->usecase);
3427 } else {
3428 if (list_empty(&in->pcm_dev_list))
3429 ALOGE("%s: pcm device list empty", __func__);
3430 else {
3431 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3432 struct pcm_device, stream_list_node);
3433 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3434 do_standby = true;
3435 }
3436 }
3437 }
3438 if (do_standby) {
3439 ret = do_in_standby_l(in);
3440 } else
3441 ret = select_devices(adev, in->usecase);
3442 }
3443 }
3444 }
3445 pthread_mutex_unlock(&adev->lock);
3446 pthread_mutex_unlock(&in->lock);
3447 pthread_mutex_unlock(&adev->lock_inputs);
3448 str_parms_destroy(parms);
3449
3450 if (ret > 0)
3451 ret = 0;
3452
3453 ALOGV("%s: exit: status(%d)", __func__, ret);
3454 return ret;
3455}
3456
3457static char* in_get_parameters(const struct audio_stream *stream,
3458 const char *keys)
3459{
3460 (void)stream;
3461 (void)keys;
3462
3463 return strdup("");
3464}
3465
3466static int in_set_gain(struct audio_stream_in *stream, float gain)
3467{
3468 (void)stream;
3469 (void)gain;
3470
3471 return 0;
3472}
3473
3474static ssize_t read_bytes_from_dsp(struct stream_in *in, void* buffer,
3475 size_t bytes)
3476{
3477 struct pcm_device *pcm_device;
3478 struct audio_device *adev = in->dev;
3479
3480 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3481 struct pcm_device, stream_list_node);
3482
3483 if (pcm_device->sound_trigger_handle > 0)
3484 return adev->sound_trigger_read_samples(pcm_device->sound_trigger_handle, buffer, bytes);
3485 else
3486 return 0;
3487}
3488
3489static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3490 size_t bytes)
3491{
3492 struct stream_in *in = (struct stream_in *)stream;
3493 struct audio_device *adev = in->dev;
3494 ssize_t frames = -1;
3495 int ret = -1;
3496 int read_and_process_successful = false;
3497
3498 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003499
3500 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3501 lock_input_stream(in);
3502
Andreas Schneider3b643832017-01-31 11:48:22 +01003503#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003504 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003505 pid_t tid = gettid();
3506 int err;
3507
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003508 err = fast_set_affinity(tid);
3509 if (err < 0) {
3510 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3511 }
3512 in->is_fastcapture_affinity_set = true;
3513 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003514#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003515
3516 if (in->standby) {
3517 pthread_mutex_unlock(&in->lock);
3518 pthread_mutex_lock(&adev->lock_inputs);
3519 lock_input_stream(in);
3520 if (!in->standby) {
3521 pthread_mutex_unlock(&adev->lock_inputs);
3522 goto false_alarm;
3523 }
3524 pthread_mutex_lock(&adev->lock);
3525 ret = start_input_stream(in);
3526 pthread_mutex_unlock(&adev->lock);
3527 pthread_mutex_unlock(&adev->lock_inputs);
3528 if (ret != 0) {
3529 goto exit;
3530 }
3531 in->standby = 0;
3532 }
3533false_alarm:
3534
3535 if (!list_empty(&in->pcm_dev_list)) {
3536 if (in->usecase == USECASE_AUDIO_CAPTURE_HOTWORD) {
3537 bytes = read_bytes_from_dsp(in, buffer, bytes);
3538 if (bytes > 0)
3539 read_and_process_successful = true;
3540 } else {
3541 /*
3542 * Read PCM and:
3543 * - resample if needed
3544 * - process if pre-processors are attached
3545 * - discard unwanted channels
3546 */
3547 frames = read_and_process_frames(in, buffer, frames_rq);
3548 if (frames >= 0)
3549 read_and_process_successful = true;
3550 }
3551 }
3552
3553 /*
3554 * Instead of writing zeroes here, we could trust the hardware
3555 * to always provide zeroes when muted.
3556 */
3557 if (read_and_process_successful == true && adev->mic_mute)
3558 memset(buffer, 0, bytes);
3559
3560exit:
3561 pthread_mutex_unlock(&in->lock);
3562
3563 if (read_and_process_successful == false) {
3564 in_standby(&in->stream.common);
3565 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003566 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3567 clock_gettime(CLOCK_MONOTONIC, &t);
3568 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3569
3570 // we do a full sleep when exiting standby.
3571 const bool standby = in->last_read_time_us == 0;
3572 const int64_t elapsed_time_since_last_read = standby ?
3573 0 : now - in->last_read_time_us;
3574 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3575 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3576 if (sleep_time > 0) {
3577 usleep(sleep_time);
3578 } else {
3579 sleep_time = 0;
3580 }
3581 in->last_read_time_us = now + sleep_time;
3582 // last_read_time_us is an approximation of when the (simulated) alsa
3583 // buffer is drained by the read, and is empty.
3584 //
3585 // On the subsequent in_read(), we measure the elapsed time spent in
3586 // the recording thread. This is subtracted from the sleep estimate based on frames,
3587 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003588 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003589 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003590
3591 if (bytes > 0) {
3592 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3593 }
3594
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003595 return bytes;
3596}
3597
3598static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3599{
3600 (void)stream;
3601
3602 return 0;
3603}
3604
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003605static int in_get_capture_position(const struct audio_stream_in *stream,
3606 int64_t *frames, int64_t *time)
3607{
3608 if (stream == NULL || frames == NULL || time == NULL) {
3609 return -EINVAL;
3610 }
3611
3612 struct stream_in *in = (struct stream_in *)stream;
3613 struct pcm_device *pcm_device;
3614 int ret = -ENOSYS;
3615
3616 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3617 struct pcm_device, stream_list_node);
3618
3619 pthread_mutex_lock(&in->lock);
3620 if (pcm_device->pcm) {
3621 struct timespec timestamp;
3622 unsigned int avail;
3623 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3624 *frames = in->frames_read + avail;
3625 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3626 ret = 0;
3627 }
3628 }
3629
3630 pthread_mutex_unlock(&in->lock);
3631 return ret;
3632}
3633
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003634static int add_remove_audio_effect(const struct audio_stream *stream,
3635 effect_handle_t effect,
3636 bool enable)
3637{
3638 struct stream_in *in = (struct stream_in *)stream;
3639 struct audio_device *adev = in->dev;
3640 int status = 0;
3641 effect_descriptor_t desc;
3642#ifdef PREPROCESSING_ENABLED
3643 int i;
3644#endif
3645 status = (*effect)->get_descriptor(effect, &desc);
3646 if (status != 0)
3647 return status;
3648
3649 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3650
3651 pthread_mutex_lock(&adev->lock_inputs);
3652 lock_input_stream(in);
3653 pthread_mutex_lock(&in->dev->lock);
3654#ifndef PREPROCESSING_ENABLED
3655 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3656 in->enable_aec != enable &&
3657 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3658 in->enable_aec = enable;
3659 if (!in->standby)
3660 select_devices(in->dev, in->usecase);
3661 }
3662#else
3663 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3664 status = -ENOSYS;
3665 goto exit;
3666 }
3667 if ( enable == true ) {
3668 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3669 /* add the supported channel of the effect in the channel_configs */
3670 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3671 in->num_preprocessors ++;
3672 /* check compatibility between main channel supported and possible auxiliary channels */
3673 in_update_aux_channels(in, effect);//wesley crash
3674 in->aux_channels_changed = true;
3675 } else {
3676 /* if ( enable == false ) */
3677 if (in->num_preprocessors <= 0) {
3678 status = -ENOSYS;
3679 goto exit;
3680 }
3681 status = -EINVAL;
3682 for (i=0; i < in->num_preprocessors; i++) {
3683 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3684 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3685 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3686 in->preprocessors[i - 1].num_channel_configs =
3687 in->preprocessors[i].num_channel_configs;
3688 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3689 continue;
3690 }
3691 if ( in->preprocessors[i].effect_itfe == effect ) {
3692 ALOGV("add_remove_audio_effect found fx at index %d", i);
3693 free(in->preprocessors[i].channel_configs);
3694 status = 0;
3695 }
3696 }
3697 if (status != 0)
3698 goto exit;
3699 in->num_preprocessors--;
3700 /* if we remove one effect, at least the last proproc should be reset */
3701 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3702 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3703 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3704 in->aux_channels_changed = false;
3705 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3706 }
3707 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3708
3709 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3710 in->enable_aec = enable;
3711 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3712 if (!in->standby) {
3713 select_devices(in->dev, in->usecase);
3714 do_in_standby_l(in);
3715 }
3716 if (in->enable_aec == true) {
3717 in_configure_reverse(in);
3718 }
3719 }
3720exit:
3721#endif
3722 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3723 pthread_mutex_unlock(&in->dev->lock);
3724 pthread_mutex_unlock(&in->lock);
3725 pthread_mutex_unlock(&adev->lock_inputs);
3726 return status;
3727}
3728
3729static int in_add_audio_effect(const struct audio_stream *stream,
3730 effect_handle_t effect)
3731{
3732 ALOGV("%s: effect %p", __func__, effect);
3733 return add_remove_audio_effect(stream, effect, true);
3734}
3735
3736static int in_remove_audio_effect(const struct audio_stream *stream,
3737 effect_handle_t effect)
3738{
3739 ALOGV("%s: effect %p", __func__, effect);
3740 return add_remove_audio_effect(stream, effect, false);
3741}
3742
3743static int adev_open_output_stream(struct audio_hw_device *dev,
3744 audio_io_handle_t handle,
3745 audio_devices_t devices,
3746 audio_output_flags_t flags,
3747 struct audio_config *config,
3748 struct audio_stream_out **stream_out,
3749 const char *address __unused)
3750{
3751 struct audio_device *adev = (struct audio_device *)dev;
3752 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003753 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003754 struct pcm_device_profile *pcm_profile;
3755
3756 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3757 __func__, config->sample_rate, config->channel_mask, devices, flags);
3758 *stream_out = NULL;
3759 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003760 if (out == NULL) {
3761 ret = -ENOMEM;
3762 goto error_config;
3763 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003764
3765 if (devices == AUDIO_DEVICE_NONE)
3766 devices = AUDIO_DEVICE_OUT_SPEAKER;
3767
3768 out->flags = flags;
3769 out->devices = devices;
3770 out->dev = adev;
3771 out->format = config->format;
3772 out->sample_rate = config->sample_rate;
3773 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3774 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3775 out->handle = handle;
3776
3777 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3778 if (pcm_profile == NULL) {
3779 ret = -EINVAL;
3780 goto error_open;
3781 }
3782 out->config = pcm_profile->config;
3783
3784 /* Init use case and pcm_config */
3785 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3786 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3787 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3788 ALOGE("%s: Unsupported Offload information", __func__);
3789 ret = -EINVAL;
3790 goto error_open;
3791 }
3792 if (!is_supported_format(config->offload_info.format)) {
3793 ALOGE("%s: Unsupported audio format", __func__);
3794 ret = -EINVAL;
3795 goto error_open;
3796 }
3797
3798 out->compr_config.codec = (struct snd_codec *)
3799 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003800 if (out->compr_config.codec == NULL) {
3801 ret = -ENOMEM;
3802 goto error_open;
3803 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003804
3805 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3806 if (config->offload_info.channel_mask)
3807 out->channel_mask = config->offload_info.channel_mask;
3808 else if (config->channel_mask)
3809 out->channel_mask = config->channel_mask;
3810 out->format = config->offload_info.format;
3811 out->sample_rate = config->offload_info.sample_rate;
3812
3813 out->stream.set_callback = out_set_callback;
3814 out->stream.pause = out_pause;
3815 out->stream.resume = out_resume;
3816 out->stream.drain = out_drain;
3817 out->stream.flush = out_flush;
3818
3819 out->compr_config.codec->id =
3820 get_snd_codec_id(config->offload_info.format);
3821 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3822 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3823 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3824 out->compr_config.codec->bit_rate =
3825 config->offload_info.bit_rate;
3826 out->compr_config.codec->ch_in =
3827 audio_channel_count_from_out_mask(config->channel_mask);
3828 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3829
3830 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3831 out->non_blocking = 1;
3832
3833 out->send_new_metadata = 1;
3834 create_offload_callback_thread(out);
3835 out->offload_state = OFFLOAD_STATE_IDLE;
3836
3837 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3838 __func__, config->offload_info.version,
3839 config->offload_info.bit_rate);
3840 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3841 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003842 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003843 out->sample_rate = out->config.rate;
3844 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3845 } else {
3846 out->usecase = USECASE_AUDIO_PLAYBACK;
3847 out->sample_rate = out->config.rate;
3848 }
3849
3850 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3851 if (adev->primary_output == NULL)
3852 adev->primary_output = out;
3853 else {
3854 ALOGE("%s: Primary output is already opened", __func__);
3855 ret = -EEXIST;
3856 goto error_open;
3857 }
3858 }
3859
3860 /* Check if this usecase is already existing */
3861 pthread_mutex_lock(&adev->lock);
3862 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3863 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3864 pthread_mutex_unlock(&adev->lock);
3865 ret = -EEXIST;
3866 goto error_open;
3867 }
3868 pthread_mutex_unlock(&adev->lock);
3869
3870 out->stream.common.get_sample_rate = out_get_sample_rate;
3871 out->stream.common.set_sample_rate = out_set_sample_rate;
3872 out->stream.common.get_buffer_size = out_get_buffer_size;
3873 out->stream.common.get_channels = out_get_channels;
3874 out->stream.common.get_format = out_get_format;
3875 out->stream.common.set_format = out_set_format;
3876 out->stream.common.standby = out_standby;
3877 out->stream.common.dump = out_dump;
3878 out->stream.common.set_parameters = out_set_parameters;
3879 out->stream.common.get_parameters = out_get_parameters;
3880 out->stream.common.add_audio_effect = out_add_audio_effect;
3881 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3882 out->stream.get_latency = out_get_latency;
3883 out->stream.set_volume = out_set_volume;
3884 out->stream.write = out_write;
3885 out->stream.get_render_position = out_get_render_position;
3886 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3887 out->stream.get_presentation_position = out_get_presentation_position;
3888
3889 out->standby = 1;
3890 /* out->muted = false; by calloc() */
3891 /* out->written = 0; by calloc() */
3892
3893 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3894 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3895 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3896
3897 config->format = out->stream.common.get_format(&out->stream.common);
3898 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3899 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3900
3901 out->is_fastmixer_affinity_set = false;
3902
3903 *stream_out = &out->stream;
3904 ALOGV("%s: exit", __func__);
3905 return 0;
3906
3907error_open:
3908 free(out);
3909 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003910error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003911 ALOGV("%s: exit: ret %d", __func__, ret);
3912 return ret;
3913}
3914
3915static void adev_close_output_stream(struct audio_hw_device *dev,
3916 struct audio_stream_out *stream)
3917{
3918 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003919 (void)dev;
3920
3921 ALOGV("%s: enter", __func__);
3922 out_standby(&stream->common);
3923 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3924 destroy_offload_callback_thread(out);
3925
3926 if (out->compr_config.codec != NULL)
3927 free(out->compr_config.codec);
3928 }
3929 pthread_cond_destroy(&out->cond);
3930 pthread_mutex_destroy(&out->lock);
3931 free(stream);
3932 ALOGV("%s: exit", __func__);
3933}
3934
3935static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3936{
3937 struct audio_device *adev = (struct audio_device *)dev;
3938 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003939 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003940#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003941 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003942#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003943 int ret;
3944
3945 ALOGV("%s: enter: %s", __func__, kvpairs);
3946
3947 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003948
Andreas Schneider05bc1882017-02-09 14:03:11 +01003949 /******************************************************
3950 *** BT SCO
3951 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003952 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3953 if (ret >= 0) {
3954 /* When set to false, HAL should disable EC and NS
3955 * But it is currently not supported.
3956 */
3957 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003958 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003959 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003960 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003961 }
3962
Andreas Schneider05bc1882017-02-09 14:03:11 +01003963 ret = str_parms_get_str(parms,
3964 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3965 value,
3966 sizeof(value));
3967 if (ret >= 0) {
3968 /* TODO: Add support in voice calls */
3969 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3970 adev->voice.bluetooth_wb = true;
3971 ALOGI("%s: Implement support for BT SCO wideband calls!!!",
3972 __func__);
3973 } else {
3974 adev->voice.bluetooth_wb = false;
3975 }
3976 }
3977
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003978 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3979 if (ret >= 0) {
3980 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3981 adev->screen_off = false;
3982 else
3983 adev->screen_off = true;
3984 }
3985
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003986#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003987 ret = str_parms_get_int(parms, "rotation", &val);
3988 if (ret >= 0) {
3989 bool reverse_speakers = false;
3990 switch(val) {
3991 /* FIXME: note that the code below assumes that the speakers are in the correct placement
3992 relative to the user when the device is rotated 90deg from its default rotation. This
3993 assumption is device-specific, not platform-specific like this code. */
3994 case 270:
3995 reverse_speakers = true;
3996 break;
3997 case 0:
3998 case 90:
3999 case 180:
4000 break;
4001 default:
4002 ALOGE("%s: unexpected rotation of %d", __func__, val);
4003 }
4004 pthread_mutex_lock(&adev->lock);
4005 if (adev->speaker_lr_swap != reverse_speakers) {
4006 adev->speaker_lr_swap = reverse_speakers;
4007 /* only update the selected device if there is active pcm playback */
4008 struct audio_usecase *usecase;
4009 struct listnode *node;
4010 list_for_each(node, &adev->usecase_list) {
4011 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
4012 if (usecase->type == PCM_PLAYBACK) {
4013 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004014 break;
4015 }
4016 }
4017 }
4018 pthread_mutex_unlock(&adev->lock);
4019 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004020#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004021
4022 str_parms_destroy(parms);
4023
4024 if (ret > 0)
4025 ret = 0;
4026
4027 ALOGV("%s: exit with code(%d)", __func__, ret);
4028 return ret;
4029}
4030
4031static char* adev_get_parameters(const struct audio_hw_device *dev,
4032 const char *keys)
4033{
4034 (void)dev;
4035 (void)keys;
4036
4037 return strdup("");
4038}
4039
4040static int adev_init_check(const struct audio_hw_device *dev)
4041{
4042 (void)dev;
4043
4044 return 0;
4045}
4046
4047static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4048{
4049 int ret = 0;
4050 struct audio_device *adev = (struct audio_device *)dev;
4051 pthread_mutex_lock(&adev->lock);
4052 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004053 adev->voice.volume = volume;
4054 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004055 pthread_mutex_unlock(&adev->lock);
4056 return ret;
4057}
4058
4059static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
4060{
4061 (void)dev;
4062 (void)volume;
4063
4064 return -ENOSYS;
4065}
4066
4067static int adev_get_master_volume(struct audio_hw_device *dev,
4068 float *volume)
4069{
4070 (void)dev;
4071 (void)volume;
4072
4073 return -ENOSYS;
4074}
4075
4076static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
4077{
4078 (void)dev;
4079 (void)muted;
4080
4081 return -ENOSYS;
4082}
4083
4084static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
4085{
4086 (void)dev;
4087 (void)muted;
4088
4089 return -ENOSYS;
4090}
4091
4092static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4093{
4094 struct audio_device *adev = (struct audio_device *)dev;
4095
4096 pthread_mutex_lock(&adev->lock);
4097 if (adev->mode != mode) {
4098 ALOGI("%s mode = %d", __func__, mode);
4099 adev->mode = mode;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004100 }
4101 pthread_mutex_unlock(&adev->lock);
4102 return 0;
4103}
4104
4105static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4106{
4107 struct audio_device *adev = (struct audio_device *)dev;
4108 int err = 0;
4109
4110 pthread_mutex_lock(&adev->lock);
4111 adev->mic_mute = state;
4112
4113 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004114 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004115 }
4116
4117 pthread_mutex_unlock(&adev->lock);
4118 return err;
4119}
4120
4121static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4122{
4123 struct audio_device *adev = (struct audio_device *)dev;
4124
4125 *state = adev->mic_mute;
4126
4127 return 0;
4128}
4129
4130static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4131 const struct audio_config *config)
4132{
4133 (void)dev;
4134
4135 /* NOTE: we default to built in mic which may cause a mismatch between what we
4136 * report here and the actual buffer size
4137 */
4138 return get_input_buffer_size(config->sample_rate,
4139 config->format,
4140 audio_channel_count_from_in_mask(config->channel_mask),
4141 PCM_CAPTURE /* usecase_type */,
4142 AUDIO_DEVICE_IN_BUILTIN_MIC);
4143}
4144
4145static int adev_open_input_stream(struct audio_hw_device *dev,
4146 audio_io_handle_t handle __unused,
4147 audio_devices_t devices,
4148 struct audio_config *config,
4149 struct audio_stream_in **stream_in,
4150 audio_input_flags_t flags,
4151 const char *address __unused,
4152 audio_source_t source)
4153{
4154 struct audio_device *adev = (struct audio_device *)dev;
4155 struct stream_in *in;
4156 struct pcm_device_profile *pcm_profile;
4157
4158 ALOGV("%s: enter", __func__);
4159
4160 *stream_in = NULL;
4161 if (check_input_parameters(config->sample_rate, config->format,
4162 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4163 return -EINVAL;
4164
4165 usecase_type_t usecase_type = source == AUDIO_SOURCE_HOTWORD ?
4166 PCM_HOTWORD_STREAMING : flags & AUDIO_INPUT_FLAG_FAST ?
4167 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4168 pcm_profile = get_pcm_device(usecase_type, devices);
4169 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4170 // a low latency profile may not exist for that device, fall back
4171 // to regular capture. the MixerThread automatically changes
4172 // to non-fast capture based on the buffer size.
4173 flags &= ~AUDIO_INPUT_FLAG_FAST;
4174 usecase_type = PCM_CAPTURE;
4175 pcm_profile = get_pcm_device(usecase_type, devices);
4176 }
4177 if (pcm_profile == NULL)
4178 return -EINVAL;
4179
4180 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004181 if (in == NULL) {
4182 return -ENOMEM;
4183 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004184
4185 in->stream.common.get_sample_rate = in_get_sample_rate;
4186 in->stream.common.set_sample_rate = in_set_sample_rate;
4187 in->stream.common.get_buffer_size = in_get_buffer_size;
4188 in->stream.common.get_channels = in_get_channels;
4189 in->stream.common.get_format = in_get_format;
4190 in->stream.common.set_format = in_set_format;
4191 in->stream.common.standby = in_standby;
4192 in->stream.common.dump = in_dump;
4193 in->stream.common.set_parameters = in_set_parameters;
4194 in->stream.common.get_parameters = in_get_parameters;
4195 in->stream.common.add_audio_effect = in_add_audio_effect;
4196 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4197 in->stream.set_gain = in_set_gain;
4198 in->stream.read = in_read;
4199 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004200 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004201
4202 in->devices = devices;
4203 in->source = source;
4204 in->dev = adev;
4205 in->standby = 1;
4206 in->main_channels = config->channel_mask;
4207 in->requested_rate = config->sample_rate;
4208 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4209 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4210 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004211 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004212 /* HW codec is limited to default channels. No need to update with
4213 * requested channels */
4214 in->config = pcm_profile->config;
4215
4216 /* Update config params with the requested sample rate and channels */
4217 if (source == AUDIO_SOURCE_HOTWORD) {
4218 in->usecase = USECASE_AUDIO_CAPTURE_HOTWORD;
4219 } else {
4220 in->usecase = USECASE_AUDIO_CAPTURE;
4221 }
4222 in->usecase_type = usecase_type;
4223
4224 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4225 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4226
4227 in->is_fastcapture_affinity_set = false;
4228
4229 *stream_in = &in->stream;
4230 ALOGV("%s: exit", __func__);
4231 return 0;
4232}
4233
4234static void adev_close_input_stream(struct audio_hw_device *dev,
4235 struct audio_stream_in *stream)
4236{
4237 struct audio_device *adev = (struct audio_device *)dev;
4238 struct stream_in *in = (struct stream_in*)stream;
4239 ALOGV("%s", __func__);
4240
4241 /* prevent concurrent out_set_parameters, or out_write from standby */
4242 pthread_mutex_lock(&adev->lock_inputs);
4243
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004244 if (in->read_buf) {
4245 free(in->read_buf);
4246 in->read_buf = NULL;
4247 }
4248
4249 if (in->resampler) {
4250 release_resampler(in->resampler);
4251 in->resampler = NULL;
4252 }
4253
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004254#ifdef PREPROCESSING_ENABLED
4255 int i;
4256
4257 for (i=0; i<in->num_preprocessors; i++) {
4258 free(in->preprocessors[i].channel_configs);
4259 }
4260
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004261 if (in->proc_buf_in) {
4262 free(in->proc_buf_in);
4263 in->proc_buf_in = NULL;
4264 }
4265
4266 if (in->proc_buf_out) {
4267 free(in->proc_buf_out);
4268 in->proc_buf_out = NULL;
4269 }
4270
4271 if (in->ref_buf) {
4272 free(in->ref_buf);
4273 in->ref_buf = NULL;
4274 }
4275
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004276#endif
4277
4278 in_standby_l(in);
4279 free(stream);
4280
4281 pthread_mutex_unlock(&adev->lock_inputs);
4282
4283 return;
4284}
4285
4286static int adev_dump(const audio_hw_device_t *device, int fd)
4287{
4288 (void)device;
4289 (void)fd;
4290
4291 return 0;
4292}
4293
4294static int adev_close(hw_device_t *device)
4295{
4296 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004297 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004298 audio_device_ref_count--;
4299 free(adev->snd_dev_ref_cnt);
4300 free_mixer_list(adev);
4301 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004302
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004303 return 0;
4304}
4305
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004306/* This returns true if the input parameter looks at all plausible as a low latency period size,
4307 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4308 * just that it _might_ work.
4309 */
4310static bool period_size_is_plausible_for_low_latency(int period_size)
4311{
4312 switch (period_size) {
4313 case 64:
4314 case 96:
4315 case 128:
4316 case 192:
4317 case 256:
4318 return true;
4319 default:
4320 return false;
4321 }
4322}
4323
4324static int adev_open(const hw_module_t *module, const char *name,
4325 hw_device_t **device)
4326{
4327 struct audio_device *adev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004328
4329 ALOGV("%s: enter", __func__);
4330 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4331
Andreas Schneider56204f62017-01-31 08:17:32 +01004332 *device = NULL;
4333
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004334 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004335 if (adev == NULL) {
4336 return -ENOMEM;
4337 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004338
4339 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4340 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4341 adev->device.common.module = (struct hw_module_t *)module;
4342 adev->device.common.close = adev_close;
4343
4344 adev->device.init_check = adev_init_check;
4345 adev->device.set_voice_volume = adev_set_voice_volume;
4346 adev->device.set_master_volume = adev_set_master_volume;
4347 adev->device.get_master_volume = adev_get_master_volume;
4348 adev->device.set_master_mute = adev_set_master_mute;
4349 adev->device.get_master_mute = adev_get_master_mute;
4350 adev->device.set_mode = adev_set_mode;
4351 adev->device.set_mic_mute = adev_set_mic_mute;
4352 adev->device.get_mic_mute = adev_get_mic_mute;
4353 adev->device.set_parameters = adev_set_parameters;
4354 adev->device.get_parameters = adev_get_parameters;
4355 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4356 adev->device.open_output_stream = adev_open_output_stream;
4357 adev->device.close_output_stream = adev_close_output_stream;
4358 adev->device.open_input_stream = adev_open_input_stream;
4359 adev->device.close_input_stream = adev_close_input_stream;
4360 adev->device.dump = adev_dump;
4361
4362 /* Set the default route before the PCM stream is opened */
4363 adev->mode = AUDIO_MODE_NORMAL;
4364 adev->active_input = NULL;
4365 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004366
4367 adev->voice.volume = 1.0f;
4368 adev->voice.bluetooth_nrec = true;
4369 adev->voice.in_call = false;
4370
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004371 /* adev->cur_hdmi_channels = 0; by calloc() */
4372 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004373 if (adev->snd_dev_ref_cnt == NULL) {
4374 free(adev);
4375 return -ENOMEM;
4376 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004377
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004378 adev->ns_in_voice_rec = false;
4379
4380 list_init(&adev->usecase_list);
4381
4382 if (mixer_init(adev) != 0) {
4383 free(adev->snd_dev_ref_cnt);
4384 free(adev);
4385 ALOGE("%s: Failed to init, aborting.", __func__);
4386 *device = NULL;
4387 return -EINVAL;
4388 }
4389
4390 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4391 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4392 if (adev->offload_fx_lib == NULL) {
4393 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4394 } else {
4395 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4396 adev->offload_fx_start_output =
4397 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4398 "visualizer_hal_start_output");
4399 adev->offload_fx_stop_output =
4400 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4401 "visualizer_hal_stop_output");
4402 }
4403 }
4404
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004405 if (access(SOUND_TRIGGER_HAL_LIBRARY_PATH, R_OK) == 0) {
4406 adev->sound_trigger_lib = dlopen(SOUND_TRIGGER_HAL_LIBRARY_PATH, RTLD_NOW);
4407 if (adev->sound_trigger_lib == NULL) {
4408 ALOGE("%s: DLOPEN failed for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4409 } else {
4410 ALOGV("%s: DLOPEN successful for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4411 adev->sound_trigger_open_for_streaming =
4412 (int (*)(void))dlsym(adev->sound_trigger_lib,
4413 "sound_trigger_open_for_streaming");
4414 adev->sound_trigger_read_samples =
4415 (size_t (*)(int, void *, size_t))dlsym(adev->sound_trigger_lib,
4416 "sound_trigger_read_samples");
4417 adev->sound_trigger_close_for_streaming =
4418 (int (*)(int))dlsym(adev->sound_trigger_lib,
4419 "sound_trigger_close_for_streaming");
4420 if (!adev->sound_trigger_open_for_streaming ||
4421 !adev->sound_trigger_read_samples ||
4422 !adev->sound_trigger_close_for_streaming) {
4423
4424 ALOGE("%s: Error grabbing functions in %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4425 adev->sound_trigger_open_for_streaming = 0;
4426 adev->sound_trigger_read_samples = 0;
4427 adev->sound_trigger_close_for_streaming = 0;
4428 }
4429 }
4430 }
4431
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004432 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004433 if (adev->voice.session == NULL) {
4434 ALOGE("%s: Failed to initialize voice session data", __func__);
4435
4436 free(adev->snd_dev_ref_cnt);
4437 free(adev);
4438
4439 *device = NULL;
4440 return -EINVAL;
4441 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004442
4443 *device = &adev->device.common;
4444
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004445 audio_device_ref_count++;
4446
4447 char value[PROPERTY_VALUE_MAX];
4448 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4449 int trial = atoi(value);
4450 if (period_size_is_plausible_for_low_latency(trial)) {
4451
4452 pcm_device_playback.config.period_size = trial;
4453 pcm_device_playback.config.start_threshold =
4454 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4455 pcm_device_playback.config.stop_threshold =
4456 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4457
4458 pcm_device_capture_low_latency.config.period_size = trial;
4459 }
4460 }
4461
4462 ALOGV("%s: exit", __func__);
4463 return 0;
4464}
4465
4466static struct hw_module_methods_t hal_module_methods = {
4467 .open = adev_open,
4468};
4469
4470struct audio_module HAL_MODULE_INFO_SYM = {
4471 .common = {
4472 .tag = HARDWARE_MODULE_TAG,
4473 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4474 .hal_api_version = HARDWARE_HAL_API_VERSION,
4475 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004476 .name = "Samsung Audio HAL",
4477 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004478 .methods = &hal_module_methods,
4479 },
4480};