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