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