blob: cc04a95c670afc863e9f7d978cfe94c581b4ab24 [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 {
3087 /* FIXME: which device to read from? */
3088 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003089 struct pcm_device *pcm_device;
3090 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003091 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003092
Andreas Schneiderd6359182017-02-08 16:58:22 +01003093 list_for_each(node, &out->pcm_dev_list) {
3094 pcm_device = node_to_item(node,
3095 struct pcm_device,
3096 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003097
Andreas Schneiderd6359182017-02-08 16:58:22 +01003098 if (pcm_device->pcm != NULL) {
3099 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3100 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3101 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3102 /* This adjustment accounts for buffering after app processor.
3103 It is based on estimated DSP latency per use case, rather than exact. */
3104 signed_frames -=
3105 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3106
3107 /* It would be unusual for this value to be negative, but check just in case ... */
3108 if (signed_frames >= 0) {
3109 *frames = signed_frames;
3110 ret = 0;
3111 goto done;
3112 }
3113 ret = -1;
3114 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003115 }
3116 }
3117 }
3118 }
3119
Andreas Schneiderd6359182017-02-08 16:58:22 +01003120done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003121 pthread_mutex_unlock(&out->lock);
3122
3123 return ret;
3124}
3125
3126static int out_set_callback(struct audio_stream_out *stream,
3127 stream_callback_t callback, void *cookie)
3128{
3129 struct stream_out *out = (struct stream_out *)stream;
3130
3131 ALOGV("%s", __func__);
3132 lock_output_stream(out);
3133 out->offload_callback = callback;
3134 out->offload_cookie = cookie;
3135 pthread_mutex_unlock(&out->lock);
3136 return 0;
3137}
3138
3139static int out_pause(struct audio_stream_out* stream)
3140{
3141 struct stream_out *out = (struct stream_out *)stream;
3142 int status = -ENOSYS;
3143 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003144 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3145 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003146 return status;
3147}
3148
3149static int out_resume(struct audio_stream_out* stream)
3150{
3151 struct stream_out *out = (struct stream_out *)stream;
3152 int status = -ENOSYS;
3153 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003154 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3155 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003156 return status;
3157}
3158
3159static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3160{
3161 struct stream_out *out = (struct stream_out *)stream;
3162 int status = -ENOSYS;
3163 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003164 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3165 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003166 return status;
3167}
3168
3169static int out_flush(struct audio_stream_out* stream)
3170{
3171 struct stream_out *out = (struct stream_out *)stream;
3172 ALOGV("%s", __func__);
3173 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003174 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003175 }
3176 return -ENOSYS;
3177}
3178
3179/** audio_stream_in implementation **/
3180static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3181{
3182 struct stream_in *in = (struct stream_in *)stream;
3183
3184 return in->requested_rate;
3185}
3186
3187static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3188{
3189 (void)stream;
3190 (void)rate;
3191 return -ENOSYS;
3192}
3193
3194static uint32_t in_get_channels(const struct audio_stream *stream)
3195{
3196 struct stream_in *in = (struct stream_in *)stream;
3197
3198 return in->main_channels;
3199}
3200
3201static audio_format_t in_get_format(const struct audio_stream *stream)
3202{
3203 (void)stream;
3204 return AUDIO_FORMAT_PCM_16_BIT;
3205}
3206
3207static int in_set_format(struct audio_stream *stream, audio_format_t format)
3208{
3209 (void)stream;
3210 (void)format;
3211
3212 return -ENOSYS;
3213}
3214
3215static size_t in_get_buffer_size(const struct audio_stream *stream)
3216{
3217 struct stream_in *in = (struct stream_in *)stream;
3218
3219 return get_input_buffer_size(in->requested_rate,
3220 in_get_format(stream),
3221 audio_channel_count_from_in_mask(in->main_channels),
3222 in->usecase_type,
3223 in->devices);
3224}
3225
3226static int in_close_pcm_devices(struct stream_in *in)
3227{
3228 struct pcm_device *pcm_device;
3229 struct listnode *node;
3230 struct audio_device *adev = in->dev;
3231
3232 list_for_each(node, &in->pcm_dev_list) {
3233 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3234 if (pcm_device) {
3235 if (pcm_device->pcm)
3236 pcm_close(pcm_device->pcm);
3237 pcm_device->pcm = NULL;
3238 if (pcm_device->sound_trigger_handle > 0)
3239 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
3240 pcm_device->sound_trigger_handle = 0;
3241 }
3242 }
3243 return 0;
3244}
3245
3246
3247/* must be called with stream and hw device mutex locked */
3248static int do_in_standby_l(struct stream_in *in)
3249{
3250 int status = 0;
3251
3252#ifdef PREPROCESSING_ENABLED
3253 struct audio_device *adev = in->dev;
3254#endif
3255 if (!in->standby) {
3256
3257 in_close_pcm_devices(in);
3258
3259#ifdef PREPROCESSING_ENABLED
3260 if (in->echo_reference != NULL) {
3261 /* stop reading from echo reference */
3262 in->echo_reference->read(in->echo_reference, NULL);
3263 put_echo_reference(adev, in->echo_reference);
3264 in->echo_reference = NULL;
3265 }
3266#ifdef HW_AEC_LOOPBACK
3267 if (in->hw_echo_reference)
3268 {
3269 if (in->hw_ref_buf) {
3270 free(in->hw_ref_buf);
3271 in->hw_ref_buf = NULL;
3272 }
3273 }
3274#endif // HW_AEC_LOOPBACK
3275#endif // PREPROCESSING_ENABLED
3276
3277 status = stop_input_stream(in);
3278
3279 if (in->read_buf) {
3280 free(in->read_buf);
3281 in->read_buf = NULL;
3282 }
3283
3284 in->standby = 1;
3285 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003286
3287 in->last_read_time_us = 0;
3288
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003289 return 0;
3290}
3291
3292// called with adev->lock_inputs locked
3293static int in_standby_l(struct stream_in *in)
3294{
3295 struct audio_device *adev = in->dev;
3296 int status = 0;
3297 lock_input_stream(in);
3298 if (!in->standby) {
3299 pthread_mutex_lock(&adev->lock);
3300 status = do_in_standby_l(in);
3301 pthread_mutex_unlock(&adev->lock);
3302 }
3303 pthread_mutex_unlock(&in->lock);
3304 return status;
3305}
3306
3307static int in_standby(struct audio_stream *stream)
3308{
3309 struct stream_in *in = (struct stream_in *)stream;
3310 struct audio_device *adev = in->dev;
3311 int status;
3312 ALOGV("%s: enter", __func__);
3313 pthread_mutex_lock(&adev->lock_inputs);
3314 status = in_standby_l(in);
3315 pthread_mutex_unlock(&adev->lock_inputs);
3316 ALOGV("%s: exit: status(%d)", __func__, status);
3317 return status;
3318}
3319
3320static int in_dump(const struct audio_stream *stream, int fd)
3321{
3322 (void)stream;
3323 (void)fd;
3324
3325 return 0;
3326}
3327
3328static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3329{
3330 struct stream_in *in = (struct stream_in *)stream;
3331 struct audio_device *adev = in->dev;
3332 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003333 char value[32];
3334 int ret, val = 0;
3335 struct audio_usecase *uc_info;
3336 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003337 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003338
3339 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3340 parms = str_parms_create_str(kvpairs);
3341
3342 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3343
3344 pthread_mutex_lock(&adev->lock_inputs);
3345 lock_input_stream(in);
3346 pthread_mutex_lock(&adev->lock);
3347 if (ret >= 0) {
3348 val = atoi(value);
3349 /* no audio source uses val == 0 */
3350 if (((int)in->source != val) && (val != 0)) {
3351 in->source = val;
3352 }
3353 }
3354
3355 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3356 if (ret >= 0) {
3357 val = atoi(value);
3358 if (((int)in->devices != val) && (val != 0)) {
3359 in->devices = val;
3360 /* If recording is in progress, change the tx device to new device */
3361 if (!in->standby) {
3362 uc_info = get_usecase_from_id(adev, in->usecase);
3363 if (uc_info == NULL) {
3364 ALOGE("%s: Could not find the usecase (%d) in the list",
3365 __func__, in->usecase);
3366 } else {
3367 if (list_empty(&in->pcm_dev_list))
3368 ALOGE("%s: pcm device list empty", __func__);
3369 else {
3370 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3371 struct pcm_device, stream_list_node);
3372 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3373 do_standby = true;
3374 }
3375 }
3376 }
3377 if (do_standby) {
3378 ret = do_in_standby_l(in);
3379 } else
3380 ret = select_devices(adev, in->usecase);
3381 }
3382 }
3383 }
3384 pthread_mutex_unlock(&adev->lock);
3385 pthread_mutex_unlock(&in->lock);
3386 pthread_mutex_unlock(&adev->lock_inputs);
3387 str_parms_destroy(parms);
3388
3389 if (ret > 0)
3390 ret = 0;
3391
3392 ALOGV("%s: exit: status(%d)", __func__, ret);
3393 return ret;
3394}
3395
3396static char* in_get_parameters(const struct audio_stream *stream,
3397 const char *keys)
3398{
3399 (void)stream;
3400 (void)keys;
3401
3402 return strdup("");
3403}
3404
3405static int in_set_gain(struct audio_stream_in *stream, float gain)
3406{
3407 (void)stream;
3408 (void)gain;
3409
3410 return 0;
3411}
3412
3413static ssize_t read_bytes_from_dsp(struct stream_in *in, void* buffer,
3414 size_t bytes)
3415{
3416 struct pcm_device *pcm_device;
3417 struct audio_device *adev = in->dev;
3418
3419 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3420 struct pcm_device, stream_list_node);
3421
3422 if (pcm_device->sound_trigger_handle > 0)
3423 return adev->sound_trigger_read_samples(pcm_device->sound_trigger_handle, buffer, bytes);
3424 else
3425 return 0;
3426}
3427
3428static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3429 size_t bytes)
3430{
3431 struct stream_in *in = (struct stream_in *)stream;
3432 struct audio_device *adev = in->dev;
3433 ssize_t frames = -1;
3434 int ret = -1;
3435 int read_and_process_successful = false;
3436
3437 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003438
3439 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3440 lock_input_stream(in);
3441
Andreas Schneider3b643832017-01-31 11:48:22 +01003442#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003443 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003444 pid_t tid = gettid();
3445 int err;
3446
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003447 err = fast_set_affinity(tid);
3448 if (err < 0) {
3449 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3450 }
3451 in->is_fastcapture_affinity_set = true;
3452 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003453#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003454
3455 if (in->standby) {
3456 pthread_mutex_unlock(&in->lock);
3457 pthread_mutex_lock(&adev->lock_inputs);
3458 lock_input_stream(in);
3459 if (!in->standby) {
3460 pthread_mutex_unlock(&adev->lock_inputs);
3461 goto false_alarm;
3462 }
3463 pthread_mutex_lock(&adev->lock);
3464 ret = start_input_stream(in);
3465 pthread_mutex_unlock(&adev->lock);
3466 pthread_mutex_unlock(&adev->lock_inputs);
3467 if (ret != 0) {
3468 goto exit;
3469 }
3470 in->standby = 0;
3471 }
3472false_alarm:
3473
3474 if (!list_empty(&in->pcm_dev_list)) {
3475 if (in->usecase == USECASE_AUDIO_CAPTURE_HOTWORD) {
3476 bytes = read_bytes_from_dsp(in, buffer, bytes);
3477 if (bytes > 0)
3478 read_and_process_successful = true;
3479 } else {
3480 /*
3481 * Read PCM and:
3482 * - resample if needed
3483 * - process if pre-processors are attached
3484 * - discard unwanted channels
3485 */
3486 frames = read_and_process_frames(in, buffer, frames_rq);
3487 if (frames >= 0)
3488 read_and_process_successful = true;
3489 }
3490 }
3491
3492 /*
3493 * Instead of writing zeroes here, we could trust the hardware
3494 * to always provide zeroes when muted.
3495 */
3496 if (read_and_process_successful == true && adev->mic_mute)
3497 memset(buffer, 0, bytes);
3498
3499exit:
3500 pthread_mutex_unlock(&in->lock);
3501
3502 if (read_and_process_successful == false) {
3503 in_standby(&in->stream.common);
3504 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003505 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3506 clock_gettime(CLOCK_MONOTONIC, &t);
3507 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3508
3509 // we do a full sleep when exiting standby.
3510 const bool standby = in->last_read_time_us == 0;
3511 const int64_t elapsed_time_since_last_read = standby ?
3512 0 : now - in->last_read_time_us;
3513 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3514 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3515 if (sleep_time > 0) {
3516 usleep(sleep_time);
3517 } else {
3518 sleep_time = 0;
3519 }
3520 in->last_read_time_us = now + sleep_time;
3521 // last_read_time_us is an approximation of when the (simulated) alsa
3522 // buffer is drained by the read, and is empty.
3523 //
3524 // On the subsequent in_read(), we measure the elapsed time spent in
3525 // the recording thread. This is subtracted from the sleep estimate based on frames,
3526 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003527 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003528 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003529
3530 if (bytes > 0) {
3531 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3532 }
3533
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003534 return bytes;
3535}
3536
3537static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3538{
3539 (void)stream;
3540
3541 return 0;
3542}
3543
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003544static int in_get_capture_position(const struct audio_stream_in *stream,
3545 int64_t *frames, int64_t *time)
3546{
3547 if (stream == NULL || frames == NULL || time == NULL) {
3548 return -EINVAL;
3549 }
3550
3551 struct stream_in *in = (struct stream_in *)stream;
3552 struct pcm_device *pcm_device;
3553 int ret = -ENOSYS;
3554
3555 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3556 struct pcm_device, stream_list_node);
3557
3558 pthread_mutex_lock(&in->lock);
3559 if (pcm_device->pcm) {
3560 struct timespec timestamp;
3561 unsigned int avail;
3562 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3563 *frames = in->frames_read + avail;
3564 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3565 ret = 0;
3566 }
3567 }
3568
3569 pthread_mutex_unlock(&in->lock);
3570 return ret;
3571}
3572
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003573static int add_remove_audio_effect(const struct audio_stream *stream,
3574 effect_handle_t effect,
3575 bool enable)
3576{
3577 struct stream_in *in = (struct stream_in *)stream;
3578 struct audio_device *adev = in->dev;
3579 int status = 0;
3580 effect_descriptor_t desc;
3581#ifdef PREPROCESSING_ENABLED
3582 int i;
3583#endif
3584 status = (*effect)->get_descriptor(effect, &desc);
3585 if (status != 0)
3586 return status;
3587
3588 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3589
3590 pthread_mutex_lock(&adev->lock_inputs);
3591 lock_input_stream(in);
3592 pthread_mutex_lock(&in->dev->lock);
3593#ifndef PREPROCESSING_ENABLED
3594 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3595 in->enable_aec != enable &&
3596 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3597 in->enable_aec = enable;
3598 if (!in->standby)
3599 select_devices(in->dev, in->usecase);
3600 }
3601#else
3602 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3603 status = -ENOSYS;
3604 goto exit;
3605 }
3606 if ( enable == true ) {
3607 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3608 /* add the supported channel of the effect in the channel_configs */
3609 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3610 in->num_preprocessors ++;
3611 /* check compatibility between main channel supported and possible auxiliary channels */
3612 in_update_aux_channels(in, effect);//wesley crash
3613 in->aux_channels_changed = true;
3614 } else {
3615 /* if ( enable == false ) */
3616 if (in->num_preprocessors <= 0) {
3617 status = -ENOSYS;
3618 goto exit;
3619 }
3620 status = -EINVAL;
3621 for (i=0; i < in->num_preprocessors; i++) {
3622 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3623 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3624 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3625 in->preprocessors[i - 1].num_channel_configs =
3626 in->preprocessors[i].num_channel_configs;
3627 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3628 continue;
3629 }
3630 if ( in->preprocessors[i].effect_itfe == effect ) {
3631 ALOGV("add_remove_audio_effect found fx at index %d", i);
3632 free(in->preprocessors[i].channel_configs);
3633 status = 0;
3634 }
3635 }
3636 if (status != 0)
3637 goto exit;
3638 in->num_preprocessors--;
3639 /* if we remove one effect, at least the last proproc should be reset */
3640 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3641 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3642 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3643 in->aux_channels_changed = false;
3644 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3645 }
3646 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3647
3648 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3649 in->enable_aec = enable;
3650 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3651 if (!in->standby) {
3652 select_devices(in->dev, in->usecase);
3653 do_in_standby_l(in);
3654 }
3655 if (in->enable_aec == true) {
3656 in_configure_reverse(in);
3657 }
3658 }
3659exit:
3660#endif
3661 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3662 pthread_mutex_unlock(&in->dev->lock);
3663 pthread_mutex_unlock(&in->lock);
3664 pthread_mutex_unlock(&adev->lock_inputs);
3665 return status;
3666}
3667
3668static int in_add_audio_effect(const struct audio_stream *stream,
3669 effect_handle_t effect)
3670{
3671 ALOGV("%s: effect %p", __func__, effect);
3672 return add_remove_audio_effect(stream, effect, true);
3673}
3674
3675static int in_remove_audio_effect(const struct audio_stream *stream,
3676 effect_handle_t effect)
3677{
3678 ALOGV("%s: effect %p", __func__, effect);
3679 return add_remove_audio_effect(stream, effect, false);
3680}
3681
3682static int adev_open_output_stream(struct audio_hw_device *dev,
3683 audio_io_handle_t handle,
3684 audio_devices_t devices,
3685 audio_output_flags_t flags,
3686 struct audio_config *config,
3687 struct audio_stream_out **stream_out,
3688 const char *address __unused)
3689{
3690 struct audio_device *adev = (struct audio_device *)dev;
3691 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003692 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003693 struct pcm_device_profile *pcm_profile;
3694
3695 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3696 __func__, config->sample_rate, config->channel_mask, devices, flags);
3697 *stream_out = NULL;
3698 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003699 if (out == NULL) {
3700 ret = -ENOMEM;
3701 goto error_config;
3702 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003703
3704 if (devices == AUDIO_DEVICE_NONE)
3705 devices = AUDIO_DEVICE_OUT_SPEAKER;
3706
3707 out->flags = flags;
3708 out->devices = devices;
3709 out->dev = adev;
3710 out->format = config->format;
3711 out->sample_rate = config->sample_rate;
3712 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3713 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3714 out->handle = handle;
3715
3716 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3717 if (pcm_profile == NULL) {
3718 ret = -EINVAL;
3719 goto error_open;
3720 }
3721 out->config = pcm_profile->config;
3722
3723 /* Init use case and pcm_config */
3724 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3725 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3726 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3727 ALOGE("%s: Unsupported Offload information", __func__);
3728 ret = -EINVAL;
3729 goto error_open;
3730 }
3731 if (!is_supported_format(config->offload_info.format)) {
3732 ALOGE("%s: Unsupported audio format", __func__);
3733 ret = -EINVAL;
3734 goto error_open;
3735 }
3736
3737 out->compr_config.codec = (struct snd_codec *)
3738 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003739 if (out->compr_config.codec == NULL) {
3740 ret = -ENOMEM;
3741 goto error_open;
3742 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003743
3744 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3745 if (config->offload_info.channel_mask)
3746 out->channel_mask = config->offload_info.channel_mask;
3747 else if (config->channel_mask)
3748 out->channel_mask = config->channel_mask;
3749 out->format = config->offload_info.format;
3750 out->sample_rate = config->offload_info.sample_rate;
3751
3752 out->stream.set_callback = out_set_callback;
3753 out->stream.pause = out_pause;
3754 out->stream.resume = out_resume;
3755 out->stream.drain = out_drain;
3756 out->stream.flush = out_flush;
3757
3758 out->compr_config.codec->id =
3759 get_snd_codec_id(config->offload_info.format);
3760 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3761 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3762 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3763 out->compr_config.codec->bit_rate =
3764 config->offload_info.bit_rate;
3765 out->compr_config.codec->ch_in =
3766 audio_channel_count_from_out_mask(config->channel_mask);
3767 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3768
3769 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3770 out->non_blocking = 1;
3771
3772 out->send_new_metadata = 1;
3773 create_offload_callback_thread(out);
3774 out->offload_state = OFFLOAD_STATE_IDLE;
3775
3776 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3777 __func__, config->offload_info.version,
3778 config->offload_info.bit_rate);
3779 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3780 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003781 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003782 out->sample_rate = out->config.rate;
3783 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3784 } else {
3785 out->usecase = USECASE_AUDIO_PLAYBACK;
3786 out->sample_rate = out->config.rate;
3787 }
3788
3789 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3790 if (adev->primary_output == NULL)
3791 adev->primary_output = out;
3792 else {
3793 ALOGE("%s: Primary output is already opened", __func__);
3794 ret = -EEXIST;
3795 goto error_open;
3796 }
3797 }
3798
3799 /* Check if this usecase is already existing */
3800 pthread_mutex_lock(&adev->lock);
3801 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3802 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3803 pthread_mutex_unlock(&adev->lock);
3804 ret = -EEXIST;
3805 goto error_open;
3806 }
3807 pthread_mutex_unlock(&adev->lock);
3808
3809 out->stream.common.get_sample_rate = out_get_sample_rate;
3810 out->stream.common.set_sample_rate = out_set_sample_rate;
3811 out->stream.common.get_buffer_size = out_get_buffer_size;
3812 out->stream.common.get_channels = out_get_channels;
3813 out->stream.common.get_format = out_get_format;
3814 out->stream.common.set_format = out_set_format;
3815 out->stream.common.standby = out_standby;
3816 out->stream.common.dump = out_dump;
3817 out->stream.common.set_parameters = out_set_parameters;
3818 out->stream.common.get_parameters = out_get_parameters;
3819 out->stream.common.add_audio_effect = out_add_audio_effect;
3820 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3821 out->stream.get_latency = out_get_latency;
3822 out->stream.set_volume = out_set_volume;
3823 out->stream.write = out_write;
3824 out->stream.get_render_position = out_get_render_position;
3825 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3826 out->stream.get_presentation_position = out_get_presentation_position;
3827
3828 out->standby = 1;
3829 /* out->muted = false; by calloc() */
3830 /* out->written = 0; by calloc() */
3831
3832 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3833 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3834 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3835
3836 config->format = out->stream.common.get_format(&out->stream.common);
3837 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3838 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3839
3840 out->is_fastmixer_affinity_set = false;
3841
3842 *stream_out = &out->stream;
3843 ALOGV("%s: exit", __func__);
3844 return 0;
3845
3846error_open:
3847 free(out);
3848 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003849error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003850 ALOGV("%s: exit: ret %d", __func__, ret);
3851 return ret;
3852}
3853
3854static void adev_close_output_stream(struct audio_hw_device *dev,
3855 struct audio_stream_out *stream)
3856{
3857 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003858 (void)dev;
3859
3860 ALOGV("%s: enter", __func__);
3861 out_standby(&stream->common);
3862 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3863 destroy_offload_callback_thread(out);
3864
3865 if (out->compr_config.codec != NULL)
3866 free(out->compr_config.codec);
3867 }
3868 pthread_cond_destroy(&out->cond);
3869 pthread_mutex_destroy(&out->lock);
3870 free(stream);
3871 ALOGV("%s: exit", __func__);
3872}
3873
3874static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3875{
3876 struct audio_device *adev = (struct audio_device *)dev;
3877 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003878 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003879#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003880 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003881#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003882 int ret;
3883
3884 ALOGV("%s: enter: %s", __func__, kvpairs);
3885
3886 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003887
3888 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3889 if (ret >= 0) {
3890 /* When set to false, HAL should disable EC and NS
3891 * But it is currently not supported.
3892 */
3893 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003894 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003895 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003896 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003897 }
3898
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003899 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3900 if (ret >= 0) {
3901 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3902 adev->screen_off = false;
3903 else
3904 adev->screen_off = true;
3905 }
3906
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003907#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003908 ret = str_parms_get_int(parms, "rotation", &val);
3909 if (ret >= 0) {
3910 bool reverse_speakers = false;
3911 switch(val) {
3912 /* FIXME: note that the code below assumes that the speakers are in the correct placement
3913 relative to the user when the device is rotated 90deg from its default rotation. This
3914 assumption is device-specific, not platform-specific like this code. */
3915 case 270:
3916 reverse_speakers = true;
3917 break;
3918 case 0:
3919 case 90:
3920 case 180:
3921 break;
3922 default:
3923 ALOGE("%s: unexpected rotation of %d", __func__, val);
3924 }
3925 pthread_mutex_lock(&adev->lock);
3926 if (adev->speaker_lr_swap != reverse_speakers) {
3927 adev->speaker_lr_swap = reverse_speakers;
3928 /* only update the selected device if there is active pcm playback */
3929 struct audio_usecase *usecase;
3930 struct listnode *node;
3931 list_for_each(node, &adev->usecase_list) {
3932 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
3933 if (usecase->type == PCM_PLAYBACK) {
3934 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003935 break;
3936 }
3937 }
3938 }
3939 pthread_mutex_unlock(&adev->lock);
3940 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003941#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003942
3943 str_parms_destroy(parms);
3944
3945 if (ret > 0)
3946 ret = 0;
3947
3948 ALOGV("%s: exit with code(%d)", __func__, ret);
3949 return ret;
3950}
3951
3952static char* adev_get_parameters(const struct audio_hw_device *dev,
3953 const char *keys)
3954{
3955 (void)dev;
3956 (void)keys;
3957
3958 return strdup("");
3959}
3960
3961static int adev_init_check(const struct audio_hw_device *dev)
3962{
3963 (void)dev;
3964
3965 return 0;
3966}
3967
3968static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3969{
3970 int ret = 0;
3971 struct audio_device *adev = (struct audio_device *)dev;
3972 pthread_mutex_lock(&adev->lock);
3973 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003974 adev->voice.volume = volume;
3975 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003976 pthread_mutex_unlock(&adev->lock);
3977 return ret;
3978}
3979
3980static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
3981{
3982 (void)dev;
3983 (void)volume;
3984
3985 return -ENOSYS;
3986}
3987
3988static int adev_get_master_volume(struct audio_hw_device *dev,
3989 float *volume)
3990{
3991 (void)dev;
3992 (void)volume;
3993
3994 return -ENOSYS;
3995}
3996
3997static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
3998{
3999 (void)dev;
4000 (void)muted;
4001
4002 return -ENOSYS;
4003}
4004
4005static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
4006{
4007 (void)dev;
4008 (void)muted;
4009
4010 return -ENOSYS;
4011}
4012
4013static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4014{
4015 struct audio_device *adev = (struct audio_device *)dev;
4016
4017 pthread_mutex_lock(&adev->lock);
4018 if (adev->mode != mode) {
4019 ALOGI("%s mode = %d", __func__, mode);
4020 adev->mode = mode;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004021 }
4022 pthread_mutex_unlock(&adev->lock);
4023 return 0;
4024}
4025
4026static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4027{
4028 struct audio_device *adev = (struct audio_device *)dev;
4029 int err = 0;
4030
4031 pthread_mutex_lock(&adev->lock);
4032 adev->mic_mute = state;
4033
4034 if (adev->mode == AUDIO_MODE_IN_CALL) {
4035 /* TODO */
4036 }
4037
4038 pthread_mutex_unlock(&adev->lock);
4039 return err;
4040}
4041
4042static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4043{
4044 struct audio_device *adev = (struct audio_device *)dev;
4045
4046 *state = adev->mic_mute;
4047
4048 return 0;
4049}
4050
4051static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4052 const struct audio_config *config)
4053{
4054 (void)dev;
4055
4056 /* NOTE: we default to built in mic which may cause a mismatch between what we
4057 * report here and the actual buffer size
4058 */
4059 return get_input_buffer_size(config->sample_rate,
4060 config->format,
4061 audio_channel_count_from_in_mask(config->channel_mask),
4062 PCM_CAPTURE /* usecase_type */,
4063 AUDIO_DEVICE_IN_BUILTIN_MIC);
4064}
4065
4066static int adev_open_input_stream(struct audio_hw_device *dev,
4067 audio_io_handle_t handle __unused,
4068 audio_devices_t devices,
4069 struct audio_config *config,
4070 struct audio_stream_in **stream_in,
4071 audio_input_flags_t flags,
4072 const char *address __unused,
4073 audio_source_t source)
4074{
4075 struct audio_device *adev = (struct audio_device *)dev;
4076 struct stream_in *in;
4077 struct pcm_device_profile *pcm_profile;
4078
4079 ALOGV("%s: enter", __func__);
4080
4081 *stream_in = NULL;
4082 if (check_input_parameters(config->sample_rate, config->format,
4083 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4084 return -EINVAL;
4085
4086 usecase_type_t usecase_type = source == AUDIO_SOURCE_HOTWORD ?
4087 PCM_HOTWORD_STREAMING : flags & AUDIO_INPUT_FLAG_FAST ?
4088 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4089 pcm_profile = get_pcm_device(usecase_type, devices);
4090 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4091 // a low latency profile may not exist for that device, fall back
4092 // to regular capture. the MixerThread automatically changes
4093 // to non-fast capture based on the buffer size.
4094 flags &= ~AUDIO_INPUT_FLAG_FAST;
4095 usecase_type = PCM_CAPTURE;
4096 pcm_profile = get_pcm_device(usecase_type, devices);
4097 }
4098 if (pcm_profile == NULL)
4099 return -EINVAL;
4100
4101 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004102 if (in == NULL) {
4103 return -ENOMEM;
4104 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004105
4106 in->stream.common.get_sample_rate = in_get_sample_rate;
4107 in->stream.common.set_sample_rate = in_set_sample_rate;
4108 in->stream.common.get_buffer_size = in_get_buffer_size;
4109 in->stream.common.get_channels = in_get_channels;
4110 in->stream.common.get_format = in_get_format;
4111 in->stream.common.set_format = in_set_format;
4112 in->stream.common.standby = in_standby;
4113 in->stream.common.dump = in_dump;
4114 in->stream.common.set_parameters = in_set_parameters;
4115 in->stream.common.get_parameters = in_get_parameters;
4116 in->stream.common.add_audio_effect = in_add_audio_effect;
4117 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4118 in->stream.set_gain = in_set_gain;
4119 in->stream.read = in_read;
4120 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004121 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004122
4123 in->devices = devices;
4124 in->source = source;
4125 in->dev = adev;
4126 in->standby = 1;
4127 in->main_channels = config->channel_mask;
4128 in->requested_rate = config->sample_rate;
4129 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4130 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4131 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004132 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004133 /* HW codec is limited to default channels. No need to update with
4134 * requested channels */
4135 in->config = pcm_profile->config;
4136
4137 /* Update config params with the requested sample rate and channels */
4138 if (source == AUDIO_SOURCE_HOTWORD) {
4139 in->usecase = USECASE_AUDIO_CAPTURE_HOTWORD;
4140 } else {
4141 in->usecase = USECASE_AUDIO_CAPTURE;
4142 }
4143 in->usecase_type = usecase_type;
4144
4145 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4146 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4147
4148 in->is_fastcapture_affinity_set = false;
4149
4150 *stream_in = &in->stream;
4151 ALOGV("%s: exit", __func__);
4152 return 0;
4153}
4154
4155static void adev_close_input_stream(struct audio_hw_device *dev,
4156 struct audio_stream_in *stream)
4157{
4158 struct audio_device *adev = (struct audio_device *)dev;
4159 struct stream_in *in = (struct stream_in*)stream;
4160 ALOGV("%s", __func__);
4161
4162 /* prevent concurrent out_set_parameters, or out_write from standby */
4163 pthread_mutex_lock(&adev->lock_inputs);
4164
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004165 if (in->read_buf) {
4166 free(in->read_buf);
4167 in->read_buf = NULL;
4168 }
4169
4170 if (in->resampler) {
4171 release_resampler(in->resampler);
4172 in->resampler = NULL;
4173 }
4174
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004175#ifdef PREPROCESSING_ENABLED
4176 int i;
4177
4178 for (i=0; i<in->num_preprocessors; i++) {
4179 free(in->preprocessors[i].channel_configs);
4180 }
4181
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004182 if (in->proc_buf_in) {
4183 free(in->proc_buf_in);
4184 in->proc_buf_in = NULL;
4185 }
4186
4187 if (in->proc_buf_out) {
4188 free(in->proc_buf_out);
4189 in->proc_buf_out = NULL;
4190 }
4191
4192 if (in->ref_buf) {
4193 free(in->ref_buf);
4194 in->ref_buf = NULL;
4195 }
4196
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004197#endif
4198
4199 in_standby_l(in);
4200 free(stream);
4201
4202 pthread_mutex_unlock(&adev->lock_inputs);
4203
4204 return;
4205}
4206
4207static int adev_dump(const audio_hw_device_t *device, int fd)
4208{
4209 (void)device;
4210 (void)fd;
4211
4212 return 0;
4213}
4214
4215static int adev_close(hw_device_t *device)
4216{
4217 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004218 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004219 audio_device_ref_count--;
4220 free(adev->snd_dev_ref_cnt);
4221 free_mixer_list(adev);
4222 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004223
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004224 return 0;
4225}
4226
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004227/* This returns true if the input parameter looks at all plausible as a low latency period size,
4228 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4229 * just that it _might_ work.
4230 */
4231static bool period_size_is_plausible_for_low_latency(int period_size)
4232{
4233 switch (period_size) {
4234 case 64:
4235 case 96:
4236 case 128:
4237 case 192:
4238 case 256:
4239 return true;
4240 default:
4241 return false;
4242 }
4243}
4244
4245static int adev_open(const hw_module_t *module, const char *name,
4246 hw_device_t **device)
4247{
4248 struct audio_device *adev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004249
4250 ALOGV("%s: enter", __func__);
4251 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4252
Andreas Schneider56204f62017-01-31 08:17:32 +01004253 *device = NULL;
4254
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004255 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004256 if (adev == NULL) {
4257 return -ENOMEM;
4258 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004259
4260 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4261 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4262 adev->device.common.module = (struct hw_module_t *)module;
4263 adev->device.common.close = adev_close;
4264
4265 adev->device.init_check = adev_init_check;
4266 adev->device.set_voice_volume = adev_set_voice_volume;
4267 adev->device.set_master_volume = adev_set_master_volume;
4268 adev->device.get_master_volume = adev_get_master_volume;
4269 adev->device.set_master_mute = adev_set_master_mute;
4270 adev->device.get_master_mute = adev_get_master_mute;
4271 adev->device.set_mode = adev_set_mode;
4272 adev->device.set_mic_mute = adev_set_mic_mute;
4273 adev->device.get_mic_mute = adev_get_mic_mute;
4274 adev->device.set_parameters = adev_set_parameters;
4275 adev->device.get_parameters = adev_get_parameters;
4276 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4277 adev->device.open_output_stream = adev_open_output_stream;
4278 adev->device.close_output_stream = adev_close_output_stream;
4279 adev->device.open_input_stream = adev_open_input_stream;
4280 adev->device.close_input_stream = adev_close_input_stream;
4281 adev->device.dump = adev_dump;
4282
4283 /* Set the default route before the PCM stream is opened */
4284 adev->mode = AUDIO_MODE_NORMAL;
4285 adev->active_input = NULL;
4286 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004287
4288 adev->voice.volume = 1.0f;
4289 adev->voice.bluetooth_nrec = true;
4290 adev->voice.in_call = false;
4291
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004292 /* adev->cur_hdmi_channels = 0; by calloc() */
4293 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004294 if (adev->snd_dev_ref_cnt == NULL) {
4295 free(adev);
4296 return -ENOMEM;
4297 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004298
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004299 adev->ns_in_voice_rec = false;
4300
4301 list_init(&adev->usecase_list);
4302
4303 if (mixer_init(adev) != 0) {
4304 free(adev->snd_dev_ref_cnt);
4305 free(adev);
4306 ALOGE("%s: Failed to init, aborting.", __func__);
4307 *device = NULL;
4308 return -EINVAL;
4309 }
4310
4311 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4312 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4313 if (adev->offload_fx_lib == NULL) {
4314 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4315 } else {
4316 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4317 adev->offload_fx_start_output =
4318 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4319 "visualizer_hal_start_output");
4320 adev->offload_fx_stop_output =
4321 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4322 "visualizer_hal_stop_output");
4323 }
4324 }
4325
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004326 if (access(SOUND_TRIGGER_HAL_LIBRARY_PATH, R_OK) == 0) {
4327 adev->sound_trigger_lib = dlopen(SOUND_TRIGGER_HAL_LIBRARY_PATH, RTLD_NOW);
4328 if (adev->sound_trigger_lib == NULL) {
4329 ALOGE("%s: DLOPEN failed for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4330 } else {
4331 ALOGV("%s: DLOPEN successful for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4332 adev->sound_trigger_open_for_streaming =
4333 (int (*)(void))dlsym(adev->sound_trigger_lib,
4334 "sound_trigger_open_for_streaming");
4335 adev->sound_trigger_read_samples =
4336 (size_t (*)(int, void *, size_t))dlsym(adev->sound_trigger_lib,
4337 "sound_trigger_read_samples");
4338 adev->sound_trigger_close_for_streaming =
4339 (int (*)(int))dlsym(adev->sound_trigger_lib,
4340 "sound_trigger_close_for_streaming");
4341 if (!adev->sound_trigger_open_for_streaming ||
4342 !adev->sound_trigger_read_samples ||
4343 !adev->sound_trigger_close_for_streaming) {
4344
4345 ALOGE("%s: Error grabbing functions in %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4346 adev->sound_trigger_open_for_streaming = 0;
4347 adev->sound_trigger_read_samples = 0;
4348 adev->sound_trigger_close_for_streaming = 0;
4349 }
4350 }
4351 }
4352
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004353 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004354 if (adev->voice.session == NULL) {
4355 ALOGE("%s: Failed to initialize voice session data", __func__);
4356
4357 free(adev->snd_dev_ref_cnt);
4358 free(adev);
4359
4360 *device = NULL;
4361 return -EINVAL;
4362 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004363
4364 *device = &adev->device.common;
4365
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004366 audio_device_ref_count++;
4367
4368 char value[PROPERTY_VALUE_MAX];
4369 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4370 int trial = atoi(value);
4371 if (period_size_is_plausible_for_low_latency(trial)) {
4372
4373 pcm_device_playback.config.period_size = trial;
4374 pcm_device_playback.config.start_threshold =
4375 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4376 pcm_device_playback.config.stop_threshold =
4377 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4378
4379 pcm_device_capture_low_latency.config.period_size = trial;
4380 }
4381 }
4382
4383 ALOGV("%s: exit", __func__);
4384 return 0;
4385}
4386
4387static struct hw_module_methods_t hal_module_methods = {
4388 .open = adev_open,
4389};
4390
4391struct audio_module HAL_MODULE_INFO_SYM = {
4392 .common = {
4393 .tag = HARDWARE_MODULE_TAG,
4394 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4395 .hal_api_version = HARDWARE_HAL_API_VERSION,
4396 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004397 .name = "Samsung Audio HAL",
4398 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004399 .methods = &hal_module_methods,
4400 },
4401};