blob: 9a94e61a96ab0874830a4a9e25d50106eb19adad [file] [log] [blame]
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001/*
2 * Copyright (C) 2013 The Android Open Source Project
Christopher N. Hesse2f6f8582017-01-28 12:46:15 +01003 * Copyright (C) 2017 Christopher N. Hesse <raymanfx@gmail.com>
Andreas Schneider759368f2017-02-02 16:11:14 +01004 * Copyright (C) 2017 Andreas Schneider <asn@cryptomilk.org>
Christopher N. Hesse297a6362017-01-28 12:40:45 +01005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#define LOG_TAG "audio_hw_primary"
20/*#define LOG_NDEBUG 0*/
21/*#define VERY_VERY_VERBOSE_LOGGING*/
22#ifdef VERY_VERY_VERBOSE_LOGGING
23#define ALOGVV ALOGV
24#else
25#define ALOGVV(a...) do { } while(0)
26#endif
27
28#define _GNU_SOURCE
29#include <errno.h>
30#include <pthread.h>
31#include <stdint.h>
32#include <sys/time.h>
33#include <stdlib.h>
34#include <math.h>
35#include <dlfcn.h>
Christopher N. Hesse297a6362017-01-28 12:40:45 +010036
37#include <cutils/log.h>
38#include <cutils/str_parms.h>
39#include <cutils/atomic.h>
40#include <cutils/sched_policy.h>
41#include <cutils/properties.h>
42
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010043#include <samsung_audio.h>
44
Christopher N. Hesse297a6362017-01-28 12:40:45 +010045#include <hardware/audio_effect.h>
46#include <system/thread_defs.h>
47#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
49#include "audio_hw.h"
Christopher N. Hesse757ac412017-01-28 14:42:48 +010050#include "compress_offload.h"
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +010051#include "voice.h"
Christopher N. Hesse297a6362017-01-28 12:40:45 +010052
53#include "sound/compress_params.h"
54
Christopher N. Hesse297a6362017-01-28 12:40:45 +010055
56/* TODO: the following PCM device profiles could be read from a config file */
57static struct pcm_device_profile pcm_device_playback = {
58 .config = {
59 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
60 .rate = PLAYBACK_DEFAULT_SAMPLING_RATE,
61 .period_size = PLAYBACK_PERIOD_SIZE,
62 .period_count = PLAYBACK_PERIOD_COUNT,
63 .format = PCM_FORMAT_S16_LE,
64 .start_threshold = PLAYBACK_START_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
65 .stop_threshold = PLAYBACK_STOP_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
66 .silence_threshold = 0,
67 .silence_size = UINT_MAX,
68 .avail_min = PLAYBACK_AVAILABLE_MIN,
69 },
70 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010071 .id = SOUND_PLAYBACK_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010072 .type = PCM_PLAYBACK,
73 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
Fevax86ac2342017-02-08 09:52:12 +010074 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010075};
76
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010077static struct pcm_device_profile pcm_device_deep_buffer = {
78 .config = {
79 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
80 .rate = DEEP_BUFFER_OUTPUT_SAMPLING_RATE,
81 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
82 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
83 .format = PCM_FORMAT_S16_LE,
84 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
85 .stop_threshold = INT_MAX,
86 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
87 },
88 .card = SOUND_CARD,
89 .id = SOUND_DEEP_BUFFER_DEVICE,
90 .type = PCM_PLAYBACK,
91 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
Fevax86ac2342017-02-08 09:52:12 +010092 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010093};
94
Christopher N. Hesse297a6362017-01-28 12:40:45 +010095static struct pcm_device_profile pcm_device_capture = {
96 .config = {
97 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
98 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
99 .period_size = CAPTURE_PERIOD_SIZE,
100 .period_count = CAPTURE_PERIOD_COUNT,
101 .format = PCM_FORMAT_S16_LE,
102 .start_threshold = CAPTURE_START_THRESHOLD,
103 .stop_threshold = 0,
104 .silence_threshold = 0,
105 .avail_min = 0,
106 },
107 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100108 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100109 .type = PCM_CAPTURE,
110 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
111};
112
113static struct pcm_device_profile pcm_device_capture_low_latency = {
114 .config = {
115 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
116 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
117 .period_size = CAPTURE_PERIOD_SIZE_LOW_LATENCY,
118 .period_count = CAPTURE_PERIOD_COUNT_LOW_LATENCY,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = CAPTURE_START_THRESHOLD,
121 .stop_threshold = 0,
122 .silence_threshold = 0,
123 .avail_min = 0,
124 },
125 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100126 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100127 .type = PCM_CAPTURE_LOW_LATENCY,
128 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC,
129};
130
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100131#ifdef SOUND_CAPTURE_LOOPBACK_AEC_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100132static struct pcm_device_profile pcm_device_capture_loopback_aec = {
133 .config = {
134 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
135 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
136 .period_size = CAPTURE_PERIOD_SIZE,
137 .period_count = CAPTURE_PERIOD_COUNT,
138 .format = PCM_FORMAT_S16_LE,
139 .start_threshold = CAPTURE_START_THRESHOLD,
140 .stop_threshold = 0,
141 .silence_threshold = 0,
142 .avail_min = 0,
143 },
144 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100145 .id = SOUND_CAPTURE_LOOPBACK_AEC_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100146 .type = PCM_CAPTURE,
147 .devices = SND_DEVICE_IN_LOOPBACK_AEC,
148};
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100149#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100150
151static struct pcm_device_profile pcm_device_playback_sco = {
152 .config = {
153 .channels = SCO_DEFAULT_CHANNEL_COUNT,
154 .rate = SCO_DEFAULT_SAMPLING_RATE,
155 .period_size = SCO_PERIOD_SIZE,
156 .period_count = SCO_PERIOD_COUNT,
157 .format = PCM_FORMAT_S16_LE,
158 .start_threshold = SCO_START_THRESHOLD,
159 .stop_threshold = SCO_STOP_THRESHOLD,
160 .silence_threshold = 0,
161 .avail_min = SCO_AVAILABLE_MIN,
162 },
163 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100164 .id = SOUND_PLAYBACK_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100165 .type = PCM_PLAYBACK,
166 .devices =
167 AUDIO_DEVICE_OUT_BLUETOOTH_SCO|AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET|
168 AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT,
169};
170
171static struct pcm_device_profile pcm_device_capture_sco = {
172 .config = {
173 .channels = SCO_DEFAULT_CHANNEL_COUNT,
174 .rate = SCO_DEFAULT_SAMPLING_RATE,
175 .period_size = SCO_PERIOD_SIZE,
176 .period_count = SCO_PERIOD_COUNT,
177 .format = PCM_FORMAT_S16_LE,
178 .start_threshold = CAPTURE_START_THRESHOLD,
179 .stop_threshold = 0,
180 .silence_threshold = 0,
181 .avail_min = 0,
182 },
183 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100184 .id = SOUND_CAPTURE_SCO_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100185 .type = PCM_CAPTURE,
186 .devices = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
187};
188
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100189#ifdef SOUND_CAPTURE_HOTWORD_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100190static struct pcm_device_profile pcm_device_hotword_streaming = {
191 .config = {
192 .channels = 1,
193 .rate = 16000,
194 .period_size = CAPTURE_PERIOD_SIZE,
195 .period_count = CAPTURE_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = CAPTURE_START_THRESHOLD,
198 .stop_threshold = 0,
199 .silence_threshold = 0,
200 .avail_min = 0,
201 },
202 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100203 .id = SOUND_CAPTURE_HOTWORD_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100204 .type = PCM_HOTWORD_STREAMING,
205 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC
206};
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100207#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100208
209static struct pcm_device_profile * const pcm_devices[] = {
210 &pcm_device_playback,
211 &pcm_device_capture,
212 &pcm_device_capture_low_latency,
213 &pcm_device_playback_sco,
214 &pcm_device_capture_sco,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100215#ifdef SOUND_CAPTURE_LOOPBACK_AEC_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100216 &pcm_device_capture_loopback_aec,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100217#endif
218#ifdef SOUND_CAPTURE_HOTWORD_DEVICE
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100219 &pcm_device_hotword_streaming,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100220#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100221 NULL,
222};
223
224static const char * const use_case_table[AUDIO_USECASE_MAX] = {
225 [USECASE_AUDIO_PLAYBACK] = "playback",
226 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "playback multi-channel",
227 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Andreas Schneiderdf6fc8a2017-02-14 11:38:41 +0100228 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "playback deep-buffer",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100229 [USECASE_AUDIO_CAPTURE] = "capture",
230 [USECASE_AUDIO_CAPTURE_HOTWORD] = "capture-hotword",
231 [USECASE_VOICE_CALL] = "voice-call",
232};
233
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100234#define STRING_TO_ENUM(string) { #string, string }
235
236static unsigned int audio_device_ref_count;
237
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100238struct string_to_enum {
239 const char *name;
240 uint32_t value;
241};
242
243static const struct string_to_enum out_channels_name_to_enum_table[] = {
244 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
245 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
246 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
247};
248
Andreas Schneider759368f2017-02-02 16:11:14 +0100249struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
250 struct timespec ret;
251 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100252
253 if (time0.tv_nsec > time1.tv_nsec) {
254 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
255 time0.tv_nsec -= (long int) (1E9 * xsec);
256 time0.tv_sec += xsec;
257 }
258
259 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
260 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
261 time0.tv_nsec += (long int) (1E9 * xsec);
262 time0.tv_sec -= xsec;
263 }
264
Paul Keithf114e2e2017-02-14 20:41:33 -0600265 ret.tv_sec = labs(time1.tv_sec - time0.tv_sec);
266 ret.tv_nsec = labs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100267
268 return ret;
269}
270
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100271static bool is_supported_format(audio_format_t format)
272{
273 if (format == AUDIO_FORMAT_MP3 ||
274 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
275 return true;
276
277 return false;
278}
279
280static int get_snd_codec_id(audio_format_t format)
281{
282 int id = 0;
283
284 switch (format & AUDIO_FORMAT_MAIN_MASK) {
285 case AUDIO_FORMAT_MP3:
286 id = SND_AUDIOCODEC_MP3;
287 break;
288 case AUDIO_FORMAT_AAC:
289 id = SND_AUDIOCODEC_AAC;
290 break;
291 default:
292 ALOGE("%s: Unsupported audio format", __func__);
293 }
294
295 return id;
296}
297
298/* Array to store sound devices */
299static const char * const device_table[SND_DEVICE_MAX] = {
300 [SND_DEVICE_NONE] = "none",
301 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100302 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100303 [SND_DEVICE_OUT_SPEAKER] = "speaker",
304 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
305 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100306 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100307 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100308 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100309 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100310 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100311 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100312 [SND_DEVICE_OUT_VOICE_BT_SCO] = "voice-bt-sco-headset",
313 [SND_DEVICE_OUT_VOICE_BT_SCO_WB] = "voice-bt-sco-headset-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100314 [SND_DEVICE_OUT_HDMI] = "hdmi",
315 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
316 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100317
318 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100319 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100320 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
321 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100322 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100323 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
324 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100325 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
326 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100327 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100328 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100329 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100330 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100331 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100332 [SND_DEVICE_IN_VOICE_BT_SCO_MIC] = "voice-bt-sco-mic",
333 [SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB] = "voice-bt-sco-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100334 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
335 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
336 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100337 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
338 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100339 [SND_DEVICE_IN_LOOPBACK_AEC] = "loopback-aec",
340};
341
342static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
343{
344 struct mixer_card *mixer_card;
345 struct listnode *node;
346
347 list_for_each(node, &adev->mixer_list) {
348 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
349 if (mixer_card->card == card)
350 return mixer_card;
351 }
352 return NULL;
353}
354
355static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
356{
357 struct mixer_card *mixer_card;
358 struct listnode *node;
359
360 list_for_each(node, &usecase->mixer_list) {
361 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
362 if (mixer_card->card == card)
363 return mixer_card;
364 }
365 return NULL;
366}
367
368static void free_mixer_list(struct audio_device *adev)
369{
370 struct mixer_card *mixer_card;
371 struct listnode *node;
372 struct listnode *next;
373
374 list_for_each_safe(node, next, &adev->mixer_list) {
375 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
376 list_remove(node);
377 audio_route_free(mixer_card->audio_route);
378 free(mixer_card);
379 }
380}
381
382static int mixer_init(struct audio_device *adev)
383{
384 int i;
385 int card;
386 int retry_num;
387 struct mixer *mixer;
388 struct audio_route *audio_route;
389 char mixer_path[PATH_MAX];
390 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100391 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100392
393 list_init(&adev->mixer_list);
394
395 for (i = 0; pcm_devices[i] != NULL; i++) {
396 card = pcm_devices[i]->card;
397 if (adev_get_mixer_for_card(adev, card) == NULL) {
398 retry_num = 0;
399 do {
400 mixer = mixer_open(card);
401 if (mixer == NULL) {
402 if (++retry_num > RETRY_NUMBER) {
403 ALOGE("%s unable to open the mixer for--card %d, aborting.",
404 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100405 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100406 goto error;
407 }
408 usleep(RETRY_US);
409 }
410 } while (mixer == NULL);
411
412 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
413 audio_route = audio_route_init(card, mixer_path);
414 if (!audio_route) {
415 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
416 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100417 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100418 goto error;
419 }
420 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100421 if (mixer_card == NULL) {
422 ret = -ENOMEM;
423 goto error;
424 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100425 mixer_card->card = card;
426 mixer_card->mixer = mixer;
427 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100428
429 /* Do not sleep on first enable_snd_device() */
430 mixer_card->dsp_poweroff_time.tv_sec = 1;
431 mixer_card->dsp_poweroff_time.tv_nsec = 0;
432
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100433 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
434 }
435 }
436
437 return 0;
438
439error:
440 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100441 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100442}
443
444static const char *get_snd_device_name(snd_device_t snd_device)
445{
446 const char *name = NULL;
447
Andreas Schneideradb788d2017-02-13 15:19:36 +0100448 if (snd_device == SND_DEVICE_NONE ||
Andreas Schneiderdde54c02017-02-15 14:10:58 +0100449 (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100450 name = device_table[snd_device];
451
452 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
453
454 return name;
455}
456
457static const char *get_snd_device_display_name(snd_device_t snd_device)
458{
459 const char *name = get_snd_device_name(snd_device);
460
461 if (name == NULL)
462 name = "SND DEVICE NOT FOUND";
463
464 return name;
465}
466
467static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
468{
469 int i;
470
471 devices &= ~AUDIO_DEVICE_BIT_IN;
472 for (i = 0; pcm_devices[i] != NULL; i++) {
473 if ((pcm_devices[i]->type == uc_type) &&
474 (devices & pcm_devices[i]->devices))
475 break;
476 }
477 return pcm_devices[i];
478}
479
480static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
481 audio_usecase_t uc_id)
482{
483 struct audio_usecase *usecase;
484 struct listnode *node;
485
486 list_for_each(node, &adev->usecase_list) {
487 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
488 if (usecase->id == uc_id)
489 return usecase;
490 }
491 return NULL;
492}
493
494static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
495 usecase_type_t type)
496{
497 struct audio_usecase *usecase;
498 struct listnode *node;
499
500 list_for_each(node, &adev->usecase_list) {
501 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
502 if (usecase->type & type)
503 return usecase;
504 }
505 return NULL;
506}
507
508/* always called with adev lock held */
509static int set_voice_volume_l(struct audio_device *adev, float volume)
510{
511 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100512
513 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100514 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100515 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100516
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100517 return err;
518}
519
520
521static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
522{
523
524 audio_mode_t mode = adev->mode;
525 snd_device_t snd_device = SND_DEVICE_NONE;
526
527 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
528 if (devices == AUDIO_DEVICE_NONE ||
529 devices & AUDIO_DEVICE_BIT_IN) {
530 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
531 goto exit;
532 }
533
534 if (mode == AUDIO_MODE_IN_CALL) {
535 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
536 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100537 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Fevax51bd12c2017-03-15 10:56:39 -0300538 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100539 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100540 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
541 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
542 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100543 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100544 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100545
546 if (voice_session_uses_wideband(adev->voice.session)) {
547 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
548 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
549 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300550 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100551 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO_WB;
Andreas Schneider59486fa2017-02-06 09:16:39 +0100552 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
553 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
554 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
555 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
556 }
557 }
558
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100559 if (snd_device != SND_DEVICE_NONE) {
560 goto exit;
561 }
562 }
563
564 if (popcount(devices) == 2) {
565 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
566 AUDIO_DEVICE_OUT_SPEAKER)) {
567 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
568 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
569 AUDIO_DEVICE_OUT_SPEAKER)) {
570 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
571 } else {
572 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
573 goto exit;
574 }
575 if (snd_device != SND_DEVICE_NONE) {
576 goto exit;
577 }
578 }
579
580 if (popcount(devices) != 1) {
581 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
582 goto exit;
583 }
584
585 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
586 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
587 snd_device = SND_DEVICE_OUT_HEADPHONES;
588 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
589 snd_device = SND_DEVICE_OUT_SPEAKER;
590 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
591 snd_device = SND_DEVICE_OUT_BT_SCO;
592 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100593 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100594 } else {
595 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
596 }
597exit:
598 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
599 return snd_device;
600}
601
602static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
603{
604 audio_source_t source;
605 audio_mode_t mode = adev->mode;
606 audio_devices_t in_device;
607 audio_channel_mask_t channel_mask;
608 snd_device_t snd_device = SND_DEVICE_NONE;
609 struct stream_in *active_input = NULL;
610 struct audio_usecase *usecase;
611
612 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
613 if (usecase != NULL) {
614 active_input = (struct stream_in *)usecase->stream;
615 }
616 source = (active_input == NULL) ?
617 AUDIO_SOURCE_DEFAULT : active_input->source;
618
Andreas Schneider757e2d82017-02-10 19:28:35 +0100619 in_device = (active_input == NULL) ?
620 AUDIO_DEVICE_NONE :
621 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100622 channel_mask = (active_input == NULL) ?
623 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
624
625 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
626 __func__, out_device, in_device);
627 if (mode == AUDIO_MODE_IN_CALL) {
628 if (out_device == AUDIO_DEVICE_NONE) {
629 ALOGE("%s: No output device set for voice call", __func__);
630 goto exit;
631 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100632
Andreas Schneider82f32482017-02-06 09:00:48 +0100633 snd_device = SND_DEVICE_IN_VOICE_MIC;
634 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100635 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100636 }
637
638 if (voice_session_uses_twomic(adev->voice.session)) {
639 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
640 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
641 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
642 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
643 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
644 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100645 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100646
647 if (voice_session_uses_wideband(adev->voice.session)) {
648 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
649 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
650 }
651
652 if (voice_session_uses_twomic(adev->voice.session)) {
653 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
654 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
655 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
656 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
657 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
658 }
659 }
660 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100661
662 /* BT SCO */
663 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
664 snd_device = SND_DEVICE_IN_VOICE_MIC;
665
666 if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
Fevax51bd12c2017-03-15 10:56:39 -0300667 if (voice_session_uses_wideband(adev->voice.session)) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100668 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300669 } else {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100670 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC;
Fevax51bd12c2017-03-15 10:56:39 -0300671 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100672 } else if (voice_session_uses_twomic(adev->voice.session)) {
673 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
674 }
675 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100676 } else if (source == AUDIO_SOURCE_CAMCORDER) {
677 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
678 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
679 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
680 }
681 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
682 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100683 if (snd_device == SND_DEVICE_NONE) {
684 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
685 }
686 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
687 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
688 }
689 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
690 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
691 in_device = AUDIO_DEVICE_IN_BACK_MIC;
692 if (active_input) {
693 if (active_input->enable_aec) {
694 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
695 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
696 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
697 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
698 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
699 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100700 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100701 }
702 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
703 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
704 }
705 }
706 /* TODO: set echo reference */
707 }
708 } else if (source == AUDIO_SOURCE_DEFAULT) {
709 goto exit;
710 }
711
712
713 if (snd_device != SND_DEVICE_NONE) {
714 goto exit;
715 }
716
717 if (in_device != AUDIO_DEVICE_NONE &&
718 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
719 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
720 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100721 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100722 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
723 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
724 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
725 snd_device = SND_DEVICE_IN_HEADSET_MIC;
726 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
727 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
728 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
729 snd_device = SND_DEVICE_IN_HDMI_MIC;
730 } else {
731 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100732 ALOGW("%s: Using default earpiece-mic", __func__);
733 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100734 }
735 } else {
736 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100737 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100738 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
739 snd_device = SND_DEVICE_IN_HEADSET_MIC;
740 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
741 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
742 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100743 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100744 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
745 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
746 } else {
747 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100748 ALOGW("%s: Using default earpiece-mic", __func__);
749 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100750 }
751 }
752exit:
753 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
754 return snd_device;
755}
756
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100757#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100758static int set_hdmi_channels(struct audio_device *adev, int channel_count)
759{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100760 (void)adev;
761 (void)channel_count;
762 /* TODO */
763
764 return 0;
765}
766
767static int edid_get_max_channels(struct audio_device *adev)
768{
769 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100770 (void)adev;
771
772 /* TODO */
773 return max_channels;
774}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100775#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100776
777/* Delay in Us */
778static int64_t render_latency(audio_usecase_t usecase)
779{
780 (void)usecase;
781 /* TODO */
782 return 0;
783}
784
785static int enable_snd_device(struct audio_device *adev,
786 struct audio_usecase *uc_info,
787 snd_device_t snd_device,
788 bool update_mixer)
789{
790 struct mixer_card *mixer_card;
791 struct listnode *node;
792 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100793#ifdef DSP_POWEROFF_DELAY
794 struct timespec activation_time;
795 struct timespec elapsed_time;
796#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100797
798 if (snd_device_name == NULL)
799 return -EINVAL;
800
801 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
802 ALOGV("Request to enable combo device: enable individual devices\n");
803 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
804 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
805 return 0;
806 }
807 adev->snd_dev_ref_cnt[snd_device]++;
808 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
809 ALOGV("%s: snd_device(%d: %s) is already active",
810 __func__, snd_device, snd_device_name);
811 return 0;
812 }
813
814 ALOGV("%s: snd_device(%d: %s)", __func__,
815 snd_device, snd_device_name);
816
817 list_for_each(node, &uc_info->mixer_list) {
818 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100819
820#ifdef DSP_POWEROFF_DELAY
821 clock_gettime(CLOCK_MONOTONIC, &activation_time);
822
Andreas Schneider58735a92017-02-13 16:48:17 +0100823 elapsed_time = time_spec_diff(activation_time,
824 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100825 if (elapsed_time.tv_sec == 0) {
826 long elapsed_usec = elapsed_time.tv_nsec / 1000;
827
828 if (elapsed_usec < DSP_POWEROFF_DELAY) {
829 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
830 }
831 }
832 update_mixer = true;
833#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100834 audio_route_apply_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100835 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100836 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100837 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100838 }
839
840 return 0;
841}
842
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100843int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100844 struct audio_usecase *uc_info,
845 snd_device_t snd_device,
846 bool update_mixer)
847{
848 struct mixer_card *mixer_card;
849 struct listnode *node;
850 const char *snd_device_name = get_snd_device_name(snd_device);
851
852 if (snd_device_name == NULL)
853 return -EINVAL;
854
855 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
856 ALOGV("Request to disable combo device: disable individual devices\n");
857 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER, update_mixer);
858 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES, update_mixer);
859 return 0;
860 }
861
862 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
863 ALOGE("%s: device ref cnt is already 0", __func__);
864 return -EINVAL;
865 }
866 adev->snd_dev_ref_cnt[snd_device]--;
867 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
868 ALOGV("%s: snd_device(%d: %s)", __func__,
869 snd_device, snd_device_name);
870 list_for_each(node, &uc_info->mixer_list) {
871 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Andreas Schneider759368f2017-02-02 16:11:14 +0100872#ifdef DSP_POWEROFF_DELAY
873 update_mixer = true;
874#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100875 audio_route_reset_path(mixer_card->audio_route, snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100876 if (update_mixer) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100877 audio_route_update_mixer(mixer_card->audio_route);
Andreas Schneider759368f2017-02-02 16:11:14 +0100878 }
879#ifdef DSP_POWEROFF_DELAY
880 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
881#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100882 }
883 }
884 return 0;
885}
886
887static int select_devices(struct audio_device *adev,
888 audio_usecase_t uc_id)
889{
890 snd_device_t out_snd_device = SND_DEVICE_NONE;
891 snd_device_t in_snd_device = SND_DEVICE_NONE;
892 struct audio_usecase *usecase = NULL;
893 struct audio_usecase *vc_usecase = NULL;
894 struct listnode *node;
895 struct stream_in *active_input = NULL;
896 struct stream_out *active_out;
897 struct mixer_card *mixer_card;
898
899 ALOGV("%s: usecase(%d)", __func__, uc_id);
900
901 if (uc_id == USECASE_AUDIO_CAPTURE_HOTWORD)
902 return 0;
903
904 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
905 if (usecase != NULL) {
906 active_input = (struct stream_in *)usecase->stream;
907 }
908
909 usecase = get_usecase_from_id(adev, uc_id);
910 if (usecase == NULL) {
911 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
912 return -EINVAL;
913 }
914 active_out = (struct stream_out *)usecase->stream;
915
Christopher N. Hesse130da9f2017-02-15 12:18:41 +0100916
917 /*
918 * If the voice call is active, use the sound devices of voice call usecase
919 * so that it would not result any device switch. All the usecases will
920 * be switched to new device when select_devices() is called for voice call
921 * usecase.
922 */
923 if (usecase->type != VOICE_CALL && adev->voice.in_call) {
924 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
925 if (vc_usecase == NULL) {
926 ALOGE("%s: Could not find the voice call usecase", __func__);
927 } else {
928 in_snd_device = vc_usecase->in_snd_device;
929 out_snd_device = vc_usecase->out_snd_device;
930 }
931 }
932
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100933 if (usecase->type == VOICE_CALL) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100934 usecase->devices = active_out->devices;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +0100935 prepare_voice_session(adev->voice.session, active_out->devices);
936 out_snd_device = get_output_snd_device(adev, active_out->devices);
937 in_snd_device = get_input_snd_device(adev, active_out->devices);
938 } else if (usecase->type == PCM_PLAYBACK) {
939 usecase->devices = active_out->devices;
940 in_snd_device = SND_DEVICE_NONE;
941 if (out_snd_device == SND_DEVICE_NONE) {
942 out_snd_device = get_output_snd_device(adev, active_out->devices);
943 if (active_out == adev->primary_output &&
944 active_input &&
945 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
946 select_devices(adev, active_input->usecase);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100947 }
948 }
Christopher N. Hesse130da9f2017-02-15 12:18:41 +0100949 } else if (usecase->type == PCM_CAPTURE) {
950 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
951 out_snd_device = SND_DEVICE_NONE;
952 if (in_snd_device == SND_DEVICE_NONE) {
953 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
954 adev->primary_output && !adev->primary_output->standby) {
955 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
956 } else {
957 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100958 }
959 }
960 }
961
962 if (out_snd_device == usecase->out_snd_device &&
963 in_snd_device == usecase->in_snd_device) {
964 return 0;
965 }
966
967 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
968 out_snd_device, get_snd_device_display_name(out_snd_device),
969 in_snd_device, get_snd_device_display_name(in_snd_device));
970
971
972 /* Disable current sound devices */
973 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100974 disable_snd_device(adev, usecase, usecase->out_snd_device, false);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100975 }
976
977 if (usecase->in_snd_device != SND_DEVICE_NONE) {
978 disable_snd_device(adev, usecase, usecase->in_snd_device, false);
979 }
980
981 /* Enable new sound devices */
982 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100983 /* We need to update the audio path if we switch the out devices */
984 if (adev->voice.in_call) {
985 set_voice_session_audio_path(adev->voice.session);
986 }
987
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100988 enable_snd_device(adev, usecase, out_snd_device, false);
989 }
990
991 if (in_snd_device != SND_DEVICE_NONE) {
992 enable_snd_device(adev, usecase, in_snd_device, false);
993 }
994
995 list_for_each(node, &usecase->mixer_list) {
996 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
997 audio_route_update_mixer(mixer_card->audio_route);
998 }
999
1000 usecase->in_snd_device = in_snd_device;
1001 usecase->out_snd_device = out_snd_device;
1002
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001003 return 0;
1004}
1005
1006
1007static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
1008static int do_in_standby_l(struct stream_in *in);
1009
1010#ifdef PREPROCESSING_ENABLED
1011static void get_capture_reference_delay(struct stream_in *in,
1012 size_t frames __unused,
1013 struct echo_reference_buffer *buffer)
1014{
1015 ALOGVV("%s: enter:)", __func__);
1016
1017 /* read frames available in kernel driver buffer */
1018 unsigned int kernel_frames;
1019 struct timespec tstamp;
1020 long buf_delay;
1021 long kernel_delay;
1022 long delay_ns;
1023 struct pcm_device *ref_device;
1024 long rsmp_delay = 0;
1025
1026 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1027 struct pcm_device, stream_list_node);
1028
1029 if (pcm_get_htimestamp(ref_device->pcm, &kernel_frames, &tstamp) < 0) {
1030 buffer->time_stamp.tv_sec = 0;
1031 buffer->time_stamp.tv_nsec = 0;
1032 buffer->delay_ns = 0;
1033 ALOGW("read get_capture_reference_delay(): pcm_htimestamp error");
1034 return;
1035 }
1036
1037 /* adjust render time stamp with delay added by current driver buffer.
1038 * Add the duration of current frame as we want the render time of the last
1039 * sample being written. */
1040
1041 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / ref_device->pcm_profile->config.rate);
1042
1043 buffer->time_stamp = tstamp;
1044 buffer->delay_ns = kernel_delay;
1045
1046 ALOGVV("get_capture_reference_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5d],"
1047 " delay_ns: [%d] , frames:[%zd]",
1048 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns, frames);
1049}
1050
1051static void get_capture_delay(struct stream_in *in,
1052 size_t frames __unused,
1053 struct echo_reference_buffer *buffer)
1054{
1055 ALOGVV("%s: enter:)", __func__);
1056 /* read frames available in kernel driver buffer */
1057 unsigned int kernel_frames;
1058 struct timespec tstamp;
1059 long buf_delay;
1060 long rsmp_delay;
1061 long kernel_delay;
1062 long delay_ns;
1063 struct pcm_device *pcm_device;
1064
1065 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1066 struct pcm_device, stream_list_node);
1067
1068 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1069 buffer->time_stamp.tv_sec = 0;
1070 buffer->time_stamp.tv_nsec = 0;
1071 buffer->delay_ns = 0;
1072 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1073 return;
1074 }
1075
1076 /* read frames available in audio HAL input buffer
1077 * add number of frames being read as we want the capture time of first sample
1078 * in current buffer */
1079 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1080 * at requested sampling rate */
1081 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1082 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1083
1084 /* add delay introduced by resampler */
1085 rsmp_delay = 0;
1086 if (in->resampler) {
1087 rsmp_delay = in->resampler->delay_ns(in->resampler);
1088 }
1089
1090 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1091
1092 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1093
1094 buffer->time_stamp = tstamp;
1095 buffer->delay_ns = delay_ns;
1096 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1097 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1098 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1099 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1100 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1101 in->read_buf_frames, in->proc_buf_frames, frames);
1102}
1103
1104static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1105{
1106 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1107 struct echo_reference_buffer b;
1108 b.delay_ns = 0;
1109 struct pcm_device *pcm_device;
1110
1111 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1112 struct pcm_device, stream_list_node);
1113
1114 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1115 "b.frame_count = [%zd]",
1116 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1117 if (in->ref_buf_frames < frames) {
1118 if (in->ref_buf_size < frames) {
1119 in->ref_buf_size = frames;
1120 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1121 ALOG_ASSERT((in->ref_buf != NULL),
1122 "update_echo_reference() failed to reallocate ref_buf");
1123 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1124 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1125 }
1126 b.frame_count = frames - in->ref_buf_frames;
1127 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1128
1129 get_capture_delay(in, frames, &b);
1130
1131 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1132 {
1133 in->ref_buf_frames += b.frame_count;
1134 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1135 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1136 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1137 }
1138 } else
1139 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1140 return b.delay_ns;
1141}
1142
1143static int set_preprocessor_param(effect_handle_t handle,
1144 effect_param_t *param)
1145{
1146 uint32_t size = sizeof(int);
1147 uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1148 param->vsize;
1149
1150 int status = (*handle)->command(handle,
1151 EFFECT_CMD_SET_PARAM,
1152 sizeof (effect_param_t) + psize,
1153 param,
1154 &size,
1155 &param->status);
1156 if (status == 0)
1157 status = param->status;
1158
1159 return status;
1160}
1161
1162static int set_preprocessor_echo_delay(effect_handle_t handle,
1163 int32_t delay_us)
1164{
1165 struct {
1166 effect_param_t param;
1167 uint32_t data_0;
1168 int32_t data_1;
1169 } buf;
1170 memset(&buf, 0, sizeof(buf));
1171
1172 buf.param.psize = sizeof(uint32_t);
1173 buf.param.vsize = sizeof(uint32_t);
1174 buf.data_0 = AEC_PARAM_ECHO_DELAY;
1175 buf.data_1 = delay_us;
1176
1177 return set_preprocessor_param(handle, &buf.param);
1178}
1179
1180static void push_echo_reference(struct stream_in *in, size_t frames)
1181{
1182 ALOGVV("%s: enter:)", __func__);
1183 /* read frames from echo reference buffer and update echo delay
1184 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1185
1186 int32_t delay_us = update_echo_reference(in, frames)/1000;
1187 int32_t size_in_bytes = 0;
1188 int i;
1189 audio_buffer_t buf;
1190
1191 if (in->ref_buf_frames < frames)
1192 frames = in->ref_buf_frames;
1193
1194 buf.frameCount = frames;
1195 buf.raw = in->ref_buf;
1196
1197 for (i = 0; i < in->num_preprocessors; i++) {
1198 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1199 continue;
1200 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1201 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1202 &buf,
1203 NULL);
1204 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1205 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1206 }
1207
1208 in->ref_buf_frames -= buf.frameCount;
1209 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1210 __func__, in->ref_buf_frames, in->config.channels);
1211 if (in->ref_buf_frames) {
1212 memcpy(in->ref_buf,
1213 in->ref_buf + buf.frameCount * in->config.channels,
1214 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1215 }
1216}
1217
1218static void put_echo_reference(struct audio_device *adev,
1219 struct echo_reference_itfe *reference)
1220{
1221 ALOGV("%s: enter:)", __func__);
1222 int32_t prev_generation = adev->echo_reference_generation;
1223 struct stream_out *out = adev->primary_output;
1224
1225 if (adev->echo_reference != NULL &&
1226 reference == adev->echo_reference) {
1227 /* echo reference is taken from the low latency output stream used
1228 * for voice use cases */
1229 adev->echo_reference = NULL;
1230 android_atomic_inc(&adev->echo_reference_generation);
1231 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1232 // if the primary output is in standby or did not pick the echo reference yet
1233 // we can safely get rid of it here.
1234 // otherwise, out_write() or out_standby() will detect the change in echo reference
1235 // generation and release the echo reference owned by the stream.
1236 if ((out->echo_reference_generation != prev_generation) || out->standby)
1237 release_echo_reference(reference);
1238 } else {
1239 release_echo_reference(reference);
1240 }
1241 ALOGV("release_echo_reference");
1242 }
1243}
1244
1245static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1246 audio_format_t format __unused,
1247 uint32_t channel_count,
1248 uint32_t sampling_rate)
1249{
1250 ALOGV("%s: enter:)", __func__);
1251 put_echo_reference(adev, adev->echo_reference);
1252 /* echo reference is taken from the low latency output stream used
1253 * for voice use cases */
1254 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1255 !adev->primary_output->standby) {
1256 struct audio_stream *stream =
1257 &adev->primary_output->stream.common;
1258 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1259 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1260 ALOGV("Calling create_echo_reference");
1261 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1262 channel_count,
1263 sampling_rate,
1264 AUDIO_FORMAT_PCM_16_BIT,
1265 wr_channel_count,
1266 wr_sampling_rate,
1267 &adev->echo_reference);
1268 if (status == 0)
1269 android_atomic_inc(&adev->echo_reference_generation);
1270 }
1271 return adev->echo_reference;
1272}
1273
1274#ifdef HW_AEC_LOOPBACK
1275static int get_hw_echo_reference(struct stream_in *in)
1276{
1277 struct pcm_device_profile *ref_pcm_profile;
1278 struct pcm_device *ref_device;
1279 struct audio_device *adev = in->dev;
1280
1281 in->hw_echo_reference = false;
1282
1283 if (adev->primary_output!= NULL &&
1284 !adev->primary_output->standby &&
1285 adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1286 adev->primary_output->devices == AUDIO_DEVICE_OUT_SPEAKER) {
1287 struct audio_stream *stream = &adev->primary_output->stream.common;
1288
1289 // TODO: currently there is no low latency mode for aec reference.
1290 ref_pcm_profile = get_pcm_device(PCM_CAPTURE, pcm_device_capture_loopback_aec.devices);
1291 if (ref_pcm_profile == NULL) {
1292 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1293 __func__, pcm_device_capture_loopback_aec.devices);
1294 return -EINVAL;
1295 }
1296
1297 ref_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01001298 if (ref_device == NULL) {
1299 return -ENOMEM;
1300 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001301 ref_device->pcm_profile = ref_pcm_profile;
1302
1303 ALOGV("%s: ref_device rate:%d, ch:%d", __func__, ref_pcm_profile->config.rate, ref_pcm_profile->config.channels);
1304 ref_device->pcm = pcm_open(ref_device->pcm_profile->card, ref_device->pcm_profile->id, PCM_IN | PCM_MONOTONIC, &ref_device->pcm_profile->config);
1305
1306 if (ref_device->pcm && !pcm_is_ready(ref_device->pcm)) {
1307 ALOGE("%s: %s", __func__, pcm_get_error(ref_device->pcm));
1308 pcm_close(ref_device->pcm);
1309 ref_device->pcm = NULL;
1310 return -EIO;
1311 }
1312 list_add_tail(&in->pcm_dev_list, &ref_device->stream_list_node);
1313
1314 in->hw_echo_reference = true;
1315
1316 ALOGV("%s: hw_echo_reference is true", __func__);
1317 }
1318
1319 return 0;
1320}
1321#endif
1322
1323static int get_playback_delay(struct stream_out *out,
1324 size_t frames,
1325 struct echo_reference_buffer *buffer)
1326{
1327 unsigned int kernel_frames;
1328 int status;
1329 int primary_pcm = 0;
1330 struct pcm_device *pcm_device;
1331
1332 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1333 struct pcm_device, stream_list_node);
1334
1335 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1336 if (status < 0) {
1337 buffer->time_stamp.tv_sec = 0;
1338 buffer->time_stamp.tv_nsec = 0;
1339 buffer->delay_ns = 0;
1340 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1341 "setting playbackTimestamp to 0");
1342 return status;
1343 }
1344
1345 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1346
1347 /* adjust render time stamp with delay added by current driver buffer.
1348 * Add the duration of current frame as we want the render time of the last
1349 * sample being written. */
1350 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1351 out->config.rate);
1352 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1353 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1354
1355 return 0;
1356}
1357
1358#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1359 do { \
1360 if (fct_status != 0) \
1361 status = fct_status; \
1362 else if (cmd_status != 0) \
1363 status = cmd_status; \
1364 } while(0)
1365
1366static int in_configure_reverse(struct stream_in *in)
1367{
1368 int32_t cmd_status;
1369 uint32_t size = sizeof(int);
1370 effect_config_t config;
1371 int32_t status = 0;
1372 int32_t fct_status = 0;
1373 int i;
1374 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1375 if (in->num_preprocessors > 0) {
1376 config.inputCfg.channels = in->main_channels;
1377 config.outputCfg.channels = in->main_channels;
1378 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1379 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1380 config.inputCfg.samplingRate = in->requested_rate;
1381 config.outputCfg.samplingRate = in->requested_rate;
1382 config.inputCfg.mask =
1383 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1384 config.outputCfg.mask =
1385 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1386
1387 for (i = 0; i < in->num_preprocessors; i++)
1388 {
1389 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1390 continue;
1391 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1392 in->preprocessors[i].effect_itfe,
1393 EFFECT_CMD_SET_CONFIG_REVERSE,
1394 sizeof(effect_config_t),
1395 &config,
1396 &size,
1397 &cmd_status);
1398 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1399 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1400 }
1401 }
1402 return status;
1403}
1404
1405#define MAX_NUM_CHANNEL_CONFIGS 10
1406
1407static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1408 struct effect_info_s *effect_info)
1409{
1410 /* size and format of the cmd are defined in hardware/audio_effect.h */
1411 effect_handle_t effect = effect_info->effect_itfe;
1412 uint32_t cmd_size = 2 * sizeof(uint32_t);
1413 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1414 /* reply = status + number of configs (n) + n x channel_config_t */
1415 uint32_t reply_size =
1416 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1417 int32_t reply[reply_size];
1418 int32_t cmd_status;
1419
1420 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1421 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1422 ALOG_ASSERT((effect_info->channel_configs == NULL),
1423 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1424
1425 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1426 * This error will be interpreted as if the effect supports the main_channels but does not
1427 * support any aux_channels */
1428 cmd_status = (*effect)->command(effect,
1429 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1430 cmd_size,
1431 (void*)&cmd,
1432 &reply_size,
1433 (void*)&reply);
1434
1435 if (cmd_status != 0) {
1436 ALOGV("in_read_audio_effect_channel_configs(): "
1437 "fx->command returned %d", cmd_status);
1438 return;
1439 }
1440
1441 if (reply[0] != 0) {
1442 ALOGW("in_read_audio_effect_channel_configs(): "
1443 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1444 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1445 return;
1446 }
1447
1448 /* the feature is not supported */
1449 ALOGV("in_read_audio_effect_channel_configs()(): "
1450 "Feature supported and adding %d channel configs to the list", reply[1]);
1451 effect_info->num_channel_configs = reply[1];
1452 effect_info->channel_configs =
1453 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1454 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1455}
1456
1457
1458#define NUM_IN_AUX_CNL_CONFIGS 2
1459static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1460 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1461 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1462};
1463static uint32_t in_get_aux_channels(struct stream_in *in)
1464{
1465 int i;
1466 channel_config_t new_chcfg = {0, 0};
1467
1468 if (in->num_preprocessors == 0)
1469 return 0;
1470
1471 /* do not enable dual mic configurations when capturing from other microphones than
1472 * main or sub */
1473 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1474 return 0;
1475
1476 /* retain most complex aux channels configuration compatible with requested main channels and
1477 * supported by audio driver and all pre processors */
1478 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1479 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1480 if (cur_chcfg->main_channels == in->main_channels) {
1481 size_t match_cnt;
1482 size_t idx_preproc;
1483 for (idx_preproc = 0, match_cnt = 0;
1484 /* no need to continue if at least one preprocessor doesn't match */
1485 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1486 idx_preproc++) {
1487 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1488 size_t idx_chcfg;
1489
1490 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1491 if (memcmp(effect_info->channel_configs + idx_chcfg,
1492 cur_chcfg,
1493 sizeof(channel_config_t)) == 0) {
1494 match_cnt++;
1495 break;
1496 }
1497 }
1498 }
1499 /* if all preprocessors match, we have a candidate */
1500 if (match_cnt == (size_t)in->num_preprocessors) {
1501 /* retain most complex aux channels configuration */
1502 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1503 new_chcfg = *cur_chcfg;
1504 }
1505 }
1506 }
1507 }
1508
1509 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1510
1511 return new_chcfg.aux_channels;
1512}
1513
1514static int in_configure_effect_channels(effect_handle_t effect,
1515 channel_config_t *channel_config)
1516{
1517 int status = 0;
1518 int fct_status;
1519 int32_t cmd_status;
1520 uint32_t reply_size;
1521 effect_config_t config;
1522 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1523
1524 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1525 channel_config->main_channels,
1526 channel_config->aux_channels);
1527
1528 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1529 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1530 reply_size = sizeof(effect_config_t);
1531 fct_status = (*effect)->command(effect,
1532 EFFECT_CMD_GET_CONFIG,
1533 0,
1534 NULL,
1535 &reply_size,
1536 &config);
1537 if (fct_status != 0) {
1538 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1539 return fct_status;
1540 }
1541
1542 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1543 config.outputCfg.channels = config.inputCfg.channels;
1544 reply_size = sizeof(uint32_t);
1545 fct_status = (*effect)->command(effect,
1546 EFFECT_CMD_SET_CONFIG,
1547 sizeof(effect_config_t),
1548 &config,
1549 &reply_size,
1550 &cmd_status);
1551 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1552
1553 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1554 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1555 reply_size = sizeof(uint32_t);
1556 fct_status = (*effect)->command(effect,
1557 EFFECT_CMD_SET_FEATURE_CONFIG,
1558 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1559 cmd,
1560 &reply_size,
1561 &cmd_status);
1562 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1563
1564 /* some implementations need to be re-enabled after a config change */
1565 reply_size = sizeof(uint32_t);
1566 fct_status = (*effect)->command(effect,
1567 EFFECT_CMD_ENABLE,
1568 0,
1569 NULL,
1570 &reply_size,
1571 &cmd_status);
1572 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1573
1574 return status;
1575}
1576
1577static int in_reconfigure_channels(struct stream_in *in,
1578 effect_handle_t effect,
1579 channel_config_t *channel_config,
1580 bool config_changed) {
1581
1582 int status = 0;
1583
1584 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1585 config_changed, effect);
1586
1587 /* if config changed, reconfigure all previously added effects */
1588 if (config_changed) {
1589 int i;
1590 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1591 for (i = 0; i < in->num_preprocessors; i++)
1592 {
1593 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1594 channel_config);
1595 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1596 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1597 if (cur_status != 0) {
1598 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1599 "%d with channels: [%04x][%04x]",
1600 cur_status,
1601 i,
1602 channel_config->main_channels,
1603 channel_config->aux_channels);
1604 status = cur_status;
1605 }
1606 }
1607 } else if (effect != NULL && channel_config->aux_channels) {
1608 /* if aux channels config did not change but aux channels are present,
1609 * we still need to configure the effect being added */
1610 status = in_configure_effect_channels(effect, channel_config);
1611 }
1612 return status;
1613}
1614
1615static void in_update_aux_channels(struct stream_in *in,
1616 effect_handle_t effect)
1617{
1618 uint32_t aux_channels;
1619 channel_config_t channel_config;
1620 int status;
1621
1622 aux_channels = in_get_aux_channels(in);
1623
1624 channel_config.main_channels = in->main_channels;
1625 channel_config.aux_channels = aux_channels;
1626 status = in_reconfigure_channels(in,
1627 effect,
1628 &channel_config,
1629 (aux_channels != in->aux_channels));
1630
1631 if (status != 0) {
1632 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1633 /* resetting aux channels configuration */
1634 aux_channels = 0;
1635 channel_config.aux_channels = 0;
1636 in_reconfigure_channels(in, effect, &channel_config, true);
1637 }
1638 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1639 if (in->aux_channels != aux_channels) {
1640 in->aux_channels_changed = true;
1641 in->aux_channels = aux_channels;
1642 do_in_standby_l(in);
1643 }
1644}
1645#endif
1646
1647/* This function reads PCM data and:
1648 * - resample if needed
1649 * - process if pre-processors are attached
1650 * - discard unwanted channels
1651 */
1652static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1653{
1654 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001655 size_t src_channels = in->config.channels;
1656 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1657 int i;
1658 void *proc_buf_out;
1659 struct pcm_device *pcm_device;
1660 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1661#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001662 audio_buffer_t in_buf;
1663 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001664 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1665#endif
1666
1667 /* Additional channels might be added on top of main_channels:
1668 * - aux_channels (by processing effects)
1669 * - extra channels due to HW limitations
1670 * In case of additional channels, we cannot work inplace
1671 */
1672 if (has_additional_channels)
1673 proc_buf_out = in->proc_buf_out;
1674 else
1675 proc_buf_out = buffer;
1676
1677 if (list_empty(&in->pcm_dev_list)) {
1678 ALOGE("%s: pcm device list empty", __func__);
1679 return -EINVAL;
1680 }
1681
1682 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1683 struct pcm_device, stream_list_node);
1684
1685#ifdef PREPROCESSING_ENABLED
1686 if (has_processing) {
1687 /* since all the processing below is done in frames and using the config.channels
1688 * as the number of channels, no changes is required in case aux_channels are present */
1689 while (frames_wr < frames) {
1690 /* first reload enough frames at the end of process input buffer */
1691 if (in->proc_buf_frames < (size_t)frames) {
1692 ssize_t frames_rd;
1693 if (in->proc_buf_size < (size_t)frames) {
1694 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1695 in->proc_buf_size = (size_t)frames;
1696 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1697 ALOG_ASSERT((in->proc_buf_in != NULL),
1698 "process_frames() failed to reallocate proc_buf_in");
1699 if (has_additional_channels) {
1700 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1701 ALOG_ASSERT((in->proc_buf_out != NULL),
1702 "process_frames() failed to reallocate proc_buf_out");
1703 proc_buf_out = in->proc_buf_out;
1704 }
1705 }
1706 frames_rd = read_frames(in,
1707 in->proc_buf_in +
1708 in->proc_buf_frames * in->config.channels,
1709 frames - in->proc_buf_frames);
1710 if (frames_rd < 0) {
1711 /* Return error code */
1712 frames_wr = frames_rd;
1713 break;
1714 }
1715 in->proc_buf_frames += frames_rd;
1716 }
1717
1718 if (in->echo_reference != NULL) {
1719 push_echo_reference(in, in->proc_buf_frames);
1720 }
1721
1722 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1723 * the maximum number of frames to be consumed and produced by process() */
1724 in_buf.frameCount = in->proc_buf_frames;
1725 in_buf.s16 = in->proc_buf_in;
1726 out_buf.frameCount = frames - frames_wr;
1727 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1728
1729 /* FIXME: this works because of current pre processing library implementation that
1730 * does the actual process only when the last enabled effect process is called.
1731 * The generic solution is to have an output buffer for each effect and pass it as
1732 * input to the next.
1733 */
1734 for (i = 0; i < in->num_preprocessors; i++) {
1735 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1736 &in_buf,
1737 &out_buf);
1738 }
1739
1740 /* process() has updated the number of frames consumed and produced in
1741 * in_buf.frameCount and out_buf.frameCount respectively
1742 * move remaining frames to the beginning of in->proc_buf_in */
1743 in->proc_buf_frames -= in_buf.frameCount;
1744
1745 if (in->proc_buf_frames) {
1746 memcpy(in->proc_buf_in,
1747 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1748 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1749 }
1750
1751 /* if not enough frames were passed to process(), read more and retry. */
1752 if (out_buf.frameCount == 0) {
1753 ALOGW("No frames produced by preproc");
1754 continue;
1755 }
1756
1757 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1758 frames_wr += out_buf.frameCount;
1759 } else {
1760 /* The effect does not comply to the API. In theory, we should never end up here! */
1761 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1762 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1763 frames_wr = frames;
1764 }
1765 }
1766 }
1767 else
1768#endif //PREPROCESSING_ENABLED
1769 {
1770 /* No processing effects attached */
1771 if (has_additional_channels) {
1772 /* With additional channels, we cannot use original buffer */
1773 if (in->proc_buf_size < (size_t)frames) {
1774 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1775 in->proc_buf_size = (size_t)frames;
1776 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1777 ALOG_ASSERT((in->proc_buf_out != NULL),
1778 "process_frames() failed to reallocate proc_buf_out");
1779 proc_buf_out = in->proc_buf_out;
1780 }
1781 }
1782 frames_wr = read_frames(in, proc_buf_out, frames);
1783 }
1784
1785 /* Remove all additional channels that have been added on top of main_channels:
1786 * - aux_channels
1787 * - extra channels from HW due to HW limitations
1788 * Assumption is made that the channels are interleaved and that the main
1789 * channels are first. */
1790
1791 if (has_additional_channels)
1792 {
1793 int16_t* src_buffer = (int16_t *)proc_buf_out;
1794 int16_t* dst_buffer = (int16_t *)buffer;
1795
1796 if (dst_channels == 1) {
1797 for (i = frames_wr; i > 0; i--)
1798 {
1799 *dst_buffer++ = *src_buffer;
1800 src_buffer += src_channels;
1801 }
1802 } else {
1803 for (i = frames_wr; i > 0; i--)
1804 {
1805 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1806 dst_buffer += dst_channels;
1807 src_buffer += src_channels;
1808 }
1809 }
1810 }
1811
1812 return frames_wr;
1813}
1814
1815static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1816 struct resampler_buffer* buffer)
1817{
1818 struct stream_in *in;
1819 struct pcm_device *pcm_device;
1820
1821 if (buffer_provider == NULL || buffer == NULL)
1822 return -EINVAL;
1823
1824 in = (struct stream_in *)((char *)buffer_provider -
1825 offsetof(struct stream_in, buf_provider));
1826
1827 if (list_empty(&in->pcm_dev_list)) {
1828 buffer->raw = NULL;
1829 buffer->frame_count = 0;
1830 in->read_status = -ENODEV;
1831 return -ENODEV;
1832 }
1833
1834 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1835 struct pcm_device, stream_list_node);
1836
1837 if (in->read_buf_frames == 0) {
1838 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1839 if (in->read_buf_size < in->config.period_size) {
1840 in->read_buf_size = in->config.period_size;
1841 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
1842 ALOG_ASSERT((in->read_buf != NULL),
1843 "get_next_buffer() failed to reallocate read_buf");
1844 }
1845
1846 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
1847
1848 if (in->read_status != 0) {
1849 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1850 buffer->raw = NULL;
1851 buffer->frame_count = 0;
1852 return in->read_status;
1853 }
1854 in->read_buf_frames = in->config.period_size;
1855
1856#ifdef PREPROCESSING_ENABLED
1857#ifdef HW_AEC_LOOPBACK
1858 if (in->hw_echo_reference) {
1859 struct pcm_device *temp_device = NULL;
1860 struct pcm_device *ref_device = NULL;
1861 struct listnode *node = NULL;
1862 struct echo_reference_buffer b;
1863 size_t size_hw_ref_bytes;
1864 size_t size_hw_ref_frames;
1865 int read_status = 0;
1866
1867 ref_device = node_to_item(list_tail(&in->pcm_dev_list),
1868 struct pcm_device, stream_list_node);
1869 list_for_each(node, &in->pcm_dev_list) {
1870 temp_device = node_to_item(node, struct pcm_device, stream_list_node);
1871 if (temp_device->pcm_profile->id == 1) {
1872 ref_device = temp_device;
1873 break;
1874 }
1875 }
1876 if (ref_device) {
1877 size_hw_ref_bytes = pcm_frames_to_bytes(ref_device->pcm, ref_device->pcm_profile->config.period_size);
1878 size_hw_ref_frames = ref_device->pcm_profile->config.period_size;
1879 if (in->hw_ref_buf_size < size_hw_ref_frames) {
1880 in->hw_ref_buf_size = size_hw_ref_frames;
1881 in->hw_ref_buf = (int16_t *) realloc(in->hw_ref_buf, size_hw_ref_bytes);
1882 ALOG_ASSERT((in->hw_ref_buf != NULL),
1883 "get_next_buffer() failed to reallocate hw_ref_buf");
1884 ALOGV("get_next_buffer(): hw_ref_buf %p extended to %zd bytes",
1885 in->hw_ref_buf, size_hw_ref_bytes);
1886 }
1887
1888 read_status = pcm_read(ref_device->pcm, (void*)in->hw_ref_buf, size_hw_ref_bytes);
1889 if (read_status != 0) {
1890 ALOGE("process_frames() pcm_read error for HW reference %d", read_status);
1891 b.raw = NULL;
1892 b.frame_count = 0;
1893 }
1894 else {
1895 get_capture_reference_delay(in, size_hw_ref_frames, &b);
1896 b.raw = (void *)in->hw_ref_buf;
1897 b.frame_count = size_hw_ref_frames;
1898 if (b.delay_ns != 0)
1899 b.delay_ns = -b.delay_ns; // as this is capture delay, it needs to be subtracted from the microphone delay
1900 in->echo_reference->write(in->echo_reference, &b);
1901 }
1902 }
1903 }
1904#endif // HW_AEC_LOOPBACK
1905#endif // PREPROCESSING_ENABLED
1906 }
1907
1908 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
1909 in->read_buf_frames : buffer->frame_count;
1910 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
1911 in->config.channels;
1912 return in->read_status;
1913}
1914
1915static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1916 struct resampler_buffer* buffer)
1917{
1918 struct stream_in *in;
1919
1920 if (buffer_provider == NULL || buffer == NULL)
1921 return;
1922
1923 in = (struct stream_in *)((char *)buffer_provider -
1924 offsetof(struct stream_in, buf_provider));
1925
1926 in->read_buf_frames -= buffer->frame_count;
1927}
1928
1929/* read_frames() reads frames from kernel driver, down samples to capture rate
1930 * if necessary and output the number of frames requested to the buffer specified */
1931static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
1932{
1933 ssize_t frames_wr = 0;
1934
1935 struct pcm_device *pcm_device;
1936
1937 if (list_empty(&in->pcm_dev_list)) {
1938 ALOGE("%s: pcm device list empty", __func__);
1939 return -EINVAL;
1940 }
1941
1942 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1943 struct pcm_device, stream_list_node);
1944
1945 while (frames_wr < frames) {
1946 size_t frames_rd = frames - frames_wr;
1947 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
1948 __func__,frames_rd,frames_wr,in->config.channels);
1949 if (in->resampler != NULL) {
1950 in->resampler->resample_from_provider(in->resampler,
1951 (int16_t *)((char *)buffer +
1952 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
1953 &frames_rd);
1954 } else {
1955 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01001956 .raw = NULL,
1957 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001958 };
1959 get_next_buffer(&in->buf_provider, &buf);
1960 if (buf.raw != NULL) {
1961 memcpy((char *)buffer +
1962 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
1963 buf.raw,
1964 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
1965 frames_rd = buf.frame_count;
1966 }
1967 release_buffer(&in->buf_provider, &buf);
1968 }
1969 /* in->read_status is updated by getNextBuffer() also called by
1970 * in->resampler->resample_from_provider() */
1971 if (in->read_status != 0)
1972 return in->read_status;
1973
1974 frames_wr += frames_rd;
1975 }
1976 return frames_wr;
1977}
1978
1979static int in_release_pcm_devices(struct stream_in *in)
1980{
1981 struct pcm_device *pcm_device;
1982 struct listnode *node;
1983 struct listnode *next;
1984
1985 list_for_each_safe(node, next, &in->pcm_dev_list) {
1986 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
1987 list_remove(node);
1988 free(pcm_device);
1989 }
1990
1991 return 0;
1992}
1993
1994static int stop_input_stream(struct stream_in *in)
1995{
1996 struct audio_usecase *uc_info;
1997 struct audio_device *adev = in->dev;
1998
1999 adev->active_input = NULL;
2000 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2001 in->usecase, use_case_table[in->usecase]);
2002 uc_info = get_usecase_from_id(adev, in->usecase);
2003 if (uc_info == NULL) {
2004 ALOGE("%s: Could not find the usecase (%d) in the list",
2005 __func__, in->usecase);
2006 return -EINVAL;
2007 }
2008
2009 /* Disable the tx device */
2010 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2011
2012 list_remove(&uc_info->adev_list_node);
2013 free(uc_info);
2014
2015 if (list_empty(&in->pcm_dev_list)) {
2016 ALOGE("%s: pcm device list empty", __func__);
2017 return -EINVAL;
2018 }
2019
2020 in_release_pcm_devices(in);
2021 list_init(&in->pcm_dev_list);
2022
2023#ifdef HW_AEC_LOOPBACK
2024 if (in->hw_echo_reference)
2025 {
2026 in->hw_echo_reference = false;
2027 }
2028#endif
2029
2030 ALOGV("%s: exit", __func__);
2031 return 0;
2032}
2033
2034static int start_input_stream(struct stream_in *in)
2035{
2036 /* Enable output device and stream routing controls */
2037 int ret = 0;
2038 bool recreate_resampler = false;
2039 struct audio_usecase *uc_info;
2040 struct audio_device *adev = in->dev;
2041 struct pcm_device_profile *pcm_profile;
2042 struct pcm_device *pcm_device;
2043
2044 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2045 adev->active_input = in;
2046 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2047 if (pcm_profile == NULL) {
2048 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2049 __func__, in->usecase);
2050 ret = -EINVAL;
2051 goto error_config;
2052 }
2053
2054 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002055 if (uc_info == NULL) {
2056 ret = -ENOMEM;
2057 goto error_config;
2058 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002059 uc_info->id = in->usecase;
2060 uc_info->type = PCM_CAPTURE;
2061 uc_info->stream = (struct audio_stream *)in;
2062 uc_info->devices = in->devices;
2063 uc_info->in_snd_device = SND_DEVICE_NONE;
2064 uc_info->out_snd_device = SND_DEVICE_NONE;
2065
2066 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002067 if (pcm_device == NULL) {
2068 free(uc_info);
2069 ret = -ENOMEM;
2070 goto error_config;
2071 }
2072
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002073 pcm_device->pcm_profile = pcm_profile;
2074 list_init(&in->pcm_dev_list);
2075 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2076
2077 list_init(&uc_info->mixer_list);
2078 list_add_tail(&uc_info->mixer_list,
2079 &adev_get_mixer_for_card(adev,
2080 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2081
2082 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2083
2084 select_devices(adev, in->usecase);
2085
2086 /* Config should be updated as profile can be changed between different calls
2087 * to this function:
2088 * - Trigger resampler creation
2089 * - Config needs to be updated */
2090 if (in->config.rate != pcm_profile->config.rate) {
2091 recreate_resampler = true;
2092 }
2093 in->config = pcm_profile->config;
2094
2095#ifdef PREPROCESSING_ENABLED
2096 if (in->aux_channels_changed) {
2097 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2098 recreate_resampler = true;
2099 }
2100#endif
2101
2102 if (in->requested_rate != in->config.rate) {
2103 recreate_resampler = true;
2104 }
2105
2106 if (recreate_resampler) {
2107 if (in->resampler) {
2108 release_resampler(in->resampler);
2109 in->resampler = NULL;
2110 }
2111 in->buf_provider.get_next_buffer = get_next_buffer;
2112 in->buf_provider.release_buffer = release_buffer;
2113 ret = create_resampler(in->config.rate,
2114 in->requested_rate,
2115 in->config.channels,
2116 RESAMPLER_QUALITY_DEFAULT,
2117 &in->buf_provider,
2118 &in->resampler);
2119 }
2120
2121#ifdef PREPROCESSING_ENABLED
2122 if (in->enable_aec && in->echo_reference == NULL) {
2123 in->echo_reference = get_echo_reference(adev,
2124 AUDIO_FORMAT_PCM_16_BIT,
2125 audio_channel_count_from_in_mask(in->main_channels),
2126 in->requested_rate
2127 );
2128 }
2129
2130#ifdef HW_AEC_LOOPBACK
2131 if (in->enable_aec) {
2132 ret = get_hw_echo_reference(in);
2133 if (ret!=0)
2134 goto error_open;
2135
2136 /* force ref buffer reallocation */
2137 in->hw_ref_buf_size = 0;
2138 }
2139#endif
2140#endif
2141
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002142 if (in->dev->voice.in_call) {
2143 ALOGV("%s: in_call, not handling PCMs", __func__);
2144 goto skip_pcm_handling;
2145 }
2146
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002147 /* Open the PCM device.
2148 * The HW is limited to support only the default pcm_profile settings.
2149 * As such a change in aux_channels will not have an effect.
2150 */
2151 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2152 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2153 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2154 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2155
2156 if (pcm_profile->type == PCM_HOTWORD_STREAMING) {
2157 if (!adev->sound_trigger_open_for_streaming) {
2158 ALOGE("%s: No handle to sound trigger HAL", __func__);
2159 ret = -EIO;
2160 goto error_open;
2161 }
2162 pcm_device->pcm = NULL;
2163 pcm_device->sound_trigger_handle = adev->sound_trigger_open_for_streaming();
2164 if (pcm_device->sound_trigger_handle <= 0) {
2165 ALOGE("%s: Failed to open DSP for streaming", __func__);
2166 ret = -EIO;
2167 goto error_open;
2168 }
2169 ALOGV("Opened DSP successfully");
2170 } else {
2171 pcm_device->sound_trigger_handle = 0;
2172 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2173 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2174
2175 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2176 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2177 pcm_close(pcm_device->pcm);
2178 pcm_device->pcm = NULL;
2179 ret = -EIO;
2180 goto error_open;
2181 }
2182 }
2183
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002184skip_pcm_handling:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002185 /* force read and proc buffer reallocation in case of frame size or
2186 * channel count change */
2187 in->proc_buf_frames = 0;
2188 in->proc_buf_size = 0;
2189 in->read_buf_size = 0;
2190 in->read_buf_frames = 0;
2191
2192 /* if no supported sample rate is available, use the resampler */
2193 if (in->resampler) {
2194 in->resampler->reset(in->resampler);
2195 }
2196
2197 ALOGV("%s: exit", __func__);
2198 return ret;
2199
2200error_open:
2201 if (in->resampler) {
2202 release_resampler(in->resampler);
2203 in->resampler = NULL;
2204 }
2205 stop_input_stream(in);
2206
2207error_config:
2208 ALOGV("%s: exit: status(%d)", __func__, ret);
2209 adev->active_input = NULL;
2210 return ret;
2211}
2212
2213void lock_input_stream(struct stream_in *in)
2214{
2215 pthread_mutex_lock(&in->pre_lock);
2216 pthread_mutex_lock(&in->lock);
2217 pthread_mutex_unlock(&in->pre_lock);
2218}
2219
2220void lock_output_stream(struct stream_out *out)
2221{
2222 pthread_mutex_lock(&out->pre_lock);
2223 pthread_mutex_lock(&out->lock);
2224 pthread_mutex_unlock(&out->pre_lock);
2225}
2226
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002227static int uc_release_pcm_devices(struct audio_usecase *usecase)
2228{
2229 struct stream_out *out = (struct stream_out *)usecase->stream;
2230 struct pcm_device *pcm_device;
2231 struct listnode *node;
2232 struct listnode *next;
2233
2234 list_for_each_safe(node, next, &out->pcm_dev_list) {
2235 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2236 list_remove(node);
2237 free(pcm_device);
2238 }
2239 list_init(&usecase->mixer_list);
2240
2241 return 0;
2242}
2243
2244static int uc_select_pcm_devices(struct audio_usecase *usecase)
2245
2246{
2247 struct stream_out *out = (struct stream_out *)usecase->stream;
2248 struct pcm_device *pcm_device;
2249 struct pcm_device_profile *pcm_profile;
2250 struct mixer_card *mixer_card;
2251 audio_devices_t devices = usecase->devices;
2252
2253 list_init(&usecase->mixer_list);
2254 list_init(&out->pcm_dev_list);
2255
2256 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2257 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002258 if (pcm_device == NULL) {
2259 return -ENOMEM;
2260 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002261 pcm_device->pcm_profile = pcm_profile;
2262 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2263 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2264 if (mixer_card == NULL) {
2265 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2266 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2267 }
2268 devices &= ~pcm_profile->devices;
2269 }
2270
2271 return 0;
2272}
2273
2274static int out_close_pcm_devices(struct stream_out *out)
2275{
2276 struct pcm_device *pcm_device;
2277 struct listnode *node;
2278 struct audio_device *adev = out->dev;
2279
2280 list_for_each(node, &out->pcm_dev_list) {
2281 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2282 if (pcm_device->sound_trigger_handle > 0) {
2283 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
2284 pcm_device->sound_trigger_handle = 0;
2285 }
2286 if (pcm_device->pcm) {
2287 pcm_close(pcm_device->pcm);
2288 pcm_device->pcm = NULL;
2289 }
2290 if (pcm_device->resampler) {
2291 release_resampler(pcm_device->resampler);
2292 pcm_device->resampler = NULL;
2293 }
2294 if (pcm_device->res_buffer) {
2295 free(pcm_device->res_buffer);
2296 pcm_device->res_buffer = NULL;
2297 }
2298 }
2299
2300 return 0;
2301}
2302
2303static int out_open_pcm_devices(struct stream_out *out)
2304{
2305 struct pcm_device *pcm_device;
2306 struct listnode *node;
2307 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002308 int pcm_device_card;
2309 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002310
2311 list_for_each(node, &out->pcm_dev_list) {
2312 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002313 pcm_device_card = pcm_device->pcm_profile->card;
2314 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002315
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002316 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2317 pcm_device_id = pcm_device_deep_buffer.id;
2318
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002319 if (out->dev->voice.in_call) {
2320 ALOGV("%s: in_call, not opening PCMs", __func__);
2321 return ret;
2322 }
2323
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002324 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2325 __func__, pcm_device_card, pcm_device_id);
2326
2327 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002328 PCM_OUT | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2329
2330 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2331 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2332 pcm_device->pcm = NULL;
2333 ret = -EIO;
2334 goto error_open;
2335 }
2336 /*
2337 * If the stream rate differs from the PCM rate, we need to
2338 * create a resampler.
2339 */
2340 if (out->sample_rate != pcm_device->pcm_profile->config.rate) {
2341 ALOGV("%s: create_resampler(), pcm_device_card(%d), pcm_device_id(%d), \
2342 out_rate(%d), device_rate(%d)",__func__,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002343 pcm_device_card, pcm_device_id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002344 out->sample_rate, pcm_device->pcm_profile->config.rate);
2345 ret = create_resampler(out->sample_rate,
2346 pcm_device->pcm_profile->config.rate,
2347 audio_channel_count_from_out_mask(out->channel_mask),
2348 RESAMPLER_QUALITY_DEFAULT,
2349 NULL,
2350 &pcm_device->resampler);
2351 pcm_device->res_byte_count = 0;
2352 pcm_device->res_buffer = NULL;
2353 }
2354 }
2355 return ret;
2356
2357error_open:
2358 out_close_pcm_devices(out);
2359 return ret;
2360}
2361
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002362int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002363{
2364 struct audio_device *adev = out->dev;
2365 struct audio_usecase *uc_info;
2366
2367 uc_info = get_usecase_from_id(adev, out->usecase);
2368 if (uc_info == NULL) {
2369 ALOGE("%s: Could not find the usecase (%d) in the list",
2370 __func__, out->usecase);
2371 return -EINVAL;
2372 }
2373 disable_snd_device(adev, uc_info, uc_info->out_snd_device, true);
2374 uc_release_pcm_devices(uc_info);
2375 list_remove(&uc_info->adev_list_node);
2376 free(uc_info);
2377
2378 return 0;
2379}
2380
Andreas Schneider56204f62017-01-31 08:17:32 +01002381int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002382{
2383 struct audio_device *adev = out->dev;
2384 struct audio_usecase *uc_info;
2385
2386 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002387 if (uc_info == NULL) {
2388 return -ENOMEM;
2389 }
2390
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002391 uc_info->id = out->usecase;
2392 uc_info->type = PCM_PLAYBACK;
2393 uc_info->stream = (struct audio_stream *)out;
2394 uc_info->devices = out->devices;
2395 uc_info->in_snd_device = SND_DEVICE_NONE;
2396 uc_info->out_snd_device = SND_DEVICE_NONE;
2397 uc_select_pcm_devices(uc_info);
2398
2399 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2400 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002401
2402 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002403}
2404
2405static int stop_output_stream(struct stream_out *out)
2406{
2407 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002408 bool do_disable = true;
2409
2410 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2411 out->usecase, use_case_table[out->usecase]);
2412
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002413 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002414
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002415 if (do_disable)
2416 ret = disable_output_path_l(out);
2417
2418 ALOGV("%s: exit: status(%d)", __func__, ret);
2419 return ret;
2420}
2421
2422static int start_output_stream(struct stream_out *out)
2423{
2424 int ret = 0;
2425 struct audio_device *adev = out->dev;
2426
2427 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2428 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2429
Andreas Schneider56204f62017-01-31 08:17:32 +01002430 ret = enable_output_path_l(out);
2431 if (ret != 0) {
2432 goto error_config;
2433 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002434
2435 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2436 out->compr = NULL;
2437 ret = out_open_pcm_devices(out);
2438 if (ret != 0)
2439 goto error_open;
2440#ifdef PREPROCESSING_ENABLED
2441 out->echo_reference = NULL;
2442 out->echo_reference_generation = adev->echo_reference_generation;
2443 if (adev->echo_reference != NULL)
2444 out->echo_reference = adev->echo_reference;
2445#endif
2446 } else {
2447 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2448 COMPRESS_IN, &out->compr_config);
2449 if (out->compr && !is_compress_ready(out->compr)) {
2450 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2451 compress_close(out->compr);
2452 out->compr = NULL;
2453 ret = -EIO;
2454 goto error_open;
2455 }
2456 if (out->offload_callback)
2457 compress_nonblock(out->compr, out->non_blocking);
2458
2459 if (adev->offload_fx_start_output != NULL)
2460 adev->offload_fx_start_output(out->handle);
2461 }
2462 ALOGV("%s: exit", __func__);
2463 return 0;
2464error_open:
2465 stop_output_stream(out);
2466error_config:
2467 return ret;
2468}
2469
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002470int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002471{
2472 struct audio_usecase *uc_info;
2473
2474 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002475 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002476
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002477 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002478
2479 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2480 if (uc_info == NULL) {
2481 ALOGE("%s: Could not find the usecase (%d) in the list",
2482 __func__, USECASE_VOICE_CALL);
2483 return -EINVAL;
2484 }
2485
2486 disable_snd_device(adev, uc_info, uc_info->out_snd_device, false);
2487 disable_snd_device(adev, uc_info, uc_info->in_snd_device, true);
2488
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002489 list_remove(&uc_info->adev_list_node);
2490 free(uc_info);
2491
2492 ALOGV("%s: exit", __func__);
2493 return 0;
2494}
2495
2496/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002497int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002498{
2499 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002500 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002501
2502 ALOGV("%s: enter", __func__);
2503
2504 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002505 if (uc_info == NULL) {
2506 ret = -ENOMEM;
2507 goto exit;
2508 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002509 /*
2510 * We set this early so that functions called after this is being set
2511 * can use it. It is e.g. needed in select_devices() to inform the RILD
2512 * which output device we use.
2513 */
2514 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002515
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002516 uc_info->id = USECASE_VOICE_CALL;
2517 uc_info->type = VOICE_CALL;
2518 uc_info->stream = (struct audio_stream *)adev->primary_output;
2519 uc_info->devices = adev->primary_output->devices;
2520 uc_info->in_snd_device = SND_DEVICE_NONE;
2521 uc_info->out_snd_device = SND_DEVICE_NONE;
2522
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002523 list_init(&uc_info->mixer_list);
2524 list_add_tail(&uc_info->mixer_list,
2525 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002526
2527 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2528
2529 select_devices(adev, USECASE_VOICE_CALL);
2530
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002531 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002532
2533 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002534 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002535
Andreas Schneider56204f62017-01-31 08:17:32 +01002536exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002537 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002538 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002539}
2540
2541static int check_input_parameters(uint32_t sample_rate,
2542 audio_format_t format,
2543 int channel_count)
2544{
2545 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2546
2547 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2548
2549 switch (sample_rate) {
2550 case 8000:
2551 case 11025:
2552 case 12000:
2553 case 16000:
2554 case 22050:
2555 case 24000:
2556 case 32000:
2557 case 44100:
2558 case 48000:
2559 break;
2560 default:
2561 return -EINVAL;
2562 }
2563
2564 return 0;
2565}
2566
2567static size_t get_input_buffer_size(uint32_t sample_rate,
2568 audio_format_t format,
2569 int channel_count,
2570 usecase_type_t usecase_type,
2571 audio_devices_t devices)
2572{
2573 size_t size = 0;
2574 struct pcm_device_profile *pcm_profile;
2575
2576 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2577 return 0;
2578
2579 pcm_profile = get_pcm_device(usecase_type, devices);
2580 if (pcm_profile == NULL)
2581 return 0;
2582
2583 /*
2584 * take resampling into account and return the closest majoring
2585 * multiple of 16 frames, as audioflinger expects audio buffers to
2586 * be a multiple of 16 frames
2587 */
2588 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2589 size = ((size + 15) / 16) * 16;
2590
2591 return (size * channel_count * audio_bytes_per_sample(format));
2592
2593}
2594
2595static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2596{
2597 struct stream_out *out = (struct stream_out *)stream;
2598
2599 return out->sample_rate;
2600}
2601
2602static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2603{
2604 (void)stream;
2605 (void)rate;
2606 return -ENOSYS;
2607}
2608
2609static size_t out_get_buffer_size(const struct audio_stream *stream)
2610{
2611 struct stream_out *out = (struct stream_out *)stream;
2612
2613 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2614 return out->compr_config.fragment_size;
2615 }
2616
2617 return out->config.period_size *
2618 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2619}
2620
2621static uint32_t out_get_channels(const struct audio_stream *stream)
2622{
2623 struct stream_out *out = (struct stream_out *)stream;
2624
2625 return out->channel_mask;
2626}
2627
2628static audio_format_t out_get_format(const struct audio_stream *stream)
2629{
2630 struct stream_out *out = (struct stream_out *)stream;
2631
2632 return out->format;
2633}
2634
2635static int out_set_format(struct audio_stream *stream, audio_format_t format)
2636{
2637 (void)stream;
2638 (void)format;
2639 return -ENOSYS;
2640}
2641
2642static int do_out_standby_l(struct stream_out *out)
2643{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002644 int status = 0;
2645
2646 out->standby = true;
2647 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2648 out_close_pcm_devices(out);
2649#ifdef PREPROCESSING_ENABLED
2650 /* stop writing to echo reference */
2651 if (out->echo_reference != NULL) {
2652 out->echo_reference->write(out->echo_reference, NULL);
2653 if (out->echo_reference_generation != adev->echo_reference_generation) {
2654 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2655 release_echo_reference(out->echo_reference);
2656 out->echo_reference_generation = adev->echo_reference_generation;
2657 }
2658 out->echo_reference = NULL;
2659 }
2660#endif
2661 } else {
2662 stop_compressed_output_l(out);
2663 out->gapless_mdata.encoder_delay = 0;
2664 out->gapless_mdata.encoder_padding = 0;
2665 if (out->compr != NULL) {
2666 compress_close(out->compr);
2667 out->compr = NULL;
2668 }
2669 }
2670 status = stop_output_stream(out);
2671
2672 return status;
2673}
2674
2675static int out_standby(struct audio_stream *stream)
2676{
2677 struct stream_out *out = (struct stream_out *)stream;
2678 struct audio_device *adev = out->dev;
2679
2680 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2681 out->usecase, use_case_table[out->usecase]);
2682 lock_output_stream(out);
2683 if (!out->standby) {
2684 pthread_mutex_lock(&adev->lock);
2685 do_out_standby_l(out);
2686 pthread_mutex_unlock(&adev->lock);
2687 }
2688 pthread_mutex_unlock(&out->lock);
2689 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002690
2691 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2692
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002693 return 0;
2694}
2695
2696static int out_dump(const struct audio_stream *stream, int fd)
2697{
2698 (void)stream;
2699 (void)fd;
2700
2701 return 0;
2702}
2703
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002704static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2705{
2706 struct stream_out *out = (struct stream_out *)stream;
2707 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002708 struct listnode *node;
2709 struct str_parms *parms;
2710 char value[32];
2711 int ret, val = 0;
2712 struct audio_usecase *uc_info;
2713 bool do_standby = false;
2714 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002715#ifdef PREPROCESSING_ENABLED
2716 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2717#endif
2718
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002719 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%#x) "
2720 "adev->mode(%#x)",
2721 __func__, out->usecase, use_case_table[out->usecase], kvpairs,
2722 out->devices, adev->mode);
2723
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002724 parms = str_parms_create_str(kvpairs);
2725 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2726 if (ret >= 0) {
2727 val = atoi(value);
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002728
2729 ALOGV("%s: routing: usecase(%d: %s) devices=(%#x) adev->mode(%#x)",
2730 __func__, out->usecase, use_case_table[out->usecase], val,
2731 adev->mode);
2732
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002733 pthread_mutex_lock(&adev->lock_inputs);
2734 lock_output_stream(out);
2735 pthread_mutex_lock(&adev->lock);
2736#ifdef PREPROCESSING_ENABLED
2737 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2738 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2739 /* reset active input:
2740 * - to attach the echo reference
2741 * - because a change in output device may change mic settings */
2742 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2743 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2744 in = adev->active_input;
2745 }
2746 }
2747#endif
2748 if (val != 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002749 bool bt_sco_active = false;
2750
2751 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
2752 bt_sco_active = true;
2753 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002754 out->devices = val;
2755
2756 if (!out->standby) {
2757 uc_info = get_usecase_from_id(adev, out->usecase);
2758 if (uc_info == NULL) {
2759 ALOGE("%s: Could not find the usecase (%d) in the list",
2760 __func__, out->usecase);
2761 } else {
2762 list_for_each(node, &out->pcm_dev_list) {
2763 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2764 if ((pcm_device->pcm_profile->devices & val) == 0)
2765 do_standby = true;
2766 val &= ~pcm_device->pcm_profile->devices;
2767 }
2768 if (val != 0)
2769 do_standby = true;
2770 }
2771 if (do_standby)
2772 do_out_standby_l(out);
2773 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002774 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2775 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002776 select_devices(adev, out->usecase);
2777 }
2778 }
2779
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002780 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002781 (out == adev->primary_output)) {
2782 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002783 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2784 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002785 (out == adev->primary_output)) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01002786 /* Turn on bluetooth if needed */
2787 if ((out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !bt_sco_active) {
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002788 select_devices(adev, USECASE_VOICE_CALL);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002789 start_voice_session_bt_sco(adev->voice.session);
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002790 } else {
2791 /*
2792 * When we select different devices we need to restart the
2793 * voice call. The modem closes the stream on its end and
2794 * we do not get any output.
2795 */
2796 stop_voice_call(adev);
2797 start_voice_call(adev);
Andreas Schneider05bc1882017-02-09 14:03:11 +01002798 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002799 }
2800 }
2801
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002802 if ((adev->mode == AUDIO_MODE_NORMAL) && adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002803 (out == adev->primary_output)) {
2804 stop_voice_call(adev);
2805 }
2806 pthread_mutex_unlock(&adev->lock);
2807 pthread_mutex_unlock(&out->lock);
2808#ifdef PREPROCESSING_ENABLED
2809 if (in) {
2810 /* The lock on adev->lock_inputs prevents input stream from being closed */
2811 lock_input_stream(in);
2812 pthread_mutex_lock(&adev->lock);
2813 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2814 do_in_standby_l(in);
2815 pthread_mutex_unlock(&adev->lock);
2816 pthread_mutex_unlock(&in->lock);
2817 }
2818#endif
2819 pthread_mutex_unlock(&adev->lock_inputs);
2820 }
2821
2822 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2823 parse_compress_metadata(out, parms);
2824 }
2825
2826 str_parms_destroy(parms);
2827
2828 if (ret > 0)
2829 ret = 0;
2830 ALOGV("%s: exit: code(%d)", __func__, ret);
2831 return ret;
2832}
2833
2834static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2835{
2836 struct stream_out *out = (struct stream_out *)stream;
2837 struct str_parms *query = str_parms_create_str(keys);
2838 char *str;
2839 char value[256];
2840 struct str_parms *reply = str_parms_create();
2841 size_t i, j;
2842 int ret;
2843 bool first = true;
2844 ALOGV("%s: enter: keys - %s", __func__, keys);
2845 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2846 if (ret >= 0) {
2847 value[0] = '\0';
2848 i = 0;
2849 while (out->supported_channel_masks[i] != 0) {
2850 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2851 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2852 if (!first) {
2853 strcat(value, "|");
2854 }
2855 strcat(value, out_channels_name_to_enum_table[j].name);
2856 first = false;
2857 break;
2858 }
2859 }
2860 i++;
2861 }
2862 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2863 str = str_parms_to_str(reply);
2864 } else {
2865 str = strdup(keys);
2866 }
2867 str_parms_destroy(query);
2868 str_parms_destroy(reply);
2869 ALOGV("%s: exit: returns - %s", __func__, str);
2870 return str;
2871}
2872
2873static uint32_t out_get_latency(const struct audio_stream_out *stream)
2874{
2875 struct stream_out *out = (struct stream_out *)stream;
2876
2877 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2878 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2879
2880 return (out->config.period_count * out->config.period_size * 1000) /
2881 (out->config.rate);
2882}
2883
2884static int out_set_volume(struct audio_stream_out *stream, float left,
2885 float right)
2886{
2887 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002888
2889 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2890 /* only take left channel into account: the API is for stereo anyway */
2891 out->muted = (left == 0.0f);
2892 return 0;
2893 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002894 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002895 }
2896
2897 return -ENOSYS;
2898}
2899
Andreas Schneider3b643832017-01-31 11:48:22 +01002900#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002901static int fast_set_affinity(pid_t tid) {
2902 cpu_set_t cpu_set;
2903 int cpu_num;
2904 const char *irq_procfs = "/proc/asound/irq_affinity";
2905 FILE *fp;
2906
2907 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2908 ALOGW("Procfs node %s not found", irq_procfs);
2909 return -1;
2910 }
2911
2912 if (fscanf(fp, "%d", &cpu_num) != 1) {
2913 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2914 fclose(fp);
2915 return -1;
2916 }
2917 fclose(fp);
2918
2919 CPU_ZERO(&cpu_set);
2920 CPU_SET(cpu_num, &cpu_set);
2921 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2922}
Andreas Schneider3b643832017-01-31 11:48:22 +01002923#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002924
2925static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2926 size_t bytes)
2927{
2928 struct stream_out *out = (struct stream_out *)stream;
2929 struct audio_device *adev = out->dev;
2930 ssize_t ret = 0;
2931 struct pcm_device *pcm_device;
2932 struct listnode *node;
2933 size_t frame_size = audio_stream_out_frame_size(stream);
2934 size_t frames_wr = 0, frames_rq = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002935#ifdef PREPROCESSING_ENABLED
2936 size_t in_frames = bytes / frame_size;
2937 size_t out_frames = in_frames;
2938 struct stream_in *in = NULL;
2939#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002940
2941 lock_output_stream(out);
2942
Andreas Schneider3b643832017-01-31 11:48:22 +01002943#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002944 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002945 pid_t tid = gettid();
2946 int err;
2947
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002948 err = fast_set_affinity(tid);
2949 if (err < 0) {
2950 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2951 }
2952 out->is_fastmixer_affinity_set = true;
2953 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002954#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002955
2956 if (out->standby) {
2957#ifdef PREPROCESSING_ENABLED
2958 pthread_mutex_unlock(&out->lock);
2959 /* Prevent input stream from being closed */
2960 pthread_mutex_lock(&adev->lock_inputs);
2961 lock_output_stream(out);
2962 if (!out->standby) {
2963 pthread_mutex_unlock(&adev->lock_inputs);
2964 goto false_alarm;
2965 }
2966#endif
2967 pthread_mutex_lock(&adev->lock);
2968 ret = start_output_stream(out);
2969 /* ToDo: If use case is compress offload should return 0 */
2970 if (ret != 0) {
2971 pthread_mutex_unlock(&adev->lock);
2972#ifdef PREPROCESSING_ENABLED
2973 pthread_mutex_unlock(&adev->lock_inputs);
2974#endif
2975 goto exit;
2976 }
2977 out->standby = false;
2978
2979#ifdef PREPROCESSING_ENABLED
2980 /* A change in output device may change the microphone selection */
2981 if (adev->active_input &&
2982 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2983 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2984 in = adev->active_input;
2985 ALOGV("%s: enter:) force_input_standby true", __func__);
2986 }
2987#endif
2988 pthread_mutex_unlock(&adev->lock);
2989#ifdef PREPROCESSING_ENABLED
2990 if (!in) {
2991 /* Leave mutex locked iff in != NULL */
2992 pthread_mutex_unlock(&adev->lock_inputs);
2993 }
2994#endif
2995 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002996#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002997false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002998#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002999
3000 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003001 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003002 return ret;
3003 } else {
3004#ifdef PREPROCESSING_ENABLED
3005 if (android_atomic_acquire_load(&adev->echo_reference_generation)
3006 != out->echo_reference_generation) {
3007 pthread_mutex_lock(&adev->lock);
3008 if (out->echo_reference != NULL) {
3009 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
3010 release_echo_reference(out->echo_reference);
3011 }
3012 // note that adev->echo_reference_generation here can be different from the one
3013 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
3014 // with what has been set by get_echo_reference() or put_echo_reference()
3015 out->echo_reference_generation = adev->echo_reference_generation;
3016 out->echo_reference = adev->echo_reference;
3017 ALOGV("%s: update echo reference generation %d", __func__,
3018 out->echo_reference_generation);
3019 pthread_mutex_unlock(&adev->lock);
3020 }
3021#endif
3022
3023 if (out->muted)
3024 memset((void *)buffer, 0, bytes);
3025 list_for_each(node, &out->pcm_dev_list) {
3026 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3027 if (pcm_device->resampler) {
3028 if (bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size
3029 > pcm_device->res_byte_count) {
3030 pcm_device->res_byte_count =
3031 bytes * pcm_device->pcm_profile->config.rate / out->sample_rate + frame_size;
3032 pcm_device->res_buffer =
3033 realloc(pcm_device->res_buffer, pcm_device->res_byte_count);
3034 ALOGV("%s: resampler res_byte_count = %zu", __func__,
3035 pcm_device->res_byte_count);
3036 }
3037 frames_rq = bytes / frame_size;
3038 frames_wr = pcm_device->res_byte_count / frame_size;
3039 ALOGVV("%s: resampler request frames = %d frame_size = %d",
3040 __func__, frames_rq, frame_size);
3041 pcm_device->resampler->resample_from_input(pcm_device->resampler,
3042 (int16_t *)buffer, &frames_rq, (int16_t *)pcm_device->res_buffer, &frames_wr);
3043 ALOGVV("%s: resampler output frames_= %d", __func__, frames_wr);
3044 }
3045 if (pcm_device->pcm) {
3046#ifdef PREPROCESSING_ENABLED
3047 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
3048 struct echo_reference_buffer b;
3049 b.raw = (void *)buffer;
3050 b.frame_count = in_frames;
3051
3052 get_playback_delay(out, out_frames, &b);
3053 out->echo_reference->write(out->echo_reference, &b);
3054 }
3055#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003056 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
3057 if (pcm_device->resampler && pcm_device->res_buffer)
3058 pcm_device->status =
3059 pcm_write(pcm_device->pcm, (void *)pcm_device->res_buffer,
3060 frames_wr * frame_size);
3061 else
3062 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
3063 if (pcm_device->status != 0)
3064 ret = pcm_device->status;
3065 }
3066 }
3067 if (ret == 0)
3068 out->written += bytes / (out->config.channels * sizeof(short));
3069 }
3070
3071exit:
3072 pthread_mutex_unlock(&out->lock);
3073
3074 if (ret != 0) {
3075 list_for_each(node, &out->pcm_dev_list) {
3076 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3077 if (pcm_device->pcm && pcm_device->status != 0)
3078 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
3079 }
3080 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003081 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3082 clock_gettime(CLOCK_MONOTONIC, &t);
3083 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3084 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
3085 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
3086 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
3087 if (sleep_time > 0) {
3088 usleep(sleep_time);
3089 } else {
3090 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
3091 sleep_time = 0;
3092 }
3093 out->last_write_time_us = now + sleep_time;
3094 // last_write_time_us is an approximation of when the (simulated) alsa
3095 // buffer is believed completely full. The usleep above waits for more space
3096 // in the buffer, but by the end of the sleep the buffer is considered
3097 // topped-off.
3098 //
3099 // On the subsequent out_write(), we measure the elapsed time spent in
3100 // the mixer. This is subtracted from the sleep estimate based on frames,
3101 // thereby accounting for drain in the alsa buffer during mixing.
3102 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003103 }
3104
3105#ifdef PREPROCESSING_ENABLED
3106 if (in) {
3107 /* The lock on adev->lock_inputs prevents input stream from being closed */
3108 lock_input_stream(in);
3109 pthread_mutex_lock(&adev->lock);
3110 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
3111 do_in_standby_l(in);
3112 pthread_mutex_unlock(&adev->lock);
3113 pthread_mutex_unlock(&in->lock);
3114 /* This mutex was left locked iff in != NULL */
3115 pthread_mutex_unlock(&adev->lock_inputs);
3116 }
3117#endif
3118
3119 return bytes;
3120}
3121
3122static int out_get_render_position(const struct audio_stream_out *stream,
3123 uint32_t *dsp_frames)
3124{
3125 struct stream_out *out = (struct stream_out *)stream;
3126 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003127 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3128 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003129 } else
3130 return -EINVAL;
3131}
3132
3133static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3134{
3135 (void)stream;
3136 (void)effect;
3137 return 0;
3138}
3139
3140static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3141{
3142 (void)stream;
3143 (void)effect;
3144 return 0;
3145}
3146
3147static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3148 int64_t *timestamp)
3149{
3150 (void)stream;
3151 (void)timestamp;
3152 return -EINVAL;
3153}
3154
3155static int out_get_presentation_position(const struct audio_stream_out *stream,
3156 uint64_t *frames, struct timespec *timestamp)
3157{
3158 struct stream_out *out = (struct stream_out *)stream;
3159 int ret = -1;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003160
3161 lock_output_stream(out);
3162
3163 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003164 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003165 } else {
Andreas Schneider97fa7f12017-02-11 14:21:56 +01003166 if (out->dev->voice.in_call) {
3167 ALOGVV("%s: in_call, do not handle PCMs", __func__);
3168 ret = 0;
3169 goto done;
3170 }
3171
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003172 /* FIXME: which device to read from? */
3173 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003174 struct pcm_device *pcm_device;
3175 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003176 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003177
Andreas Schneiderd6359182017-02-08 16:58:22 +01003178 list_for_each(node, &out->pcm_dev_list) {
3179 pcm_device = node_to_item(node,
3180 struct pcm_device,
3181 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003182
Andreas Schneiderd6359182017-02-08 16:58:22 +01003183 if (pcm_device->pcm != NULL) {
3184 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3185 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3186 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3187 /* This adjustment accounts for buffering after app processor.
3188 It is based on estimated DSP latency per use case, rather than exact. */
3189 signed_frames -=
3190 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3191
3192 /* It would be unusual for this value to be negative, but check just in case ... */
3193 if (signed_frames >= 0) {
3194 *frames = signed_frames;
3195 ret = 0;
3196 goto done;
3197 }
3198 ret = -1;
3199 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003200 }
3201 }
3202 }
3203 }
3204
Andreas Schneiderd6359182017-02-08 16:58:22 +01003205done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003206 pthread_mutex_unlock(&out->lock);
3207
3208 return ret;
3209}
3210
3211static int out_set_callback(struct audio_stream_out *stream,
3212 stream_callback_t callback, void *cookie)
3213{
3214 struct stream_out *out = (struct stream_out *)stream;
3215
3216 ALOGV("%s", __func__);
3217 lock_output_stream(out);
3218 out->offload_callback = callback;
3219 out->offload_cookie = cookie;
3220 pthread_mutex_unlock(&out->lock);
3221 return 0;
3222}
3223
3224static int out_pause(struct audio_stream_out* stream)
3225{
3226 struct stream_out *out = (struct stream_out *)stream;
3227 int status = -ENOSYS;
3228 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003229 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3230 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003231 return status;
3232}
3233
3234static int out_resume(struct audio_stream_out* stream)
3235{
3236 struct stream_out *out = (struct stream_out *)stream;
3237 int status = -ENOSYS;
3238 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003239 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3240 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003241 return status;
3242}
3243
3244static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3245{
3246 struct stream_out *out = (struct stream_out *)stream;
3247 int status = -ENOSYS;
3248 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003249 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3250 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003251 return status;
3252}
3253
3254static int out_flush(struct audio_stream_out* stream)
3255{
3256 struct stream_out *out = (struct stream_out *)stream;
3257 ALOGV("%s", __func__);
3258 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003259 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003260 }
3261 return -ENOSYS;
3262}
3263
3264/** audio_stream_in implementation **/
3265static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3266{
3267 struct stream_in *in = (struct stream_in *)stream;
3268
3269 return in->requested_rate;
3270}
3271
3272static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3273{
3274 (void)stream;
3275 (void)rate;
3276 return -ENOSYS;
3277}
3278
3279static uint32_t in_get_channels(const struct audio_stream *stream)
3280{
3281 struct stream_in *in = (struct stream_in *)stream;
3282
3283 return in->main_channels;
3284}
3285
3286static audio_format_t in_get_format(const struct audio_stream *stream)
3287{
3288 (void)stream;
3289 return AUDIO_FORMAT_PCM_16_BIT;
3290}
3291
3292static int in_set_format(struct audio_stream *stream, audio_format_t format)
3293{
3294 (void)stream;
3295 (void)format;
3296
3297 return -ENOSYS;
3298}
3299
3300static size_t in_get_buffer_size(const struct audio_stream *stream)
3301{
3302 struct stream_in *in = (struct stream_in *)stream;
3303
3304 return get_input_buffer_size(in->requested_rate,
3305 in_get_format(stream),
3306 audio_channel_count_from_in_mask(in->main_channels),
3307 in->usecase_type,
3308 in->devices);
3309}
3310
3311static int in_close_pcm_devices(struct stream_in *in)
3312{
3313 struct pcm_device *pcm_device;
3314 struct listnode *node;
3315 struct audio_device *adev = in->dev;
3316
3317 list_for_each(node, &in->pcm_dev_list) {
3318 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3319 if (pcm_device) {
3320 if (pcm_device->pcm)
3321 pcm_close(pcm_device->pcm);
3322 pcm_device->pcm = NULL;
3323 if (pcm_device->sound_trigger_handle > 0)
3324 adev->sound_trigger_close_for_streaming(pcm_device->sound_trigger_handle);
3325 pcm_device->sound_trigger_handle = 0;
3326 }
3327 }
3328 return 0;
3329}
3330
3331
3332/* must be called with stream and hw device mutex locked */
3333static int do_in_standby_l(struct stream_in *in)
3334{
3335 int status = 0;
3336
3337#ifdef PREPROCESSING_ENABLED
3338 struct audio_device *adev = in->dev;
3339#endif
3340 if (!in->standby) {
3341
3342 in_close_pcm_devices(in);
3343
3344#ifdef PREPROCESSING_ENABLED
3345 if (in->echo_reference != NULL) {
3346 /* stop reading from echo reference */
3347 in->echo_reference->read(in->echo_reference, NULL);
3348 put_echo_reference(adev, in->echo_reference);
3349 in->echo_reference = NULL;
3350 }
3351#ifdef HW_AEC_LOOPBACK
3352 if (in->hw_echo_reference)
3353 {
3354 if (in->hw_ref_buf) {
3355 free(in->hw_ref_buf);
3356 in->hw_ref_buf = NULL;
3357 }
3358 }
3359#endif // HW_AEC_LOOPBACK
3360#endif // PREPROCESSING_ENABLED
3361
3362 status = stop_input_stream(in);
3363
3364 if (in->read_buf) {
3365 free(in->read_buf);
3366 in->read_buf = NULL;
3367 }
3368
3369 in->standby = 1;
3370 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003371
3372 in->last_read_time_us = 0;
3373
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003374 return 0;
3375}
3376
3377// called with adev->lock_inputs locked
3378static int in_standby_l(struct stream_in *in)
3379{
3380 struct audio_device *adev = in->dev;
3381 int status = 0;
3382 lock_input_stream(in);
3383 if (!in->standby) {
3384 pthread_mutex_lock(&adev->lock);
3385 status = do_in_standby_l(in);
3386 pthread_mutex_unlock(&adev->lock);
3387 }
3388 pthread_mutex_unlock(&in->lock);
3389 return status;
3390}
3391
3392static int in_standby(struct audio_stream *stream)
3393{
3394 struct stream_in *in = (struct stream_in *)stream;
3395 struct audio_device *adev = in->dev;
3396 int status;
3397 ALOGV("%s: enter", __func__);
3398 pthread_mutex_lock(&adev->lock_inputs);
3399 status = in_standby_l(in);
3400 pthread_mutex_unlock(&adev->lock_inputs);
3401 ALOGV("%s: exit: status(%d)", __func__, status);
3402 return status;
3403}
3404
3405static int in_dump(const struct audio_stream *stream, int fd)
3406{
3407 (void)stream;
3408 (void)fd;
3409
3410 return 0;
3411}
3412
3413static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3414{
3415 struct stream_in *in = (struct stream_in *)stream;
3416 struct audio_device *adev = in->dev;
3417 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003418 char value[32];
3419 int ret, val = 0;
3420 struct audio_usecase *uc_info;
3421 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003422 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003423
3424 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3425 parms = str_parms_create_str(kvpairs);
3426
3427 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3428
3429 pthread_mutex_lock(&adev->lock_inputs);
3430 lock_input_stream(in);
3431 pthread_mutex_lock(&adev->lock);
3432 if (ret >= 0) {
3433 val = atoi(value);
3434 /* no audio source uses val == 0 */
3435 if (((int)in->source != val) && (val != 0)) {
3436 in->source = val;
3437 }
3438 }
3439
3440 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3441 if (ret >= 0) {
3442 val = atoi(value);
3443 if (((int)in->devices != val) && (val != 0)) {
3444 in->devices = val;
3445 /* If recording is in progress, change the tx device to new device */
3446 if (!in->standby) {
3447 uc_info = get_usecase_from_id(adev, in->usecase);
3448 if (uc_info == NULL) {
3449 ALOGE("%s: Could not find the usecase (%d) in the list",
3450 __func__, in->usecase);
3451 } else {
3452 if (list_empty(&in->pcm_dev_list))
3453 ALOGE("%s: pcm device list empty", __func__);
3454 else {
3455 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3456 struct pcm_device, stream_list_node);
3457 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3458 do_standby = true;
3459 }
3460 }
3461 }
3462 if (do_standby) {
3463 ret = do_in_standby_l(in);
3464 } else
3465 ret = select_devices(adev, in->usecase);
3466 }
3467 }
3468 }
3469 pthread_mutex_unlock(&adev->lock);
3470 pthread_mutex_unlock(&in->lock);
3471 pthread_mutex_unlock(&adev->lock_inputs);
3472 str_parms_destroy(parms);
3473
3474 if (ret > 0)
3475 ret = 0;
3476
3477 ALOGV("%s: exit: status(%d)", __func__, ret);
3478 return ret;
3479}
3480
3481static char* in_get_parameters(const struct audio_stream *stream,
3482 const char *keys)
3483{
3484 (void)stream;
3485 (void)keys;
3486
3487 return strdup("");
3488}
3489
3490static int in_set_gain(struct audio_stream_in *stream, float gain)
3491{
3492 (void)stream;
3493 (void)gain;
3494
3495 return 0;
3496}
3497
3498static ssize_t read_bytes_from_dsp(struct stream_in *in, void* buffer,
3499 size_t bytes)
3500{
3501 struct pcm_device *pcm_device;
3502 struct audio_device *adev = in->dev;
3503
3504 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3505 struct pcm_device, stream_list_node);
3506
3507 if (pcm_device->sound_trigger_handle > 0)
3508 return adev->sound_trigger_read_samples(pcm_device->sound_trigger_handle, buffer, bytes);
3509 else
3510 return 0;
3511}
3512
3513static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3514 size_t bytes)
3515{
3516 struct stream_in *in = (struct stream_in *)stream;
3517 struct audio_device *adev = in->dev;
3518 ssize_t frames = -1;
3519 int ret = -1;
3520 int read_and_process_successful = false;
3521
3522 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003523
3524 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3525 lock_input_stream(in);
3526
Andreas Schneider3b643832017-01-31 11:48:22 +01003527#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003528 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003529 pid_t tid = gettid();
3530 int err;
3531
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003532 err = fast_set_affinity(tid);
3533 if (err < 0) {
3534 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3535 }
3536 in->is_fastcapture_affinity_set = true;
3537 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003538#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003539
3540 if (in->standby) {
3541 pthread_mutex_unlock(&in->lock);
3542 pthread_mutex_lock(&adev->lock_inputs);
3543 lock_input_stream(in);
3544 if (!in->standby) {
3545 pthread_mutex_unlock(&adev->lock_inputs);
3546 goto false_alarm;
3547 }
3548 pthread_mutex_lock(&adev->lock);
3549 ret = start_input_stream(in);
3550 pthread_mutex_unlock(&adev->lock);
3551 pthread_mutex_unlock(&adev->lock_inputs);
3552 if (ret != 0) {
3553 goto exit;
3554 }
3555 in->standby = 0;
3556 }
3557false_alarm:
3558
3559 if (!list_empty(&in->pcm_dev_list)) {
3560 if (in->usecase == USECASE_AUDIO_CAPTURE_HOTWORD) {
3561 bytes = read_bytes_from_dsp(in, buffer, bytes);
3562 if (bytes > 0)
3563 read_and_process_successful = true;
3564 } else {
3565 /*
3566 * Read PCM and:
3567 * - resample if needed
3568 * - process if pre-processors are attached
3569 * - discard unwanted channels
3570 */
3571 frames = read_and_process_frames(in, buffer, frames_rq);
3572 if (frames >= 0)
3573 read_and_process_successful = true;
3574 }
3575 }
3576
3577 /*
3578 * Instead of writing zeroes here, we could trust the hardware
3579 * to always provide zeroes when muted.
3580 */
3581 if (read_and_process_successful == true && adev->mic_mute)
3582 memset(buffer, 0, bytes);
3583
3584exit:
3585 pthread_mutex_unlock(&in->lock);
3586
3587 if (read_and_process_successful == false) {
3588 in_standby(&in->stream.common);
3589 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003590 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3591 clock_gettime(CLOCK_MONOTONIC, &t);
3592 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3593
3594 // we do a full sleep when exiting standby.
3595 const bool standby = in->last_read_time_us == 0;
3596 const int64_t elapsed_time_since_last_read = standby ?
3597 0 : now - in->last_read_time_us;
3598 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3599 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3600 if (sleep_time > 0) {
3601 usleep(sleep_time);
3602 } else {
3603 sleep_time = 0;
3604 }
3605 in->last_read_time_us = now + sleep_time;
3606 // last_read_time_us is an approximation of when the (simulated) alsa
3607 // buffer is drained by the read, and is empty.
3608 //
3609 // On the subsequent in_read(), we measure the elapsed time spent in
3610 // the recording thread. This is subtracted from the sleep estimate based on frames,
3611 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003612 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003613 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003614
3615 if (bytes > 0) {
3616 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3617 }
3618
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003619 return bytes;
3620}
3621
3622static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3623{
3624 (void)stream;
3625
3626 return 0;
3627}
3628
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003629static int in_get_capture_position(const struct audio_stream_in *stream,
3630 int64_t *frames, int64_t *time)
3631{
3632 if (stream == NULL || frames == NULL || time == NULL) {
3633 return -EINVAL;
3634 }
3635
3636 struct stream_in *in = (struct stream_in *)stream;
3637 struct pcm_device *pcm_device;
3638 int ret = -ENOSYS;
3639
3640 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3641 struct pcm_device, stream_list_node);
3642
3643 pthread_mutex_lock(&in->lock);
3644 if (pcm_device->pcm) {
3645 struct timespec timestamp;
3646 unsigned int avail;
3647 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3648 *frames = in->frames_read + avail;
3649 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3650 ret = 0;
3651 }
3652 }
3653
3654 pthread_mutex_unlock(&in->lock);
3655 return ret;
3656}
3657
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003658static int add_remove_audio_effect(const struct audio_stream *stream,
3659 effect_handle_t effect,
3660 bool enable)
3661{
3662 struct stream_in *in = (struct stream_in *)stream;
3663 struct audio_device *adev = in->dev;
3664 int status = 0;
3665 effect_descriptor_t desc;
3666#ifdef PREPROCESSING_ENABLED
3667 int i;
3668#endif
3669 status = (*effect)->get_descriptor(effect, &desc);
3670 if (status != 0)
3671 return status;
3672
3673 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3674
3675 pthread_mutex_lock(&adev->lock_inputs);
3676 lock_input_stream(in);
3677 pthread_mutex_lock(&in->dev->lock);
3678#ifndef PREPROCESSING_ENABLED
3679 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3680 in->enable_aec != enable &&
3681 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3682 in->enable_aec = enable;
3683 if (!in->standby)
3684 select_devices(in->dev, in->usecase);
3685 }
3686#else
3687 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3688 status = -ENOSYS;
3689 goto exit;
3690 }
3691 if ( enable == true ) {
3692 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3693 /* add the supported channel of the effect in the channel_configs */
3694 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3695 in->num_preprocessors ++;
3696 /* check compatibility between main channel supported and possible auxiliary channels */
3697 in_update_aux_channels(in, effect);//wesley crash
3698 in->aux_channels_changed = true;
3699 } else {
3700 /* if ( enable == false ) */
3701 if (in->num_preprocessors <= 0) {
3702 status = -ENOSYS;
3703 goto exit;
3704 }
3705 status = -EINVAL;
3706 for (i=0; i < in->num_preprocessors; i++) {
3707 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3708 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3709 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3710 in->preprocessors[i - 1].num_channel_configs =
3711 in->preprocessors[i].num_channel_configs;
3712 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3713 continue;
3714 }
3715 if ( in->preprocessors[i].effect_itfe == effect ) {
3716 ALOGV("add_remove_audio_effect found fx at index %d", i);
3717 free(in->preprocessors[i].channel_configs);
3718 status = 0;
3719 }
3720 }
3721 if (status != 0)
3722 goto exit;
3723 in->num_preprocessors--;
3724 /* if we remove one effect, at least the last proproc should be reset */
3725 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3726 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3727 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3728 in->aux_channels_changed = false;
3729 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3730 }
3731 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3732
3733 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3734 in->enable_aec = enable;
3735 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3736 if (!in->standby) {
3737 select_devices(in->dev, in->usecase);
3738 do_in_standby_l(in);
3739 }
3740 if (in->enable_aec == true) {
3741 in_configure_reverse(in);
3742 }
3743 }
3744exit:
3745#endif
3746 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3747 pthread_mutex_unlock(&in->dev->lock);
3748 pthread_mutex_unlock(&in->lock);
3749 pthread_mutex_unlock(&adev->lock_inputs);
3750 return status;
3751}
3752
3753static int in_add_audio_effect(const struct audio_stream *stream,
3754 effect_handle_t effect)
3755{
3756 ALOGV("%s: effect %p", __func__, effect);
3757 return add_remove_audio_effect(stream, effect, true);
3758}
3759
3760static int in_remove_audio_effect(const struct audio_stream *stream,
3761 effect_handle_t effect)
3762{
3763 ALOGV("%s: effect %p", __func__, effect);
3764 return add_remove_audio_effect(stream, effect, false);
3765}
3766
3767static int adev_open_output_stream(struct audio_hw_device *dev,
3768 audio_io_handle_t handle,
3769 audio_devices_t devices,
3770 audio_output_flags_t flags,
3771 struct audio_config *config,
3772 struct audio_stream_out **stream_out,
3773 const char *address __unused)
3774{
3775 struct audio_device *adev = (struct audio_device *)dev;
3776 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003777 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003778 struct pcm_device_profile *pcm_profile;
3779
3780 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3781 __func__, config->sample_rate, config->channel_mask, devices, flags);
3782 *stream_out = NULL;
3783 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003784 if (out == NULL) {
3785 ret = -ENOMEM;
3786 goto error_config;
3787 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003788
3789 if (devices == AUDIO_DEVICE_NONE)
3790 devices = AUDIO_DEVICE_OUT_SPEAKER;
3791
3792 out->flags = flags;
3793 out->devices = devices;
3794 out->dev = adev;
3795 out->format = config->format;
3796 out->sample_rate = config->sample_rate;
3797 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3798 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3799 out->handle = handle;
3800
3801 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3802 if (pcm_profile == NULL) {
3803 ret = -EINVAL;
3804 goto error_open;
3805 }
3806 out->config = pcm_profile->config;
3807
3808 /* Init use case and pcm_config */
3809 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3810 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3811 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3812 ALOGE("%s: Unsupported Offload information", __func__);
3813 ret = -EINVAL;
3814 goto error_open;
3815 }
3816 if (!is_supported_format(config->offload_info.format)) {
3817 ALOGE("%s: Unsupported audio format", __func__);
3818 ret = -EINVAL;
3819 goto error_open;
3820 }
3821
3822 out->compr_config.codec = (struct snd_codec *)
3823 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003824 if (out->compr_config.codec == NULL) {
3825 ret = -ENOMEM;
3826 goto error_open;
3827 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003828
3829 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3830 if (config->offload_info.channel_mask)
3831 out->channel_mask = config->offload_info.channel_mask;
3832 else if (config->channel_mask)
3833 out->channel_mask = config->channel_mask;
3834 out->format = config->offload_info.format;
3835 out->sample_rate = config->offload_info.sample_rate;
3836
3837 out->stream.set_callback = out_set_callback;
3838 out->stream.pause = out_pause;
3839 out->stream.resume = out_resume;
3840 out->stream.drain = out_drain;
3841 out->stream.flush = out_flush;
3842
3843 out->compr_config.codec->id =
3844 get_snd_codec_id(config->offload_info.format);
3845 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3846 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3847 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3848 out->compr_config.codec->bit_rate =
3849 config->offload_info.bit_rate;
3850 out->compr_config.codec->ch_in =
3851 audio_channel_count_from_out_mask(config->channel_mask);
3852 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3853
3854 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3855 out->non_blocking = 1;
3856
3857 out->send_new_metadata = 1;
3858 create_offload_callback_thread(out);
3859 out->offload_state = OFFLOAD_STATE_IDLE;
3860
3861 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3862 __func__, config->offload_info.version,
3863 config->offload_info.bit_rate);
3864 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3865 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003866 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003867 out->sample_rate = out->config.rate;
3868 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3869 } else {
3870 out->usecase = USECASE_AUDIO_PLAYBACK;
3871 out->sample_rate = out->config.rate;
3872 }
3873
3874 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3875 if (adev->primary_output == NULL)
3876 adev->primary_output = out;
3877 else {
3878 ALOGE("%s: Primary output is already opened", __func__);
3879 ret = -EEXIST;
3880 goto error_open;
3881 }
3882 }
3883
3884 /* Check if this usecase is already existing */
3885 pthread_mutex_lock(&adev->lock);
3886 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3887 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3888 pthread_mutex_unlock(&adev->lock);
3889 ret = -EEXIST;
3890 goto error_open;
3891 }
3892 pthread_mutex_unlock(&adev->lock);
3893
3894 out->stream.common.get_sample_rate = out_get_sample_rate;
3895 out->stream.common.set_sample_rate = out_set_sample_rate;
3896 out->stream.common.get_buffer_size = out_get_buffer_size;
3897 out->stream.common.get_channels = out_get_channels;
3898 out->stream.common.get_format = out_get_format;
3899 out->stream.common.set_format = out_set_format;
3900 out->stream.common.standby = out_standby;
3901 out->stream.common.dump = out_dump;
3902 out->stream.common.set_parameters = out_set_parameters;
3903 out->stream.common.get_parameters = out_get_parameters;
3904 out->stream.common.add_audio_effect = out_add_audio_effect;
3905 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3906 out->stream.get_latency = out_get_latency;
3907 out->stream.set_volume = out_set_volume;
3908 out->stream.write = out_write;
3909 out->stream.get_render_position = out_get_render_position;
3910 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3911 out->stream.get_presentation_position = out_get_presentation_position;
3912
3913 out->standby = 1;
3914 /* out->muted = false; by calloc() */
3915 /* out->written = 0; by calloc() */
3916
3917 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3918 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3919 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3920
3921 config->format = out->stream.common.get_format(&out->stream.common);
3922 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3923 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3924
3925 out->is_fastmixer_affinity_set = false;
3926
3927 *stream_out = &out->stream;
3928 ALOGV("%s: exit", __func__);
3929 return 0;
3930
3931error_open:
3932 free(out);
3933 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003934error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003935 ALOGV("%s: exit: ret %d", __func__, ret);
3936 return ret;
3937}
3938
3939static void adev_close_output_stream(struct audio_hw_device *dev,
3940 struct audio_stream_out *stream)
3941{
3942 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003943 (void)dev;
3944
3945 ALOGV("%s: enter", __func__);
3946 out_standby(&stream->common);
3947 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3948 destroy_offload_callback_thread(out);
3949
3950 if (out->compr_config.codec != NULL)
3951 free(out->compr_config.codec);
3952 }
3953 pthread_cond_destroy(&out->cond);
3954 pthread_mutex_destroy(&out->lock);
3955 free(stream);
3956 ALOGV("%s: exit", __func__);
3957}
3958
3959static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3960{
3961 struct audio_device *adev = (struct audio_device *)dev;
3962 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003963 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003964#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003965 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003966#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003967 int ret;
3968
3969 ALOGV("%s: enter: %s", __func__, kvpairs);
3970
3971 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003972
Andreas Schneider05bc1882017-02-09 14:03:11 +01003973 /******************************************************
3974 *** BT SCO
3975 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003976 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3977 if (ret >= 0) {
3978 /* When set to false, HAL should disable EC and NS
3979 * But it is currently not supported.
3980 */
3981 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003982 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003983 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003984 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003985 }
3986
Andreas Schneider05bc1882017-02-09 14:03:11 +01003987 ret = str_parms_get_str(parms,
3988 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3989 value,
3990 sizeof(value));
3991 if (ret >= 0) {
3992 /* TODO: Add support in voice calls */
3993 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3994 adev->voice.bluetooth_wb = true;
3995 ALOGI("%s: Implement support for BT SCO wideband calls!!!",
3996 __func__);
3997 } else {
3998 adev->voice.bluetooth_wb = false;
3999 }
4000 }
4001
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01004002 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4003 if (ret >= 0) {
4004 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4005 adev->screen_off = false;
4006 else
4007 adev->screen_off = true;
4008 }
4009
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004010#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004011 ret = str_parms_get_int(parms, "rotation", &val);
4012 if (ret >= 0) {
4013 bool reverse_speakers = false;
4014 switch(val) {
4015 /* FIXME: note that the code below assumes that the speakers are in the correct placement
4016 relative to the user when the device is rotated 90deg from its default rotation. This
4017 assumption is device-specific, not platform-specific like this code. */
4018 case 270:
4019 reverse_speakers = true;
4020 break;
4021 case 0:
4022 case 90:
4023 case 180:
4024 break;
4025 default:
4026 ALOGE("%s: unexpected rotation of %d", __func__, val);
4027 }
4028 pthread_mutex_lock(&adev->lock);
4029 if (adev->speaker_lr_swap != reverse_speakers) {
4030 adev->speaker_lr_swap = reverse_speakers;
4031 /* only update the selected device if there is active pcm playback */
4032 struct audio_usecase *usecase;
4033 struct listnode *node;
4034 list_for_each(node, &adev->usecase_list) {
4035 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
4036 if (usecase->type == PCM_PLAYBACK) {
4037 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004038 break;
4039 }
4040 }
4041 }
4042 pthread_mutex_unlock(&adev->lock);
4043 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01004044#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004045
4046 str_parms_destroy(parms);
4047
4048 if (ret > 0)
4049 ret = 0;
4050
4051 ALOGV("%s: exit with code(%d)", __func__, ret);
4052 return ret;
4053}
4054
4055static char* adev_get_parameters(const struct audio_hw_device *dev,
4056 const char *keys)
4057{
4058 (void)dev;
4059 (void)keys;
4060
4061 return strdup("");
4062}
4063
4064static int adev_init_check(const struct audio_hw_device *dev)
4065{
4066 (void)dev;
4067
4068 return 0;
4069}
4070
4071static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4072{
4073 int ret = 0;
4074 struct audio_device *adev = (struct audio_device *)dev;
4075 pthread_mutex_lock(&adev->lock);
4076 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004077 adev->voice.volume = volume;
4078 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004079 pthread_mutex_unlock(&adev->lock);
4080 return ret;
4081}
4082
4083static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
4084{
4085 (void)dev;
4086 (void)volume;
4087
4088 return -ENOSYS;
4089}
4090
4091static int adev_get_master_volume(struct audio_hw_device *dev,
4092 float *volume)
4093{
4094 (void)dev;
4095 (void)volume;
4096
4097 return -ENOSYS;
4098}
4099
4100static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
4101{
4102 (void)dev;
4103 (void)muted;
4104
4105 return -ENOSYS;
4106}
4107
4108static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
4109{
4110 (void)dev;
4111 (void)muted;
4112
4113 return -ENOSYS;
4114}
4115
4116static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4117{
4118 struct audio_device *adev = (struct audio_device *)dev;
4119
4120 pthread_mutex_lock(&adev->lock);
4121 if (adev->mode != mode) {
4122 ALOGI("%s mode = %d", __func__, mode);
4123 adev->mode = mode;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004124 }
4125 pthread_mutex_unlock(&adev->lock);
4126 return 0;
4127}
4128
4129static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4130{
4131 struct audio_device *adev = (struct audio_device *)dev;
4132 int err = 0;
4133
4134 pthread_mutex_lock(&adev->lock);
4135 adev->mic_mute = state;
4136
4137 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01004138 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004139 }
4140
4141 pthread_mutex_unlock(&adev->lock);
4142 return err;
4143}
4144
4145static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4146{
4147 struct audio_device *adev = (struct audio_device *)dev;
4148
4149 *state = adev->mic_mute;
4150
4151 return 0;
4152}
4153
4154static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4155 const struct audio_config *config)
4156{
4157 (void)dev;
4158
4159 /* NOTE: we default to built in mic which may cause a mismatch between what we
4160 * report here and the actual buffer size
4161 */
4162 return get_input_buffer_size(config->sample_rate,
4163 config->format,
4164 audio_channel_count_from_in_mask(config->channel_mask),
4165 PCM_CAPTURE /* usecase_type */,
4166 AUDIO_DEVICE_IN_BUILTIN_MIC);
4167}
4168
4169static int adev_open_input_stream(struct audio_hw_device *dev,
4170 audio_io_handle_t handle __unused,
4171 audio_devices_t devices,
4172 struct audio_config *config,
4173 struct audio_stream_in **stream_in,
4174 audio_input_flags_t flags,
4175 const char *address __unused,
4176 audio_source_t source)
4177{
4178 struct audio_device *adev = (struct audio_device *)dev;
4179 struct stream_in *in;
4180 struct pcm_device_profile *pcm_profile;
4181
4182 ALOGV("%s: enter", __func__);
4183
4184 *stream_in = NULL;
4185 if (check_input_parameters(config->sample_rate, config->format,
4186 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4187 return -EINVAL;
4188
4189 usecase_type_t usecase_type = source == AUDIO_SOURCE_HOTWORD ?
4190 PCM_HOTWORD_STREAMING : flags & AUDIO_INPUT_FLAG_FAST ?
4191 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4192 pcm_profile = get_pcm_device(usecase_type, devices);
4193 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4194 // a low latency profile may not exist for that device, fall back
4195 // to regular capture. the MixerThread automatically changes
4196 // to non-fast capture based on the buffer size.
4197 flags &= ~AUDIO_INPUT_FLAG_FAST;
4198 usecase_type = PCM_CAPTURE;
4199 pcm_profile = get_pcm_device(usecase_type, devices);
4200 }
4201 if (pcm_profile == NULL)
4202 return -EINVAL;
4203
4204 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004205 if (in == NULL) {
4206 return -ENOMEM;
4207 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004208
4209 in->stream.common.get_sample_rate = in_get_sample_rate;
4210 in->stream.common.set_sample_rate = in_set_sample_rate;
4211 in->stream.common.get_buffer_size = in_get_buffer_size;
4212 in->stream.common.get_channels = in_get_channels;
4213 in->stream.common.get_format = in_get_format;
4214 in->stream.common.set_format = in_set_format;
4215 in->stream.common.standby = in_standby;
4216 in->stream.common.dump = in_dump;
4217 in->stream.common.set_parameters = in_set_parameters;
4218 in->stream.common.get_parameters = in_get_parameters;
4219 in->stream.common.add_audio_effect = in_add_audio_effect;
4220 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4221 in->stream.set_gain = in_set_gain;
4222 in->stream.read = in_read;
4223 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004224 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004225
4226 in->devices = devices;
4227 in->source = source;
4228 in->dev = adev;
4229 in->standby = 1;
4230 in->main_channels = config->channel_mask;
4231 in->requested_rate = config->sample_rate;
4232 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4233 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4234 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004235 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004236 /* HW codec is limited to default channels. No need to update with
4237 * requested channels */
4238 in->config = pcm_profile->config;
4239
4240 /* Update config params with the requested sample rate and channels */
4241 if (source == AUDIO_SOURCE_HOTWORD) {
4242 in->usecase = USECASE_AUDIO_CAPTURE_HOTWORD;
4243 } else {
4244 in->usecase = USECASE_AUDIO_CAPTURE;
4245 }
4246 in->usecase_type = usecase_type;
4247
4248 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4249 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4250
4251 in->is_fastcapture_affinity_set = false;
4252
4253 *stream_in = &in->stream;
4254 ALOGV("%s: exit", __func__);
4255 return 0;
4256}
4257
4258static void adev_close_input_stream(struct audio_hw_device *dev,
4259 struct audio_stream_in *stream)
4260{
4261 struct audio_device *adev = (struct audio_device *)dev;
4262 struct stream_in *in = (struct stream_in*)stream;
4263 ALOGV("%s", __func__);
4264
4265 /* prevent concurrent out_set_parameters, or out_write from standby */
4266 pthread_mutex_lock(&adev->lock_inputs);
4267
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004268 if (in->read_buf) {
4269 free(in->read_buf);
4270 in->read_buf = NULL;
4271 }
4272
4273 if (in->resampler) {
4274 release_resampler(in->resampler);
4275 in->resampler = NULL;
4276 }
4277
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004278#ifdef PREPROCESSING_ENABLED
4279 int i;
4280
4281 for (i=0; i<in->num_preprocessors; i++) {
4282 free(in->preprocessors[i].channel_configs);
4283 }
4284
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004285 if (in->proc_buf_in) {
4286 free(in->proc_buf_in);
4287 in->proc_buf_in = NULL;
4288 }
4289
4290 if (in->proc_buf_out) {
4291 free(in->proc_buf_out);
4292 in->proc_buf_out = NULL;
4293 }
4294
4295 if (in->ref_buf) {
4296 free(in->ref_buf);
4297 in->ref_buf = NULL;
4298 }
4299
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004300#endif
4301
4302 in_standby_l(in);
4303 free(stream);
4304
4305 pthread_mutex_unlock(&adev->lock_inputs);
4306
4307 return;
4308}
4309
4310static int adev_dump(const audio_hw_device_t *device, int fd)
4311{
4312 (void)device;
4313 (void)fd;
4314
4315 return 0;
4316}
4317
4318static int adev_close(hw_device_t *device)
4319{
4320 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004321 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004322 audio_device_ref_count--;
4323 free(adev->snd_dev_ref_cnt);
4324 free_mixer_list(adev);
4325 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004326
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004327 return 0;
4328}
4329
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004330/* This returns true if the input parameter looks at all plausible as a low latency period size,
4331 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4332 * just that it _might_ work.
4333 */
4334static bool period_size_is_plausible_for_low_latency(int period_size)
4335{
4336 switch (period_size) {
4337 case 64:
4338 case 96:
4339 case 128:
4340 case 192:
4341 case 256:
4342 return true;
4343 default:
4344 return false;
4345 }
4346}
4347
4348static int adev_open(const hw_module_t *module, const char *name,
4349 hw_device_t **device)
4350{
4351 struct audio_device *adev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004352
4353 ALOGV("%s: enter", __func__);
4354 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4355
Andreas Schneider56204f62017-01-31 08:17:32 +01004356 *device = NULL;
4357
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004358 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004359 if (adev == NULL) {
4360 return -ENOMEM;
4361 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004362
4363 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4364 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4365 adev->device.common.module = (struct hw_module_t *)module;
4366 adev->device.common.close = adev_close;
4367
4368 adev->device.init_check = adev_init_check;
4369 adev->device.set_voice_volume = adev_set_voice_volume;
4370 adev->device.set_master_volume = adev_set_master_volume;
4371 adev->device.get_master_volume = adev_get_master_volume;
4372 adev->device.set_master_mute = adev_set_master_mute;
4373 adev->device.get_master_mute = adev_get_master_mute;
4374 adev->device.set_mode = adev_set_mode;
4375 adev->device.set_mic_mute = adev_set_mic_mute;
4376 adev->device.get_mic_mute = adev_get_mic_mute;
4377 adev->device.set_parameters = adev_set_parameters;
4378 adev->device.get_parameters = adev_get_parameters;
4379 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4380 adev->device.open_output_stream = adev_open_output_stream;
4381 adev->device.close_output_stream = adev_close_output_stream;
4382 adev->device.open_input_stream = adev_open_input_stream;
4383 adev->device.close_input_stream = adev_close_input_stream;
4384 adev->device.dump = adev_dump;
4385
4386 /* Set the default route before the PCM stream is opened */
4387 adev->mode = AUDIO_MODE_NORMAL;
4388 adev->active_input = NULL;
4389 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004390
4391 adev->voice.volume = 1.0f;
4392 adev->voice.bluetooth_nrec = true;
4393 adev->voice.in_call = false;
4394
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004395 /* adev->cur_hdmi_channels = 0; by calloc() */
4396 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004397 if (adev->snd_dev_ref_cnt == NULL) {
4398 free(adev);
4399 return -ENOMEM;
4400 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004401
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004402 adev->ns_in_voice_rec = false;
4403
4404 list_init(&adev->usecase_list);
4405
4406 if (mixer_init(adev) != 0) {
4407 free(adev->snd_dev_ref_cnt);
4408 free(adev);
4409 ALOGE("%s: Failed to init, aborting.", __func__);
4410 *device = NULL;
4411 return -EINVAL;
4412 }
4413
4414 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4415 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4416 if (adev->offload_fx_lib == NULL) {
4417 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4418 } else {
4419 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4420 adev->offload_fx_start_output =
4421 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4422 "visualizer_hal_start_output");
4423 adev->offload_fx_stop_output =
4424 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4425 "visualizer_hal_stop_output");
4426 }
4427 }
4428
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004429 if (access(SOUND_TRIGGER_HAL_LIBRARY_PATH, R_OK) == 0) {
4430 adev->sound_trigger_lib = dlopen(SOUND_TRIGGER_HAL_LIBRARY_PATH, RTLD_NOW);
4431 if (adev->sound_trigger_lib == NULL) {
4432 ALOGE("%s: DLOPEN failed for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4433 } else {
4434 ALOGV("%s: DLOPEN successful for %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4435 adev->sound_trigger_open_for_streaming =
4436 (int (*)(void))dlsym(adev->sound_trigger_lib,
4437 "sound_trigger_open_for_streaming");
4438 adev->sound_trigger_read_samples =
4439 (size_t (*)(int, void *, size_t))dlsym(adev->sound_trigger_lib,
4440 "sound_trigger_read_samples");
4441 adev->sound_trigger_close_for_streaming =
4442 (int (*)(int))dlsym(adev->sound_trigger_lib,
4443 "sound_trigger_close_for_streaming");
4444 if (!adev->sound_trigger_open_for_streaming ||
4445 !adev->sound_trigger_read_samples ||
4446 !adev->sound_trigger_close_for_streaming) {
4447
4448 ALOGE("%s: Error grabbing functions in %s", __func__, SOUND_TRIGGER_HAL_LIBRARY_PATH);
4449 adev->sound_trigger_open_for_streaming = 0;
4450 adev->sound_trigger_read_samples = 0;
4451 adev->sound_trigger_close_for_streaming = 0;
4452 }
4453 }
4454 }
4455
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004456 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004457 if (adev->voice.session == NULL) {
4458 ALOGE("%s: Failed to initialize voice session data", __func__);
4459
4460 free(adev->snd_dev_ref_cnt);
4461 free(adev);
4462
4463 *device = NULL;
4464 return -EINVAL;
4465 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004466
4467 *device = &adev->device.common;
4468
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004469 audio_device_ref_count++;
4470
4471 char value[PROPERTY_VALUE_MAX];
4472 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4473 int trial = atoi(value);
4474 if (period_size_is_plausible_for_low_latency(trial)) {
4475
4476 pcm_device_playback.config.period_size = trial;
4477 pcm_device_playback.config.start_threshold =
4478 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4479 pcm_device_playback.config.stop_threshold =
4480 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4481
4482 pcm_device_capture_low_latency.config.period_size = trial;
4483 }
4484 }
4485
4486 ALOGV("%s: exit", __func__);
4487 return 0;
4488}
4489
4490static struct hw_module_methods_t hal_module_methods = {
4491 .open = adev_open,
4492};
4493
4494struct audio_module HAL_MODULE_INFO_SYM = {
4495 .common = {
4496 .tag = HARDWARE_MODULE_TAG,
4497 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4498 .hal_api_version = HARDWARE_HAL_API_VERSION,
4499 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004500 .name = "Samsung Audio HAL",
4501 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004502 .methods = &hal_module_methods,
4503 },
4504};