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