blob: 61b28e2d36265d46b5a9626bbb920ad06d2319cf [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",
228 [USECASE_AUDIO_CAPTURE] = "capture",
229 [USECASE_AUDIO_CAPTURE_HOTWORD] = "capture-hotword",
230 [USECASE_VOICE_CALL] = "voice-call",
231};
232
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100233#define STRING_TO_ENUM(string) { #string, string }
234
235static unsigned int audio_device_ref_count;
236
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100237struct string_to_enum {
238 const char *name;
239 uint32_t value;
240};
241
242static const struct string_to_enum out_channels_name_to_enum_table[] = {
243 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
245 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
246};
247
Andreas Schneider759368f2017-02-02 16:11:14 +0100248struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
249 struct timespec ret;
250 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100251
252 if (time0.tv_nsec > time1.tv_nsec) {
253 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
254 time0.tv_nsec -= (long int) (1E9 * xsec);
255 time0.tv_sec += xsec;
256 }
257
258 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
259 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
260 time0.tv_nsec += (long int) (1E9 * xsec);
261 time0.tv_sec -= xsec;
262 }
263
Andreas Schneider58735a92017-02-13 16:48:17 +0100264 ret.tv_sec = abs(time1.tv_sec - time0.tv_sec);
265 ret.tv_nsec = abs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100266
267 return ret;
268}
269
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100270static bool is_supported_format(audio_format_t format)
271{
272 if (format == AUDIO_FORMAT_MP3 ||
273 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
274 return true;
275
276 return false;
277}
278
279static int get_snd_codec_id(audio_format_t format)
280{
281 int id = 0;
282
283 switch (format & AUDIO_FORMAT_MAIN_MASK) {
284 case AUDIO_FORMAT_MP3:
285 id = SND_AUDIOCODEC_MP3;
286 break;
287 case AUDIO_FORMAT_AAC:
288 id = SND_AUDIOCODEC_AAC;
289 break;
290 default:
291 ALOGE("%s: Unsupported audio format", __func__);
292 }
293
294 return id;
295}
296
297/* Array to store sound devices */
298static const char * const device_table[SND_DEVICE_MAX] = {
299 [SND_DEVICE_NONE] = "none",
300 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100301 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100302 [SND_DEVICE_OUT_SPEAKER] = "speaker",
303 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
304 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100305 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100306 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100307 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100308 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100309 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100310 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100311 [SND_DEVICE_OUT_HDMI] = "hdmi",
312 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
313 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100314
315 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100316 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100317 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
318 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100319 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100320 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
321 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100322 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
323 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100324 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100325 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100326 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100327 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100328 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100329 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
330 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
331 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100332 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
333 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100334 [SND_DEVICE_IN_LOOPBACK_AEC] = "loopback-aec",
335};
336
337static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
338{
339 struct mixer_card *mixer_card;
340 struct listnode *node;
341
342 list_for_each(node, &adev->mixer_list) {
343 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
344 if (mixer_card->card == card)
345 return mixer_card;
346 }
347 return NULL;
348}
349
350static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
351{
352 struct mixer_card *mixer_card;
353 struct listnode *node;
354
355 list_for_each(node, &usecase->mixer_list) {
356 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
357 if (mixer_card->card == card)
358 return mixer_card;
359 }
360 return NULL;
361}
362
363static void free_mixer_list(struct audio_device *adev)
364{
365 struct mixer_card *mixer_card;
366 struct listnode *node;
367 struct listnode *next;
368
369 list_for_each_safe(node, next, &adev->mixer_list) {
370 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
371 list_remove(node);
372 audio_route_free(mixer_card->audio_route);
373 free(mixer_card);
374 }
375}
376
377static int mixer_init(struct audio_device *adev)
378{
379 int i;
380 int card;
381 int retry_num;
382 struct mixer *mixer;
383 struct audio_route *audio_route;
384 char mixer_path[PATH_MAX];
385 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100386 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100387
388 list_init(&adev->mixer_list);
389
390 for (i = 0; pcm_devices[i] != NULL; i++) {
391 card = pcm_devices[i]->card;
392 if (adev_get_mixer_for_card(adev, card) == NULL) {
393 retry_num = 0;
394 do {
395 mixer = mixer_open(card);
396 if (mixer == NULL) {
397 if (++retry_num > RETRY_NUMBER) {
398 ALOGE("%s unable to open the mixer for--card %d, aborting.",
399 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100400 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100401 goto error;
402 }
403 usleep(RETRY_US);
404 }
405 } while (mixer == NULL);
406
407 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
408 audio_route = audio_route_init(card, mixer_path);
409 if (!audio_route) {
410 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
411 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100412 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100413 goto error;
414 }
415 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100416 if (mixer_card == NULL) {
417 ret = -ENOMEM;
418 goto error;
419 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100420 mixer_card->card = card;
421 mixer_card->mixer = mixer;
422 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100423
424 /* Do not sleep on first enable_snd_device() */
425 mixer_card->dsp_poweroff_time.tv_sec = 1;
426 mixer_card->dsp_poweroff_time.tv_nsec = 0;
427
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100428 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
429 }
430 }
431
432 return 0;
433
434error:
435 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100436 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100437}
438
439static const char *get_snd_device_name(snd_device_t snd_device)
440{
441 const char *name = NULL;
442
Andreas Schneideradb788d2017-02-13 15:19:36 +0100443 if (snd_device == SND_DEVICE_NONE ||
444 (snd_device > SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100445 name = device_table[snd_device];
446
447 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
448
449 return name;
450}
451
452static const char *get_snd_device_display_name(snd_device_t snd_device)
453{
454 const char *name = get_snd_device_name(snd_device);
455
456 if (name == NULL)
457 name = "SND DEVICE NOT FOUND";
458
459 return name;
460}
461
462static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
463{
464 int i;
465
466 devices &= ~AUDIO_DEVICE_BIT_IN;
467 for (i = 0; pcm_devices[i] != NULL; i++) {
468 if ((pcm_devices[i]->type == uc_type) &&
469 (devices & pcm_devices[i]->devices))
470 break;
471 }
472 return pcm_devices[i];
473}
474
475static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
476 audio_usecase_t uc_id)
477{
478 struct audio_usecase *usecase;
479 struct listnode *node;
480
481 list_for_each(node, &adev->usecase_list) {
482 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
483 if (usecase->id == uc_id)
484 return usecase;
485 }
486 return NULL;
487}
488
489static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
490 usecase_type_t type)
491{
492 struct audio_usecase *usecase;
493 struct listnode *node;
494
495 list_for_each(node, &adev->usecase_list) {
496 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
497 if (usecase->type & type)
498 return usecase;
499 }
500 return NULL;
501}
502
503/* always called with adev lock held */
504static int set_voice_volume_l(struct audio_device *adev, float volume)
505{
506 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100507
508 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100509 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100510 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100511
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100512 return err;
513}
514
515
516static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
517{
518
519 audio_mode_t mode = adev->mode;
520 snd_device_t snd_device = SND_DEVICE_NONE;
521
522 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
523 if (devices == AUDIO_DEVICE_NONE ||
524 devices & AUDIO_DEVICE_BIT_IN) {
525 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
526 goto exit;
527 }
528
529 if (mode == AUDIO_MODE_IN_CALL) {
530 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
531 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100532 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100533 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
534 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
535 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100536 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100537 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100538
539 if (voice_session_uses_wideband(adev->voice.session)) {
540 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
541 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
542 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
543 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
544 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
545 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
546 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
547 }
548 }
549
550 if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
551 snd_device = SND_DEVICE_OUT_BT_SCO;
552 }
553
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100554 if (snd_device != SND_DEVICE_NONE) {
555 goto exit;
556 }
557 }
558
559 if (popcount(devices) == 2) {
560 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
561 AUDIO_DEVICE_OUT_SPEAKER)) {
562 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
563 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
564 AUDIO_DEVICE_OUT_SPEAKER)) {
565 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
566 } else {
567 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
568 goto exit;
569 }
570 if (snd_device != SND_DEVICE_NONE) {
571 goto exit;
572 }
573 }
574
575 if (popcount(devices) != 1) {
576 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
577 goto exit;
578 }
579
580 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
581 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
582 snd_device = SND_DEVICE_OUT_HEADPHONES;
583 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
584 snd_device = SND_DEVICE_OUT_SPEAKER;
585 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
586 snd_device = SND_DEVICE_OUT_BT_SCO;
587 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100588 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100589 } else {
590 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
591 }
592exit:
593 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
594 return snd_device;
595}
596
597static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
598{
599 audio_source_t source;
600 audio_mode_t mode = adev->mode;
601 audio_devices_t in_device;
602 audio_channel_mask_t channel_mask;
603 snd_device_t snd_device = SND_DEVICE_NONE;
604 struct stream_in *active_input = NULL;
605 struct audio_usecase *usecase;
606
607 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
608 if (usecase != NULL) {
609 active_input = (struct stream_in *)usecase->stream;
610 }
611 source = (active_input == NULL) ?
612 AUDIO_SOURCE_DEFAULT : active_input->source;
613
Andreas Schneider757e2d82017-02-10 19:28:35 +0100614 in_device = (active_input == NULL) ?
615 AUDIO_DEVICE_NONE :
616 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100617 channel_mask = (active_input == NULL) ?
618 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
619
620 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
621 __func__, out_device, in_device);
622 if (mode == AUDIO_MODE_IN_CALL) {
623 if (out_device == AUDIO_DEVICE_NONE) {
624 ALOGE("%s: No output device set for voice call", __func__);
625 goto exit;
626 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100627
Andreas Schneider82f32482017-02-06 09:00:48 +0100628 snd_device = SND_DEVICE_IN_VOICE_MIC;
629 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100630 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100631 }
632
633 if (voice_session_uses_twomic(adev->voice.session)) {
634 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
635 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
636 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
637 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
638 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
639 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100640 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100641
642 if (voice_session_uses_wideband(adev->voice.session)) {
643 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
644 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
645 }
646
647 if (voice_session_uses_twomic(adev->voice.session)) {
648 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
649 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
650 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
651 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
652 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
653 }
654 }
655 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100656
657 /* BT SCO */
658 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
659 snd_device = SND_DEVICE_IN_VOICE_MIC;
660
661 if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
662 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
663 } else if (voice_session_uses_twomic(adev->voice.session)) {
664 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
665 }
666 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100667 } else if (source == AUDIO_SOURCE_CAMCORDER) {
668 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
669 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
670 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
671 }
672 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
673 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100674 if (snd_device == SND_DEVICE_NONE) {
675 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
676 }
677 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
678 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
679 }
680 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
681 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
682 in_device = AUDIO_DEVICE_IN_BACK_MIC;
683 if (active_input) {
684 if (active_input->enable_aec) {
685 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
686 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
687 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
688 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
689 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
690 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100691 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100692 }
693 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
694 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
695 }
696 }
697 /* TODO: set echo reference */
698 }
699 } else if (source == AUDIO_SOURCE_DEFAULT) {
700 goto exit;
701 }
702
703
704 if (snd_device != SND_DEVICE_NONE) {
705 goto exit;
706 }
707
708 if (in_device != AUDIO_DEVICE_NONE &&
709 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
710 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
711 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100712 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100713 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
714 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
715 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
716 snd_device = SND_DEVICE_IN_HEADSET_MIC;
717 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
718 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
719 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
720 snd_device = SND_DEVICE_IN_HDMI_MIC;
721 } else {
722 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100723 ALOGW("%s: Using default earpiece-mic", __func__);
724 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100725 }
726 } else {
727 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100728 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100729 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
730 snd_device = SND_DEVICE_IN_HEADSET_MIC;
731 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
732 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
733 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100734 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100735 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
736 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
737 } else {
738 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100739 ALOGW("%s: Using default earpiece-mic", __func__);
740 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100741 }
742 }
743exit:
744 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
745 return snd_device;
746}
747
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100748#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100749static int set_hdmi_channels(struct audio_device *adev, int channel_count)
750{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100751 (void)adev;
752 (void)channel_count;
753 /* TODO */
754
755 return 0;
756}
757
758static int edid_get_max_channels(struct audio_device *adev)
759{
760 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100761 (void)adev;
762
763 /* TODO */
764 return max_channels;
765}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100766#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100767
768/* Delay in Us */
769static int64_t render_latency(audio_usecase_t usecase)
770{
771 (void)usecase;
772 /* TODO */
773 return 0;
774}
775
776static int enable_snd_device(struct audio_device *adev,
777 struct audio_usecase *uc_info,
778 snd_device_t snd_device,
779 bool update_mixer)
780{
781 struct mixer_card *mixer_card;
782 struct listnode *node;
783 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100784#ifdef DSP_POWEROFF_DELAY
785 struct timespec activation_time;
786 struct timespec elapsed_time;
787#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100788
789 if (snd_device_name == NULL)
790 return -EINVAL;
791
792 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
793 ALOGV("Request to enable combo device: enable individual devices\n");
794 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
795 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
796 return 0;
797 }
798 adev->snd_dev_ref_cnt[snd_device]++;
799 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
800 ALOGV("%s: snd_device(%d: %s) is already active",
801 __func__, snd_device, snd_device_name);
802 return 0;
803 }
804
805 ALOGV("%s: snd_device(%d: %s)", __func__,
806 snd_device, snd_device_name);
807
808 list_for_each(node, &uc_info->mixer_list) {
809 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100810
811#ifdef DSP_POWEROFF_DELAY
812 clock_gettime(CLOCK_MONOTONIC, &activation_time);
813
Andreas Schneider58735a92017-02-13 16:48:17 +0100814 elapsed_time = time_spec_diff(activation_time,
815 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100816 if (elapsed_time.tv_sec == 0) {
817 long elapsed_usec = elapsed_time.tv_nsec / 1000;
818
819 if (elapsed_usec < DSP_POWEROFF_DELAY) {
820 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
821 }
822 }
823 update_mixer = true;
824#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100825 audio_route_apply_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100826 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100827 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100828 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100829 }
830
831 return 0;
832}
833
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100834int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100835 struct audio_usecase *uc_info,
836 snd_device_t snd_device,
837 bool update_mixer)
838{
839 struct mixer_card *mixer_card;
840 struct listnode *node;
841 const char *snd_device_name = get_snd_device_name(snd_device);
842
843 if (snd_device_name == NULL)
844 return -EINVAL;
845
846 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
847 ALOGV("Request to disable combo device: disable individual devices\n");
848 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
849 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
850 return 0;
851 }
852
853 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
854 ALOGE("%s: device ref cnt is already 0", __func__);
855 return -EINVAL;
856 }
857 adev->snd_dev_ref_cnt[snd_device]--;
858 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
859 ALOGV("%s: snd_device(%d: %s)", __func__,
860 snd_device, snd_device_name);
861 list_for_each(node, &uc_info->mixer_list) {
862 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100863#ifdef DSP_POWEROFF_DELAY
864 update_mixer = true;
865#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100866 audio_route_reset_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100867 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100868 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100869 }
870#ifdef DSP_POWEROFF_DELAY
871 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
872#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100873 }
874 }
875 return 0;
876}
877
878static int select_devices(struct audio_device *adev,
879 audio_usecase_t uc_id)
880{
881 snd_device_t out_snd_device = SND_DEVICE_NONE;
882 snd_device_t in_snd_device = SND_DEVICE_NONE;
883 struct audio_usecase *usecase = NULL;
884 struct audio_usecase *vc_usecase = NULL;
885 struct listnode *node;
886 struct stream_in *active_input = NULL;
887 struct stream_out *active_out;
888 struct mixer_card *mixer_card;
889
890 ALOGV("%s: usecase(%d)", __func__, uc_id);
891
892 if (uc_id == USECASE_AUDIO_CAPTURE_HOTWORD)
893 return 0;
894
895 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
896 if (usecase != NULL) {
897 active_input = (struct stream_in *)usecase->stream;
898 }
899
900 usecase = get_usecase_from_id(adev, uc_id);
901 if (usecase == NULL) {
902 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
903 return -EINVAL;
904 }
905 active_out = (struct stream_out *)usecase->stream;
906
907 if (usecase->type == VOICE_CALL) {
908 out_snd_device = get_output_snd_device(adev, active_out->devices);
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100909 prepare_voice_session(adev->voice.session, active_out->devices);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100910 in_snd_device = get_input_snd_device(adev, active_out->devices);
911 usecase->devices = active_out->devices;
912 } else {
913 /*
914 * If the voice call is active, use the sound devices of voice call usecase
915 * so that it would not result any device switch. All the usecases will
916 * be switched to new device when select_devices() is called for voice call
917 * usecase.
918 */
Andreas Schneider74ef3a12017-02-02 18:29:12 +0100919 if (adev->voice.in_call) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100920 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
921 if (usecase == NULL) {
922 ALOGE("%s: Could not find the voice call usecase", __func__);
923 } else {
924 in_snd_device = vc_usecase->in_snd_device;
925 out_snd_device = vc_usecase->out_snd_device;
926 }
927 }
928 if (usecase->type == PCM_PLAYBACK) {
929 usecase->devices = active_out->devices;
930 in_snd_device = SND_DEVICE_NONE;
931 if (out_snd_device == SND_DEVICE_NONE) {
932 out_snd_device = get_output_snd_device(adev, active_out->devices);
933 if (active_out == adev->primary_output &&
934 active_input &&
935 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
936 select_devices(adev, active_input->usecase);
937 }
938 }
939 } else if (usecase->type == PCM_CAPTURE) {
940 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
941 out_snd_device = SND_DEVICE_NONE;
942 if (in_snd_device == SND_DEVICE_NONE) {
943 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
944 adev->primary_output && !adev->primary_output->standby) {
945 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
946 } else {
947 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
948 }
949 }
950 }
951 }
952
953 if (out_snd_device == usecase->out_snd_device &&
954 in_snd_device == usecase->in_snd_device) {
955 return 0;
956 }
957
958 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
959 out_snd_device, get_snd_device_display_name(out_snd_device),
960 in_snd_device, get_snd_device_display_name(in_snd_device));
961
962
963 /* Disable current sound devices */
964 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100965 disable_snd_device(adev, usecase, usecase->out_snd_device, false);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100966 }
967
968 if (usecase->in_snd_device != SND_DEVICE_NONE) {
969 disable_snd_device(adev, usecase, usecase->in_snd_device, false);
970 }
971
972 /* Enable new sound devices */
973 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100974 /* We need to update the audio path if we switch the out devices */
975 if (adev->voice.in_call) {
976 set_voice_session_audio_path(adev->voice.session);
977 }
978
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100979 enable_snd_device(adev, usecase, out_snd_device, false);
980 }
981
982 if (in_snd_device != SND_DEVICE_NONE) {
983 enable_snd_device(adev, usecase, in_snd_device, false);
984 }
985
986 list_for_each(node, &usecase->mixer_list) {
987 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
988 audio_route_update_mixer(mixer_card->audio_route);
989 }
990
991 usecase->in_snd_device = in_snd_device;
992 usecase->out_snd_device = out_snd_device;
993
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100994 return 0;
995}
996
997
998static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
999static int do_in_standby_l(struct stream_in *in);
1000
1001#ifdef PREPROCESSING_ENABLED
1002static void get_capture_reference_delay(struct stream_in *in,
1003 size_t frames __unused,
1004 struct echo_reference_buffer *buffer)
1005{
1006 ALOGVV("%s: enter:)", __func__);
1007
1008 /* read frames available in kernel driver buffer */
1009 unsigned int kernel_frames;
1010 struct timespec tstamp;
1011 long buf_delay;
1012 long kernel_delay;
1013 long delay_ns;
1014 struct pcm_device *ref_device;
1015 long rsmp_delay = 0;
1016
1017 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1018 struct pcm_device, stream_list_node);
1019
1020 if (pcm_get_htimestamp(ref_device->pcm, &kernel_frames, &tstamp) < 0) {
1021 buffer->time_stamp.tv_sec = 0;
1022 buffer->time_stamp.tv_nsec = 0;
1023 buffer->delay_ns = 0;
1024 ALOGW("read get_capture_reference_delay(): pcm_htimestamp error");
1025 return;
1026 }
1027
1028 /* adjust render time stamp with delay added by current driver buffer.
1029 * Add the duration of current frame as we want the render time of the last
1030 * sample being written. */
1031
1032 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / ref_device->pcm_profile->config.rate);
1033
1034 buffer->time_stamp = tstamp;
1035 buffer->delay_ns = kernel_delay;
1036
1037 ALOGVV("get_capture_reference_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5d],"
1038 " delay_ns: [%d] , frames:[%zd]",
1039 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns, frames);
1040}
1041
1042static void get_capture_delay(struct stream_in *in,
1043 size_t frames __unused,
1044 struct echo_reference_buffer *buffer)
1045{
1046 ALOGVV("%s: enter:)", __func__);
1047 /* read frames available in kernel driver buffer */
1048 unsigned int kernel_frames;
1049 struct timespec tstamp;
1050 long buf_delay;
1051 long rsmp_delay;
1052 long kernel_delay;
1053 long delay_ns;
1054 struct pcm_device *pcm_device;
1055
1056 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1057 struct pcm_device, stream_list_node);
1058
1059 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1060 buffer->time_stamp.tv_sec = 0;
1061 buffer->time_stamp.tv_nsec = 0;
1062 buffer->delay_ns = 0;
1063 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1064 return;
1065 }
1066
1067 /* read frames available in audio HAL input buffer
1068 * add number of frames being read as we want the capture time of first sample
1069 * in current buffer */
1070 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1071 * at requested sampling rate */
1072 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1073 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1074
1075 /* add delay introduced by resampler */
1076 rsmp_delay = 0;
1077 if (in->resampler) {
1078 rsmp_delay = in->resampler->delay_ns(in->resampler);
1079 }
1080
1081 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1082
1083 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1084
1085 buffer->time_stamp = tstamp;
1086 buffer->delay_ns = delay_ns;
1087 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1088 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1089 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1090 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1091 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1092 in->read_buf_frames, in->proc_buf_frames, frames);
1093}
1094
1095static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1096{
1097 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1098 struct echo_reference_buffer b;
1099 b.delay_ns = 0;
1100 struct pcm_device *pcm_device;
1101
1102 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1103 struct pcm_device, stream_list_node);
1104
1105 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1106 "b.frame_count = [%zd]",
1107 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1108 if (in->ref_buf_frames < frames) {
1109 if (in->ref_buf_size < frames) {
1110 in->ref_buf_size = frames;
1111 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1112 ALOG_ASSERT((in->ref_buf != NULL),
1113 "update_echo_reference() failed to reallocate ref_buf");
1114 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1115 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1116 }
1117 b.frame_count = frames - in->ref_buf_frames;
1118 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1119
1120 get_capture_delay(in, frames, &b);
1121
1122 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1123 {
1124 in->ref_buf_frames += b.frame_count;
1125 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1126 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1127 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1128 }
1129 } else
1130 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1131 return b.delay_ns;
1132}
1133
1134static int set_preprocessor_param(effect_handle_t handle,
1135 effect_param_t *param)
1136{
1137 uint32_t size = sizeof(int);
1138 uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1139 param->vsize;
1140
1141 int status = (*handle)->command(handle,
1142 EFFECT_CMD_SET_PARAM,
1143 sizeof (effect_param_t) + psize,
1144 param,
1145 &size,
1146 &param->status);
1147 if (status == 0)
1148 status = param->status;
1149
1150 return status;
1151}
1152
1153static int set_preprocessor_echo_delay(effect_handle_t handle,
1154 int32_t delay_us)
1155{
1156 struct {
1157 effect_param_t param;
1158 uint32_t data_0;
1159 int32_t data_1;
1160 } buf;
1161 memset(&buf, 0, sizeof(buf));
1162
1163 buf.param.psize = sizeof(uint32_t);
1164 buf.param.vsize = sizeof(uint32_t);
1165 buf.data_0 = AEC_PARAM_ECHO_DELAY;
1166 buf.data_1 = delay_us;
1167
1168 return set_preprocessor_param(handle, &buf.param);
1169}
1170
1171static void push_echo_reference(struct stream_in *in, size_t frames)
1172{
1173 ALOGVV("%s: enter:)", __func__);
1174 /* read frames from echo reference buffer and update echo delay
1175 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1176
1177 int32_t delay_us = update_echo_reference(in, frames)/1000;
1178 int32_t size_in_bytes = 0;
1179 int i;
1180 audio_buffer_t buf;
1181
1182 if (in->ref_buf_frames < frames)
1183 frames = in->ref_buf_frames;
1184
1185 buf.frameCount = frames;
1186 buf.raw = in->ref_buf;
1187
1188 for (i = 0; i < in->num_preprocessors; i++) {
1189 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1190 continue;
1191 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1192 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1193 &buf,
1194 NULL);
1195 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1196 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1197 }
1198
1199 in->ref_buf_frames -= buf.frameCount;
1200 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1201 __func__, in->ref_buf_frames, in->config.channels);
1202 if (in->ref_buf_frames) {
1203 memcpy(in->ref_buf,
1204 in->ref_buf + buf.frameCount * in->config.channels,
1205 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1206 }
1207}
1208
1209static void put_echo_reference(struct audio_device *adev,
1210 struct echo_reference_itfe *reference)
1211{
1212 ALOGV("%s: enter:)", __func__);
1213 int32_t prev_generation = adev->echo_reference_generation;
1214 struct stream_out *out = adev->primary_output;
1215
1216 if (adev->echo_reference != NULL &&
1217 reference == adev->echo_reference) {
1218 /* echo reference is taken from the low latency output stream used
1219 * for voice use cases */
1220 adev->echo_reference = NULL;
1221 android_atomic_inc(&adev->echo_reference_generation);
1222 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1223 // if the primary output is in standby or did not pick the echo reference yet
1224 // we can safely get rid of it here.
1225 // otherwise, out_write() or out_standby() will detect the change in echo reference
1226 // generation and release the echo reference owned by the stream.
1227 if ((out->echo_reference_generation != prev_generation) || out->standby)
1228 release_echo_reference(reference);
1229 } else {
1230 release_echo_reference(reference);
1231 }
1232 ALOGV("release_echo_reference");
1233 }
1234}
1235
1236static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1237 audio_format_t format __unused,
1238 uint32_t channel_count,
1239 uint32_t sampling_rate)
1240{
1241 ALOGV("%s: enter:)", __func__);
1242 put_echo_reference(adev, adev->echo_reference);
1243 /* echo reference is taken from the low latency output stream used
1244 * for voice use cases */
1245 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1246 !adev->primary_output->standby) {
1247 struct audio_stream *stream =
1248 &adev->primary_output->stream.common;
1249 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1250 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1251 ALOGV("Calling create_echo_reference");
1252 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1253 channel_count,
1254 sampling_rate,
1255 AUDIO_FORMAT_PCM_16_BIT,
1256 wr_channel_count,
1257 wr_sampling_rate,
1258 &adev->echo_reference);
1259 if (status == 0)
1260 android_atomic_inc(&adev->echo_reference_generation);
1261 }
1262 return adev->echo_reference;
1263}
1264
1265#ifdef HW_AEC_LOOPBACK
1266static int get_hw_echo_reference(struct stream_in *in)
1267{
1268 struct pcm_device_profile *ref_pcm_profile;
1269 struct pcm_device *ref_device;
1270 struct audio_device *adev = in->dev;
1271
1272 in->hw_echo_reference = false;
1273
1274 if (adev->primary_output!= NULL &&
1275 !adev->primary_output->standby &&
1276 adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1277 adev->primary_output->devices == AUDIO_DEVICE_OUT_SPEAKER) {
1278 struct audio_stream *stream = &adev->primary_output->stream.common;
1279
1280 // TODO: currently there is no low latency mode for aec reference.
1281 ref_pcm_profile = get_pcm_device(PCM_CAPTURE, pcm_device_capture_loopback_aec.devices);
1282 if (ref_pcm_profile == NULL) {
1283 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1284 __func__, pcm_device_capture_loopback_aec.devices);
1285 return -EINVAL;
1286 }
1287
1288 ref_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01001289 if (ref_device == NULL) {
1290 return -ENOMEM;
1291 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001292 ref_device->pcm_profile = ref_pcm_profile;
1293
1294 ALOGV("%s: ref_device rate:%d, ch:%d", __func__, ref_pcm_profile->config.rate, ref_pcm_profile->config.channels);
1295 ref_device->pcm = pcm_open(ref_device->pcm_profile->card, ref_device->pcm_profile->id, PCM_IN | PCM_MONOTONIC, &ref_device->pcm_profile->config);
1296
1297 if (ref_device->pcm && !pcm_is_ready(ref_device->pcm)) {
1298 ALOGE("%s: %s", __func__, pcm_get_error(ref_device->pcm));
1299 pcm_close(ref_device->pcm);
1300 ref_device->pcm = NULL;
1301 return -EIO;
1302 }
1303 list_add_tail(&in->pcm_dev_list, &ref_device->stream_list_node);
1304
1305 in->hw_echo_reference = true;
1306
1307 ALOGV("%s: hw_echo_reference is true", __func__);
1308 }
1309
1310 return 0;
1311}
1312#endif
1313
1314static int get_playback_delay(struct stream_out *out,
1315 size_t frames,
1316 struct echo_reference_buffer *buffer)
1317{
1318 unsigned int kernel_frames;
1319 int status;
1320 int primary_pcm = 0;
1321 struct pcm_device *pcm_device;
1322
1323 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1324 struct pcm_device, stream_list_node);
1325
1326 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1327 if (status < 0) {
1328 buffer->time_stamp.tv_sec = 0;
1329 buffer->time_stamp.tv_nsec = 0;
1330 buffer->delay_ns = 0;
1331 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1332 "setting playbackTimestamp to 0");
1333 return status;
1334 }
1335
1336 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1337
1338 /* adjust render time stamp with delay added by current driver buffer.
1339 * Add the duration of current frame as we want the render time of the last
1340 * sample being written. */
1341 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1342 out->config.rate);
1343 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1344 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1345
1346 return 0;
1347}
1348
1349#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1350 do { \
1351 if (fct_status != 0) \
1352 status = fct_status; \
1353 else if (cmd_status != 0) \
1354 status = cmd_status; \
1355 } while(0)
1356
1357static int in_configure_reverse(struct stream_in *in)
1358{
1359 int32_t cmd_status;
1360 uint32_t size = sizeof(int);
1361 effect_config_t config;
1362 int32_t status = 0;
1363 int32_t fct_status = 0;
1364 int i;
1365 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1366 if (in->num_preprocessors > 0) {
1367 config.inputCfg.channels = in->main_channels;
1368 config.outputCfg.channels = in->main_channels;
1369 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1370 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1371 config.inputCfg.samplingRate = in->requested_rate;
1372 config.outputCfg.samplingRate = in->requested_rate;
1373 config.inputCfg.mask =
1374 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1375 config.outputCfg.mask =
1376 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1377
1378 for (i = 0; i < in->num_preprocessors; i++)
1379 {
1380 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1381 continue;
1382 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1383 in->preprocessors[i].effect_itfe,
1384 EFFECT_CMD_SET_CONFIG_REVERSE,
1385 sizeof(effect_config_t),
1386 &config,
1387 &size,
1388 &cmd_status);
1389 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1390 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1391 }
1392 }
1393 return status;
1394}
1395
1396#define MAX_NUM_CHANNEL_CONFIGS 10
1397
1398static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1399 struct effect_info_s *effect_info)
1400{
1401 /* size and format of the cmd are defined in hardware/audio_effect.h */
1402 effect_handle_t effect = effect_info->effect_itfe;
1403 uint32_t cmd_size = 2 * sizeof(uint32_t);
1404 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1405 /* reply = status + number of configs (n) + n x channel_config_t */
1406 uint32_t reply_size =
1407 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1408 int32_t reply[reply_size];
1409 int32_t cmd_status;
1410
1411 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1412 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1413 ALOG_ASSERT((effect_info->channel_configs == NULL),
1414 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1415
1416 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1417 * This error will be interpreted as if the effect supports the main_channels but does not
1418 * support any aux_channels */
1419 cmd_status = (*effect)->command(effect,
1420 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1421 cmd_size,
1422 (void*)&cmd,
1423 &reply_size,
1424 (void*)&reply);
1425
1426 if (cmd_status != 0) {
1427 ALOGV("in_read_audio_effect_channel_configs(): "
1428 "fx->command returned %d", cmd_status);
1429 return;
1430 }
1431
1432 if (reply[0] != 0) {
1433 ALOGW("in_read_audio_effect_channel_configs(): "
1434 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1435 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1436 return;
1437 }
1438
1439 /* the feature is not supported */
1440 ALOGV("in_read_audio_effect_channel_configs()(): "
1441 "Feature supported and adding %d channel configs to the list", reply[1]);
1442 effect_info->num_channel_configs = reply[1];
1443 effect_info->channel_configs =
1444 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1445 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1446}
1447
1448
1449#define NUM_IN_AUX_CNL_CONFIGS 2
1450static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1451 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1452 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1453};
1454static uint32_t in_get_aux_channels(struct stream_in *in)
1455{
1456 int i;
1457 channel_config_t new_chcfg = {0, 0};
1458
1459 if (in->num_preprocessors == 0)
1460 return 0;
1461
1462 /* do not enable dual mic configurations when capturing from other microphones than
1463 * main or sub */
1464 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1465 return 0;
1466
1467 /* retain most complex aux channels configuration compatible with requested main channels and
1468 * supported by audio driver and all pre processors */
1469 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1470 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1471 if (cur_chcfg->main_channels == in->main_channels) {
1472 size_t match_cnt;
1473 size_t idx_preproc;
1474 for (idx_preproc = 0, match_cnt = 0;
1475 /* no need to continue if at least one preprocessor doesn't match */
1476 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1477 idx_preproc++) {
1478 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1479 size_t idx_chcfg;
1480
1481 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1482 if (memcmp(effect_info->channel_configs + idx_chcfg,
1483 cur_chcfg,
1484 sizeof(channel_config_t)) == 0) {
1485 match_cnt++;
1486 break;
1487 }
1488 }
1489 }
1490 /* if all preprocessors match, we have a candidate */
1491 if (match_cnt == (size_t)in->num_preprocessors) {
1492 /* retain most complex aux channels configuration */
1493 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1494 new_chcfg = *cur_chcfg;
1495 }
1496 }
1497 }
1498 }
1499
1500 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1501
1502 return new_chcfg.aux_channels;
1503}
1504
1505static int in_configure_effect_channels(effect_handle_t effect,
1506 channel_config_t *channel_config)
1507{
1508 int status = 0;
1509 int fct_status;
1510 int32_t cmd_status;
1511 uint32_t reply_size;
1512 effect_config_t config;
1513 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1514
1515 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1516 channel_config->main_channels,
1517 channel_config->aux_channels);
1518
1519 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1520 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1521 reply_size = sizeof(effect_config_t);
1522 fct_status = (*effect)->command(effect,
1523 EFFECT_CMD_GET_CONFIG,
1524 0,
1525 NULL,
1526 &reply_size,
1527 &config);
1528 if (fct_status != 0) {
1529 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1530 return fct_status;
1531 }
1532
1533 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1534 config.outputCfg.channels = config.inputCfg.channels;
1535 reply_size = sizeof(uint32_t);
1536 fct_status = (*effect)->command(effect,
1537 EFFECT_CMD_SET_CONFIG,
1538 sizeof(effect_config_t),
1539 &config,
1540 &reply_size,
1541 &cmd_status);
1542 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1543
1544 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1545 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1546 reply_size = sizeof(uint32_t);
1547 fct_status = (*effect)->command(effect,
1548 EFFECT_CMD_SET_FEATURE_CONFIG,
1549 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1550 cmd,
1551 &reply_size,
1552 &cmd_status);
1553 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1554
1555 /* some implementations need to be re-enabled after a config change */
1556 reply_size = sizeof(uint32_t);
1557 fct_status = (*effect)->command(effect,
1558 EFFECT_CMD_ENABLE,
1559 0,
1560 NULL,
1561 &reply_size,
1562 &cmd_status);
1563 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1564
1565 return status;
1566}
1567
1568static int in_reconfigure_channels(struct stream_in *in,
1569 effect_handle_t effect,
1570 channel_config_t *channel_config,
1571 bool config_changed) {
1572
1573 int status = 0;
1574
1575 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1576 config_changed, effect);
1577
1578 /* if config changed, reconfigure all previously added effects */
1579 if (config_changed) {
1580 int i;
1581 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1582 for (i = 0; i < in->num_preprocessors; i++)
1583 {
1584 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1585 channel_config);
1586 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1587 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1588 if (cur_status != 0) {
1589 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1590 "%d with channels: [%04x][%04x]",
1591 cur_status,
1592 i,
1593 channel_config->main_channels,
1594 channel_config->aux_channels);
1595 status = cur_status;
1596 }
1597 }
1598 } else if (effect != NULL && channel_config->aux_channels) {
1599 /* if aux channels config did not change but aux channels are present,
1600 * we still need to configure the effect being added */
1601 status = in_configure_effect_channels(effect, channel_config);
1602 }
1603 return status;
1604}
1605
1606static void in_update_aux_channels(struct stream_in *in,
1607 effect_handle_t effect)
1608{
1609 uint32_t aux_channels;
1610 channel_config_t channel_config;
1611 int status;
1612
1613 aux_channels = in_get_aux_channels(in);
1614
1615 channel_config.main_channels = in->main_channels;
1616 channel_config.aux_channels = aux_channels;
1617 status = in_reconfigure_channels(in,
1618 effect,
1619 &channel_config,
1620 (aux_channels != in->aux_channels));
1621
1622 if (status != 0) {
1623 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1624 /* resetting aux channels configuration */
1625 aux_channels = 0;
1626 channel_config.aux_channels = 0;
1627 in_reconfigure_channels(in, effect, &channel_config, true);
1628 }
1629 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1630 if (in->aux_channels != aux_channels) {
1631 in->aux_channels_changed = true;
1632 in->aux_channels = aux_channels;
1633 do_in_standby_l(in);
1634 }
1635}
1636#endif
1637
1638/* This function reads PCM data and:
1639 * - resample if needed
1640 * - process if pre-processors are attached
1641 * - discard unwanted channels
1642 */
1643static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1644{
1645 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001646 size_t src_channels = in->config.channels;
1647 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1648 int i;
1649 void *proc_buf_out;
1650 struct pcm_device *pcm_device;
1651 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1652#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001653 audio_buffer_t in_buf;
1654 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001655 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1656#endif
1657
1658 /* Additional channels might be added on top of main_channels:
1659 * - aux_channels (by processing effects)
1660 * - extra channels due to HW limitations
1661 * In case of additional channels, we cannot work inplace
1662 */
1663 if (has_additional_channels)
1664 proc_buf_out = in->proc_buf_out;
1665 else
1666 proc_buf_out = buffer;
1667
1668 if (list_empty(&in->pcm_dev_list)) {
1669 ALOGE("%s: pcm device list empty", __func__);
1670 return -EINVAL;
1671 }
1672
1673 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1674 struct pcm_device, stream_list_node);
1675
1676#ifdef PREPROCESSING_ENABLED
1677 if (has_processing) {
1678 /* since all the processing below is done in frames and using the config.channels
1679 * as the number of channels, no changes is required in case aux_channels are present */
1680 while (frames_wr < frames) {
1681 /* first reload enough frames at the end of process input buffer */
1682 if (in->proc_buf_frames < (size_t)frames) {
1683 ssize_t frames_rd;
1684 if (in->proc_buf_size < (size_t)frames) {
1685 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1686 in->proc_buf_size = (size_t)frames;
1687 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1688 ALOG_ASSERT((in->proc_buf_in != NULL),
1689 "process_frames() failed to reallocate proc_buf_in");
1690 if (has_additional_channels) {
1691 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1692 ALOG_ASSERT((in->proc_buf_out != NULL),
1693 "process_frames() failed to reallocate proc_buf_out");
1694 proc_buf_out = in->proc_buf_out;
1695 }
1696 }
1697 frames_rd = read_frames(in,
1698 in->proc_buf_in +
1699 in->proc_buf_frames * in->config.channels,
1700 frames - in->proc_buf_frames);
1701 if (frames_rd < 0) {
1702 /* Return error code */
1703 frames_wr = frames_rd;
1704 break;
1705 }
1706 in->proc_buf_frames += frames_rd;
1707 }
1708
1709 if (in->echo_reference != NULL) {
1710 push_echo_reference(in, in->proc_buf_frames);
1711 }
1712
1713 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1714 * the maximum number of frames to be consumed and produced by process() */
1715 in_buf.frameCount = in->proc_buf_frames;
1716 in_buf.s16 = in->proc_buf_in;
1717 out_buf.frameCount = frames - frames_wr;
1718 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1719
1720 /* FIXME: this works because of current pre processing library implementation that
1721 * does the actual process only when the last enabled effect process is called.
1722 * The generic solution is to have an output buffer for each effect and pass it as
1723 * input to the next.
1724 */
1725 for (i = 0; i < in->num_preprocessors; i++) {
1726 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1727 &in_buf,
1728 &out_buf);
1729 }
1730
1731 /* process() has updated the number of frames consumed and produced in
1732 * in_buf.frameCount and out_buf.frameCount respectively
1733 * move remaining frames to the beginning of in->proc_buf_in */
1734 in->proc_buf_frames -= in_buf.frameCount;
1735
1736 if (in->proc_buf_frames) {
1737 memcpy(in->proc_buf_in,
1738 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1739 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1740 }
1741
1742 /* if not enough frames were passed to process(), read more and retry. */
1743 if (out_buf.frameCount == 0) {
1744 ALOGW("No frames produced by preproc");
1745 continue;
1746 }
1747
1748 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1749 frames_wr += out_buf.frameCount;
1750 } else {
1751 /* The effect does not comply to the API. In theory, we should never end up here! */
1752 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1753 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1754 frames_wr = frames;
1755 }
1756 }
1757 }
1758 else
1759#endif //PREPROCESSING_ENABLED
1760 {
1761 /* No processing effects attached */
1762 if (has_additional_channels) {
1763 /* With additional channels, we cannot use original buffer */
1764 if (in->proc_buf_size < (size_t)frames) {
1765 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1766 in->proc_buf_size = (size_t)frames;
1767 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1768 ALOG_ASSERT((in->proc_buf_out != NULL),
1769 "process_frames() failed to reallocate proc_buf_out");
1770 proc_buf_out = in->proc_buf_out;
1771 }
1772 }
1773 frames_wr = read_frames(in, proc_buf_out, frames);
1774 }
1775
1776 /* Remove all additional channels that have been added on top of main_channels:
1777 * - aux_channels
1778 * - extra channels from HW due to HW limitations
1779 * Assumption is made that the channels are interleaved and that the main
1780 * channels are first. */
1781
1782 if (has_additional_channels)
1783 {
1784 int16_t* src_buffer = (int16_t *)proc_buf_out;
1785 int16_t* dst_buffer = (int16_t *)buffer;
1786
1787 if (dst_channels == 1) {
1788 for (i = frames_wr; i > 0; i--)
1789 {
1790 *dst_buffer++ = *src_buffer;
1791 src_buffer += src_channels;
1792 }
1793 } else {
1794 for (i = frames_wr; i > 0; i--)
1795 {
1796 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1797 dst_buffer += dst_channels;
1798 src_buffer += src_channels;
1799 }
1800 }
1801 }
1802
1803 return frames_wr;
1804}
1805
1806static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1807 struct resampler_buffer* buffer)
1808{
1809 struct stream_in *in;
1810 struct pcm_device *pcm_device;
1811
1812 if (buffer_provider == NULL || buffer == NULL)
1813 return -EINVAL;
1814
1815 in = (struct stream_in *)((char *)buffer_provider -
1816 offsetof(struct stream_in, buf_provider));
1817
1818 if (list_empty(&in->pcm_dev_list)) {
1819 buffer->raw = NULL;
1820 buffer->frame_count = 0;
1821 in->read_status = -ENODEV;
1822 return -ENODEV;
1823 }
1824
1825 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1826 struct pcm_device, stream_list_node);
1827
1828 if (in->read_buf_frames == 0) {
1829 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1830 if (in->read_buf_size < in->config.period_size) {
1831 in->read_buf_size = in->config.period_size;
1832 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
1833 ALOG_ASSERT((in->read_buf != NULL),
1834 "get_next_buffer() failed to reallocate read_buf");
1835 }
1836
1837 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
1838
1839 if (in->read_status != 0) {
1840 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1841 buffer->raw = NULL;
1842 buffer->frame_count = 0;
1843 return in->read_status;
1844 }
1845 in->read_buf_frames = in->config.period_size;
1846
1847#ifdef PREPROCESSING_ENABLED
1848#ifdef HW_AEC_LOOPBACK
1849 if (in->hw_echo_reference) {
1850 struct pcm_device *temp_device = NULL;
1851 struct pcm_device *ref_device = NULL;
1852 struct listnode *node = NULL;
1853 struct echo_reference_buffer b;
1854 size_t size_hw_ref_bytes;
1855 size_t size_hw_ref_frames;
1856 int read_status = 0;
1857
1858 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1859 struct pcm_device, stream_list_node);
1860 list_for_each(node, &in->pcm_dev_list) {
1861 temp_device = node_to_item(node, struct pcm_device, stream_list_node);
1862 if (temp_device->pcm_profile->id == 1) {
1863 ref_device = temp_device;
1864 break;
1865 }
1866 }
1867 if (ref_device) {
1868 size_hw_ref_bytes = pcm_frames_to_bytes(ref_device->pcm, ref_device->pcm_profile->config.period_size);
1869 size_hw_ref_frames = ref_device->pcm_profile->config.period_size;
1870 if (in->hw_ref_buf_size < size_hw_ref_frames) {
1871 in->hw_ref_buf_size = size_hw_ref_frames;
1872 in->hw_ref_buf = (int16_t *) realloc(in->hw_ref_buf, size_hw_ref_bytes);
1873 ALOG_ASSERT((in->hw_ref_buf != NULL),
1874 "get_next_buffer() failed to reallocate hw_ref_buf");
1875 ALOGV("get_next_buffer(): hw_ref_buf %p extended to %zd bytes",
1876 in->hw_ref_buf, size_hw_ref_bytes);
1877 }
1878
1879 read_status = pcm_read(ref_device->pcm, (void*)in->hw_ref_buf, size_hw_ref_bytes);
1880 if (read_status != 0) {
1881 ALOGE("process_frames() pcm_read error for HW reference %d", read_status);
1882 b.raw = NULL;
1883 b.frame_count = 0;
1884 }
1885 else {
1886 get_capture_reference_delay(in, size_hw_ref_frames, &b);
1887 b.raw = (void *)in->hw_ref_buf;
1888 b.frame_count = size_hw_ref_frames;
1889 if (b.delay_ns != 0)
1890 b.delay_ns = -b.delay_ns; // as this is capture delay, it needs to be subtracted from the microphone delay
1891 in->echo_reference->write(in->echo_reference, &b);
1892 }
1893 }
1894 }
1895#endif // HW_AEC_LOOPBACK
1896#endif // PREPROCESSING_ENABLED
1897 }
1898
1899 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
1900 in->read_buf_frames : buffer->frame_count;
1901 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
1902 in->config.channels;
1903 return in->read_status;
1904}
1905
1906static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1907 struct resampler_buffer* buffer)
1908{
1909 struct stream_in *in;
1910
1911 if (buffer_provider == NULL || buffer == NULL)
1912 return;
1913
1914 in = (struct stream_in *)((char *)buffer_provider -
1915 offsetof(struct stream_in, buf_provider));
1916
1917 in->read_buf_frames -= buffer->frame_count;
1918}
1919
1920/* read_frames() reads frames from kernel driver, down samples to capture rate
1921 * if necessary and output the number of frames requested to the buffer specified */
1922static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
1923{
1924 ssize_t frames_wr = 0;
1925
1926 struct pcm_device *pcm_device;
1927
1928 if (list_empty(&in->pcm_dev_list)) {
1929 ALOGE("%s: pcm device list empty", __func__);
1930 return -EINVAL;
1931 }
1932
1933 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1934 struct pcm_device, stream_list_node);
1935
1936 while (frames_wr < frames) {
1937 size_t frames_rd = frames - frames_wr;
1938 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
1939 __func__,frames_rd,frames_wr,in->config.channels);
1940 if (in->resampler != NULL) {
1941 in->resampler->resample_from_provider(in->resampler,
1942 (int16_t *)((char *)buffer +
1943 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
1944 &frames_rd);
1945 } else {
1946 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01001947 .raw = NULL,
1948 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001949 };
1950 get_next_buffer(&in->buf_provider, &buf);
1951 if (buf.raw != NULL) {
1952 memcpy((char *)buffer +
1953 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
1954 buf.raw,
1955 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
1956 frames_rd = buf.frame_count;
1957 }
1958 release_buffer(&in->buf_provider, &buf);
1959 }
1960 /* in->read_status is updated by getNextBuffer() also called by
1961 * in->resampler->resample_from_provider() */
1962 if (in->read_status != 0)
1963 return in->read_status;
1964
1965 frames_wr += frames_rd;
1966 }
1967 return frames_wr;
1968}
1969
1970static int in_release_pcm_devices(struct stream_in *in)
1971{
1972 struct pcm_device *pcm_device;
1973 struct listnode *node;
1974 struct listnode *next;
1975
1976 list_for_each_safe(node, next, &in->pcm_dev_list) {
1977 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
1978 list_remove(node);
1979 free(pcm_device);
1980 }
1981
1982 return 0;
1983}
1984
1985static int stop_input_stream(struct stream_in *in)
1986{
1987 struct audio_usecase *uc_info;
1988 struct audio_device *adev = in->dev;
1989
1990 adev->active_input = NULL;
1991 ALOGV("%s: enter: usecase(%d: %s)", __func__,
1992 in->usecase, use_case_table[in->usecase]);
1993 uc_info = get_usecase_from_id(adev, in->usecase);
1994 if (uc_info == NULL) {
1995 ALOGE("%s: Could not find the usecase (%d) in the list",
1996 __func__, in->usecase);
1997 return -EINVAL;
1998 }
1999
2000 /* Disable the tx device */
2001 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2002
2003 list_remove(&uc_info->adev_list_node);
2004 free(uc_info);
2005
2006 if (list_empty(&in->pcm_dev_list)) {
2007 ALOGE("%s: pcm device list empty", __func__);
2008 return -EINVAL;
2009 }
2010
2011 in_release_pcm_devices(in);
2012 list_init(&in->pcm_dev_list);
2013
2014#ifdef HW_AEC_LOOPBACK
2015 if (in->hw_echo_reference)
2016 {
2017 in->hw_echo_reference = false;
2018 }
2019#endif
2020
2021 ALOGV("%s: exit", __func__);
2022 return 0;
2023}
2024
2025static int start_input_stream(struct stream_in *in)
2026{
2027 /* Enable output device and stream routing controls */
2028 int ret = 0;
2029 bool recreate_resampler = false;
2030 struct audio_usecase *uc_info;
2031 struct audio_device *adev = in->dev;
2032 struct pcm_device_profile *pcm_profile;
2033 struct pcm_device *pcm_device;
2034
2035 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2036 adev->active_input = in;
2037 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2038 if (pcm_profile == NULL) {
2039 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2040 __func__, in->usecase);
2041 ret = -EINVAL;
2042 goto error_config;
2043 }
2044
2045 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002046 if (uc_info == NULL) {
2047 ret = -ENOMEM;
2048 goto error_config;
2049 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002050 uc_info->id = in->usecase;
2051 uc_info->type = PCM_CAPTURE;
2052 uc_info->stream = (struct audio_stream *)in;
2053 uc_info->devices = in->devices;
2054 uc_info->in_snd_device = SND_DEVICE_NONE;
2055 uc_info->out_snd_device = SND_DEVICE_NONE;
2056
2057 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002058 if (pcm_device == NULL) {
2059 free(uc_info);
2060 ret = -ENOMEM;
2061 goto error_config;
2062 }
2063
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002064 pcm_device->pcm_profile = pcm_profile;
2065 list_init(&in->pcm_dev_list);
2066 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2067
2068 list_init(&uc_info->mixer_list);
2069 list_add_tail(&uc_info->mixer_list,
2070 &adev_get_mixer_for_card(adev,
2071 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2072
2073 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2074
2075 select_devices(adev, in->usecase);
2076
2077 /* Config should be updated as profile can be changed between different calls
2078 * to this function:
2079 * - Trigger resampler creation
2080 * - Config needs to be updated */
2081 if (in->config.rate != pcm_profile->config.rate) {
2082 recreate_resampler = true;
2083 }
2084 in->config = pcm_profile->config;
2085
2086#ifdef PREPROCESSING_ENABLED
2087 if (in->aux_channels_changed) {
2088 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2089 recreate_resampler = true;
2090 }
2091#endif
2092
2093 if (in->requested_rate != in->config.rate) {
2094 recreate_resampler = true;
2095 }
2096
2097 if (recreate_resampler) {
2098 if (in->resampler) {
2099 release_resampler(in->resampler);
2100 in->resampler = NULL;
2101 }
2102 in->buf_provider.get_next_buffer = get_next_buffer;
2103 in->buf_provider.release_buffer = release_buffer;
2104 ret = create_resampler(in->config.rate,
2105 in->requested_rate,
2106 in->config.channels,
2107 RESAMPLER_QUALITY_DEFAULT,
2108 &in->buf_provider,
2109 &in->resampler);
2110 }
2111
2112#ifdef PREPROCESSING_ENABLED
2113 if (in->enable_aec && in->echo_reference == NULL) {
2114 in->echo_reference = get_echo_reference(adev,
2115 AUDIO_FORMAT_PCM_16_BIT,
2116 audio_channel_count_from_in_mask(in->main_channels),
2117 in->requested_rate
2118 );
2119 }
2120
2121#ifdef HW_AEC_LOOPBACK
2122 if (in->enable_aec) {
2123 ret = get_hw_echo_reference(in);
2124 if (ret!=0)
2125 goto error_open;
2126
2127 /* force ref buffer reallocation */
2128 in->hw_ref_buf_size = 0;
2129 }
2130#endif
2131#endif
2132
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002133 if (in->dev->voice.in_call) {
2134 ALOGV("%s: in_call, not handling PCMs", __func__);
2135 goto skip_pcm_handling;
2136 }
2137
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002138 /* Open the PCM device.
2139 * The HW is limited to support only the default pcm_profile settings.
2140 * As such a change in aux_channels will not have an effect.
2141 */
2142 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2143 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2144 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2145 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2146
2147 if (pcm_profile->type == PCM_HOTWORD_STREAMING) {
2148 if (!adev->sound_trigger_open_for_streaming) {
2149 ALOGE("%s: No handle to sound trigger HAL", __func__);
2150 ret = -EIO;
2151 goto error_open;
2152 }
2153 pcm_device->pcm = NULL;
2154 pcm_device->sound_trigger_handle = adev->sound_trigger_open_for_streaming();
2155 if (pcm_device->sound_trigger_handle <= 0) {
2156 ALOGE("%s: Failed to open DSP for streaming", __func__);
2157 ret = -EIO;
2158 goto error_open;
2159 }
2160 ALOGV("Opened DSP successfully");
2161 } else {
2162 pcm_device->sound_trigger_handle = 0;
2163 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2164 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2165
2166 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2167 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2168 pcm_close(pcm_device->pcm);
2169 pcm_device->pcm = NULL;
2170 ret = -EIO;
2171 goto error_open;
2172 }
2173 }
2174
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002175skip_pcm_handling:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002176 /* force read and proc buffer reallocation in case of frame size or
2177 * channel count change */
2178 in->proc_buf_frames = 0;
2179 in->proc_buf_size = 0;
2180 in->read_buf_size = 0;
2181 in->read_buf_frames = 0;
2182
2183 /* if no supported sample rate is available, use the resampler */
2184 if (in->resampler) {
2185 in->resampler->reset(in->resampler);
2186 }
2187
2188 ALOGV("%s: exit", __func__);
2189 return ret;
2190
2191error_open:
2192 if (in->resampler) {
2193 release_resampler(in->resampler);
2194 in->resampler = NULL;
2195 }
2196 stop_input_stream(in);
2197
2198error_config:
2199 ALOGV("%s: exit: status(%d)", __func__, ret);
2200 adev->active_input = NULL;
2201 return ret;
2202}
2203
2204void lock_input_stream(struct stream_in *in)
2205{
2206 pthread_mutex_lock(&in->pre_lock);
2207 pthread_mutex_lock(&in->lock);
2208 pthread_mutex_unlock(&in->pre_lock);
2209}
2210
2211void lock_output_stream(struct stream_out *out)
2212{
2213 pthread_mutex_lock(&out->pre_lock);
2214 pthread_mutex_lock(&out->lock);
2215 pthread_mutex_unlock(&out->pre_lock);
2216}
2217
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002218static int uc_release_pcm_devices(struct audio_usecase *usecase)
2219{
2220 struct stream_out *out = (struct stream_out *)usecase->stream;
2221 struct pcm_device *pcm_device;
2222 struct listnode *node;
2223 struct listnode *next;
2224
2225 list_for_each_safe(node, next, &out->pcm_dev_list) {
2226 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2227 list_remove(node);
2228 free(pcm_device);
2229 }
2230 list_init(&usecase->mixer_list);
2231
2232 return 0;
2233}
2234
2235static int uc_select_pcm_devices(struct audio_usecase *usecase)
2236
2237{
2238 struct stream_out *out = (struct stream_out *)usecase->stream;
2239 struct pcm_device *pcm_device;
2240 struct pcm_device_profile *pcm_profile;
2241 struct mixer_card *mixer_card;
2242 audio_devices_t devices = usecase->devices;
2243
2244 list_init(&usecase->mixer_list);
2245 list_init(&out->pcm_dev_list);
2246
2247 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2248 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002249 if (pcm_device == NULL) {
2250 return -ENOMEM;
2251 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002252 pcm_device->pcm_profile = pcm_profile;
2253 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2254 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2255 if (mixer_card == NULL) {
2256 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2257 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2258 }
2259 devices &= ~pcm_profile->devices;
2260 }
2261
2262 return 0;
2263}
2264
2265static int out_close_pcm_devices(struct stream_out *out)
2266{
2267 struct pcm_device *pcm_device;
2268 struct listnode *node;
2269 struct audio_device *adev = out->dev;
2270
2271 list_for_each(node, &out->pcm_dev_list) {
2272 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2273 if (pcm_device->sound_trigger_handle > 0) {
2274 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
2275 pcm_device->sound_trigger_handle = 0;
2276 }
2277 if (pcm_device->pcm) {
2278 pcm_close(pcm_device->pcm);
2279 pcm_device->pcm = NULL;
2280 }
2281 if (pcm_device->resampler) {
2282 release_resampler(pcm_device->resampler);
2283 pcm_device->resampler = NULL;
2284 }
2285 if (pcm_device->res_buffer) {
2286 free(pcm_device->res_buffer);
2287 pcm_device->res_buffer = NULL;
2288 }
2289 }
2290
2291 return 0;
2292}
2293
2294static int out_open_pcm_devices(struct stream_out *out)
2295{
2296 struct pcm_device *pcm_device;
2297 struct listnode *node;
2298 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002299 int pcm_device_card;
2300 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002301
2302 list_for_each(node, &out->pcm_dev_list) {
2303 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002304 pcm_device_card = pcm_device->pcm_profile->card;
2305 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002306
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002307 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2308 pcm_device_id = pcm_device_deep_buffer.id;
2309
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002310 if (out->dev->voice.in_call) {
2311 ALOGV("%s: in_call, not opening PCMs", __func__);
2312 return ret;
2313 }
2314
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002315 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2316 __func__, pcm_device_card, pcm_device_id);
2317
2318 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002319 PCM_OUT | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2320
2321 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2322 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2323 pcm_device->pcm = NULL;
2324 ret = -EIO;
2325 goto error_open;
2326 }
2327 /*
2328 * If the stream rate differs from the PCM rate, we need to
2329 * create a resampler.
2330 */
2331 if (out->sample_rate != pcm_device->pcm_profile->config.rate) {
2332 ALOGV("%s: create_resampler(), pcm_device_card(%d), pcm_device_id(%d), \
2333 out_rate(%d), device_rate(%d)",__func__,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002334 pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002335 out->sample_rate, pcm_device->pcm_profile->config.rate);
2336 ret = create_resampler(out->sample_rate,
2337 pcm_device->pcm_profile->config.rate,
2338 audio_channel_count_from_out_mask(out->channel_mask),
2339 RESAMPLER_QUALITY_DEFAULT,
2340 NULL,
2341 &pcm_device->resampler);
2342 pcm_device->res_byte_count = 0;
2343 pcm_device->res_buffer = NULL;
2344 }
2345 }
2346 return ret;
2347
2348error_open:
2349 out_close_pcm_devices(out);
2350 return ret;
2351}
2352
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002353int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002354{
2355 struct audio_device *adev = out->dev;
2356 struct audio_usecase *uc_info;
2357
2358 uc_info = get_usecase_from_id(adev, out->usecase);
2359 if (uc_info == NULL) {
2360 ALOGE("%s: Could not find the usecase (%d) in the list",
2361 __func__, out->usecase);
2362 return -EINVAL;
2363 }
2364 disable_snd_device(adev, uc_info, uc_info->out_snd_device, true);
2365 uc_release_pcm_devices(uc_info);
2366 list_remove(&uc_info->adev_list_node);
2367 free(uc_info);
2368
2369 return 0;
2370}
2371
Andreas Schneider56204f62017-01-31 08:17:32 +01002372int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002373{
2374 struct audio_device *adev = out->dev;
2375 struct audio_usecase *uc_info;
2376
2377 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002378 if (uc_info == NULL) {
2379 return -ENOMEM;
2380 }
2381
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002382 uc_info->id = out->usecase;
2383 uc_info->type = PCM_PLAYBACK;
2384 uc_info->stream = (struct audio_stream *)out;
2385 uc_info->devices = out->devices;
2386 uc_info->in_snd_device = SND_DEVICE_NONE;
2387 uc_info->out_snd_device = SND_DEVICE_NONE;
2388 uc_select_pcm_devices(uc_info);
2389
2390 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2391 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002392
2393 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002394}
2395
2396static int stop_output_stream(struct stream_out *out)
2397{
2398 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002399 bool do_disable = true;
2400
2401 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2402 out->usecase, use_case_table[out->usecase]);
2403
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002404 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002405
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002406 if (do_disable)
2407 ret = disable_output_path_l(out);
2408
2409 ALOGV("%s: exit: status(%d)", __func__, ret);
2410 return ret;
2411}
2412
2413static int start_output_stream(struct stream_out *out)
2414{
2415 int ret = 0;
2416 struct audio_device *adev = out->dev;
2417
2418 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2419 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2420
Andreas Schneider56204f62017-01-31 08:17:32 +01002421 ret = enable_output_path_l(out);
2422 if (ret != 0) {
2423 goto error_config;
2424 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002425
2426 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2427 out->compr = NULL;
2428 ret = out_open_pcm_devices(out);
2429 if (ret != 0)
2430 goto error_open;
2431#ifdef PREPROCESSING_ENABLED
2432 out->echo_reference = NULL;
2433 out->echo_reference_generation = adev->echo_reference_generation;
2434 if (adev->echo_reference != NULL)
2435 out->echo_reference = adev->echo_reference;
2436#endif
2437 } else {
2438 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2439 COMPRESS_IN, &out->compr_config);
2440 if (out->compr && !is_compress_ready(out->compr)) {
2441 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2442 compress_close(out->compr);
2443 out->compr = NULL;
2444 ret = -EIO;
2445 goto error_open;
2446 }
2447 if (out->offload_callback)
2448 compress_nonblock(out->compr, out->non_blocking);
2449
2450 if (adev->offload_fx_start_output != NULL)
2451 adev->offload_fx_start_output(out->handle);
2452 }
2453 ALOGV("%s: exit", __func__);
2454 return 0;
2455error_open:
2456 stop_output_stream(out);
2457error_config:
2458 return ret;
2459}
2460
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002461int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002462{
2463 struct audio_usecase *uc_info;
2464
2465 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002466 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002467
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002468 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002469
2470 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2471 if (uc_info == NULL) {
2472 ALOGE("%s: Could not find the usecase (%d) in the list",
2473 __func__, USECASE_VOICE_CALL);
2474 return -EINVAL;
2475 }
2476
2477 disable_snd_device(adev, uc_info, uc_info->out_snd_device, false);
2478 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2479
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002480 list_remove(&uc_info->adev_list_node);
2481 free(uc_info);
2482
2483 ALOGV("%s: exit", __func__);
2484 return 0;
2485}
2486
2487/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002488int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002489{
2490 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002491 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002492
2493 ALOGV("%s: enter", __func__);
2494
2495 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002496 if (uc_info == NULL) {
2497 ret = -ENOMEM;
2498 goto exit;
2499 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002500 /*
2501 * We set this early so that functions called after this is being set
2502 * can use it. It is e.g. needed in select_devices() to inform the RILD
2503 * which output device we use.
2504 */
2505 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002506
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002507 uc_info->id = USECASE_VOICE_CALL;
2508 uc_info->type = VOICE_CALL;
2509 uc_info->stream = (struct audio_stream *)adev->primary_output;
2510 uc_info->devices = adev->primary_output->devices;
2511 uc_info->in_snd_device = SND_DEVICE_NONE;
2512 uc_info->out_snd_device = SND_DEVICE_NONE;
2513
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002514 list_init(&uc_info->mixer_list);
2515 list_add_tail(&uc_info->mixer_list,
2516 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002517
2518 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2519
2520 select_devices(adev, USECASE_VOICE_CALL);
2521
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002522 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002523
2524 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002525 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002526
Andreas Schneider56204f62017-01-31 08:17:32 +01002527exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002528 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002529 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002530}
2531
2532static int check_input_parameters(uint32_t sample_rate,
2533 audio_format_t format,
2534 int channel_count)
2535{
2536 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2537
2538 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2539
2540 switch (sample_rate) {
2541 case 8000:
2542 case 11025:
2543 case 12000:
2544 case 16000:
2545 case 22050:
2546 case 24000:
2547 case 32000:
2548 case 44100:
2549 case 48000:
2550 break;
2551 default:
2552 return -EINVAL;
2553 }
2554
2555 return 0;
2556}
2557
2558static size_t get_input_buffer_size(uint32_t sample_rate,
2559 audio_format_t format,
2560 int channel_count,
2561 usecase_type_t usecase_type,
2562 audio_devices_t devices)
2563{
2564 size_t size = 0;
2565 struct pcm_device_profile *pcm_profile;
2566
2567 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2568 return 0;
2569
2570 pcm_profile = get_pcm_device(usecase_type, devices);
2571 if (pcm_profile == NULL)
2572 return 0;
2573
2574 /*
2575 * take resampling into account and return the closest majoring
2576 * multiple of 16 frames, as audioflinger expects audio buffers to
2577 * be a multiple of 16 frames
2578 */
2579 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2580 size = ((size + 15) / 16) * 16;
2581
2582 return (size * channel_count * audio_bytes_per_sample(format));
2583
2584}
2585
2586static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2587{
2588 struct stream_out *out = (struct stream_out *)stream;
2589
2590 return out->sample_rate;
2591}
2592
2593static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2594{
2595 (void)stream;
2596 (void)rate;
2597 return -ENOSYS;
2598}
2599
2600static size_t out_get_buffer_size(const struct audio_stream *stream)
2601{
2602 struct stream_out *out = (struct stream_out *)stream;
2603
2604 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2605 return out->compr_config.fragment_size;
2606 }
2607
2608 return out->config.period_size *
2609 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2610}
2611
2612static uint32_t out_get_channels(const struct audio_stream *stream)
2613{
2614 struct stream_out *out = (struct stream_out *)stream;
2615
2616 return out->channel_mask;
2617}
2618
2619static audio_format_t out_get_format(const struct audio_stream *stream)
2620{
2621 struct stream_out *out = (struct stream_out *)stream;
2622
2623 return out->format;
2624}
2625
2626static int out_set_format(struct audio_stream *stream, audio_format_t format)
2627{
2628 (void)stream;
2629 (void)format;
2630 return -ENOSYS;
2631}
2632
2633static int do_out_standby_l(struct stream_out *out)
2634{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002635 int status = 0;
2636
2637 out->standby = true;
2638 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2639 out_close_pcm_devices(out);
2640#ifdef PREPROCESSING_ENABLED
2641 /* stop writing to echo reference */
2642 if (out->echo_reference != NULL) {
2643 out->echo_reference->write(out->echo_reference, NULL);
2644 if (out->echo_reference_generation != adev->echo_reference_generation) {
2645 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2646 release_echo_reference(out->echo_reference);
2647 out->echo_reference_generation = adev->echo_reference_generation;
2648 }
2649 out->echo_reference = NULL;
2650 }
2651#endif
2652 } else {
2653 stop_compressed_output_l(out);
2654 out->gapless_mdata.encoder_delay = 0;
2655 out->gapless_mdata.encoder_padding = 0;
2656 if (out->compr != NULL) {
2657 compress_close(out->compr);
2658 out->compr = NULL;
2659 }
2660 }
2661 status = stop_output_stream(out);
2662
2663 return status;
2664}
2665
2666static int out_standby(struct audio_stream *stream)
2667{
2668 struct stream_out *out = (struct stream_out *)stream;
2669 struct audio_device *adev = out->dev;
2670
2671 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2672 out->usecase, use_case_table[out->usecase]);
2673 lock_output_stream(out);
2674 if (!out->standby) {
2675 pthread_mutex_lock(&adev->lock);
2676 do_out_standby_l(out);
2677 pthread_mutex_unlock(&adev->lock);
2678 }
2679 pthread_mutex_unlock(&out->lock);
2680 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002681
2682 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2683
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002684 return 0;
2685}
2686
2687static int out_dump(const struct audio_stream *stream, int fd)
2688{
2689 (void)stream;
2690 (void)fd;
2691
2692 return 0;
2693}
2694
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002695static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2696{
2697 struct stream_out *out = (struct stream_out *)stream;
2698 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002699 struct listnode *node;
2700 struct str_parms *parms;
2701 char value[32];
2702 int ret, val = 0;
2703 struct audio_usecase *uc_info;
2704 bool do_standby = false;
2705 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002706#ifdef PREPROCESSING_ENABLED
2707 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2708#endif
2709
2710 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%d) adev->mode(%d)",
2711 __func__, out->usecase, use_case_table[out->usecase], kvpairs, out->devices, adev->mode);
2712 parms = str_parms_create_str(kvpairs);
2713 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2714 if (ret >= 0) {
2715 val = atoi(value);
2716 pthread_mutex_lock(&adev->lock_inputs);
2717 lock_output_stream(out);
2718 pthread_mutex_lock(&adev->lock);
2719#ifdef PREPROCESSING_ENABLED
2720 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2721 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2722 /* reset active input:
2723 * - to attach the echo reference
2724 * - because a change in output device may change mic settings */
2725 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2726 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2727 in = adev->active_input;
2728 }
2729 }
2730#endif
2731 if (val != 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002732 bool bt_sco_active = false;
2733
2734 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2735 bt_sco_active = true;
2736 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002737 out->devices = val;
2738
2739 if (!out->standby) {
2740 uc_info = get_usecase_from_id(adev, out->usecase);
2741 if (uc_info == NULL) {
2742 ALOGE("%s: Could not find the usecase (%d) in the list",
2743 __func__, out->usecase);
2744 } else {
2745 list_for_each(node, &out->pcm_dev_list) {
2746 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2747 if ((pcm_device->pcm_profile->devices & val) == 0)
2748 do_standby = true;
2749 val &= ~pcm_device->pcm_profile->devices;
2750 }
2751 if (val != 0)
2752 do_standby = true;
2753 }
2754 if (do_standby)
2755 do_out_standby_l(out);
2756 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002757 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2758 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002759 select_devices(adev, out->usecase);
2760 }
2761 }
2762
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002763 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002764 (out == adev->primary_output)) {
2765 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002766 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2767 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002768 (out == adev->primary_output)) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002769 /* Turn on bluetooth if needed */
2770 if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
2771 start_voice_session_bt_sco(adev->voice.session);
2772 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002773 select_devices(adev, USECASE_VOICE_CALL);
2774 }
2775 }
2776
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002777 if ((adev->mode == AUDIO_MODE_NORMAL) && adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002778 (out == adev->primary_output)) {
2779 stop_voice_call(adev);
2780 }
2781 pthread_mutex_unlock(&adev->lock);
2782 pthread_mutex_unlock(&out->lock);
2783#ifdef PREPROCESSING_ENABLED
2784 if (in) {
2785 /* The lock on adev->lock_inputs prevents input stream from being closed */
2786 lock_input_stream(in);
2787 pthread_mutex_lock(&adev->lock);
2788 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2789 do_in_standby_l(in);
2790 pthread_mutex_unlock(&adev->lock);
2791 pthread_mutex_unlock(&in->lock);
2792 }
2793#endif
2794 pthread_mutex_unlock(&adev->lock_inputs);
2795 }
2796
2797 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2798 parse_compress_metadata(out, parms);
2799 }
2800
2801 str_parms_destroy(parms);
2802
2803 if (ret > 0)
2804 ret = 0;
2805 ALOGV("%s: exit: code(%d)", __func__, ret);
2806 return ret;
2807}
2808
2809static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2810{
2811 struct stream_out *out = (struct stream_out *)stream;
2812 struct str_parms *query = str_parms_create_str(keys);
2813 char *str;
2814 char value[256];
2815 struct str_parms *reply = str_parms_create();
2816 size_t i, j;
2817 int ret;
2818 bool first = true;
2819 ALOGV("%s: enter: keys - %s", __func__, keys);
2820 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2821 if (ret >= 0) {
2822 value[0] = '\0';
2823 i = 0;
2824 while (out->supported_channel_masks[i] != 0) {
2825 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2826 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2827 if (!first) {
2828 strcat(value, "|");
2829 }
2830 strcat(value, out_channels_name_to_enum_table[j].name);
2831 first = false;
2832 break;
2833 }
2834 }
2835 i++;
2836 }
2837 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2838 str = str_parms_to_str(reply);
2839 } else {
2840 str = strdup(keys);
2841 }
2842 str_parms_destroy(query);
2843 str_parms_destroy(reply);
2844 ALOGV("%s: exit: returns - %s", __func__, str);
2845 return str;
2846}
2847
2848static uint32_t out_get_latency(const struct audio_stream_out *stream)
2849{
2850 struct stream_out *out = (struct stream_out *)stream;
2851
2852 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2853 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2854
2855 return (out->config.period_count * out->config.period_size * 1000) /
2856 (out->config.rate);
2857}
2858
2859static int out_set_volume(struct audio_stream_out *stream, float left,
2860 float right)
2861{
2862 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002863
2864 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2865 /* only take left channel into account: the API is for stereo anyway */
2866 out->muted = (left == 0.0f);
2867 return 0;
2868 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002869 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002870 }
2871
2872 return -ENOSYS;
2873}
2874
Andreas Schneider3b643832017-01-31 11:48:22 +01002875#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002876static int fast_set_affinity(pid_t tid) {
2877 cpu_set_t cpu_set;
2878 int cpu_num;
2879 const char *irq_procfs = "/proc/asound/irq_affinity";
2880 FILE *fp;
2881
2882 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2883 ALOGW("Procfs node %s not found", irq_procfs);
2884 return -1;
2885 }
2886
2887 if (fscanf(fp, "%d", &cpu_num) != 1) {
2888 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2889 fclose(fp);
2890 return -1;
2891 }
2892 fclose(fp);
2893
2894 CPU_ZERO(&cpu_set);
2895 CPU_SET(cpu_num, &cpu_set);
2896 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2897}
Andreas Schneider3b643832017-01-31 11:48:22 +01002898#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002899
2900static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2901 size_t bytes)
2902{
2903 struct stream_out *out = (struct stream_out *)stream;
2904 struct audio_device *adev = out->dev;
2905 ssize_t ret = 0;
2906 struct pcm_device *pcm_device;
2907 struct listnode *node;
2908 size_t frame_size = audio_stream_out_frame_size(stream);
2909 size_t frames_wr = 0, frames_rq = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002910#ifdef PREPROCESSING_ENABLED
2911 size_t in_frames = bytes / frame_size;
2912 size_t out_frames = in_frames;
2913 struct stream_in *in = NULL;
2914#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002915
2916 lock_output_stream(out);
2917
Andreas Schneider3b643832017-01-31 11:48:22 +01002918#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002919 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002920 pid_t tid = gettid();
2921 int err;
2922
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002923 err = fast_set_affinity(tid);
2924 if (err < 0) {
2925 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2926 }
2927 out->is_fastmixer_affinity_set = true;
2928 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002929#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002930
2931 if (out->standby) {
2932#ifdef PREPROCESSING_ENABLED
2933 pthread_mutex_unlock(&out->lock);
2934 /* Prevent input stream from being closed */
2935 pthread_mutex_lock(&adev->lock_inputs);
2936 lock_output_stream(out);
2937 if (!out->standby) {
2938 pthread_mutex_unlock(&adev->lock_inputs);
2939 goto false_alarm;
2940 }
2941#endif
2942 pthread_mutex_lock(&adev->lock);
2943 ret = start_output_stream(out);
2944 /* ToDo: If use case is compress offload should return 0 */
2945 if (ret != 0) {
2946 pthread_mutex_unlock(&adev->lock);
2947#ifdef PREPROCESSING_ENABLED
2948 pthread_mutex_unlock(&adev->lock_inputs);
2949#endif
2950 goto exit;
2951 }
2952 out->standby = false;
2953
2954#ifdef PREPROCESSING_ENABLED
2955 /* A change in output device may change the microphone selection */
2956 if (adev->active_input &&
2957 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2958 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2959 in = adev->active_input;
2960 ALOGV("%s: enter:) force_input_standby true", __func__);
2961 }
2962#endif
2963 pthread_mutex_unlock(&adev->lock);
2964#ifdef PREPROCESSING_ENABLED
2965 if (!in) {
2966 /* Leave mutex locked iff in != NULL */
2967 pthread_mutex_unlock(&adev->lock_inputs);
2968 }
2969#endif
2970 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002971#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002972false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002973#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002974
2975 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002976 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002977 return ret;
2978 } else {
2979#ifdef PREPROCESSING_ENABLED
2980 if (android_atomic_acquire_load(&adev->echo_reference_generation)
2981 != out->echo_reference_generation) {
2982 pthread_mutex_lock(&adev->lock);
2983 if (out->echo_reference != NULL) {
2984 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2985 release_echo_reference(out->echo_reference);
2986 }
2987 // note that adev->echo_reference_generation here can be different from the one
2988 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
2989 // with what has been set by get_echo_reference() or put_echo_reference()
2990 out->echo_reference_generation = adev->echo_reference_generation;
2991 out->echo_reference = adev->echo_reference;
2992 ALOGV("%s: update echo reference generation %d", __func__,
2993 out->echo_reference_generation);
2994 pthread_mutex_unlock(&adev->lock);
2995 }
2996#endif
2997
2998 if (out->muted)
2999 memset((void *)buffer, 0, bytes);
3000 list_for_each(node, &out->pcm_dev_list) {
3001 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3002 if (pcm_device->resampler) {
3003 if (bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size
3004 > pcm_device->res_byte_count) {
3005 pcm_device->res_byte_count =
3006 bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size;
3007 pcm_device->res_buffer =
3008 realloc(pcm_device->res_buffer, pcm_device->res_byte_count);
3009 ALOGV("%s: resampler res_byte_count = %zu", __func__,
3010 pcm_device->res_byte_count);
3011 }
3012 frames_rq = bytes / frame_size;
3013 frames_wr = pcm_device->res_byte_count / frame_size;
3014 ALOGVV("%s: resampler request frames = %d frame_size = %d",
3015 __func__, frames_rq, frame_size);
3016 pcm_device->resampler->resample_from_input(pcm_device->resampler,
3017 (int16_t *)buffer, &frames_rq, (int16_t *)pcm_device->res_buffer, &frames_wr);
3018 ALOGVV("%s: resampler output frames_= %d", __func__, frames_wr);
3019 }
3020 if (pcm_device->pcm) {
3021#ifdef PREPROCESSING_ENABLED
3022 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
3023 struct echo_reference_buffer b;
3024 b.raw = (void *)buffer;
3025 b.frame_count = in_frames;
3026
3027 get_playback_delay(out, out_frames, &b);
3028 out->echo_reference->write(out->echo_reference, &b);
3029 }
3030#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003031 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
3032 if (pcm_device->resampler && pcm_device->res_buffer)
3033 pcm_device->status =
3034 pcm_write(pcm_device->pcm, (void *)pcm_device->res_buffer,
3035 frames_wr * frame_size);
3036 else
3037 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
3038 if (pcm_device->status != 0)
3039 ret = pcm_device->status;
3040 }
3041 }
3042 if (ret == 0)
3043 out->written += bytes / (out->config.channels * sizeof(short));
3044 }
3045
3046exit:
3047 pthread_mutex_unlock(&out->lock);
3048
3049 if (ret != 0) {
3050 list_for_each(node, &out->pcm_dev_list) {
3051 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3052 if (pcm_device->pcm && pcm_device->status != 0)
3053 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
3054 }
3055 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003056 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3057 clock_gettime(CLOCK_MONOTONIC, &t);
3058 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3059 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
3060 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
3061 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
3062 if (sleep_time > 0) {
3063 usleep(sleep_time);
3064 } else {
3065 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
3066 sleep_time = 0;
3067 }
3068 out->last_write_time_us = now + sleep_time;
3069 // last_write_time_us is an approximation of when the (simulated) alsa
3070 // buffer is believed completely full. The usleep above waits for more space
3071 // in the buffer, but by the end of the sleep the buffer is considered
3072 // topped-off.
3073 //
3074 // On the subsequent out_write(), we measure the elapsed time spent in
3075 // the mixer. This is subtracted from the sleep estimate based on frames,
3076 // thereby accounting for drain in the alsa buffer during mixing.
3077 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003078 }
3079
3080#ifdef PREPROCESSING_ENABLED
3081 if (in) {
3082 /* The lock on adev->lock_inputs prevents input stream from being closed */
3083 lock_input_stream(in);
3084 pthread_mutex_lock(&adev->lock);
3085 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3086 do_in_standby_l(in);
3087 pthread_mutex_unlock(&adev->lock);
3088 pthread_mutex_unlock(&in->lock);
3089 /* This mutex was left locked iff in != NULL */
3090 pthread_mutex_unlock(&adev->lock_inputs);
3091 }
3092#endif
3093
3094 return bytes;
3095}
3096
3097static int out_get_render_position(const struct audio_stream_out *stream,
3098 uint32_t *dsp_frames)
3099{
3100 struct stream_out *out = (struct stream_out *)stream;
3101 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003102 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3103 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003104 } else
3105 return -EINVAL;
3106}
3107
3108static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3109{
3110 (void)stream;
3111 (void)effect;
3112 return 0;
3113}
3114
3115static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3116{
3117 (void)stream;
3118 (void)effect;
3119 return 0;
3120}
3121
3122static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3123 int64_t *timestamp)
3124{
3125 (void)stream;
3126 (void)timestamp;
3127 return -EINVAL;
3128}
3129
3130static int out_get_presentation_position(const struct audio_stream_out *stream,
3131 uint64_t *frames, struct timespec *timestamp)
3132{
3133 struct stream_out *out = (struct stream_out *)stream;
3134 int ret = -1;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003135
3136 lock_output_stream(out);
3137
3138 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003139 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003140 } else {
Andreas Schneider97fa7f12017-02-11 14:21:56 +01003141 if (out->dev->voice.in_call) {
3142 ALOGVV("%s: in_call, do not handle PCMs", __func__);
3143 ret = 0;
3144 goto done;
3145 }
3146
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003147 /* FIXME: which device to read from? */
3148 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003149 struct pcm_device *pcm_device;
3150 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003151 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003152
Andreas Schneiderd6359182017-02-08 16:58:22 +01003153 list_for_each(node, &out->pcm_dev_list) {
3154 pcm_device = node_to_item(node,
3155 struct pcm_device,
3156 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003157
Andreas Schneiderd6359182017-02-08 16:58:22 +01003158 if (pcm_device->pcm != NULL) {
3159 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3160 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3161 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3162 /* This adjustment accounts for buffering after app processor.
3163 It is based on estimated DSP latency per use case, rather than exact. */
3164 signed_frames -=
3165 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3166
3167 /* It would be unusual for this value to be negative, but check just in case ... */
3168 if (signed_frames >= 0) {
3169 *frames = signed_frames;
3170 ret = 0;
3171 goto done;
3172 }
3173 ret = -1;
3174 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003175 }
3176 }
3177 }
3178 }
3179
Andreas Schneiderd6359182017-02-08 16:58:22 +01003180done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003181 pthread_mutex_unlock(&out->lock);
3182
3183 return ret;
3184}
3185
3186static int out_set_callback(struct audio_stream_out *stream,
3187 stream_callback_t callback, void *cookie)
3188{
3189 struct stream_out *out = (struct stream_out *)stream;
3190
3191 ALOGV("%s", __func__);
3192 lock_output_stream(out);
3193 out->offload_callback = callback;
3194 out->offload_cookie = cookie;
3195 pthread_mutex_unlock(&out->lock);
3196 return 0;
3197}
3198
3199static int out_pause(struct audio_stream_out* stream)
3200{
3201 struct stream_out *out = (struct stream_out *)stream;
3202 int status = -ENOSYS;
3203 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003204 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3205 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003206 return status;
3207}
3208
3209static int out_resume(struct audio_stream_out* stream)
3210{
3211 struct stream_out *out = (struct stream_out *)stream;
3212 int status = -ENOSYS;
3213 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003214 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3215 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003216 return status;
3217}
3218
3219static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3220{
3221 struct stream_out *out = (struct stream_out *)stream;
3222 int status = -ENOSYS;
3223 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003224 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3225 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003226 return status;
3227}
3228
3229static int out_flush(struct audio_stream_out* stream)
3230{
3231 struct stream_out *out = (struct stream_out *)stream;
3232 ALOGV("%s", __func__);
3233 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003234 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003235 }
3236 return -ENOSYS;
3237}
3238
3239/** audio_stream_in implementation **/
3240static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3241{
3242 struct stream_in *in = (struct stream_in *)stream;
3243
3244 return in->requested_rate;
3245}
3246
3247static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3248{
3249 (void)stream;
3250 (void)rate;
3251 return -ENOSYS;
3252}
3253
3254static uint32_t in_get_channels(const struct audio_stream *stream)
3255{
3256 struct stream_in *in = (struct stream_in *)stream;
3257
3258 return in->main_channels;
3259}
3260
3261static audio_format_t in_get_format(const struct audio_stream *stream)
3262{
3263 (void)stream;
3264 return AUDIO_FORMAT_PCM_16_BIT;
3265}
3266
3267static int in_set_format(struct audio_stream *stream, audio_format_t format)
3268{
3269 (void)stream;
3270 (void)format;
3271
3272 return -ENOSYS;
3273}
3274
3275static size_t in_get_buffer_size(const struct audio_stream *stream)
3276{
3277 struct stream_in *in = (struct stream_in *)stream;
3278
3279 return get_input_buffer_size(in->requested_rate,
3280 in_get_format(stream),
3281 audio_channel_count_from_in_mask(in->main_channels),
3282 in->usecase_type,
3283 in->devices);
3284}
3285
3286static int in_close_pcm_devices(struct stream_in *in)
3287{
3288 struct pcm_device *pcm_device;
3289 struct listnode *node;
3290 struct audio_device *adev = in->dev;
3291
3292 list_for_each(node, &in->pcm_dev_list) {
3293 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3294 if (pcm_device) {
3295 if (pcm_device->pcm)
3296 pcm_close(pcm_device->pcm);
3297 pcm_device->pcm = NULL;
3298 if (pcm_device->sound_trigger_handle > 0)
3299 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
3300 pcm_device->sound_trigger_handle = 0;
3301 }
3302 }
3303 return 0;
3304}
3305
3306
3307/* must be called with stream and hw device mutex locked */
3308static int do_in_standby_l(struct stream_in *in)
3309{
3310 int status = 0;
3311
3312#ifdef PREPROCESSING_ENABLED
3313 struct audio_device *adev = in->dev;
3314#endif
3315 if (!in->standby) {
3316
3317 in_close_pcm_devices(in);
3318
3319#ifdef PREPROCESSING_ENABLED
3320 if (in->echo_reference != NULL) {
3321 /* stop reading from echo reference */
3322 in->echo_reference->read(in->echo_reference, NULL);
3323 put_echo_reference(adev, in->echo_reference);
3324 in->echo_reference = NULL;
3325 }
3326#ifdef HW_AEC_LOOPBACK
3327 if (in->hw_echo_reference)
3328 {
3329 if (in->hw_ref_buf) {
3330 free(in->hw_ref_buf);
3331 in->hw_ref_buf = NULL;
3332 }
3333 }
3334#endif // HW_AEC_LOOPBACK
3335#endif // PREPROCESSING_ENABLED
3336
3337 status = stop_input_stream(in);
3338
3339 if (in->read_buf) {
3340 free(in->read_buf);
3341 in->read_buf = NULL;
3342 }
3343
3344 in->standby = 1;
3345 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003346
3347 in->last_read_time_us = 0;
3348
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003349 return 0;
3350}
3351
3352// called with adev->lock_inputs locked
3353static int in_standby_l(struct stream_in *in)
3354{
3355 struct audio_device *adev = in->dev;
3356 int status = 0;
3357 lock_input_stream(in);
3358 if (!in->standby) {
3359 pthread_mutex_lock(&adev->lock);
3360 status = do_in_standby_l(in);
3361 pthread_mutex_unlock(&adev->lock);
3362 }
3363 pthread_mutex_unlock(&in->lock);
3364 return status;
3365}
3366
3367static int in_standby(struct audio_stream *stream)
3368{
3369 struct stream_in *in = (struct stream_in *)stream;
3370 struct audio_device *adev = in->dev;
3371 int status;
3372 ALOGV("%s: enter", __func__);
3373 pthread_mutex_lock(&adev->lock_inputs);
3374 status = in_standby_l(in);
3375 pthread_mutex_unlock(&adev->lock_inputs);
3376 ALOGV("%s: exit: status(%d)", __func__, status);
3377 return status;
3378}
3379
3380static int in_dump(const struct audio_stream *stream, int fd)
3381{
3382 (void)stream;
3383 (void)fd;
3384
3385 return 0;
3386}
3387
3388static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3389{
3390 struct stream_in *in = (struct stream_in *)stream;
3391 struct audio_device *adev = in->dev;
3392 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003393 char value[32];
3394 int ret, val = 0;
3395 struct audio_usecase *uc_info;
3396 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003397 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003398
3399 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3400 parms = str_parms_create_str(kvpairs);
3401
3402 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3403
3404 pthread_mutex_lock(&adev->lock_inputs);
3405 lock_input_stream(in);
3406 pthread_mutex_lock(&adev->lock);
3407 if (ret >= 0) {
3408 val = atoi(value);
3409 /* no audio source uses val == 0 */
3410 if (((int)in->source != val) && (val != 0)) {
3411 in->source = val;
3412 }
3413 }
3414
3415 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3416 if (ret >= 0) {
3417 val = atoi(value);
3418 if (((int)in->devices != val) && (val != 0)) {
3419 in->devices = val;
3420 /* If recording is in progress, change the tx device to new device */
3421 if (!in->standby) {
3422 uc_info = get_usecase_from_id(adev, in->usecase);
3423 if (uc_info == NULL) {
3424 ALOGE("%s: Could not find the usecase (%d) in the list",
3425 __func__, in->usecase);
3426 } else {
3427 if (list_empty(&in->pcm_dev_list))
3428 ALOGE("%s: pcm device list empty", __func__);
3429 else {
3430 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3431 struct pcm_device, stream_list_node);
3432 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3433 do_standby = true;
3434 }
3435 }
3436 }
3437 if (do_standby) {
3438 ret = do_in_standby_l(in);
3439 } else
3440 ret = select_devices(adev, in->usecase);
3441 }
3442 }
3443 }
3444 pthread_mutex_unlock(&adev->lock);
3445 pthread_mutex_unlock(&in->lock);
3446 pthread_mutex_unlock(&adev->lock_inputs);
3447 str_parms_destroy(parms);
3448
3449 if (ret > 0)
3450 ret = 0;
3451
3452 ALOGV("%s: exit: status(%d)", __func__, ret);
3453 return ret;
3454}
3455
3456static char* in_get_parameters(const struct audio_stream *stream,
3457 const char *keys)
3458{
3459 (void)stream;
3460 (void)keys;
3461
3462 return strdup("");
3463}
3464
3465static int in_set_gain(struct audio_stream_in *stream, float gain)
3466{
3467 (void)stream;
3468 (void)gain;
3469
3470 return 0;
3471}
3472
3473static ssize_t read_bytes_from_dsp(struct stream_in *in, void* buffer,
3474 size_t bytes)
3475{
3476 struct pcm_device *pcm_device;
3477 struct audio_device *adev = in->dev;
3478
3479 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3480 struct pcm_device, stream_list_node);
3481
3482 if (pcm_device->sound_trigger_handle > 0)
3483 return adev->sound_trigger_read_samples(pcm_device->sound_trigger_handle, buffer, bytes);
3484 else
3485 return 0;
3486}
3487
3488static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3489 size_t bytes)
3490{
3491 struct stream_in *in = (struct stream_in *)stream;
3492 struct audio_device *adev = in->dev;
3493 ssize_t frames = -1;
3494 int ret = -1;
3495 int read_and_process_successful = false;
3496
3497 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003498
3499 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3500 lock_input_stream(in);
3501
Andreas Schneider3b643832017-01-31 11:48:22 +01003502#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003503 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003504 pid_t tid = gettid();
3505 int err;
3506
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003507 err = fast_set_affinity(tid);
3508 if (err < 0) {
3509 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3510 }
3511 in->is_fastcapture_affinity_set = true;
3512 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003513#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003514
3515 if (in->standby) {
3516 pthread_mutex_unlock(&in->lock);
3517 pthread_mutex_lock(&adev->lock_inputs);
3518 lock_input_stream(in);
3519 if (!in->standby) {
3520 pthread_mutex_unlock(&adev->lock_inputs);
3521 goto false_alarm;
3522 }
3523 pthread_mutex_lock(&adev->lock);
3524 ret = start_input_stream(in);
3525 pthread_mutex_unlock(&adev->lock);
3526 pthread_mutex_unlock(&adev->lock_inputs);
3527 if (ret != 0) {
3528 goto exit;
3529 }
3530 in->standby = 0;
3531 }
3532false_alarm:
3533
3534 if (!list_empty(&in->pcm_dev_list)) {
3535 if (in->usecase == USECASE_AUDIO_CAPTURE_HOTWORD) {
3536 bytes = read_bytes_from_dsp(in, buffer, bytes);
3537 if (bytes > 0)
3538 read_and_process_successful = true;
3539 } else {
3540 /*
3541 * Read PCM and:
3542 * - resample if needed
3543 * - process if pre-processors are attached
3544 * - discard unwanted channels
3545 */
3546 frames = read_and_process_frames(in, buffer, frames_rq);
3547 if (frames >= 0)
3548 read_and_process_successful = true;
3549 }
3550 }
3551
3552 /*
3553 * Instead of writing zeroes here, we could trust the hardware
3554 * to always provide zeroes when muted.
3555 */
3556 if (read_and_process_successful == true && adev->mic_mute)
3557 memset(buffer, 0, bytes);
3558
3559exit:
3560 pthread_mutex_unlock(&in->lock);
3561
3562 if (read_and_process_successful == false) {
3563 in_standby(&in->stream.common);
3564 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003565 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3566 clock_gettime(CLOCK_MONOTONIC, &t);
3567 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3568
3569 // we do a full sleep when exiting standby.
3570 const bool standby = in->last_read_time_us == 0;
3571 const int64_t elapsed_time_since_last_read = standby ?
3572 0 : now - in->last_read_time_us;
3573 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3574 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3575 if (sleep_time > 0) {
3576 usleep(sleep_time);
3577 } else {
3578 sleep_time = 0;
3579 }
3580 in->last_read_time_us = now + sleep_time;
3581 // last_read_time_us is an approximation of when the (simulated) alsa
3582 // buffer is drained by the read, and is empty.
3583 //
3584 // On the subsequent in_read(), we measure the elapsed time spent in
3585 // the recording thread. This is subtracted from the sleep estimate based on frames,
3586 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003587 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003588 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003589
3590 if (bytes > 0) {
3591 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3592 }
3593
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003594 return bytes;
3595}
3596
3597static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3598{
3599 (void)stream;
3600
3601 return 0;
3602}
3603
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003604static int in_get_capture_position(const struct audio_stream_in *stream,
3605 int64_t *frames, int64_t *time)
3606{
3607 if (stream == NULL || frames == NULL || time == NULL) {
3608 return -EINVAL;
3609 }
3610
3611 struct stream_in *in = (struct stream_in *)stream;
3612 struct pcm_device *pcm_device;
3613 int ret = -ENOSYS;
3614
3615 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3616 struct pcm_device, stream_list_node);
3617
3618 pthread_mutex_lock(&in->lock);
3619 if (pcm_device->pcm) {
3620 struct timespec timestamp;
3621 unsigned int avail;
3622 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3623 *frames = in->frames_read + avail;
3624 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3625 ret = 0;
3626 }
3627 }
3628
3629 pthread_mutex_unlock(&in->lock);
3630 return ret;
3631}
3632
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003633static int add_remove_audio_effect(const struct audio_stream *stream,
3634 effect_handle_t effect,
3635 bool enable)
3636{
3637 struct stream_in *in = (struct stream_in *)stream;
3638 struct audio_device *adev = in->dev;
3639 int status = 0;
3640 effect_descriptor_t desc;
3641#ifdef PREPROCESSING_ENABLED
3642 int i;
3643#endif
3644 status = (*effect)->get_descriptor(effect, &desc);
3645 if (status != 0)
3646 return status;
3647
3648 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3649
3650 pthread_mutex_lock(&adev->lock_inputs);
3651 lock_input_stream(in);
3652 pthread_mutex_lock(&in->dev->lock);
3653#ifndef PREPROCESSING_ENABLED
3654 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3655 in->enable_aec != enable &&
3656 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3657 in->enable_aec = enable;
3658 if (!in->standby)
3659 select_devices(in->dev, in->usecase);
3660 }
3661#else
3662 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3663 status = -ENOSYS;
3664 goto exit;
3665 }
3666 if ( enable == true ) {
3667 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3668 /* add the supported channel of the effect in the channel_configs */
3669 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3670 in->num_preprocessors ++;
3671 /* check compatibility between main channel supported and possible auxiliary channels */
3672 in_update_aux_channels(in, effect);//wesley crash
3673 in->aux_channels_changed = true;
3674 } else {
3675 /* if ( enable == false ) */
3676 if (in->num_preprocessors <= 0) {
3677 status = -ENOSYS;
3678 goto exit;
3679 }
3680 status = -EINVAL;
3681 for (i=0; i < in->num_preprocessors; i++) {
3682 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3683 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3684 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3685 in->preprocessors[i - 1].num_channel_configs =
3686 in->preprocessors[i].num_channel_configs;
3687 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3688 continue;
3689 }
3690 if ( in->preprocessors[i].effect_itfe == effect ) {
3691 ALOGV("add_remove_audio_effect found fx at index %d", i);
3692 free(in->preprocessors[i].channel_configs);
3693 status = 0;
3694 }
3695 }
3696 if (status != 0)
3697 goto exit;
3698 in->num_preprocessors--;
3699 /* if we remove one effect, at least the last proproc should be reset */
3700 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3701 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3702 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3703 in->aux_channels_changed = false;
3704 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3705 }
3706 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3707
3708 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3709 in->enable_aec = enable;
3710 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3711 if (!in->standby) {
3712 select_devices(in->dev, in->usecase);
3713 do_in_standby_l(in);
3714 }
3715 if (in->enable_aec == true) {
3716 in_configure_reverse(in);
3717 }
3718 }
3719exit:
3720#endif
3721 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3722 pthread_mutex_unlock(&in->dev->lock);
3723 pthread_mutex_unlock(&in->lock);
3724 pthread_mutex_unlock(&adev->lock_inputs);
3725 return status;
3726}
3727
3728static int in_add_audio_effect(const struct audio_stream *stream,
3729 effect_handle_t effect)
3730{
3731 ALOGV("%s: effect %p", __func__, effect);
3732 return add_remove_audio_effect(stream, effect, true);
3733}
3734
3735static int in_remove_audio_effect(const struct audio_stream *stream,
3736 effect_handle_t effect)
3737{
3738 ALOGV("%s: effect %p", __func__, effect);
3739 return add_remove_audio_effect(stream, effect, false);
3740}
3741
3742static int adev_open_output_stream(struct audio_hw_device *dev,
3743 audio_io_handle_t handle,
3744 audio_devices_t devices,
3745 audio_output_flags_t flags,
3746 struct audio_config *config,
3747 struct audio_stream_out **stream_out,
3748 const char *address __unused)
3749{
3750 struct audio_device *adev = (struct audio_device *)dev;
3751 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003752 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003753 struct pcm_device_profile *pcm_profile;
3754
3755 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3756 __func__, config->sample_rate, config->channel_mask, devices, flags);
3757 *stream_out = NULL;
3758 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003759 if (out == NULL) {
3760 ret = -ENOMEM;
3761 goto error_config;
3762 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003763
3764 if (devices == AUDIO_DEVICE_NONE)
3765 devices = AUDIO_DEVICE_OUT_SPEAKER;
3766
3767 out->flags = flags;
3768 out->devices = devices;
3769 out->dev = adev;
3770 out->format = config->format;
3771 out->sample_rate = config->sample_rate;
3772 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3773 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3774 out->handle = handle;
3775
3776 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3777 if (pcm_profile == NULL) {
3778 ret = -EINVAL;
3779 goto error_open;
3780 }
3781 out->config = pcm_profile->config;
3782
3783 /* Init use case and pcm_config */
3784 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3785 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3786 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3787 ALOGE("%s: Unsupported Offload information", __func__);
3788 ret = -EINVAL;
3789 goto error_open;
3790 }
3791 if (!is_supported_format(config->offload_info.format)) {
3792 ALOGE("%s: Unsupported audio format", __func__);
3793 ret = -EINVAL;
3794 goto error_open;
3795 }
3796
3797 out->compr_config.codec = (struct snd_codec *)
3798 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003799 if (out->compr_config.codec == NULL) {
3800 ret = -ENOMEM;
3801 goto error_open;
3802 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003803
3804 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3805 if (config->offload_info.channel_mask)
3806 out->channel_mask = config->offload_info.channel_mask;
3807 else if (config->channel_mask)
3808 out->channel_mask = config->channel_mask;
3809 out->format = config->offload_info.format;
3810 out->sample_rate = config->offload_info.sample_rate;
3811
3812 out->stream.set_callback = out_set_callback;
3813 out->stream.pause = out_pause;
3814 out->stream.resume = out_resume;
3815 out->stream.drain = out_drain;
3816 out->stream.flush = out_flush;
3817
3818 out->compr_config.codec->id =
3819 get_snd_codec_id(config->offload_info.format);
3820 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3821 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3822 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3823 out->compr_config.codec->bit_rate =
3824 config->offload_info.bit_rate;
3825 out->compr_config.codec->ch_in =
3826 audio_channel_count_from_out_mask(config->channel_mask);
3827 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3828
3829 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3830 out->non_blocking = 1;
3831
3832 out->send_new_metadata = 1;
3833 create_offload_callback_thread(out);
3834 out->offload_state = OFFLOAD_STATE_IDLE;
3835
3836 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3837 __func__, config->offload_info.version,
3838 config->offload_info.bit_rate);
3839 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3840 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003841 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003842 out->sample_rate = out->config.rate;
3843 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3844 } else {
3845 out->usecase = USECASE_AUDIO_PLAYBACK;
3846 out->sample_rate = out->config.rate;
3847 }
3848
3849 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3850 if (adev->primary_output == NULL)
3851 adev->primary_output = out;
3852 else {
3853 ALOGE("%s: Primary output is already opened", __func__);
3854 ret = -EEXIST;
3855 goto error_open;
3856 }
3857 }
3858
3859 /* Check if this usecase is already existing */
3860 pthread_mutex_lock(&adev->lock);
3861 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3862 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3863 pthread_mutex_unlock(&adev->lock);
3864 ret = -EEXIST;
3865 goto error_open;
3866 }
3867 pthread_mutex_unlock(&adev->lock);
3868
3869 out->stream.common.get_sample_rate = out_get_sample_rate;
3870 out->stream.common.set_sample_rate = out_set_sample_rate;
3871 out->stream.common.get_buffer_size = out_get_buffer_size;
3872 out->stream.common.get_channels = out_get_channels;
3873 out->stream.common.get_format = out_get_format;
3874 out->stream.common.set_format = out_set_format;
3875 out->stream.common.standby = out_standby;
3876 out->stream.common.dump = out_dump;
3877 out->stream.common.set_parameters = out_set_parameters;
3878 out->stream.common.get_parameters = out_get_parameters;
3879 out->stream.common.add_audio_effect = out_add_audio_effect;
3880 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3881 out->stream.get_latency = out_get_latency;
3882 out->stream.set_volume = out_set_volume;
3883 out->stream.write = out_write;
3884 out->stream.get_render_position = out_get_render_position;
3885 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3886 out->stream.get_presentation_position = out_get_presentation_position;
3887
3888 out->standby = 1;
3889 /* out->muted = false; by calloc() */
3890 /* out->written = 0; by calloc() */
3891
3892 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3893 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3894 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3895
3896 config->format = out->stream.common.get_format(&out->stream.common);
3897 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3898 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3899
3900 out->is_fastmixer_affinity_set = false;
3901
3902 *stream_out = &out->stream;
3903 ALOGV("%s: exit", __func__);
3904 return 0;
3905
3906error_open:
3907 free(out);
3908 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003909error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003910 ALOGV("%s: exit: ret %d", __func__, ret);
3911 return ret;
3912}
3913
3914static void adev_close_output_stream(struct audio_hw_device *dev,
3915 struct audio_stream_out *stream)
3916{
3917 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003918 (void)dev;
3919
3920 ALOGV("%s: enter", __func__);
3921 out_standby(&stream->common);
3922 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3923 destroy_offload_callback_thread(out);
3924
3925 if (out->compr_config.codec != NULL)
3926 free(out->compr_config.codec);
3927 }
3928 pthread_cond_destroy(&out->cond);
3929 pthread_mutex_destroy(&out->lock);
3930 free(stream);
3931 ALOGV("%s: exit", __func__);
3932}
3933
3934static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3935{
3936 struct audio_device *adev = (struct audio_device *)dev;
3937 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003938 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003939#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003940 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003941#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003942 int ret;
3943
3944 ALOGV("%s: enter: %s", __func__, kvpairs);
3945
3946 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003947
Andreas Schneider05bc1882017-02-09 14:03:11 +01003948 /******************************************************
3949 *** BT SCO
3950 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003951 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3952 if (ret >= 0) {
3953 /* When set to false, HAL should disable EC and NS
3954 * But it is currently not supported.
3955 */
3956 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003957 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003958 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003959 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003960 }
3961
Andreas Schneider05bc1882017-02-09 14:03:11 +01003962 ret = str_parms_get_str(parms,
3963 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3964 value,
3965 sizeof(value));
3966 if (ret >= 0) {
3967 /* TODO: Add support in voice calls */
3968 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3969 adev->voice.bluetooth_wb = true;
3970 ALOGI("%s: Implement support for BT SCO wideband calls!!!",
3971 __func__);
3972 } else {
3973 adev->voice.bluetooth_wb = false;
3974 }
3975 }
3976
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003977 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3978 if (ret >= 0) {
3979 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3980 adev->screen_off = false;
3981 else
3982 adev->screen_off = true;
3983 }
3984
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003985#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003986 ret = str_parms_get_int(parms, "rotation", &val);
3987 if (ret >= 0) {
3988 bool reverse_speakers = false;
3989 switch(val) {
3990 /* FIXME: note that the code below assumes that the speakers are in the correct placement
3991 relative to the user when the device is rotated 90deg from its default rotation. This
3992 assumption is device-specific, not platform-specific like this code. */
3993 case 270:
3994 reverse_speakers = true;
3995 break;
3996 case 0:
3997 case 90:
3998 case 180:
3999 break;
4000 default:
4001 ALOGE("%s: unexpected rotation of %d", __func__, val);
4002 }
4003 pthread_mutex_lock(&adev->lock);
4004 if (adev->speaker_lr_swap != reverse_speakers) {
4005 adev->speaker_lr_swap = reverse_speakers;
4006 /* only update the selected device if there is active pcm playback */
4007 struct audio_usecase *usecase;
4008 struct listnode *node;
4009 list_for_each(node, &adev->usecase_list) {
4010 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
4011 if (usecase->type == PCM_PLAYBACK) {
4012 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004013 break;
4014 }
4015 }
4016 }
4017 pthread_mutex_unlock(&adev->lock);
4018 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004019#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004020
4021 str_parms_destroy(parms);
4022
4023 if (ret > 0)
4024 ret = 0;
4025
4026 ALOGV("%s: exit with code(%d)", __func__, ret);
4027 return ret;
4028}
4029
4030static char* adev_get_parameters(const struct audio_hw_device *dev,
4031 const char *keys)
4032{
4033 (void)dev;
4034 (void)keys;
4035
4036 return strdup("");
4037}
4038
4039static int adev_init_check(const struct audio_hw_device *dev)
4040{
4041 (void)dev;
4042
4043 return 0;
4044}
4045
4046static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4047{
4048 int ret = 0;
4049 struct audio_device *adev = (struct audio_device *)dev;
4050 pthread_mutex_lock(&adev->lock);
4051 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004052 adev->voice.volume = volume;
4053 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004054 pthread_mutex_unlock(&adev->lock);
4055 return ret;
4056}
4057
4058static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
4059{
4060 (void)dev;
4061 (void)volume;
4062
4063 return -ENOSYS;
4064}
4065
4066static int adev_get_master_volume(struct audio_hw_device *dev,
4067 float *volume)
4068{
4069 (void)dev;
4070 (void)volume;
4071
4072 return -ENOSYS;
4073}
4074
4075static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
4076{
4077 (void)dev;
4078 (void)muted;
4079
4080 return -ENOSYS;
4081}
4082
4083static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
4084{
4085 (void)dev;
4086 (void)muted;
4087
4088 return -ENOSYS;
4089}
4090
4091static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4092{
4093 struct audio_device *adev = (struct audio_device *)dev;
4094
4095 pthread_mutex_lock(&adev->lock);
4096 if (adev->mode != mode) {
4097 ALOGI("%s mode = %d", __func__, mode);
4098 adev->mode = mode;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004099 }
4100 pthread_mutex_unlock(&adev->lock);
4101 return 0;
4102}
4103
4104static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4105{
4106 struct audio_device *adev = (struct audio_device *)dev;
4107 int err = 0;
4108
4109 pthread_mutex_lock(&adev->lock);
4110 adev->mic_mute = state;
4111
4112 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004113 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004114 }
4115
4116 pthread_mutex_unlock(&adev->lock);
4117 return err;
4118}
4119
4120static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4121{
4122 struct audio_device *adev = (struct audio_device *)dev;
4123
4124 *state = adev->mic_mute;
4125
4126 return 0;
4127}
4128
4129static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4130 const struct audio_config *config)
4131{
4132 (void)dev;
4133
4134 /* NOTE: we default to built in mic which may cause a mismatch between what we
4135 * report here and the actual buffer size
4136 */
4137 return get_input_buffer_size(config->sample_rate,
4138 config->format,
4139 audio_channel_count_from_in_mask(config->channel_mask),
4140 PCM_CAPTURE /* usecase_type */,
4141 AUDIO_DEVICE_IN_BUILTIN_MIC);
4142}
4143
4144static int adev_open_input_stream(struct audio_hw_device *dev,
4145 audio_io_handle_t handle __unused,
4146 audio_devices_t devices,
4147 struct audio_config *config,
4148 struct audio_stream_in **stream_in,
4149 audio_input_flags_t flags,
4150 const char *address __unused,
4151 audio_source_t source)
4152{
4153 struct audio_device *adev = (struct audio_device *)dev;
4154 struct stream_in *in;
4155 struct pcm_device_profile *pcm_profile;
4156
4157 ALOGV("%s: enter", __func__);
4158
4159 *stream_in = NULL;
4160 if (check_input_parameters(config->sample_rate, config->format,
4161 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4162 return -EINVAL;
4163
4164 usecase_type_t usecase_type = source == AUDIO_SOURCE_HOTWORD ?
4165 PCM_HOTWORD_STREAMING : flags & AUDIO_INPUT_FLAG_FAST ?
4166 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4167 pcm_profile = get_pcm_device(usecase_type, devices);
4168 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4169 // a low latency profile may not exist for that device, fall back
4170 // to regular capture. the MixerThread automatically changes
4171 // to non-fast capture based on the buffer size.
4172 flags &= ~AUDIO_INPUT_FLAG_FAST;
4173 usecase_type = PCM_CAPTURE;
4174 pcm_profile = get_pcm_device(usecase_type, devices);
4175 }
4176 if (pcm_profile == NULL)
4177 return -EINVAL;
4178
4179 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004180 if (in == NULL) {
4181 return -ENOMEM;
4182 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004183
4184 in->stream.common.get_sample_rate = in_get_sample_rate;
4185 in->stream.common.set_sample_rate = in_set_sample_rate;
4186 in->stream.common.get_buffer_size = in_get_buffer_size;
4187 in->stream.common.get_channels = in_get_channels;
4188 in->stream.common.get_format = in_get_format;
4189 in->stream.common.set_format = in_set_format;
4190 in->stream.common.standby = in_standby;
4191 in->stream.common.dump = in_dump;
4192 in->stream.common.set_parameters = in_set_parameters;
4193 in->stream.common.get_parameters = in_get_parameters;
4194 in->stream.common.add_audio_effect = in_add_audio_effect;
4195 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4196 in->stream.set_gain = in_set_gain;
4197 in->stream.read = in_read;
4198 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004199 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004200
4201 in->devices = devices;
4202 in->source = source;
4203 in->dev = adev;
4204 in->standby = 1;
4205 in->main_channels = config->channel_mask;
4206 in->requested_rate = config->sample_rate;
4207 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4208 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4209 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004210 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004211 /* HW codec is limited to default channels. No need to update with
4212 * requested channels */
4213 in->config = pcm_profile->config;
4214
4215 /* Update config params with the requested sample rate and channels */
4216 if (source == AUDIO_SOURCE_HOTWORD) {
4217 in->usecase = USECASE_AUDIO_CAPTURE_HOTWORD;
4218 } else {
4219 in->usecase = USECASE_AUDIO_CAPTURE;
4220 }
4221 in->usecase_type = usecase_type;
4222
4223 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4224 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4225
4226 in->is_fastcapture_affinity_set = false;
4227
4228 *stream_in = &in->stream;
4229 ALOGV("%s: exit", __func__);
4230 return 0;
4231}
4232
4233static void adev_close_input_stream(struct audio_hw_device *dev,
4234 struct audio_stream_in *stream)
4235{
4236 struct audio_device *adev = (struct audio_device *)dev;
4237 struct stream_in *in = (struct stream_in*)stream;
4238 ALOGV("%s", __func__);
4239
4240 /* prevent concurrent out_set_parameters, or out_write from standby */
4241 pthread_mutex_lock(&adev->lock_inputs);
4242
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004243 if (in->read_buf) {
4244 free(in->read_buf);
4245 in->read_buf = NULL;
4246 }
4247
4248 if (in->resampler) {
4249 release_resampler(in->resampler);
4250 in->resampler = NULL;
4251 }
4252
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004253#ifdef PREPROCESSING_ENABLED
4254 int i;
4255
4256 for (i=0; i<in->num_preprocessors; i++) {
4257 free(in->preprocessors[i].channel_configs);
4258 }
4259
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004260 if (in->proc_buf_in) {
4261 free(in->proc_buf_in);
4262 in->proc_buf_in = NULL;
4263 }
4264
4265 if (in->proc_buf_out) {
4266 free(in->proc_buf_out);
4267 in->proc_buf_out = NULL;
4268 }
4269
4270 if (in->ref_buf) {
4271 free(in->ref_buf);
4272 in->ref_buf = NULL;
4273 }
4274
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004275#endif
4276
4277 in_standby_l(in);
4278 free(stream);
4279
4280 pthread_mutex_unlock(&adev->lock_inputs);
4281
4282 return;
4283}
4284
4285static int adev_dump(const audio_hw_device_t *device, int fd)
4286{
4287 (void)device;
4288 (void)fd;
4289
4290 return 0;
4291}
4292
4293static int adev_close(hw_device_t *device)
4294{
4295 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004296 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004297 audio_device_ref_count--;
4298 free(adev->snd_dev_ref_cnt);
4299 free_mixer_list(adev);
4300 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004301
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004302 return 0;
4303}
4304
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004305/* This returns true if the input parameter looks at all plausible as a low latency period size,
4306 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4307 * just that it _might_ work.
4308 */
4309static bool period_size_is_plausible_for_low_latency(int period_size)
4310{
4311 switch (period_size) {
4312 case 64:
4313 case 96:
4314 case 128:
4315 case 192:
4316 case 256:
4317 return true;
4318 default:
4319 return false;
4320 }
4321}
4322
4323static int adev_open(const hw_module_t *module, const char *name,
4324 hw_device_t **device)
4325{
4326 struct audio_device *adev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004327
4328 ALOGV("%s: enter", __func__);
4329 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4330
Andreas Schneider56204f62017-01-31 08:17:32 +01004331 *device = NULL;
4332
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004333 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004334 if (adev == NULL) {
4335 return -ENOMEM;
4336 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004337
4338 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4339 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4340 adev->device.common.module = (struct hw_module_t *)module;
4341 adev->device.common.close = adev_close;
4342
4343 adev->device.init_check = adev_init_check;
4344 adev->device.set_voice_volume = adev_set_voice_volume;
4345 adev->device.set_master_volume = adev_set_master_volume;
4346 adev->device.get_master_volume = adev_get_master_volume;
4347 adev->device.set_master_mute = adev_set_master_mute;
4348 adev->device.get_master_mute = adev_get_master_mute;
4349 adev->device.set_mode = adev_set_mode;
4350 adev->device.set_mic_mute = adev_set_mic_mute;
4351 adev->device.get_mic_mute = adev_get_mic_mute;
4352 adev->device.set_parameters = adev_set_parameters;
4353 adev->device.get_parameters = adev_get_parameters;
4354 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4355 adev->device.open_output_stream = adev_open_output_stream;
4356 adev->device.close_output_stream = adev_close_output_stream;
4357 adev->device.open_input_stream = adev_open_input_stream;
4358 adev->device.close_input_stream = adev_close_input_stream;
4359 adev->device.dump = adev_dump;
4360
4361 /* Set the default route before the PCM stream is opened */
4362 adev->mode = AUDIO_MODE_NORMAL;
4363 adev->active_input = NULL;
4364 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004365
4366 adev->voice.volume = 1.0f;
4367 adev->voice.bluetooth_nrec = true;
4368 adev->voice.in_call = false;
4369
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004370 /* adev->cur_hdmi_channels = 0; by calloc() */
4371 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004372 if (adev->snd_dev_ref_cnt == NULL) {
4373 free(adev);
4374 return -ENOMEM;
4375 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004376
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004377 adev->ns_in_voice_rec = false;
4378
4379 list_init(&adev->usecase_list);
4380
4381 if (mixer_init(adev) != 0) {
4382 free(adev->snd_dev_ref_cnt);
4383 free(adev);
4384 ALOGE("%s: Failed to init, aborting.", __func__);
4385 *device = NULL;
4386 return -EINVAL;
4387 }
4388
4389 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4390 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4391 if (adev->offload_fx_lib == NULL) {
4392 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4393 } else {
4394 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4395 adev->offload_fx_start_output =
4396 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4397 "visualizer_hal_start_output");
4398 adev->offload_fx_stop_output =
4399 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4400 "visualizer_hal_stop_output");
4401 }
4402 }
4403
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004404 if (access(SOUND_TRIGGER_HAL_LIBRARY_PATH, R_OK) == 0) {
4405 adev->sound_trigger_lib = dlopen(SOUND_TRIGGER_HAL_LIBRARY_PATH, RTLD_NOW);
4406 if (adev->sound_trigger_lib == NULL) {
4407 ALOGE("%s: DLOPEN failed for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4408 } else {
4409 ALOGV("%s: DLOPEN successful for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4410 adev->sound_trigger_open_for_streaming =
4411 (int (*)(void))dlsym(adev->sound_trigger_lib,
4412 "sound_trigger_open_for_streaming");
4413 adev->sound_trigger_read_samples =
4414 (size_t (*)(int, void *, size_t))dlsym(adev->sound_trigger_lib,
4415 "sound_trigger_read_samples");
4416 adev->sound_trigger_close_for_streaming =
4417 (int (*)(int))dlsym(adev->sound_trigger_lib,
4418 "sound_trigger_close_for_streaming");
4419 if (!adev->sound_trigger_open_for_streaming ||
4420 !adev->sound_trigger_read_samples ||
4421 !adev->sound_trigger_close_for_streaming) {
4422
4423 ALOGE("%s: Error grabbing functions in %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4424 adev->sound_trigger_open_for_streaming = 0;
4425 adev->sound_trigger_read_samples = 0;
4426 adev->sound_trigger_close_for_streaming = 0;
4427 }
4428 }
4429 }
4430
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004431 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004432 if (adev->voice.session == NULL) {
4433 ALOGE("%s: Failed to initialize voice session data", __func__);
4434
4435 free(adev->snd_dev_ref_cnt);
4436 free(adev);
4437
4438 *device = NULL;
4439 return -EINVAL;
4440 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004441
4442 *device = &adev->device.common;
4443
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004444 audio_device_ref_count++;
4445
4446 char value[PROPERTY_VALUE_MAX];
4447 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4448 int trial = atoi(value);
4449 if (period_size_is_plausible_for_low_latency(trial)) {
4450
4451 pcm_device_playback.config.period_size = trial;
4452 pcm_device_playback.config.start_threshold =
4453 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4454 pcm_device_playback.config.stop_threshold =
4455 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4456
4457 pcm_device_capture_low_latency.config.period_size = trial;
4458 }
4459 }
4460
4461 ALOGV("%s: exit", __func__);
4462 return 0;
4463}
4464
4465static struct hw_module_methods_t hal_module_methods = {
4466 .open = adev_open,
4467};
4468
4469struct audio_module HAL_MODULE_INFO_SYM = {
4470 .common = {
4471 .tag = HARDWARE_MODULE_TAG,
4472 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4473 .hal_api_version = HARDWARE_HAL_API_VERSION,
4474 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004475 .name = "Samsung Audio HAL",
4476 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004477 .methods = &hal_module_methods,
4478 },
4479};