blob: fd9c0b00e10709e45d0ad3be8c0c6e6176fa34b8 [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>
stenkinevgeniy44335362018-05-07 18:00:13 +00005 * Copyright (C) 2018 The LineageOS Project
Christopher N. Hesse297a6362017-01-28 12:40:45 +01006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
21/*#define LOG_NDEBUG 0*/
22/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
28
29#define _GNU_SOURCE
30#include <errno.h>
31#include <pthread.h>
32#include <stdint.h>
33#include <sys/time.h>
34#include <stdlib.h>
35#include <math.h>
36#include <dlfcn.h>
Christopher N. Hesse297a6362017-01-28 12:40:45 +010037
38#include <cutils/log.h>
39#include <cutils/str_parms.h>
40#include <cutils/atomic.h>
41#include <cutils/sched_policy.h>
42#include <cutils/properties.h>
43
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010044#include <samsung_audio.h>
45
Christopher N. Hesse297a6362017-01-28 12:40:45 +010046#include <hardware/audio_effect.h>
47#include <system/thread_defs.h>
48#include <audio_effects/effect_aec.h>
49#include <audio_effects/effect_ns.h>
50#include "audio_hw.h"
Christopher N. Hesse757ac412017-01-28 14:42:48 +010051#include "compress_offload.h"
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +010052#include "voice.h"
Christopher N. Hesse297a6362017-01-28 12:40:45 +010053
54#include "sound/compress_params.h"
55
Christopher N. Hesse297a6362017-01-28 12:40:45 +010056
57/* TODO: the following PCM device profiles could be read from a config file */
58static struct pcm_device_profile pcm_device_playback = {
59 .config = {
60 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
61 .rate = PLAYBACK_DEFAULT_SAMPLING_RATE,
62 .period_size = PLAYBACK_PERIOD_SIZE,
63 .period_count = PLAYBACK_PERIOD_COUNT,
64 .format = PCM_FORMAT_S16_LE,
65 .start_threshold = PLAYBACK_START_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
66 .stop_threshold = PLAYBACK_STOP_THRESHOLD(PLAYBACK_PERIOD_SIZE, PLAYBACK_PERIOD_COUNT),
67 .silence_threshold = 0,
68 .silence_size = UINT_MAX,
69 .avail_min = PLAYBACK_AVAILABLE_MIN,
70 },
71 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +010072 .id = SOUND_PLAYBACK_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010073 .type = PCM_PLAYBACK,
74 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
stenkinevgeniy53929f72018-07-09 11:20:36 +000075 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
Christopher N. Hesse297a6362017-01-28 12:40:45 +010076};
77
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010078static struct pcm_device_profile pcm_device_deep_buffer = {
79 .config = {
80 .channels = PLAYBACK_DEFAULT_CHANNEL_COUNT,
81 .rate = DEEP_BUFFER_OUTPUT_SAMPLING_RATE,
82 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
83 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
84 .format = PCM_FORMAT_S16_LE,
85 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
86 .stop_threshold = INT_MAX,
87 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
88 },
89 .card = SOUND_CARD,
90 .id = SOUND_DEEP_BUFFER_DEVICE,
91 .type = PCM_PLAYBACK,
92 .devices = AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|
stenkinevgeniy53929f72018-07-09 11:20:36 +000093 AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_EARPIECE|AUDIO_DEVICE_OUT_ALL_SCO,
Christopher N. Hesse8414bd22017-01-30 18:57:20 +010094};
95
Christopher N. Hesse297a6362017-01-28 12:40:45 +010096static struct pcm_device_profile pcm_device_capture = {
97 .config = {
98 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
99 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
100 .period_size = CAPTURE_PERIOD_SIZE,
101 .period_count = CAPTURE_PERIOD_COUNT,
102 .format = PCM_FORMAT_S16_LE,
103 .start_threshold = CAPTURE_START_THRESHOLD,
104 .stop_threshold = 0,
105 .silence_threshold = 0,
106 .avail_min = 0,
107 },
108 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100109 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100110 .type = PCM_CAPTURE,
stenkinevgeniy53929f72018-07-09 11:20:36 +0000111 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100112};
113
114static struct pcm_device_profile pcm_device_capture_low_latency = {
115 .config = {
116 .channels = CAPTURE_DEFAULT_CHANNEL_COUNT,
117 .rate = CAPTURE_DEFAULT_SAMPLING_RATE,
118 .period_size = CAPTURE_PERIOD_SIZE_LOW_LATENCY,
119 .period_count = CAPTURE_PERIOD_COUNT_LOW_LATENCY,
120 .format = PCM_FORMAT_S16_LE,
121 .start_threshold = CAPTURE_START_THRESHOLD,
122 .stop_threshold = 0,
123 .silence_threshold = 0,
124 .avail_min = 0,
125 },
126 .card = SOUND_CARD,
Christopher N. Hessed23c6b52017-01-28 14:18:10 +0100127 .id = SOUND_CAPTURE_DEVICE,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100128 .type = PCM_CAPTURE_LOW_LATENCY,
stenkinevgeniy53929f72018-07-09 11:20:36 +0000129 .devices = AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100130};
131
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100132static struct pcm_device_profile * const pcm_devices[] = {
133 &pcm_device_playback,
134 &pcm_device_capture,
135 &pcm_device_capture_low_latency,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100136 NULL,
137};
138
139static const char * const use_case_table[AUDIO_USECASE_MAX] = {
140 [USECASE_AUDIO_PLAYBACK] = "playback",
141 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "playback multi-channel",
142 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Andreas Schneiderdf6fc8a2017-02-14 11:38:41 +0100143 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "playback deep-buffer",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100144 [USECASE_AUDIO_CAPTURE] = "capture",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100145 [USECASE_VOICE_CALL] = "voice-call",
146};
147
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100148#define STRING_TO_ENUM(string) { #string, string }
149
150static unsigned int audio_device_ref_count;
151
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100152struct string_to_enum {
153 const char *name;
154 uint32_t value;
155};
156
157static const struct string_to_enum out_channels_name_to_enum_table[] = {
158 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
159 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
160 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
161};
162
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200163static struct audio_device *adev = NULL;
164
165static amplifier_device_t * get_amplifier_device(void)
166{
167 if (adev)
168 return adev->amp;
169
170 return NULL;
171}
172
173static int amplifier_open(void)
174{
175 int rc;
176 amplifier_module_t *module;
177
178 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
179 (const hw_module_t **) &module);
180 if (rc) {
Christopher N. Hessec487bbe2018-07-12 13:51:43 +0200181 if (rc == -ENOENT) {
182 // no amplifier HAL present
183 return -ENOENT;
184 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200185 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
186 __func__, strerror(-rc));
187 return -ENODEV;
188 }
189
190 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
191 if (rc) {
192 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
193 __func__, strerror(-rc));
194 return -ENODEV;
195 }
196
197 return 0;
198}
199
200static int amplifier_set_input_devices(uint32_t devices)
201{
202 amplifier_device_t *amp = get_amplifier_device();
203 if (amp && amp->set_input_devices)
204 return amp->set_input_devices(amp, devices);
205
206 return 0;
207}
208
209static int amplifier_set_output_devices(uint32_t devices)
210{
211 amplifier_device_t *amp = get_amplifier_device();
212 if (amp && amp->set_output_devices)
213 return amp->set_output_devices(amp, devices);
214
215 return 0;
216}
217
218static int amplifier_enable_devices(uint32_t devices, bool enable)
219{
220 amplifier_device_t *amp = get_amplifier_device();
221 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
222 devices < SND_DEVICE_OUT_END;
223
224 if (amp && amp->enable_output_devices && is_output)
225 return amp->enable_output_devices(amp, devices, enable);
226
227 if (amp && amp->enable_input_devices && !is_output)
228 return amp->enable_input_devices(amp, devices, enable);
229
230 return 0;
231}
232
233static int amplifier_set_mode(audio_mode_t mode)
234{
235 amplifier_device_t *amp = get_amplifier_device();
236 if (amp && amp->set_mode)
237 return amp->set_mode(amp, mode);
238
239 return 0;
240}
241
242static int amplifier_output_stream_start(struct audio_stream_out *stream,
243 bool offload)
244{
245 amplifier_device_t *amp = get_amplifier_device();
246 if (amp && amp->output_stream_start)
247 return amp->output_stream_start(amp, stream, offload);
248
249 return 0;
250}
251
252static int amplifier_input_stream_start(struct audio_stream_in *stream)
253{
254 amplifier_device_t *amp = get_amplifier_device();
255 if (amp && amp->input_stream_start)
256 return amp->input_stream_start(amp, stream);
257
258 return 0;
259}
260
261static int amplifier_output_stream_standby(struct audio_stream_out *stream)
262{
263 amplifier_device_t *amp = get_amplifier_device();
264 if (amp && amp->output_stream_standby)
265 return amp->output_stream_standby(amp, stream);
266
267 return 0;
268}
269
270static int amplifier_input_stream_standby(struct audio_stream_in *stream)
271{
272 amplifier_device_t *amp = get_amplifier_device();
273 if (amp && amp->input_stream_standby)
274 return amp->input_stream_standby(amp, stream);
275
276 return 0;
277}
278
279static int amplifier_set_parameters(struct str_parms *parms)
280{
281 amplifier_device_t *amp = get_amplifier_device();
282 if (amp && amp->set_parameters)
283 return amp->set_parameters(amp, parms);
284
285 return 0;
286}
287
288static int amplifier_close(void)
289{
290 amplifier_device_t *amp = get_amplifier_device();
291 if (amp)
292 amplifier_device_close(amp);
293
294 return 0;
295}
296
Andreas Schneider759368f2017-02-02 16:11:14 +0100297struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
298 struct timespec ret;
299 int xsec = 0;
Andreas Schneider759368f2017-02-02 16:11:14 +0100300
301 if (time0.tv_nsec > time1.tv_nsec) {
302 xsec = (int) ((time0.tv_nsec - time1.tv_nsec) / (1E9 + 1));
303 time0.tv_nsec -= (long int) (1E9 * xsec);
304 time0.tv_sec += xsec;
305 }
306
307 if ((time1.tv_nsec - time0.tv_nsec) > 1E9) {
308 xsec = (int) ((time1.tv_nsec - time0.tv_nsec) / 1E9);
309 time0.tv_nsec += (long int) (1E9 * xsec);
310 time0.tv_sec -= xsec;
311 }
312
Paul Keithf114e2e2017-02-14 20:41:33 -0600313 ret.tv_sec = labs(time1.tv_sec - time0.tv_sec);
314 ret.tv_nsec = labs(time1.tv_nsec - time0.tv_nsec);
Andreas Schneider759368f2017-02-02 16:11:14 +0100315
316 return ret;
317}
318
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100319static bool is_supported_format(audio_format_t format)
320{
321 if (format == AUDIO_FORMAT_MP3 ||
322 ((format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC))
323 return true;
324
325 return false;
326}
327
328static int get_snd_codec_id(audio_format_t format)
329{
330 int id = 0;
331
332 switch (format & AUDIO_FORMAT_MAIN_MASK) {
333 case AUDIO_FORMAT_MP3:
334 id = SND_AUDIOCODEC_MP3;
335 break;
336 case AUDIO_FORMAT_AAC:
337 id = SND_AUDIOCODEC_AAC;
338 break;
339 default:
340 ALOGE("%s: Unsupported audio format", __func__);
341 }
342
343 return id;
344}
345
346/* Array to store sound devices */
347static const char * const device_table[SND_DEVICE_MAX] = {
348 [SND_DEVICE_NONE] = "none",
349 /* Playback sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100350 [SND_DEVICE_OUT_EARPIECE] = "earpiece",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100351 [SND_DEVICE_OUT_SPEAKER] = "speaker",
352 [SND_DEVICE_OUT_HEADPHONES] = "headphones",
353 [SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES] = "speaker-and-headphones",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100354 [SND_DEVICE_OUT_VOICE_EARPIECE] = "voice-earpiece",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100355 [SND_DEVICE_OUT_VOICE_EARPIECE_WB] = "voice-earpiece-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100356 [SND_DEVICE_OUT_VOICE_SPEAKER] = "voice-speaker",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100357 [SND_DEVICE_OUT_VOICE_SPEAKER_WB] = "voice-speaker-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100358 [SND_DEVICE_OUT_VOICE_HEADPHONES] = "voice-headphones",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100359 [SND_DEVICE_OUT_VOICE_HEADPHONES_WB] = "voice-headphones-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100360 [SND_DEVICE_OUT_VOICE_BT_SCO] = "voice-bt-sco-headset",
361 [SND_DEVICE_OUT_VOICE_BT_SCO_WB] = "voice-bt-sco-headset-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100362 [SND_DEVICE_OUT_HDMI] = "hdmi",
363 [SND_DEVICE_OUT_SPEAKER_AND_HDMI] = "speaker-and-hdmi",
364 [SND_DEVICE_OUT_BT_SCO] = "bt-sco-headset",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100365
366 /* Capture sound devices */
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100367 [SND_DEVICE_IN_EARPIECE_MIC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100368 [SND_DEVICE_IN_SPEAKER_MIC] = "speaker-mic",
369 [SND_DEVICE_IN_HEADSET_MIC] = "headset-mic",
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100370 [SND_DEVICE_IN_EARPIECE_MIC_AEC] = "earpiece-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100371 [SND_DEVICE_IN_SPEAKER_MIC_AEC] = "voice-speaker-mic",
372 [SND_DEVICE_IN_HEADSET_MIC_AEC] = "headset-mic",
Andreas Schneider82f32482017-02-06 09:00:48 +0100373 [SND_DEVICE_IN_VOICE_MIC] = "voice-mic",
374 [SND_DEVICE_IN_VOICE_EARPIECE_MIC] = "voice-earpiece-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100375 [SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB] = "voice-earpiece-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100376 [SND_DEVICE_IN_VOICE_SPEAKER_MIC] = "voice-speaker-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100377 [SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB] = "voice-speaker-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100378 [SND_DEVICE_IN_VOICE_HEADSET_MIC] = "voice-headset-mic",
Andreas Schneider59486fa2017-02-06 09:16:39 +0100379 [SND_DEVICE_IN_VOICE_HEADSET_MIC_WB] = "voice-headset-mic-wb",
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100380 [SND_DEVICE_IN_VOICE_BT_SCO_MIC] = "voice-bt-sco-mic",
381 [SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB] = "voice-bt-sco-mic-wb",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100382 [SND_DEVICE_IN_HDMI_MIC] = "hdmi-mic",
383 [SND_DEVICE_IN_BT_SCO_MIC] = "bt-sco-mic",
384 [SND_DEVICE_IN_CAMCORDER_MIC] = "camcorder-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100385 [SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "voice-rec-headset-mic",
386 [SND_DEVICE_IN_VOICE_REC_MIC] = "voice-rec-mic",
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100387};
388
389static struct mixer_card *adev_get_mixer_for_card(struct audio_device *adev, int card)
390{
391 struct mixer_card *mixer_card;
392 struct listnode *node;
393
394 list_for_each(node, &adev->mixer_list) {
395 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
396 if (mixer_card->card == card)
397 return mixer_card;
398 }
399 return NULL;
400}
401
402static struct mixer_card *uc_get_mixer_for_card(struct audio_usecase *usecase, int card)
403{
404 struct mixer_card *mixer_card;
405 struct listnode *node;
406
407 list_for_each(node, &usecase->mixer_list) {
408 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[usecase->id]);
409 if (mixer_card->card == card)
410 return mixer_card;
411 }
412 return NULL;
413}
414
415static void free_mixer_list(struct audio_device *adev)
416{
417 struct mixer_card *mixer_card;
418 struct listnode *node;
419 struct listnode *next;
420
421 list_for_each_safe(node, next, &adev->mixer_list) {
422 mixer_card = node_to_item(node, struct mixer_card, adev_list_node);
423 list_remove(node);
424 audio_route_free(mixer_card->audio_route);
425 free(mixer_card);
426 }
427}
428
429static int mixer_init(struct audio_device *adev)
430{
431 int i;
432 int card;
433 int retry_num;
434 struct mixer *mixer;
435 struct audio_route *audio_route;
436 char mixer_path[PATH_MAX];
437 struct mixer_card *mixer_card;
Andreas Schneider56204f62017-01-31 08:17:32 +0100438 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100439
440 list_init(&adev->mixer_list);
441
442 for (i = 0; pcm_devices[i] != NULL; i++) {
443 card = pcm_devices[i]->card;
444 if (adev_get_mixer_for_card(adev, card) == NULL) {
445 retry_num = 0;
446 do {
447 mixer = mixer_open(card);
448 if (mixer == NULL) {
449 if (++retry_num > RETRY_NUMBER) {
450 ALOGE("%s unable to open the mixer for--card %d, aborting.",
451 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100452 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100453 goto error;
454 }
455 usleep(RETRY_US);
456 }
457 } while (mixer == NULL);
458
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100459 sprintf(mixer_path, "/vendor/etc/mixer_paths_%d.xml", card);
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100460 if (access(mixer_path, F_OK) == -1) {
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100461 ALOGW("%s: Failed to open mixer paths from %s, retrying with legacy location",
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100462 __func__, mixer_path);
Christopher N. Hessed8d04fd2018-01-28 00:07:47 +0100463 sprintf(mixer_path, "/system/etc/mixer_paths_%d.xml", card);
464 if (access(mixer_path, F_OK) == -1) {
465 ALOGE("%s: Failed to load a mixer paths configuration, your system will crash",
466 __func__);
467 }
Christopher N. Hesse2beff422018-01-28 13:16:17 +0100468 }
469
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100470 audio_route = audio_route_init(card, mixer_path);
471 if (!audio_route) {
472 ALOGE("%s: Failed to init audio route controls for card %d, aborting.",
473 __func__, card);
Andreas Schneider56204f62017-01-31 08:17:32 +0100474 ret = -ENODEV;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100475 goto error;
476 }
477 mixer_card = calloc(1, sizeof(struct mixer_card));
Andreas Schneider56204f62017-01-31 08:17:32 +0100478 if (mixer_card == NULL) {
479 ret = -ENOMEM;
480 goto error;
481 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100482 mixer_card->card = card;
483 mixer_card->mixer = mixer;
484 mixer_card->audio_route = audio_route;
Andreas Schneider759368f2017-02-02 16:11:14 +0100485
486 /* Do not sleep on first enable_snd_device() */
487 mixer_card->dsp_poweroff_time.tv_sec = 1;
488 mixer_card->dsp_poweroff_time.tv_nsec = 0;
489
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100490 list_add_tail(&adev->mixer_list, &mixer_card->adev_list_node);
491 }
492 }
493
494 return 0;
495
496error:
497 free_mixer_list(adev);
Andreas Schneider56204f62017-01-31 08:17:32 +0100498 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100499}
500
501static const char *get_snd_device_name(snd_device_t snd_device)
502{
503 const char *name = NULL;
504
Andreas Schneideradb788d2017-02-13 15:19:36 +0100505 if (snd_device == SND_DEVICE_NONE ||
Andreas Schneiderdde54c02017-02-15 14:10:58 +0100506 (snd_device >= SND_DEVICE_MIN && snd_device < SND_DEVICE_MAX))
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100507 name = device_table[snd_device];
508
509 ALOGE_IF(name == NULL, "%s: invalid snd device %d", __func__, snd_device);
510
511 return name;
512}
513
514static const char *get_snd_device_display_name(snd_device_t snd_device)
515{
516 const char *name = get_snd_device_name(snd_device);
517
518 if (name == NULL)
519 name = "SND DEVICE NOT FOUND";
520
521 return name;
522}
523
524static struct pcm_device_profile *get_pcm_device(usecase_type_t uc_type, audio_devices_t devices)
525{
526 int i;
527
528 devices &= ~AUDIO_DEVICE_BIT_IN;
529 for (i = 0; pcm_devices[i] != NULL; i++) {
530 if ((pcm_devices[i]->type == uc_type) &&
531 (devices & pcm_devices[i]->devices))
532 break;
533 }
534 return pcm_devices[i];
535}
536
537static struct audio_usecase *get_usecase_from_id(struct audio_device *adev,
538 audio_usecase_t uc_id)
539{
540 struct audio_usecase *usecase;
541 struct listnode *node;
542
543 list_for_each(node, &adev->usecase_list) {
544 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
545 if (usecase->id == uc_id)
546 return usecase;
547 }
548 return NULL;
549}
550
551static struct audio_usecase *get_usecase_from_type(struct audio_device *adev,
552 usecase_type_t type)
553{
554 struct audio_usecase *usecase;
555 struct listnode *node;
556
557 list_for_each(node, &adev->usecase_list) {
558 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
559 if (usecase->type & type)
560 return usecase;
561 }
562 return NULL;
563}
564
565/* always called with adev lock held */
566static int set_voice_volume_l(struct audio_device *adev, float volume)
567{
568 int err = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100569
570 if (adev->mode == AUDIO_MODE_IN_CALL) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100571 set_voice_session_volume(adev->voice.session, volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100572 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +0100573
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100574 return err;
575}
576
577
578static snd_device_t get_output_snd_device(struct audio_device *adev, audio_devices_t devices)
579{
580
581 audio_mode_t mode = adev->mode;
582 snd_device_t snd_device = SND_DEVICE_NONE;
583
584 ALOGV("%s: enter: output devices(%#x), mode(%d)", __func__, devices, mode);
585 if (devices == AUDIO_DEVICE_NONE ||
586 devices & AUDIO_DEVICE_BIT_IN) {
587 ALOGV("%s: Invalid output devices (%#x)", __func__, devices);
588 goto exit;
589 }
590
591 if (mode == AUDIO_MODE_IN_CALL) {
592 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
593 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Andreas Schneidera2b77322017-01-30 22:33:56 +0100594 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES;
Fevax51bd12c2017-03-15 10:56:39 -0300595 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100596 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100597 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
598 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER;
599 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Andreas Schneider59486fa2017-02-06 09:16:39 +0100600 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100601 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100602
603 if (voice_session_uses_wideband(adev->voice.session)) {
604 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
605 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
606 snd_device = SND_DEVICE_OUT_VOICE_HEADPHONES_WB;
Fevax51bd12c2017-03-15 10:56:39 -0300607 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100608 snd_device = SND_DEVICE_OUT_VOICE_BT_SCO_WB;
Andreas Schneider59486fa2017-02-06 09:16:39 +0100609 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
610 snd_device = SND_DEVICE_OUT_VOICE_SPEAKER_WB;
611 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
612 snd_device = SND_DEVICE_OUT_VOICE_EARPIECE_WB;
613 }
614 }
615
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100616 if (snd_device != SND_DEVICE_NONE) {
617 goto exit;
618 }
619 }
620
621 if (popcount(devices) == 2) {
622 if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
623 AUDIO_DEVICE_OUT_SPEAKER)) {
624 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
625 } else if (devices == (AUDIO_DEVICE_OUT_WIRED_HEADSET |
626 AUDIO_DEVICE_OUT_SPEAKER)) {
627 snd_device = SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES;
628 } else {
629 ALOGE("%s: Invalid combo device(%#x)", __func__, devices);
630 goto exit;
631 }
632 if (snd_device != SND_DEVICE_NONE) {
633 goto exit;
634 }
635 }
636
637 if (popcount(devices) != 1) {
638 ALOGE("%s: Invalid output devices(%#x)", __func__, devices);
639 goto exit;
640 }
641
642 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE ||
643 devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
644 snd_device = SND_DEVICE_OUT_HEADPHONES;
645 } else if (devices & AUDIO_DEVICE_OUT_SPEAKER) {
646 snd_device = SND_DEVICE_OUT_SPEAKER;
647 } else if (devices & AUDIO_DEVICE_OUT_ALL_SCO) {
648 snd_device = SND_DEVICE_OUT_BT_SCO;
649 } else if (devices & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100650 snd_device = SND_DEVICE_OUT_EARPIECE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100651 } else {
652 ALOGE("%s: Unknown device(s) %#x", __func__, devices);
653 }
654exit:
655 ALOGV("%s: exit: snd_device(%s)", __func__, device_table[snd_device]);
656 return snd_device;
657}
658
659static snd_device_t get_input_snd_device(struct audio_device *adev, audio_devices_t out_device)
660{
661 audio_source_t source;
662 audio_mode_t mode = adev->mode;
663 audio_devices_t in_device;
664 audio_channel_mask_t channel_mask;
665 snd_device_t snd_device = SND_DEVICE_NONE;
666 struct stream_in *active_input = NULL;
667 struct audio_usecase *usecase;
668
669 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
670 if (usecase != NULL) {
671 active_input = (struct stream_in *)usecase->stream;
672 }
673 source = (active_input == NULL) ?
674 AUDIO_SOURCE_DEFAULT : active_input->source;
675
Andreas Schneider757e2d82017-02-10 19:28:35 +0100676 in_device = (active_input == NULL) ?
677 AUDIO_DEVICE_NONE :
678 (active_input->devices & ~AUDIO_DEVICE_BIT_IN);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100679 channel_mask = (active_input == NULL) ?
680 AUDIO_CHANNEL_IN_MONO : active_input->main_channels;
681
682 ALOGV("%s: enter: out_device(%#x) in_device(%#x)",
683 __func__, out_device, in_device);
684 if (mode == AUDIO_MODE_IN_CALL) {
685 if (out_device == AUDIO_DEVICE_NONE) {
686 ALOGE("%s: No output device set for voice call", __func__);
687 goto exit;
688 }
Andreas Schneidera2b77322017-01-30 22:33:56 +0100689
Andreas Schneider82f32482017-02-06 09:00:48 +0100690 snd_device = SND_DEVICE_IN_VOICE_MIC;
691 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100692 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
Andreas Schneider82f32482017-02-06 09:00:48 +0100693 }
694
695 if (voice_session_uses_twomic(adev->voice.session)) {
696 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
697 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
698 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC;
699 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
700 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
701 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100702 }
Andreas Schneider59486fa2017-02-06 09:16:39 +0100703
704 if (voice_session_uses_wideband(adev->voice.session)) {
705 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
706 snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC_WB;
707 }
708
709 if (voice_session_uses_twomic(adev->voice.session)) {
710 if (out_device & AUDIO_DEVICE_OUT_EARPIECE ||
711 out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
712 snd_device = SND_DEVICE_IN_VOICE_EARPIECE_MIC_WB;
713 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
714 snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC_WB;
715 }
716 }
717 }
Andreas Schneider05bc1882017-02-09 14:03:11 +0100718
719 /* BT SCO */
720 if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
Andreas Schneider05bc1882017-02-09 14:03:11 +0100721
stenkinevgeniy097e2942018-05-22 18:06:48 +0000722 if (voice_session_uses_wideband(adev->voice.session)) {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100723 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC_WB;
stenkinevgeniy097e2942018-05-22 18:06:48 +0000724 } else {
Christopher N. Hesse56caa262017-03-20 19:40:53 +0100725 snd_device = SND_DEVICE_IN_VOICE_BT_SCO_MIC;
Andreas Schneider05bc1882017-02-09 14:03:11 +0100726 }
727 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100728 } else if (source == AUDIO_SOURCE_CAMCORDER) {
729 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC ||
730 in_device & AUDIO_DEVICE_IN_BACK_MIC) {
731 snd_device = SND_DEVICE_IN_CAMCORDER_MIC;
732 }
733 } else if (source == AUDIO_SOURCE_VOICE_RECOGNITION) {
734 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100735 if (snd_device == SND_DEVICE_NONE) {
736 snd_device = SND_DEVICE_IN_VOICE_REC_MIC;
737 }
738 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
739 snd_device = SND_DEVICE_IN_VOICE_REC_HEADSET_MIC;
740 }
741 } else if (source == AUDIO_SOURCE_VOICE_COMMUNICATION || source == AUDIO_SOURCE_MIC) {
742 if (out_device & AUDIO_DEVICE_OUT_SPEAKER)
743 in_device = AUDIO_DEVICE_IN_BACK_MIC;
744 if (active_input) {
745 if (active_input->enable_aec) {
746 if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
747 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
748 } else if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
749 if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
750 snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
751 } else {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100752 snd_device = SND_DEVICE_IN_EARPIECE_MIC_AEC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100753 }
754 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
755 snd_device = SND_DEVICE_IN_HEADSET_MIC_AEC;
756 }
757 }
758 /* TODO: set echo reference */
759 }
760 } else if (source == AUDIO_SOURCE_DEFAULT) {
761 goto exit;
762 }
763
764
765 if (snd_device != SND_DEVICE_NONE) {
766 goto exit;
767 }
768
769 if (in_device != AUDIO_DEVICE_NONE &&
770 !(in_device & AUDIO_DEVICE_IN_VOICE_CALL) &&
771 !(in_device & AUDIO_DEVICE_IN_COMMUNICATION)) {
772 if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100773 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100774 } else if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
775 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
776 } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
777 snd_device = SND_DEVICE_IN_HEADSET_MIC;
778 } else if (in_device & AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
779 snd_device = SND_DEVICE_IN_BT_SCO_MIC ;
780 } else if (in_device & AUDIO_DEVICE_IN_AUX_DIGITAL) {
781 snd_device = SND_DEVICE_IN_HDMI_MIC;
782 } else {
783 ALOGE("%s: Unknown input device(s) %#x", __func__, in_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100784 ALOGW("%s: Using default earpiece-mic", __func__);
785 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100786 }
787 } else {
788 if (out_device & AUDIO_DEVICE_OUT_EARPIECE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100789 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100790 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
791 snd_device = SND_DEVICE_IN_HEADSET_MIC;
792 } else if (out_device & AUDIO_DEVICE_OUT_SPEAKER) {
793 snd_device = SND_DEVICE_IN_SPEAKER_MIC;
794 } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) {
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100795 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100796 } else if (out_device & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET) {
797 snd_device = SND_DEVICE_IN_BT_SCO_MIC;
798 } else {
799 ALOGE("%s: Unknown output device(s) %#x", __func__, out_device);
Christopher N. Hesse530cf0d2017-01-31 21:59:54 +0100800 ALOGW("%s: Using default earpiece-mic", __func__);
801 snd_device = SND_DEVICE_IN_EARPIECE_MIC;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100802 }
803 }
804exit:
805 ALOGV("%s: exit: in_snd_device(%s)", __func__, device_table[snd_device]);
806 return snd_device;
807}
808
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100809#if 0
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100810static int set_hdmi_channels(struct audio_device *adev, int channel_count)
811{
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100812 (void)adev;
813 (void)channel_count;
814 /* TODO */
815
816 return 0;
817}
818
819static int edid_get_max_channels(struct audio_device *adev)
820{
821 int max_channels = 2;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100822 (void)adev;
823
824 /* TODO */
825 return max_channels;
826}
Andreas Schneider5a2f1002017-02-09 10:59:04 +0100827#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100828
829/* Delay in Us */
830static int64_t render_latency(audio_usecase_t usecase)
831{
832 (void)usecase;
833 /* TODO */
834 return 0;
835}
836
837static int enable_snd_device(struct audio_device *adev,
838 struct audio_usecase *uc_info,
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100839 snd_device_t snd_device)
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100840{
841 struct mixer_card *mixer_card;
842 struct listnode *node;
843 const char *snd_device_name = get_snd_device_name(snd_device);
Andreas Schneider759368f2017-02-02 16:11:14 +0100844#ifdef DSP_POWEROFF_DELAY
845 struct timespec activation_time;
846 struct timespec elapsed_time;
847#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100848
849 if (snd_device_name == NULL)
850 return -EINVAL;
851
852 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
853 ALOGV("Request to enable combo device: enable individual devices\n");
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100854 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER);
855 enable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100856 return 0;
857 }
858 adev->snd_dev_ref_cnt[snd_device]++;
859 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
860 ALOGV("%s: snd_device(%d: %s) is already active",
861 __func__, snd_device, snd_device_name);
862 return 0;
863 }
864
865 ALOGV("%s: snd_device(%d: %s)", __func__,
866 snd_device, snd_device_name);
867
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
871#ifdef DSP_POWEROFF_DELAY
872 clock_gettime(CLOCK_MONOTONIC, &activation_time);
873
Andreas Schneider58735a92017-02-13 16:48:17 +0100874 elapsed_time = time_spec_diff(activation_time,
875 mixer_card->dsp_poweroff_time);
Andreas Schneider759368f2017-02-02 16:11:14 +0100876 if (elapsed_time.tv_sec == 0) {
877 long elapsed_usec = elapsed_time.tv_nsec / 1000;
878
879 if (elapsed_usec < DSP_POWEROFF_DELAY) {
880 usleep(DSP_POWEROFF_DELAY - elapsed_usec);
881 }
882 }
Andreas Schneider759368f2017-02-02 16:11:14 +0100883#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200884
885 amplifier_enable_devices(snd_device, true);
886
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100887 audio_route_apply_and_update_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100888 }
889
890 return 0;
891}
892
Christopher N. Hesse757ac412017-01-28 14:42:48 +0100893int disable_snd_device(struct audio_device *adev,
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100894 struct audio_usecase *uc_info,
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100895 snd_device_t snd_device)
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100896{
897 struct mixer_card *mixer_card;
898 struct listnode *node;
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100899 struct audio_usecase *out_uc_info = get_usecase_from_type(adev, PCM_PLAYBACK);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100900 const char *snd_device_name = get_snd_device_name(snd_device);
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100901 const char *out_snd_device_name = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100902
903 if (snd_device_name == NULL)
904 return -EINVAL;
905
906 if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HEADPHONES) {
907 ALOGV("Request to disable combo device: disable individual devices\n");
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100908 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_SPEAKER);
909 disable_snd_device(adev, uc_info, SND_DEVICE_OUT_HEADPHONES);
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100910 return 0;
911 }
912
913 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
914 ALOGE("%s: device ref cnt is already 0", __func__);
915 return -EINVAL;
916 }
917 adev->snd_dev_ref_cnt[snd_device]--;
918 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
919 ALOGV("%s: snd_device(%d: %s)", __func__,
920 snd_device, snd_device_name);
921 list_for_each(node, &uc_info->mixer_list) {
922 mixer_card = node_to_item(node, struct mixer_card, uc_list_node[uc_info->id]);
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100923 audio_route_reset_and_update_path(mixer_card->audio_route, snd_device_name);
Christopher N. Hesse719630a2018-02-12 01:47:48 +0100924 if (snd_device > SND_DEVICE_IN_BEGIN && out_uc_info != NULL) {
Christopher N. Hesse11ef2112018-02-02 23:19:42 +0100925 /*
926 * Cycle the rx device to eliminate routing conflicts.
927 * This prevents issues when an input route shares mixer controls with an output
928 * route.
929 */
930 out_snd_device_name = get_snd_device_name(out_uc_info->out_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +0100931 audio_route_apply_and_update_path(mixer_card->audio_route, out_snd_device_name);
Andreas Schneider759368f2017-02-02 16:11:14 +0100932 }
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +0200933
934 amplifier_enable_devices(snd_device, false);
Andreas Schneider759368f2017-02-02 16:11:14 +0100935#ifdef DSP_POWEROFF_DELAY
936 clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
937#endif /* DSP_POWEROFF_DELAY */
Christopher N. Hesse297a6362017-01-28 12:40:45 +0100938 }
939 }
940 return 0;
941}
942
stenkinevgeniyb81e05f2018-05-08 12:02:35 +0000943static void check_and_route_usecases(struct audio_device *adev,
944 struct audio_usecase *uc_info,
945 usecase_type_t type,
946 snd_device_t snd_device)
947{
948 struct listnode *node;
949 struct audio_usecase *usecase;
950 bool switch_device[AUDIO_USECASE_MAX], need_switch = false;
951 snd_device_t usecase_snd_device = SND_DEVICE_NONE;
952 int i;
953
954 /*
955 * This function is to make sure that all the usecases that are active on
956 * the hardware codec backend are always routed to any one device that is
957 * handled by the hardware codec.
958 * For example, if low-latency and deep-buffer usecases are currently active
959 * on speaker and out_set_parameters(headset) is received on low-latency
960 * output, then we have to make sure deep-buffer is also switched to headset or
961 * if audio-record and voice-call usecases are currently
962 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
963 * is received for voice call then we have to make sure that audio-record
964 * usecase is also switched to earpiece i.e.
965 * because of the limitation that both the devices cannot be enabled
966 * at the same time as they share the same backend.
967 */
968 /* Disable all the usecases on the shared backend other than the
969 specified usecase */
970 for (i = 0; i < AUDIO_USECASE_MAX; i++)
971 switch_device[i] = false;
972
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
975 if (usecase->type != type || usecase == uc_info)
976 continue;
977 usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device :
978 usecase->in_snd_device;
979 if (usecase_snd_device != snd_device) {
980 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
981 __func__, use_case_table[usecase->id],
982 get_snd_device_name(usecase_snd_device));
983 switch_device[usecase->id] = true;
984 need_switch = true;
985 }
986 }
987 if (need_switch) {
988 list_for_each(node, &adev->usecase_list) {
989 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
990 usecase_snd_device = (type == PCM_PLAYBACK) ? usecase->out_snd_device :
991 usecase->in_snd_device;
992 if (switch_device[usecase->id]) {
993 disable_snd_device(adev, usecase, usecase_snd_device);
994 enable_snd_device(adev, usecase, snd_device);
995 if (type == PCM_PLAYBACK)
996 usecase->out_snd_device = snd_device;
997 else
998 usecase->in_snd_device = snd_device;
999 }
1000 }
1001 }
1002}
1003
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001004static int select_devices(struct audio_device *adev,
1005 audio_usecase_t uc_id)
1006{
1007 snd_device_t out_snd_device = SND_DEVICE_NONE;
1008 snd_device_t in_snd_device = SND_DEVICE_NONE;
1009 struct audio_usecase *usecase = NULL;
1010 struct audio_usecase *vc_usecase = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001011 struct stream_in *active_input = NULL;
1012 struct stream_out *active_out;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001013
1014 ALOGV("%s: usecase(%d)", __func__, uc_id);
1015
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001016 usecase = get_usecase_from_type(adev, PCM_CAPTURE|VOICE_CALL);
1017 if (usecase != NULL) {
1018 active_input = (struct stream_in *)usecase->stream;
1019 }
1020
1021 usecase = get_usecase_from_id(adev, uc_id);
1022 if (usecase == NULL) {
1023 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1024 return -EINVAL;
1025 }
1026 active_out = (struct stream_out *)usecase->stream;
1027
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001028
1029 /*
1030 * If the voice call is active, use the sound devices of voice call usecase
1031 * so that it would not result any device switch. All the usecases will
1032 * be switched to new device when select_devices() is called for voice call
1033 * usecase.
1034 */
1035 if (usecase->type != VOICE_CALL && adev->voice.in_call) {
1036 vc_usecase = get_usecase_from_id(adev, USECASE_VOICE_CALL);
1037 if (vc_usecase == NULL) {
1038 ALOGE("%s: Could not find the voice call usecase", __func__);
1039 } else {
stenkinevgeniy5ca267a2018-05-30 15:43:14 +00001040 in_snd_device = vc_usecase->in_snd_device;
1041 out_snd_device = vc_usecase->out_snd_device;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001042 }
1043 }
1044
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001045 if (usecase->type == VOICE_CALL) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001046 usecase->devices = active_out->devices;
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001047 prepare_voice_session(adev->voice.session, active_out->devices);
1048 out_snd_device = get_output_snd_device(adev, active_out->devices);
1049 in_snd_device = get_input_snd_device(adev, active_out->devices);
1050 } else if (usecase->type == PCM_PLAYBACK) {
1051 usecase->devices = active_out->devices;
1052 in_snd_device = SND_DEVICE_NONE;
1053 if (out_snd_device == SND_DEVICE_NONE) {
1054 out_snd_device = get_output_snd_device(adev, active_out->devices);
1055 if (active_out == adev->primary_output &&
1056 active_input &&
1057 active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1058 select_devices(adev, active_input->usecase);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001059 }
1060 }
Christopher N. Hesse130da9f2017-02-15 12:18:41 +01001061 } else if (usecase->type == PCM_CAPTURE) {
1062 usecase->devices = ((struct stream_in *)usecase->stream)->devices;
1063 out_snd_device = SND_DEVICE_NONE;
1064 if (in_snd_device == SND_DEVICE_NONE) {
1065 if (active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
1066 adev->primary_output && !adev->primary_output->standby) {
1067 in_snd_device = get_input_snd_device(adev, adev->primary_output->devices);
1068 } else {
1069 in_snd_device = get_input_snd_device(adev, AUDIO_DEVICE_NONE);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001070 }
1071 }
1072 }
1073
1074 if (out_snd_device == usecase->out_snd_device &&
1075 in_snd_device == usecase->in_snd_device) {
1076 return 0;
1077 }
1078
1079 ALOGV("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
1080 out_snd_device, get_snd_device_display_name(out_snd_device),
1081 in_snd_device, get_snd_device_display_name(in_snd_device));
1082
1083
1084 /* Disable current sound devices */
1085 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001086 disable_snd_device(adev, usecase, usecase->out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001087 }
1088
1089 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001090 disable_snd_device(adev, usecase, usecase->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001091 }
1092
1093 /* Enable new sound devices */
1094 if (out_snd_device != SND_DEVICE_NONE) {
Christopher N. Hesse696959d2017-02-02 20:49:55 +01001095 /* We need to update the audio path if we switch the out devices */
1096 if (adev->voice.in_call) {
1097 set_voice_session_audio_path(adev->voice.session);
1098 }
1099
stenkinevgeniyb81e05f2018-05-08 12:02:35 +00001100 check_and_route_usecases(adev, usecase, PCM_PLAYBACK, out_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001101 enable_snd_device(adev, usecase, out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001102 }
1103
1104 if (in_snd_device != SND_DEVICE_NONE) {
stenkinevgeniyb81e05f2018-05-08 12:02:35 +00001105 check_and_route_usecases(adev, usecase, PCM_CAPTURE, in_snd_device);
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001106 enable_snd_device(adev, usecase, in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001107 }
1108
1109 usecase->in_snd_device = in_snd_device;
1110 usecase->out_snd_device = out_snd_device;
1111
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02001112 /* Rely on amplifier_set_devices to distinguish between in/out devices */
1113 amplifier_set_input_devices(in_snd_device);
1114 amplifier_set_output_devices(out_snd_device);
1115
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001116 return 0;
1117}
1118
1119
1120static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames);
1121static int do_in_standby_l(struct stream_in *in);
1122
1123#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001124static void get_capture_delay(struct stream_in *in,
1125 size_t frames __unused,
1126 struct echo_reference_buffer *buffer)
1127{
1128 ALOGVV("%s: enter:)", __func__);
1129 /* read frames available in kernel driver buffer */
1130 unsigned int kernel_frames;
1131 struct timespec tstamp;
1132 long buf_delay;
1133 long rsmp_delay;
1134 long kernel_delay;
1135 long delay_ns;
1136 struct pcm_device *pcm_device;
1137
1138 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1139 struct pcm_device, stream_list_node);
1140
1141 if (pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &tstamp) < 0) {
1142 buffer->time_stamp.tv_sec = 0;
1143 buffer->time_stamp.tv_nsec = 0;
1144 buffer->delay_ns = 0;
1145 ALOGW("read get_capture_delay(): pcm_htimestamp error");
1146 return;
1147 }
1148
1149 /* read frames available in audio HAL input buffer
1150 * add number of frames being read as we want the capture time of first sample
1151 * in current buffer */
1152 /* frames in in->read_buf are at driver sampling rate while frames in in->proc_buf are
1153 * at requested sampling rate */
1154 buf_delay = (long)(((int64_t)(in->read_buf_frames) * 1000000000) / in->config.rate +
1155 ((int64_t)(in->proc_buf_frames) * 1000000000) / in->requested_rate );
1156
1157 /* add delay introduced by resampler */
1158 rsmp_delay = 0;
1159 if (in->resampler) {
1160 rsmp_delay = in->resampler->delay_ns(in->resampler);
1161 }
1162
1163 kernel_delay = (long)(((int64_t)kernel_frames * 1000000000) / in->config.rate);
1164
1165 delay_ns = kernel_delay + buf_delay + rsmp_delay;
1166
1167 buffer->time_stamp = tstamp;
1168 buffer->delay_ns = delay_ns;
1169 ALOGVV("get_capture_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames:[%5d],"
1170 " delay_ns: [%d], kernel_delay:[%ld], buf_delay:[%ld], rsmp_delay:[%ld], "
1171 "in->read_buf_frames:[%zd], in->proc_buf_frames:[%zd], frames:[%zd]",
1172 buffer->time_stamp.tv_sec , buffer->time_stamp.tv_nsec, kernel_frames,
1173 buffer->delay_ns, kernel_delay, buf_delay, rsmp_delay,
1174 in->read_buf_frames, in->proc_buf_frames, frames);
1175}
1176
1177static int32_t update_echo_reference(struct stream_in *in, size_t frames)
1178{
1179 ALOGVV("%s: enter:), in->config.channels(%d)", __func__,in->config.channels);
1180 struct echo_reference_buffer b;
1181 b.delay_ns = 0;
1182 struct pcm_device *pcm_device;
1183
1184 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1185 struct pcm_device, stream_list_node);
1186
1187 ALOGVV("update_echo_reference, in->config.channels(%d), frames = [%zd], in->ref_buf_frames = [%zd], "
1188 "b.frame_count = [%zd]",
1189 in->config.channels, frames, in->ref_buf_frames, frames - in->ref_buf_frames);
1190 if (in->ref_buf_frames < frames) {
1191 if (in->ref_buf_size < frames) {
1192 in->ref_buf_size = frames;
1193 in->ref_buf = (int16_t *)realloc(in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1194 ALOG_ASSERT((in->ref_buf != NULL),
1195 "update_echo_reference() failed to reallocate ref_buf");
1196 ALOGVV("update_echo_reference(): ref_buf %p extended to %d bytes",
1197 in->ref_buf, pcm_frames_to_bytes(pcm_device->pcm, frames));
1198 }
1199 b.frame_count = frames - in->ref_buf_frames;
1200 b.raw = (void *)(in->ref_buf + in->ref_buf_frames * in->config.channels);
1201
1202 get_capture_delay(in, frames, &b);
1203
1204 if (in->echo_reference->read(in->echo_reference, &b) == 0)
1205 {
1206 in->ref_buf_frames += b.frame_count;
1207 ALOGVV("update_echo_reference(): in->ref_buf_frames:[%zd], "
1208 "in->ref_buf_size:[%zd], frames:[%zd], b.frame_count:[%zd]",
1209 in->ref_buf_frames, in->ref_buf_size, frames, b.frame_count);
1210 }
1211 } else
1212 ALOGW("update_echo_reference(): NOT enough frames to read ref buffer");
1213 return b.delay_ns;
1214}
1215
1216static int set_preprocessor_param(effect_handle_t handle,
1217 effect_param_t *param)
1218{
1219 uint32_t size = sizeof(int);
Basil Gelloefdfdba2018-05-21 18:29:12 +03001220 uint32_t bufsize = sizeof(effect_param_t) +
1221 ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
1222 param->vsize;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001223
1224 int status = (*handle)->command(handle,
1225 EFFECT_CMD_SET_PARAM,
Basil Gelloefdfdba2018-05-21 18:29:12 +03001226 bufsize,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001227 param,
1228 &size,
1229 &param->status);
1230 if (status == 0)
1231 status = param->status;
1232
1233 return status;
1234}
1235
1236static int set_preprocessor_echo_delay(effect_handle_t handle,
1237 int32_t delay_us)
1238{
Basil Gelloefdfdba2018-05-21 18:29:12 +03001239 const uint32_t param_size = sizeof(uint32_t);
1240 const uint32_t value_size = sizeof(uint32_t);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001241
Basil Gelloefdfdba2018-05-21 18:29:12 +03001242 const uint32_t param_padded_size =
1243 ((param_size - 1) / sizeof(int) + 1) * sizeof(int);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001244
Basil Gelloefdfdba2018-05-21 18:29:12 +03001245 const uint32_t bufsize = sizeof(effect_param_t) +
1246 param_padded_size + value_size;
1247
1248 uint8_t buf[bufsize];
1249 memset(&buf, 0, bufsize);
1250
1251 effect_param_t *effect_param = (effect_param_t *)&buf;
1252
1253 effect_param->psize = param_size;
1254 effect_param->vsize = value_size;
1255
1256 *(uint32_t *)&buf[sizeof(effect_param_t)] = AEC_PARAM_ECHO_DELAY;
1257 *(int32_t *)&buf[sizeof(effect_param_t) + param_padded_size] = delay_us;
1258
1259 return set_preprocessor_param(handle, effect_param);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001260}
1261
1262static void push_echo_reference(struct stream_in *in, size_t frames)
1263{
1264 ALOGVV("%s: enter:)", __func__);
1265 /* read frames from echo reference buffer and update echo delay
1266 * in->ref_buf_frames is updated with frames available in in->ref_buf */
1267
1268 int32_t delay_us = update_echo_reference(in, frames)/1000;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001269 int i;
1270 audio_buffer_t buf;
1271
1272 if (in->ref_buf_frames < frames)
1273 frames = in->ref_buf_frames;
1274
1275 buf.frameCount = frames;
1276 buf.raw = in->ref_buf;
1277
1278 for (i = 0; i < in->num_preprocessors; i++) {
1279 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1280 continue;
1281 ALOGVV("%s: effect_itfe)->process_reverse() BEGIN i=(%d) ", __func__, i);
1282 (*in->preprocessors[i].effect_itfe)->process_reverse(in->preprocessors[i].effect_itfe,
1283 &buf,
1284 NULL);
1285 ALOGVV("%s: effect_itfe)->process_reverse() END i=(%d) ", __func__, i);
1286 set_preprocessor_echo_delay(in->preprocessors[i].effect_itfe, delay_us);
1287 }
1288
1289 in->ref_buf_frames -= buf.frameCount;
1290 ALOGVV("%s: in->ref_buf_frames(%zd), in->config.channels(%d) ",
1291 __func__, in->ref_buf_frames, in->config.channels);
1292 if (in->ref_buf_frames) {
1293 memcpy(in->ref_buf,
1294 in->ref_buf + buf.frameCount * in->config.channels,
1295 in->ref_buf_frames * in->config.channels * sizeof(int16_t));
1296 }
1297}
1298
1299static void put_echo_reference(struct audio_device *adev,
1300 struct echo_reference_itfe *reference)
1301{
1302 ALOGV("%s: enter:)", __func__);
1303 int32_t prev_generation = adev->echo_reference_generation;
1304 struct stream_out *out = adev->primary_output;
1305
1306 if (adev->echo_reference != NULL &&
1307 reference == adev->echo_reference) {
1308 /* echo reference is taken from the low latency output stream used
1309 * for voice use cases */
1310 adev->echo_reference = NULL;
1311 android_atomic_inc(&adev->echo_reference_generation);
1312 if (out != NULL && out->usecase == USECASE_AUDIO_PLAYBACK) {
1313 // if the primary output is in standby or did not pick the echo reference yet
1314 // we can safely get rid of it here.
1315 // otherwise, out_write() or out_standby() will detect the change in echo reference
1316 // generation and release the echo reference owned by the stream.
1317 if ((out->echo_reference_generation != prev_generation) || out->standby)
1318 release_echo_reference(reference);
1319 } else {
1320 release_echo_reference(reference);
1321 }
1322 ALOGV("release_echo_reference");
1323 }
1324}
1325
1326static struct echo_reference_itfe *get_echo_reference(struct audio_device *adev,
1327 audio_format_t format __unused,
1328 uint32_t channel_count,
1329 uint32_t sampling_rate)
1330{
1331 ALOGV("%s: enter:)", __func__);
1332 put_echo_reference(adev, adev->echo_reference);
1333 /* echo reference is taken from the low latency output stream used
1334 * for voice use cases */
1335 if (adev->primary_output!= NULL && adev->primary_output->usecase == USECASE_AUDIO_PLAYBACK &&
1336 !adev->primary_output->standby) {
1337 struct audio_stream *stream =
1338 &adev->primary_output->stream.common;
1339 uint32_t wr_channel_count = audio_channel_count_from_out_mask(stream->get_channels(stream));
1340 uint32_t wr_sampling_rate = stream->get_sample_rate(stream);
1341 ALOGV("Calling create_echo_reference");
1342 int status = create_echo_reference(AUDIO_FORMAT_PCM_16_BIT,
1343 channel_count,
1344 sampling_rate,
1345 AUDIO_FORMAT_PCM_16_BIT,
1346 wr_channel_count,
1347 wr_sampling_rate,
1348 &adev->echo_reference);
1349 if (status == 0)
1350 android_atomic_inc(&adev->echo_reference_generation);
1351 }
1352 return adev->echo_reference;
1353}
1354
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001355static int get_playback_delay(struct stream_out *out,
1356 size_t frames,
1357 struct echo_reference_buffer *buffer)
1358{
1359 unsigned int kernel_frames;
1360 int status;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001361 struct pcm_device *pcm_device;
1362
1363 pcm_device = node_to_item(list_head(&out->pcm_dev_list),
1364 struct pcm_device, stream_list_node);
1365
1366 status = pcm_get_htimestamp(pcm_device->pcm, &kernel_frames, &buffer->time_stamp);
1367 if (status < 0) {
1368 buffer->time_stamp.tv_sec = 0;
1369 buffer->time_stamp.tv_nsec = 0;
1370 buffer->delay_ns = 0;
1371 ALOGV("get_playback_delay(): pcm_get_htimestamp error,"
1372 "setting playbackTimestamp to 0");
1373 return status;
1374 }
1375
1376 kernel_frames = pcm_get_buffer_size(pcm_device->pcm) - kernel_frames;
1377
1378 /* adjust render time stamp with delay added by current driver buffer.
1379 * Add the duration of current frame as we want the render time of the last
1380 * sample being written. */
1381 buffer->delay_ns = (long)(((int64_t)(kernel_frames + frames)* 1000000000)/
1382 out->config.rate);
1383 ALOGVV("get_playback_delay_time_stamp Secs: [%10ld], nSecs: [%9ld], kernel_frames: [%5u], delay_ns: [%d],",
1384 buffer->time_stamp.tv_sec, buffer->time_stamp.tv_nsec, kernel_frames, buffer->delay_ns);
1385
1386 return 0;
1387}
1388
1389#define GET_COMMAND_STATUS(status, fct_status, cmd_status) \
1390 do { \
1391 if (fct_status != 0) \
1392 status = fct_status; \
1393 else if (cmd_status != 0) \
1394 status = cmd_status; \
1395 } while(0)
1396
1397static int in_configure_reverse(struct stream_in *in)
1398{
1399 int32_t cmd_status;
1400 uint32_t size = sizeof(int);
1401 effect_config_t config;
1402 int32_t status = 0;
1403 int32_t fct_status = 0;
1404 int i;
1405 ALOGV("%s: enter: in->num_preprocessors(%d)", __func__, in->num_preprocessors);
1406 if (in->num_preprocessors > 0) {
1407 config.inputCfg.channels = in->main_channels;
1408 config.outputCfg.channels = in->main_channels;
1409 config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1410 config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
1411 config.inputCfg.samplingRate = in->requested_rate;
1412 config.outputCfg.samplingRate = in->requested_rate;
1413 config.inputCfg.mask =
1414 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1415 config.outputCfg.mask =
1416 ( EFFECT_CONFIG_SMP_RATE | EFFECT_CONFIG_CHANNELS | EFFECT_CONFIG_FORMAT );
1417
1418 for (i = 0; i < in->num_preprocessors; i++)
1419 {
1420 if ((*in->preprocessors[i].effect_itfe)->process_reverse == NULL)
1421 continue;
1422 fct_status = (*(in->preprocessors[i].effect_itfe))->command(
1423 in->preprocessors[i].effect_itfe,
1424 EFFECT_CMD_SET_CONFIG_REVERSE,
1425 sizeof(effect_config_t),
1426 &config,
1427 &size,
1428 &cmd_status);
1429 ALOGV("%s: calling EFFECT_CMD_SET_CONFIG_REVERSE",__func__);
1430 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1431 }
1432 }
1433 return status;
1434}
1435
1436#define MAX_NUM_CHANNEL_CONFIGS 10
1437
1438static void in_read_audio_effect_channel_configs(struct stream_in *in __unused,
1439 struct effect_info_s *effect_info)
1440{
1441 /* size and format of the cmd are defined in hardware/audio_effect.h */
1442 effect_handle_t effect = effect_info->effect_itfe;
1443 uint32_t cmd_size = 2 * sizeof(uint32_t);
1444 uint32_t cmd[] = { EFFECT_FEATURE_AUX_CHANNELS, MAX_NUM_CHANNEL_CONFIGS };
1445 /* reply = status + number of configs (n) + n x channel_config_t */
1446 uint32_t reply_size =
1447 2 * sizeof(uint32_t) + (MAX_NUM_CHANNEL_CONFIGS * sizeof(channel_config_t));
1448 int32_t reply[reply_size];
1449 int32_t cmd_status;
1450
1451 ALOG_ASSERT((effect_info->num_channel_configs == 0),
1452 "in_read_audio_effect_channel_configs() num_channel_configs not cleared");
1453 ALOG_ASSERT((effect_info->channel_configs == NULL),
1454 "in_read_audio_effect_channel_configs() channel_configs not cleared");
1455
1456 /* if this command is not supported, then the effect is supposed to return -EINVAL.
1457 * This error will be interpreted as if the effect supports the main_channels but does not
1458 * support any aux_channels */
1459 cmd_status = (*effect)->command(effect,
1460 EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS,
1461 cmd_size,
1462 (void*)&cmd,
1463 &reply_size,
1464 (void*)&reply);
1465
1466 if (cmd_status != 0) {
1467 ALOGV("in_read_audio_effect_channel_configs(): "
1468 "fx->command returned %d", cmd_status);
1469 return;
1470 }
1471
1472 if (reply[0] != 0) {
1473 ALOGW("in_read_audio_effect_channel_configs(): "
1474 "command EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS error %d num configs %d",
1475 reply[0], (reply[0] == -ENOMEM) ? reply[1] : MAX_NUM_CHANNEL_CONFIGS);
1476 return;
1477 }
1478
1479 /* the feature is not supported */
1480 ALOGV("in_read_audio_effect_channel_configs()(): "
1481 "Feature supported and adding %d channel configs to the list", reply[1]);
1482 effect_info->num_channel_configs = reply[1];
1483 effect_info->channel_configs =
1484 (channel_config_t *) malloc(sizeof(channel_config_t) * reply[1]); /* n x configs */
1485 memcpy(effect_info->channel_configs, (reply + 2), sizeof(channel_config_t) * reply[1]);
1486}
1487
1488
1489#define NUM_IN_AUX_CNL_CONFIGS 2
1490static const channel_config_t in_aux_cnl_configs[NUM_IN_AUX_CNL_CONFIGS] = {
1491 { AUDIO_CHANNEL_IN_FRONT , AUDIO_CHANNEL_IN_BACK},
1492 { AUDIO_CHANNEL_IN_STEREO , AUDIO_CHANNEL_IN_RIGHT}
1493};
1494static uint32_t in_get_aux_channels(struct stream_in *in)
1495{
1496 int i;
1497 channel_config_t new_chcfg = {0, 0};
1498
1499 if (in->num_preprocessors == 0)
1500 return 0;
1501
1502 /* do not enable dual mic configurations when capturing from other microphones than
1503 * main or sub */
1504 if (!(in->devices & (AUDIO_DEVICE_IN_BUILTIN_MIC | AUDIO_DEVICE_IN_BACK_MIC)))
1505 return 0;
1506
1507 /* retain most complex aux channels configuration compatible with requested main channels and
1508 * supported by audio driver and all pre processors */
1509 for (i = 0; i < NUM_IN_AUX_CNL_CONFIGS; i++) {
1510 const channel_config_t *cur_chcfg = &in_aux_cnl_configs[i];
1511 if (cur_chcfg->main_channels == in->main_channels) {
1512 size_t match_cnt;
1513 size_t idx_preproc;
1514 for (idx_preproc = 0, match_cnt = 0;
1515 /* no need to continue if at least one preprocessor doesn't match */
1516 idx_preproc < (size_t)in->num_preprocessors && match_cnt == idx_preproc;
1517 idx_preproc++) {
1518 struct effect_info_s *effect_info = &in->preprocessors[idx_preproc];
1519 size_t idx_chcfg;
1520
1521 for (idx_chcfg = 0; idx_chcfg < effect_info->num_channel_configs; idx_chcfg++) {
1522 if (memcmp(effect_info->channel_configs + idx_chcfg,
1523 cur_chcfg,
1524 sizeof(channel_config_t)) == 0) {
1525 match_cnt++;
1526 break;
1527 }
1528 }
1529 }
1530 /* if all preprocessors match, we have a candidate */
1531 if (match_cnt == (size_t)in->num_preprocessors) {
1532 /* retain most complex aux channels configuration */
1533 if (audio_channel_count_from_in_mask(cur_chcfg->aux_channels) > audio_channel_count_from_in_mask(new_chcfg.aux_channels)) {
1534 new_chcfg = *cur_chcfg;
1535 }
1536 }
1537 }
1538 }
1539
1540 ALOGV("in_get_aux_channels(): return %04x", new_chcfg.aux_channels);
1541
1542 return new_chcfg.aux_channels;
1543}
1544
1545static int in_configure_effect_channels(effect_handle_t effect,
1546 channel_config_t *channel_config)
1547{
1548 int status = 0;
1549 int fct_status;
1550 int32_t cmd_status;
1551 uint32_t reply_size;
1552 effect_config_t config;
1553 uint32_t cmd[(sizeof(uint32_t) + sizeof(channel_config_t) - 1) / sizeof(uint32_t) + 1];
1554
1555 ALOGV("in_configure_effect_channels(): configure effect with channels: [%04x][%04x]",
1556 channel_config->main_channels,
1557 channel_config->aux_channels);
1558
1559 config.inputCfg.mask = EFFECT_CONFIG_CHANNELS;
1560 config.outputCfg.mask = EFFECT_CONFIG_CHANNELS;
1561 reply_size = sizeof(effect_config_t);
1562 fct_status = (*effect)->command(effect,
1563 EFFECT_CMD_GET_CONFIG,
1564 0,
1565 NULL,
1566 &reply_size,
1567 &config);
1568 if (fct_status != 0) {
1569 ALOGE("in_configure_effect_channels(): EFFECT_CMD_GET_CONFIG failed");
1570 return fct_status;
1571 }
1572
1573 config.inputCfg.channels = channel_config->main_channels | channel_config->aux_channels;
1574 config.outputCfg.channels = config.inputCfg.channels;
1575 reply_size = sizeof(uint32_t);
1576 fct_status = (*effect)->command(effect,
1577 EFFECT_CMD_SET_CONFIG,
1578 sizeof(effect_config_t),
1579 &config,
1580 &reply_size,
1581 &cmd_status);
1582 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1583
1584 cmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
1585 memcpy(cmd + 1, channel_config, sizeof(channel_config_t));
1586 reply_size = sizeof(uint32_t);
1587 fct_status = (*effect)->command(effect,
1588 EFFECT_CMD_SET_FEATURE_CONFIG,
1589 sizeof(cmd), //sizeof(uint32_t) + sizeof(channel_config_t),
1590 cmd,
1591 &reply_size,
1592 &cmd_status);
1593 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1594
1595 /* some implementations need to be re-enabled after a config change */
1596 reply_size = sizeof(uint32_t);
1597 fct_status = (*effect)->command(effect,
1598 EFFECT_CMD_ENABLE,
1599 0,
1600 NULL,
1601 &reply_size,
1602 &cmd_status);
1603 GET_COMMAND_STATUS(status, fct_status, cmd_status);
1604
1605 return status;
1606}
1607
1608static int in_reconfigure_channels(struct stream_in *in,
1609 effect_handle_t effect,
1610 channel_config_t *channel_config,
1611 bool config_changed) {
1612
1613 int status = 0;
1614
1615 ALOGV("in_reconfigure_channels(): config_changed %d effect %p",
1616 config_changed, effect);
1617
1618 /* if config changed, reconfigure all previously added effects */
1619 if (config_changed) {
1620 int i;
1621 ALOGV("%s: config_changed (%d)", __func__, config_changed);
1622 for (i = 0; i < in->num_preprocessors; i++)
1623 {
1624 int cur_status = in_configure_effect_channels(in->preprocessors[i].effect_itfe,
1625 channel_config);
1626 ALOGV("%s: in_configure_effect_channels i=(%d), [main_channel,aux_channel]=[%d|%d], status=%d",
1627 __func__, i, channel_config->main_channels, channel_config->aux_channels, cur_status);
1628 if (cur_status != 0) {
1629 ALOGV("in_reconfigure_channels(): error %d configuring effect "
1630 "%d with channels: [%04x][%04x]",
1631 cur_status,
1632 i,
1633 channel_config->main_channels,
1634 channel_config->aux_channels);
1635 status = cur_status;
1636 }
1637 }
1638 } else if (effect != NULL && channel_config->aux_channels) {
1639 /* if aux channels config did not change but aux channels are present,
1640 * we still need to configure the effect being added */
1641 status = in_configure_effect_channels(effect, channel_config);
1642 }
1643 return status;
1644}
1645
1646static void in_update_aux_channels(struct stream_in *in,
1647 effect_handle_t effect)
1648{
1649 uint32_t aux_channels;
1650 channel_config_t channel_config;
1651 int status;
1652
1653 aux_channels = in_get_aux_channels(in);
1654
1655 channel_config.main_channels = in->main_channels;
1656 channel_config.aux_channels = aux_channels;
1657 status = in_reconfigure_channels(in,
1658 effect,
1659 &channel_config,
1660 (aux_channels != in->aux_channels));
1661
1662 if (status != 0) {
1663 ALOGV("in_update_aux_channels(): in_reconfigure_channels error %d", status);
1664 /* resetting aux channels configuration */
1665 aux_channels = 0;
1666 channel_config.aux_channels = 0;
1667 in_reconfigure_channels(in, effect, &channel_config, true);
1668 }
1669 ALOGV("%s: aux_channels=%d, in->aux_channels_changed=%d", __func__, aux_channels, in->aux_channels_changed);
1670 if (in->aux_channels != aux_channels) {
1671 in->aux_channels_changed = true;
1672 in->aux_channels = aux_channels;
1673 do_in_standby_l(in);
1674 }
1675}
1676#endif
1677
1678/* This function reads PCM data and:
1679 * - resample if needed
1680 * - process if pre-processors are attached
1681 * - discard unwanted channels
1682 */
1683static ssize_t read_and_process_frames(struct stream_in *in, void* buffer, ssize_t frames)
1684{
1685 ssize_t frames_wr = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001686 size_t src_channels = in->config.channels;
1687 size_t dst_channels = audio_channel_count_from_in_mask(in->main_channels);
1688 int i;
1689 void *proc_buf_out;
1690 struct pcm_device *pcm_device;
1691 bool has_additional_channels = (dst_channels != src_channels) ? true : false;
1692#ifdef PREPROCESSING_ENABLED
Andreas Schneider5a2f1002017-02-09 10:59:04 +01001693 audio_buffer_t in_buf;
1694 audio_buffer_t out_buf;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001695 bool has_processing = (in->num_preprocessors != 0) ? true : false;
1696#endif
1697
1698 /* Additional channels might be added on top of main_channels:
1699 * - aux_channels (by processing effects)
1700 * - extra channels due to HW limitations
1701 * In case of additional channels, we cannot work inplace
1702 */
1703 if (has_additional_channels)
1704 proc_buf_out = in->proc_buf_out;
1705 else
1706 proc_buf_out = buffer;
1707
1708 if (list_empty(&in->pcm_dev_list)) {
1709 ALOGE("%s: pcm device list empty", __func__);
1710 return -EINVAL;
1711 }
1712
1713 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1714 struct pcm_device, stream_list_node);
1715
1716#ifdef PREPROCESSING_ENABLED
1717 if (has_processing) {
1718 /* since all the processing below is done in frames and using the config.channels
1719 * as the number of channels, no changes is required in case aux_channels are present */
1720 while (frames_wr < frames) {
1721 /* first reload enough frames at the end of process input buffer */
1722 if (in->proc_buf_frames < (size_t)frames) {
1723 ssize_t frames_rd;
1724 if (in->proc_buf_size < (size_t)frames) {
1725 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1726 in->proc_buf_size = (size_t)frames;
1727 in->proc_buf_in = (int16_t *)realloc(in->proc_buf_in, size_in_bytes);
1728 ALOG_ASSERT((in->proc_buf_in != NULL),
1729 "process_frames() failed to reallocate proc_buf_in");
1730 if (has_additional_channels) {
1731 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1732 ALOG_ASSERT((in->proc_buf_out != NULL),
1733 "process_frames() failed to reallocate proc_buf_out");
1734 proc_buf_out = in->proc_buf_out;
1735 }
1736 }
1737 frames_rd = read_frames(in,
1738 in->proc_buf_in +
1739 in->proc_buf_frames * in->config.channels,
1740 frames - in->proc_buf_frames);
1741 if (frames_rd < 0) {
1742 /* Return error code */
1743 frames_wr = frames_rd;
1744 break;
1745 }
1746 in->proc_buf_frames += frames_rd;
1747 }
1748
1749 if (in->echo_reference != NULL) {
1750 push_echo_reference(in, in->proc_buf_frames);
1751 }
1752
1753 /* in_buf.frameCount and out_buf.frameCount indicate respectively
1754 * the maximum number of frames to be consumed and produced by process() */
1755 in_buf.frameCount = in->proc_buf_frames;
1756 in_buf.s16 = in->proc_buf_in;
1757 out_buf.frameCount = frames - frames_wr;
1758 out_buf.s16 = (int16_t *)proc_buf_out + frames_wr * in->config.channels;
1759
1760 /* FIXME: this works because of current pre processing library implementation that
1761 * does the actual process only when the last enabled effect process is called.
1762 * The generic solution is to have an output buffer for each effect and pass it as
1763 * input to the next.
1764 */
1765 for (i = 0; i < in->num_preprocessors; i++) {
1766 (*in->preprocessors[i].effect_itfe)->process(in->preprocessors[i].effect_itfe,
1767 &in_buf,
1768 &out_buf);
1769 }
1770
1771 /* process() has updated the number of frames consumed and produced in
1772 * in_buf.frameCount and out_buf.frameCount respectively
1773 * move remaining frames to the beginning of in->proc_buf_in */
1774 in->proc_buf_frames -= in_buf.frameCount;
1775
1776 if (in->proc_buf_frames) {
1777 memcpy(in->proc_buf_in,
1778 in->proc_buf_in + in_buf.frameCount * in->config.channels,
1779 in->proc_buf_frames * in->config.channels * sizeof(int16_t));
1780 }
1781
1782 /* if not enough frames were passed to process(), read more and retry. */
1783 if (out_buf.frameCount == 0) {
1784 ALOGW("No frames produced by preproc");
1785 continue;
1786 }
1787
1788 if ((frames_wr + (ssize_t)out_buf.frameCount) <= frames) {
1789 frames_wr += out_buf.frameCount;
1790 } else {
1791 /* The effect does not comply to the API. In theory, we should never end up here! */
1792 ALOGE("preprocessing produced too many frames: %d + %zd > %d !",
1793 (unsigned int)frames_wr, out_buf.frameCount, (unsigned int)frames);
1794 frames_wr = frames;
1795 }
1796 }
1797 }
1798 else
1799#endif //PREPROCESSING_ENABLED
1800 {
1801 /* No processing effects attached */
1802 if (has_additional_channels) {
1803 /* With additional channels, we cannot use original buffer */
1804 if (in->proc_buf_size < (size_t)frames) {
1805 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, frames);
1806 in->proc_buf_size = (size_t)frames;
1807 in->proc_buf_out = (int16_t *)realloc(in->proc_buf_out, size_in_bytes);
1808 ALOG_ASSERT((in->proc_buf_out != NULL),
1809 "process_frames() failed to reallocate proc_buf_out");
1810 proc_buf_out = in->proc_buf_out;
1811 }
1812 }
1813 frames_wr = read_frames(in, proc_buf_out, frames);
1814 }
1815
1816 /* Remove all additional channels that have been added on top of main_channels:
1817 * - aux_channels
1818 * - extra channels from HW due to HW limitations
1819 * Assumption is made that the channels are interleaved and that the main
1820 * channels are first. */
1821
1822 if (has_additional_channels)
1823 {
1824 int16_t* src_buffer = (int16_t *)proc_buf_out;
1825 int16_t* dst_buffer = (int16_t *)buffer;
1826
1827 if (dst_channels == 1) {
1828 for (i = frames_wr; i > 0; i--)
1829 {
1830 *dst_buffer++ = *src_buffer;
1831 src_buffer += src_channels;
1832 }
1833 } else {
1834 for (i = frames_wr; i > 0; i--)
1835 {
1836 memcpy(dst_buffer, src_buffer, dst_channels*sizeof(int16_t));
1837 dst_buffer += dst_channels;
1838 src_buffer += src_channels;
1839 }
1840 }
1841 }
1842
1843 return frames_wr;
1844}
1845
1846static int get_next_buffer(struct resampler_buffer_provider *buffer_provider,
1847 struct resampler_buffer* buffer)
1848{
1849 struct stream_in *in;
1850 struct pcm_device *pcm_device;
1851
1852 if (buffer_provider == NULL || buffer == NULL)
1853 return -EINVAL;
1854
1855 in = (struct stream_in *)((char *)buffer_provider -
1856 offsetof(struct stream_in, buf_provider));
1857
1858 if (list_empty(&in->pcm_dev_list)) {
1859 buffer->raw = NULL;
1860 buffer->frame_count = 0;
1861 in->read_status = -ENODEV;
1862 return -ENODEV;
1863 }
1864
1865 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1866 struct pcm_device, stream_list_node);
1867
1868 if (in->read_buf_frames == 0) {
1869 size_t size_in_bytes = pcm_frames_to_bytes(pcm_device->pcm, in->config.period_size);
1870 if (in->read_buf_size < in->config.period_size) {
1871 in->read_buf_size = in->config.period_size;
1872 in->read_buf = (int16_t *) realloc(in->read_buf, size_in_bytes);
1873 ALOG_ASSERT((in->read_buf != NULL),
1874 "get_next_buffer() failed to reallocate read_buf");
1875 }
1876
1877 in->read_status = pcm_read(pcm_device->pcm, (void*)in->read_buf, size_in_bytes);
1878
1879 if (in->read_status != 0) {
1880 ALOGE("get_next_buffer() pcm_read error %d", in->read_status);
1881 buffer->raw = NULL;
1882 buffer->frame_count = 0;
1883 return in->read_status;
1884 }
1885 in->read_buf_frames = in->config.period_size;
1886
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001887 }
1888
1889 buffer->frame_count = (buffer->frame_count > in->read_buf_frames) ?
1890 in->read_buf_frames : buffer->frame_count;
1891 buffer->i16 = in->read_buf + (in->config.period_size - in->read_buf_frames) *
1892 in->config.channels;
1893 return in->read_status;
1894}
1895
1896static void release_buffer(struct resampler_buffer_provider *buffer_provider,
1897 struct resampler_buffer* buffer)
1898{
1899 struct stream_in *in;
1900
1901 if (buffer_provider == NULL || buffer == NULL)
1902 return;
1903
1904 in = (struct stream_in *)((char *)buffer_provider -
1905 offsetof(struct stream_in, buf_provider));
1906
1907 in->read_buf_frames -= buffer->frame_count;
1908}
1909
1910/* read_frames() reads frames from kernel driver, down samples to capture rate
1911 * if necessary and output the number of frames requested to the buffer specified */
1912static ssize_t read_frames(struct stream_in *in, void *buffer, ssize_t frames)
1913{
1914 ssize_t frames_wr = 0;
1915
1916 struct pcm_device *pcm_device;
1917
1918 if (list_empty(&in->pcm_dev_list)) {
1919 ALOGE("%s: pcm device list empty", __func__);
1920 return -EINVAL;
1921 }
1922
1923 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
1924 struct pcm_device, stream_list_node);
1925
1926 while (frames_wr < frames) {
1927 size_t frames_rd = frames - frames_wr;
1928 ALOGVV("%s: frames_rd: %zd, frames_wr: %zd, in->config.channels: %d",
1929 __func__,frames_rd,frames_wr,in->config.channels);
1930 if (in->resampler != NULL) {
1931 in->resampler->resample_from_provider(in->resampler,
1932 (int16_t *)((char *)buffer +
1933 pcm_frames_to_bytes(pcm_device->pcm, frames_wr)),
1934 &frames_rd);
1935 } else {
1936 struct resampler_buffer buf = {
Andreas Schneiderb7f32122017-01-31 08:18:34 +01001937 .raw = NULL,
1938 .frame_count = frames_rd,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001939 };
1940 get_next_buffer(&in->buf_provider, &buf);
1941 if (buf.raw != NULL) {
1942 memcpy((char *)buffer +
1943 pcm_frames_to_bytes(pcm_device->pcm, frames_wr),
1944 buf.raw,
1945 pcm_frames_to_bytes(pcm_device->pcm, buf.frame_count));
1946 frames_rd = buf.frame_count;
1947 }
1948 release_buffer(&in->buf_provider, &buf);
1949 }
1950 /* in->read_status is updated by getNextBuffer() also called by
1951 * in->resampler->resample_from_provider() */
1952 if (in->read_status != 0)
1953 return in->read_status;
1954
1955 frames_wr += frames_rd;
1956 }
1957 return frames_wr;
1958}
1959
1960static int in_release_pcm_devices(struct stream_in *in)
1961{
1962 struct pcm_device *pcm_device;
1963 struct listnode *node;
1964 struct listnode *next;
1965
1966 list_for_each_safe(node, next, &in->pcm_dev_list) {
1967 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
1968 list_remove(node);
1969 free(pcm_device);
1970 }
1971
1972 return 0;
1973}
1974
1975static int stop_input_stream(struct stream_in *in)
1976{
1977 struct audio_usecase *uc_info;
1978 struct audio_device *adev = in->dev;
1979
1980 adev->active_input = NULL;
1981 ALOGV("%s: enter: usecase(%d: %s)", __func__,
1982 in->usecase, use_case_table[in->usecase]);
1983 uc_info = get_usecase_from_id(adev, in->usecase);
1984 if (uc_info == NULL) {
1985 ALOGE("%s: Could not find the usecase (%d) in the list",
1986 __func__, in->usecase);
1987 return -EINVAL;
1988 }
1989
1990 /* Disable the tx device */
Christopher N. Hesse8179c012018-03-09 23:20:55 +01001991 disable_snd_device(adev, uc_info, uc_info->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01001992
1993 list_remove(&uc_info->adev_list_node);
1994 free(uc_info);
1995
1996 if (list_empty(&in->pcm_dev_list)) {
1997 ALOGE("%s: pcm device list empty", __func__);
1998 return -EINVAL;
1999 }
2000
2001 in_release_pcm_devices(in);
2002 list_init(&in->pcm_dev_list);
2003
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002004 ALOGV("%s: exit", __func__);
2005 return 0;
2006}
2007
2008static int start_input_stream(struct stream_in *in)
2009{
2010 /* Enable output device and stream routing controls */
2011 int ret = 0;
2012 bool recreate_resampler = false;
2013 struct audio_usecase *uc_info;
2014 struct audio_device *adev = in->dev;
2015 struct pcm_device_profile *pcm_profile;
2016 struct pcm_device *pcm_device;
2017
2018 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
2019 adev->active_input = in;
2020 pcm_profile = get_pcm_device(in->usecase_type, in->devices);
2021 if (pcm_profile == NULL) {
2022 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2023 __func__, in->usecase);
2024 ret = -EINVAL;
2025 goto error_config;
2026 }
2027
2028 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002029 if (uc_info == NULL) {
2030 ret = -ENOMEM;
2031 goto error_config;
2032 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002033 uc_info->id = in->usecase;
2034 uc_info->type = PCM_CAPTURE;
2035 uc_info->stream = (struct audio_stream *)in;
2036 uc_info->devices = in->devices;
2037 uc_info->in_snd_device = SND_DEVICE_NONE;
2038 uc_info->out_snd_device = SND_DEVICE_NONE;
2039
2040 pcm_device = (struct pcm_device *)calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002041 if (pcm_device == NULL) {
2042 free(uc_info);
2043 ret = -ENOMEM;
2044 goto error_config;
2045 }
2046
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002047 pcm_device->pcm_profile = pcm_profile;
2048 list_init(&in->pcm_dev_list);
2049 list_add_tail(&in->pcm_dev_list, &pcm_device->stream_list_node);
2050
2051 list_init(&uc_info->mixer_list);
2052 list_add_tail(&uc_info->mixer_list,
2053 &adev_get_mixer_for_card(adev,
2054 pcm_device->pcm_profile->card)->uc_list_node[uc_info->id]);
2055
2056 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2057
2058 select_devices(adev, in->usecase);
2059
2060 /* Config should be updated as profile can be changed between different calls
2061 * to this function:
2062 * - Trigger resampler creation
2063 * - Config needs to be updated */
2064 if (in->config.rate != pcm_profile->config.rate) {
2065 recreate_resampler = true;
2066 }
2067 in->config = pcm_profile->config;
2068
2069#ifdef PREPROCESSING_ENABLED
2070 if (in->aux_channels_changed) {
2071 in->config.channels = audio_channel_count_from_in_mask(in->main_channels | in->aux_channels);
2072 recreate_resampler = true;
2073 }
2074#endif
2075
2076 if (in->requested_rate != in->config.rate) {
2077 recreate_resampler = true;
2078 }
2079
2080 if (recreate_resampler) {
2081 if (in->resampler) {
2082 release_resampler(in->resampler);
2083 in->resampler = NULL;
2084 }
2085 in->buf_provider.get_next_buffer = get_next_buffer;
2086 in->buf_provider.release_buffer = release_buffer;
2087 ret = create_resampler(in->config.rate,
2088 in->requested_rate,
2089 in->config.channels,
2090 RESAMPLER_QUALITY_DEFAULT,
2091 &in->buf_provider,
2092 &in->resampler);
2093 }
2094
2095#ifdef PREPROCESSING_ENABLED
2096 if (in->enable_aec && in->echo_reference == NULL) {
2097 in->echo_reference = get_echo_reference(adev,
2098 AUDIO_FORMAT_PCM_16_BIT,
2099 audio_channel_count_from_in_mask(in->main_channels),
2100 in->requested_rate
2101 );
2102 }
2103
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002104#endif
2105
2106 /* Open the PCM device.
2107 * The HW is limited to support only the default pcm_profile settings.
2108 * As such a change in aux_channels will not have an effect.
2109 */
2110 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d, smp rate %d format %d, \
2111 period_size %d", __func__, pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
2112 pcm_device->pcm_profile->config.channels,pcm_device->pcm_profile->config.rate,
2113 pcm_device->pcm_profile->config.format, pcm_device->pcm_profile->config.period_size);
2114
stenkinevgeniy44335362018-05-07 18:00:13 +00002115 pcm_device->pcm = pcm_open(pcm_device->pcm_profile->card, pcm_device->pcm_profile->id,
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002116 PCM_IN | PCM_MONOTONIC, &pcm_device->pcm_profile->config);
2117
stenkinevgeniy44335362018-05-07 18:00:13 +00002118 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2119 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2120 pcm_close(pcm_device->pcm);
2121 pcm_device->pcm = NULL;
2122 ret = -EIO;
2123 goto error_open;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002124 }
2125
2126 /* force read and proc buffer reallocation in case of frame size or
2127 * channel count change */
2128 in->proc_buf_frames = 0;
2129 in->proc_buf_size = 0;
2130 in->read_buf_size = 0;
2131 in->read_buf_frames = 0;
2132
2133 /* if no supported sample rate is available, use the resampler */
2134 if (in->resampler) {
2135 in->resampler->reset(in->resampler);
2136 }
2137
2138 ALOGV("%s: exit", __func__);
2139 return ret;
2140
2141error_open:
2142 if (in->resampler) {
2143 release_resampler(in->resampler);
2144 in->resampler = NULL;
2145 }
2146 stop_input_stream(in);
2147
2148error_config:
2149 ALOGV("%s: exit: status(%d)", __func__, ret);
2150 adev->active_input = NULL;
2151 return ret;
2152}
2153
2154void lock_input_stream(struct stream_in *in)
2155{
2156 pthread_mutex_lock(&in->pre_lock);
2157 pthread_mutex_lock(&in->lock);
2158 pthread_mutex_unlock(&in->pre_lock);
2159}
2160
2161void lock_output_stream(struct stream_out *out)
2162{
2163 pthread_mutex_lock(&out->pre_lock);
2164 pthread_mutex_lock(&out->lock);
2165 pthread_mutex_unlock(&out->pre_lock);
2166}
2167
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002168static int uc_release_pcm_devices(struct audio_usecase *usecase)
2169{
2170 struct stream_out *out = (struct stream_out *)usecase->stream;
2171 struct pcm_device *pcm_device;
2172 struct listnode *node;
2173 struct listnode *next;
2174
2175 list_for_each_safe(node, next, &out->pcm_dev_list) {
2176 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2177 list_remove(node);
2178 free(pcm_device);
2179 }
2180 list_init(&usecase->mixer_list);
2181
2182 return 0;
2183}
2184
2185static int uc_select_pcm_devices(struct audio_usecase *usecase)
2186
2187{
2188 struct stream_out *out = (struct stream_out *)usecase->stream;
2189 struct pcm_device *pcm_device;
2190 struct pcm_device_profile *pcm_profile;
2191 struct mixer_card *mixer_card;
2192 audio_devices_t devices = usecase->devices;
2193
2194 list_init(&usecase->mixer_list);
2195 list_init(&out->pcm_dev_list);
2196
2197 while ((pcm_profile = get_pcm_device(usecase->type, devices)) != NULL) {
2198 pcm_device = calloc(1, sizeof(struct pcm_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01002199 if (pcm_device == NULL) {
2200 return -ENOMEM;
2201 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002202 pcm_device->pcm_profile = pcm_profile;
2203 list_add_tail(&out->pcm_dev_list, &pcm_device->stream_list_node);
2204 mixer_card = uc_get_mixer_for_card(usecase, pcm_profile->card);
2205 if (mixer_card == NULL) {
2206 mixer_card = adev_get_mixer_for_card(out->dev, pcm_profile->card);
2207 list_add_tail(&usecase->mixer_list, &mixer_card->uc_list_node[usecase->id]);
2208 }
2209 devices &= ~pcm_profile->devices;
2210 }
2211
2212 return 0;
2213}
2214
2215static int out_close_pcm_devices(struct stream_out *out)
2216{
2217 struct pcm_device *pcm_device;
2218 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002219
2220 list_for_each(node, &out->pcm_dev_list) {
2221 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002222 if (pcm_device->pcm) {
2223 pcm_close(pcm_device->pcm);
2224 pcm_device->pcm = NULL;
2225 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002226 }
2227
2228 return 0;
2229}
2230
2231static int out_open_pcm_devices(struct stream_out *out)
2232{
2233 struct pcm_device *pcm_device;
2234 struct listnode *node;
2235 int ret = 0;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002236 int pcm_device_card;
2237 int pcm_device_id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002238
2239 list_for_each(node, &out->pcm_dev_list) {
2240 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002241 pcm_device_card = pcm_device->pcm_profile->card;
2242 pcm_device_id = pcm_device->pcm_profile->id;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002243
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01002244 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER)
2245 pcm_device_id = pcm_device_deep_buffer.id;
2246
2247 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)",
2248 __func__, pcm_device_card, pcm_device_id);
2249
2250 pcm_device->pcm = pcm_open(pcm_device_card, pcm_device_id,
stenkinevgeniy2ef158a2018-05-08 06:52:05 +00002251 PCM_OUT | PCM_MONOTONIC, &out->config);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002252
2253 if (pcm_device->pcm && !pcm_is_ready(pcm_device->pcm)) {
2254 ALOGE("%s: %s", __func__, pcm_get_error(pcm_device->pcm));
2255 pcm_device->pcm = NULL;
2256 ret = -EIO;
2257 goto error_open;
2258 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002259 }
2260 return ret;
2261
2262error_open:
2263 out_close_pcm_devices(out);
2264 return ret;
2265}
2266
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002267int disable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002268{
2269 struct audio_device *adev = out->dev;
2270 struct audio_usecase *uc_info;
2271
2272 uc_info = get_usecase_from_id(adev, out->usecase);
2273 if (uc_info == NULL) {
2274 ALOGE("%s: Could not find the usecase (%d) in the list",
2275 __func__, out->usecase);
2276 return -EINVAL;
2277 }
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002278 disable_snd_device(adev, uc_info, uc_info->out_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002279 uc_release_pcm_devices(uc_info);
2280 list_remove(&uc_info->adev_list_node);
2281 free(uc_info);
2282
2283 return 0;
2284}
2285
Andreas Schneider56204f62017-01-31 08:17:32 +01002286int enable_output_path_l(struct stream_out *out)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002287{
2288 struct audio_device *adev = out->dev;
2289 struct audio_usecase *uc_info;
2290
2291 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002292 if (uc_info == NULL) {
2293 return -ENOMEM;
2294 }
2295
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002296 uc_info->id = out->usecase;
2297 uc_info->type = PCM_PLAYBACK;
2298 uc_info->stream = (struct audio_stream *)out;
2299 uc_info->devices = out->devices;
2300 uc_info->in_snd_device = SND_DEVICE_NONE;
2301 uc_info->out_snd_device = SND_DEVICE_NONE;
2302 uc_select_pcm_devices(uc_info);
2303
2304 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2305 select_devices(adev, out->usecase);
Andreas Schneider56204f62017-01-31 08:17:32 +01002306
2307 return 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002308}
2309
2310static int stop_output_stream(struct stream_out *out)
2311{
2312 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002313 bool do_disable = true;
2314
2315 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2316 out->usecase, use_case_table[out->usecase]);
2317
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002318 stop_output_offload_stream(out, &do_disable);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002319
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002320 if (do_disable)
2321 ret = disable_output_path_l(out);
2322
2323 ALOGV("%s: exit: status(%d)", __func__, ret);
2324 return ret;
2325}
2326
2327static int start_output_stream(struct stream_out *out)
2328{
2329 int ret = 0;
2330 struct audio_device *adev = out->dev;
2331
2332 ALOGV("%s: enter: usecase(%d: %s) devices(%#x) channels(%d)",
2333 __func__, out->usecase, use_case_table[out->usecase], out->devices, out->config.channels);
2334
Andreas Schneider56204f62017-01-31 08:17:32 +01002335 ret = enable_output_path_l(out);
2336 if (ret != 0) {
2337 goto error_config;
2338 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002339
2340 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2341 out->compr = NULL;
2342 ret = out_open_pcm_devices(out);
2343 if (ret != 0)
2344 goto error_open;
2345#ifdef PREPROCESSING_ENABLED
2346 out->echo_reference = NULL;
2347 out->echo_reference_generation = adev->echo_reference_generation;
2348 if (adev->echo_reference != NULL)
2349 out->echo_reference = adev->echo_reference;
2350#endif
2351 } else {
2352 out->compr = compress_open(COMPRESS_CARD, COMPRESS_DEVICE,
2353 COMPRESS_IN, &out->compr_config);
2354 if (out->compr && !is_compress_ready(out->compr)) {
2355 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2356 compress_close(out->compr);
2357 out->compr = NULL;
2358 ret = -EIO;
2359 goto error_open;
2360 }
2361 if (out->offload_callback)
2362 compress_nonblock(out->compr, out->non_blocking);
2363
2364 if (adev->offload_fx_start_output != NULL)
2365 adev->offload_fx_start_output(out->handle);
2366 }
2367 ALOGV("%s: exit", __func__);
2368 return 0;
2369error_open:
2370 stop_output_stream(out);
2371error_config:
2372 return ret;
2373}
2374
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002375int stop_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002376{
2377 struct audio_usecase *uc_info;
2378
2379 ALOGV("%s: enter", __func__);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002380 adev->voice.in_call = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002381
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002382 stop_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002383
2384 uc_info = get_usecase_from_id(adev, USECASE_VOICE_CALL);
2385 if (uc_info == NULL) {
2386 ALOGE("%s: Could not find the usecase (%d) in the list",
2387 __func__, USECASE_VOICE_CALL);
2388 return -EINVAL;
2389 }
2390
Christopher N. Hesse8179c012018-03-09 23:20:55 +01002391 disable_snd_device(adev, uc_info, uc_info->out_snd_device);
2392 disable_snd_device(adev, uc_info, uc_info->in_snd_device);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002393
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002394 list_remove(&uc_info->adev_list_node);
2395 free(uc_info);
2396
2397 ALOGV("%s: exit", __func__);
2398 return 0;
2399}
2400
2401/* always called with adev lock held */
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002402int start_voice_call(struct audio_device *adev)
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002403{
2404 struct audio_usecase *uc_info;
Andreas Schneider56204f62017-01-31 08:17:32 +01002405 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002406
2407 ALOGV("%s: enter", __func__);
2408
2409 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Andreas Schneider56204f62017-01-31 08:17:32 +01002410 if (uc_info == NULL) {
2411 ret = -ENOMEM;
2412 goto exit;
2413 }
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002414 /*
2415 * We set this early so that functions called after this is being set
2416 * can use it. It is e.g. needed in select_devices() to inform the RILD
2417 * which output device we use.
2418 */
2419 adev->voice.in_call = true;
Andreas Schneider56204f62017-01-31 08:17:32 +01002420
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002421 uc_info->id = USECASE_VOICE_CALL;
2422 uc_info->type = VOICE_CALL;
2423 uc_info->stream = (struct audio_stream *)adev->primary_output;
2424 uc_info->devices = adev->primary_output->devices;
2425 uc_info->in_snd_device = SND_DEVICE_NONE;
2426 uc_info->out_snd_device = SND_DEVICE_NONE;
2427
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002428 list_init(&uc_info->mixer_list);
2429 list_add_tail(&uc_info->mixer_list,
2430 &adev_get_mixer_for_card(adev, SOUND_CARD)->uc_list_node[uc_info->id]);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002431
2432 list_add_tail(&adev->usecase_list, &uc_info->adev_list_node);
2433
2434 select_devices(adev, USECASE_VOICE_CALL);
2435
Christopher N. Hesse696959d2017-02-02 20:49:55 +01002436 start_voice_session(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002437
2438 /* set cached volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002439 set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002440
Andreas Schneider56204f62017-01-31 08:17:32 +01002441exit:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002442 ALOGV("%s: exit", __func__);
Andreas Schneider56204f62017-01-31 08:17:32 +01002443 return ret;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002444}
2445
2446static int check_input_parameters(uint32_t sample_rate,
2447 audio_format_t format,
2448 int channel_count)
2449{
2450 if (format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
2451
2452 if ((channel_count < 1) || (channel_count > 2)) return -EINVAL;
2453
2454 switch (sample_rate) {
2455 case 8000:
2456 case 11025:
2457 case 12000:
2458 case 16000:
2459 case 22050:
2460 case 24000:
2461 case 32000:
2462 case 44100:
2463 case 48000:
2464 break;
2465 default:
2466 return -EINVAL;
2467 }
2468
2469 return 0;
2470}
2471
2472static size_t get_input_buffer_size(uint32_t sample_rate,
2473 audio_format_t format,
2474 int channel_count,
2475 usecase_type_t usecase_type,
2476 audio_devices_t devices)
2477{
2478 size_t size = 0;
2479 struct pcm_device_profile *pcm_profile;
2480
2481 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2482 return 0;
2483
2484 pcm_profile = get_pcm_device(usecase_type, devices);
2485 if (pcm_profile == NULL)
2486 return 0;
2487
2488 /*
2489 * take resampling into account and return the closest majoring
2490 * multiple of 16 frames, as audioflinger expects audio buffers to
2491 * be a multiple of 16 frames
2492 */
2493 size = (pcm_profile->config.period_size * sample_rate) / pcm_profile->config.rate;
2494 size = ((size + 15) / 16) * 16;
2495
2496 return (size * channel_count * audio_bytes_per_sample(format));
2497
2498}
2499
2500static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2501{
2502 struct stream_out *out = (struct stream_out *)stream;
2503
2504 return out->sample_rate;
2505}
2506
2507static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
2508{
2509 (void)stream;
2510 (void)rate;
2511 return -ENOSYS;
2512}
2513
2514static size_t out_get_buffer_size(const struct audio_stream *stream)
2515{
2516 struct stream_out *out = (struct stream_out *)stream;
2517
2518 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2519 return out->compr_config.fragment_size;
2520 }
2521
2522 return out->config.period_size *
2523 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
2524}
2525
2526static uint32_t out_get_channels(const struct audio_stream *stream)
2527{
2528 struct stream_out *out = (struct stream_out *)stream;
2529
2530 return out->channel_mask;
2531}
2532
2533static audio_format_t out_get_format(const struct audio_stream *stream)
2534{
2535 struct stream_out *out = (struct stream_out *)stream;
2536
2537 return out->format;
2538}
2539
2540static int out_set_format(struct audio_stream *stream, audio_format_t format)
2541{
2542 (void)stream;
2543 (void)format;
2544 return -ENOSYS;
2545}
2546
2547static int do_out_standby_l(struct stream_out *out)
2548{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002549 int status = 0;
2550
2551 out->standby = true;
2552 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2553 out_close_pcm_devices(out);
2554#ifdef PREPROCESSING_ENABLED
2555 /* stop writing to echo reference */
2556 if (out->echo_reference != NULL) {
2557 out->echo_reference->write(out->echo_reference, NULL);
2558 if (out->echo_reference_generation != adev->echo_reference_generation) {
2559 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2560 release_echo_reference(out->echo_reference);
2561 out->echo_reference_generation = adev->echo_reference_generation;
2562 }
2563 out->echo_reference = NULL;
2564 }
2565#endif
2566 } else {
2567 stop_compressed_output_l(out);
2568 out->gapless_mdata.encoder_delay = 0;
2569 out->gapless_mdata.encoder_padding = 0;
2570 if (out->compr != NULL) {
2571 compress_close(out->compr);
2572 out->compr = NULL;
2573 }
2574 }
2575 status = stop_output_stream(out);
2576
2577 return status;
2578}
2579
2580static int out_standby(struct audio_stream *stream)
2581{
2582 struct stream_out *out = (struct stream_out *)stream;
2583 struct audio_device *adev = out->dev;
2584
2585 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2586 out->usecase, use_case_table[out->usecase]);
2587 lock_output_stream(out);
2588 if (!out->standby) {
2589 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002590 amplifier_output_stream_standby((struct audio_stream_out *) stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002591 do_out_standby_l(out);
2592 pthread_mutex_unlock(&adev->lock);
2593 }
2594 pthread_mutex_unlock(&out->lock);
2595 ALOGV("%s: exit", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002596
2597 // out->last_write_time_us = 0; unnecessary as a stale write time has same effect
2598
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002599 return 0;
2600}
2601
2602static int out_dump(const struct audio_stream *stream, int fd)
2603{
2604 (void)stream;
2605 (void)fd;
2606
2607 return 0;
2608}
2609
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002610static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2611{
2612 struct stream_out *out = (struct stream_out *)stream;
2613 struct audio_device *adev = out->dev;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002614 struct listnode *node;
2615 struct str_parms *parms;
2616 char value[32];
2617 int ret, val = 0;
2618 struct audio_usecase *uc_info;
2619 bool do_standby = false;
2620 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002621#ifdef PREPROCESSING_ENABLED
2622 struct stream_in *in = NULL; /* if non-NULL, then force input to standby */
2623#endif
2624
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002625 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s out->devices(%#x) "
2626 "adev->mode(%#x)",
2627 __func__, out->usecase, use_case_table[out->usecase], kvpairs,
2628 out->devices, adev->mode);
2629
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002630 parms = str_parms_create_str(kvpairs);
2631 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2632 if (ret >= 0) {
2633 val = atoi(value);
Andreas Schneiderdd8a3692017-02-14 12:51:30 +01002634
2635 ALOGV("%s: routing: usecase(%d: %s) devices=(%#x) adev->mode(%#x)",
2636 __func__, out->usecase, use_case_table[out->usecase], val,
2637 adev->mode);
2638
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002639 pthread_mutex_lock(&adev->lock_inputs);
2640 lock_output_stream(out);
2641 pthread_mutex_lock(&adev->lock);
2642#ifdef PREPROCESSING_ENABLED
2643 if (((int)out->devices != val) && (val != 0) && (!out->standby) &&
2644 (out->usecase == USECASE_AUDIO_PLAYBACK)) {
2645 /* reset active input:
2646 * - to attach the echo reference
2647 * - because a change in output device may change mic settings */
2648 if (adev->active_input && (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2649 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2650 in = adev->active_input;
2651 }
2652 }
2653#endif
Christopher N. Hesse33affb82017-11-16 17:01:37 +01002654 if (val != SND_DEVICE_NONE) {
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002655 out->devices = val;
2656
2657 if (!out->standby) {
2658 uc_info = get_usecase_from_id(adev, out->usecase);
2659 if (uc_info == NULL) {
2660 ALOGE("%s: Could not find the usecase (%d) in the list",
2661 __func__, out->usecase);
2662 } else {
2663 list_for_each(node, &out->pcm_dev_list) {
2664 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2665 if ((pcm_device->pcm_profile->devices & val) == 0)
2666 do_standby = true;
2667 val &= ~pcm_device->pcm_profile->devices;
2668 }
2669 if (val != 0)
2670 do_standby = true;
2671 }
2672 if (do_standby)
2673 do_out_standby_l(out);
2674 else {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002675 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2676 out_set_offload_parameters(adev, uc_info);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002677 select_devices(adev, out->usecase);
2678 }
2679 }
2680
stenkinevgeniy53929f72018-07-09 11:20:36 +00002681 /* Turn on bluetooth sco if needed */
2682 if ((adev->mode == AUDIO_MODE_IN_COMMUNICATION || adev->mode == AUDIO_MODE_IN_CALL) &&
2683 (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && !adev->bt_sco_active) {
2684 adev->bt_sco_active = true;
2685 start_voice_session_bt_sco(adev);
2686 }
2687 else if (!(out->devices & AUDIO_DEVICE_OUT_ALL_SCO) && adev->bt_sco_active) {
2688 adev->bt_sco_active = false;
2689 stop_voice_session_bt_sco(adev);
2690 }
2691
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002692 if ((adev->mode == AUDIO_MODE_IN_CALL) && !adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002693 (out == adev->primary_output)) {
2694 start_voice_call(adev);
Andreas Schneider74ef3a12017-02-02 18:29:12 +01002695 } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
2696 adev->voice.in_call &&
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002697 (out == adev->primary_output)) {
Andreas Schneidere9a44a22017-02-14 13:00:48 +01002698 /*
2699 * When we select different devices we need to restart the
2700 * voice call. The modem closes the stream on its end and
2701 * we do not get any output.
2702 */
2703 stop_voice_call(adev);
2704 start_voice_call(adev);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002705 }
2706 }
2707
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002708 pthread_mutex_unlock(&adev->lock);
2709 pthread_mutex_unlock(&out->lock);
2710#ifdef PREPROCESSING_ENABLED
2711 if (in) {
2712 /* The lock on adev->lock_inputs prevents input stream from being closed */
2713 lock_input_stream(in);
2714 pthread_mutex_lock(&adev->lock);
2715 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2716 do_in_standby_l(in);
2717 pthread_mutex_unlock(&adev->lock);
2718 pthread_mutex_unlock(&in->lock);
2719 }
2720#endif
2721 pthread_mutex_unlock(&adev->lock_inputs);
2722 }
2723
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002724 amplifier_set_parameters(parms);
2725
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002726 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2727 parse_compress_metadata(out, parms);
2728 }
2729
2730 str_parms_destroy(parms);
2731
2732 if (ret > 0)
2733 ret = 0;
2734 ALOGV("%s: exit: code(%d)", __func__, ret);
2735 return ret;
2736}
2737
2738static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2739{
2740 struct stream_out *out = (struct stream_out *)stream;
2741 struct str_parms *query = str_parms_create_str(keys);
2742 char *str;
2743 char value[256];
2744 struct str_parms *reply = str_parms_create();
2745 size_t i, j;
2746 int ret;
2747 bool first = true;
2748 ALOGV("%s: enter: keys - %s", __func__, keys);
2749 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2750 if (ret >= 0) {
2751 value[0] = '\0';
2752 i = 0;
2753 while (out->supported_channel_masks[i] != 0) {
2754 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2755 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2756 if (!first) {
2757 strcat(value, "|");
2758 }
2759 strcat(value, out_channels_name_to_enum_table[j].name);
2760 first = false;
2761 break;
2762 }
2763 }
2764 i++;
2765 }
2766 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2767 str = str_parms_to_str(reply);
2768 } else {
2769 str = strdup(keys);
2770 }
2771 str_parms_destroy(query);
2772 str_parms_destroy(reply);
2773 ALOGV("%s: exit: returns - %s", __func__, str);
2774 return str;
2775}
2776
2777static uint32_t out_get_latency(const struct audio_stream_out *stream)
2778{
2779 struct stream_out *out = (struct stream_out *)stream;
2780
2781 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2782 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
2783
2784 return (out->config.period_count * out->config.period_size * 1000) /
2785 (out->config.rate);
2786}
2787
2788static int out_set_volume(struct audio_stream_out *stream, float left,
2789 float right)
2790{
2791 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002792
2793 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2794 /* only take left channel into account: the API is for stereo anyway */
2795 out->muted = (left == 0.0f);
2796 return 0;
2797 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002798 out_set_offload_volume(left, right);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002799 }
2800
2801 return -ENOSYS;
2802}
2803
Andreas Schneider3b643832017-01-31 11:48:22 +01002804#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002805static int fast_set_affinity(pid_t tid) {
2806 cpu_set_t cpu_set;
2807 int cpu_num;
2808 const char *irq_procfs = "/proc/asound/irq_affinity";
2809 FILE *fp;
2810
2811 if ((fp = fopen(irq_procfs, "r")) == NULL) {
2812 ALOGW("Procfs node %s not found", irq_procfs);
2813 return -1;
2814 }
2815
2816 if (fscanf(fp, "%d", &cpu_num) != 1) {
2817 ALOGW("Couldn't read CPU id from procfs node %s", irq_procfs);
2818 fclose(fp);
2819 return -1;
2820 }
2821 fclose(fp);
2822
2823 CPU_ZERO(&cpu_set);
2824 CPU_SET(cpu_num, &cpu_set);
2825 return sched_setaffinity(tid, sizeof(cpu_set), &cpu_set);
2826}
Andreas Schneider3b643832017-01-31 11:48:22 +01002827#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002828
2829static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2830 size_t bytes)
2831{
2832 struct stream_out *out = (struct stream_out *)stream;
2833 struct audio_device *adev = out->dev;
2834 ssize_t ret = 0;
2835 struct pcm_device *pcm_device;
2836 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002837#ifdef PREPROCESSING_ENABLED
stenkinevgeniyd0a02c02018-05-08 07:17:53 +00002838 size_t frame_size = audio_stream_out_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002839 size_t in_frames = bytes / frame_size;
2840 size_t out_frames = in_frames;
2841 struct stream_in *in = NULL;
2842#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002843
2844 lock_output_stream(out);
2845
Andreas Schneider3b643832017-01-31 11:48:22 +01002846#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002847 if (out->usecase == USECASE_AUDIO_PLAYBACK && !out->is_fastmixer_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002848 pid_t tid = gettid();
2849 int err;
2850
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002851 err = fast_set_affinity(tid);
2852 if (err < 0) {
2853 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
2854 }
2855 out->is_fastmixer_affinity_set = true;
2856 }
Andreas Schneider3b643832017-01-31 11:48:22 +01002857#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002858
2859 if (out->standby) {
2860#ifdef PREPROCESSING_ENABLED
2861 pthread_mutex_unlock(&out->lock);
2862 /* Prevent input stream from being closed */
2863 pthread_mutex_lock(&adev->lock_inputs);
2864 lock_output_stream(out);
2865 if (!out->standby) {
2866 pthread_mutex_unlock(&adev->lock_inputs);
2867 goto false_alarm;
2868 }
2869#endif
2870 pthread_mutex_lock(&adev->lock);
2871 ret = start_output_stream(out);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02002872 if (ret == 0) {
2873 amplifier_output_stream_start(stream, out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD);
2874 }
2875
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002876 /* ToDo: If use case is compress offload should return 0 */
2877 if (ret != 0) {
2878 pthread_mutex_unlock(&adev->lock);
2879#ifdef PREPROCESSING_ENABLED
2880 pthread_mutex_unlock(&adev->lock_inputs);
2881#endif
2882 goto exit;
2883 }
2884 out->standby = false;
2885
2886#ifdef PREPROCESSING_ENABLED
2887 /* A change in output device may change the microphone selection */
2888 if (adev->active_input &&
2889 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2890 adev->active_input->source == AUDIO_SOURCE_MIC)) {
2891 in = adev->active_input;
2892 ALOGV("%s: enter:) force_input_standby true", __func__);
2893 }
2894#endif
2895 pthread_mutex_unlock(&adev->lock);
2896#ifdef PREPROCESSING_ENABLED
2897 if (!in) {
2898 /* Leave mutex locked iff in != NULL */
2899 pthread_mutex_unlock(&adev->lock_inputs);
2900 }
2901#endif
2902 }
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002903#ifdef PREPROCESSING_ENABLED
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002904false_alarm:
Andreas Schneider5a2f1002017-02-09 10:59:04 +01002905#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002906
2907 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01002908 ret = out_write_offload(stream, buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002909 return ret;
2910 } else {
2911#ifdef PREPROCESSING_ENABLED
2912 if (android_atomic_acquire_load(&adev->echo_reference_generation)
2913 != out->echo_reference_generation) {
2914 pthread_mutex_lock(&adev->lock);
2915 if (out->echo_reference != NULL) {
2916 ALOGV("%s: release_echo_reference %p", __func__, out->echo_reference);
2917 release_echo_reference(out->echo_reference);
2918 }
2919 // note that adev->echo_reference_generation here can be different from the one
2920 // tested above but it doesn't matter as we now have the adev mutex and it is consistent
2921 // with what has been set by get_echo_reference() or put_echo_reference()
2922 out->echo_reference_generation = adev->echo_reference_generation;
2923 out->echo_reference = adev->echo_reference;
2924 ALOGV("%s: update echo reference generation %d", __func__,
2925 out->echo_reference_generation);
2926 pthread_mutex_unlock(&adev->lock);
2927 }
2928#endif
2929
2930 if (out->muted)
2931 memset((void *)buffer, 0, bytes);
2932 list_for_each(node, &out->pcm_dev_list) {
2933 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002934 if (pcm_device->pcm) {
2935#ifdef PREPROCESSING_ENABLED
2936 if (out->echo_reference != NULL && pcm_device->pcm_profile->devices != SND_DEVICE_OUT_SPEAKER) {
2937 struct echo_reference_buffer b;
2938 b.raw = (void *)buffer;
2939 b.frame_count = in_frames;
2940
2941 get_playback_delay(out, out_frames, &b);
2942 out->echo_reference->write(out->echo_reference, &b);
2943 }
2944#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002945 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
stenkinevgeniyd0a02c02018-05-08 07:17:53 +00002946 pcm_device->status = pcm_write(pcm_device->pcm, (void *)buffer, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002947 if (pcm_device->status != 0)
2948 ret = pcm_device->status;
2949 }
2950 }
2951 if (ret == 0)
2952 out->written += bytes / (out->config.channels * sizeof(short));
2953 }
2954
2955exit:
2956 pthread_mutex_unlock(&out->lock);
2957
2958 if (ret != 0) {
2959 list_for_each(node, &out->pcm_dev_list) {
2960 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
2961 if (pcm_device->pcm && pcm_device->status != 0)
2962 ALOGE("%s: error %zd - %s", __func__, ret, pcm_get_error(pcm_device->pcm));
2963 }
2964 out_standby(&out->stream.common);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01002965 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
2966 clock_gettime(CLOCK_MONOTONIC, &t);
2967 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
2968 const int64_t elapsed_time_since_last_write = now - out->last_write_time_us;
2969 int64_t sleep_time = bytes * 1000000LL / audio_stream_out_frame_size(stream) /
2970 out_get_sample_rate(&stream->common) - elapsed_time_since_last_write;
2971 if (sleep_time > 0) {
2972 usleep(sleep_time);
2973 } else {
2974 // we don't sleep when we exit standby (this is typical for a real alsa buffer).
2975 sleep_time = 0;
2976 }
2977 out->last_write_time_us = now + sleep_time;
2978 // last_write_time_us is an approximation of when the (simulated) alsa
2979 // buffer is believed completely full. The usleep above waits for more space
2980 // in the buffer, but by the end of the sleep the buffer is considered
2981 // topped-off.
2982 //
2983 // On the subsequent out_write(), we measure the elapsed time spent in
2984 // the mixer. This is subtracted from the sleep estimate based on frames,
2985 // thereby accounting for drain in the alsa buffer during mixing.
2986 // This is a crude approximation; we don't handle underruns precisely.
Christopher N. Hesse297a6362017-01-28 12:40:45 +01002987 }
2988
2989#ifdef PREPROCESSING_ENABLED
2990 if (in) {
2991 /* The lock on adev->lock_inputs prevents input stream from being closed */
2992 lock_input_stream(in);
2993 pthread_mutex_lock(&adev->lock);
2994 LOG_ALWAYS_FATAL_IF(in != adev->active_input);
2995 do_in_standby_l(in);
2996 pthread_mutex_unlock(&adev->lock);
2997 pthread_mutex_unlock(&in->lock);
2998 /* This mutex was left locked iff in != NULL */
2999 pthread_mutex_unlock(&adev->lock_inputs);
3000 }
3001#endif
3002
3003 return bytes;
3004}
3005
3006static int out_get_render_position(const struct audio_stream_out *stream,
3007 uint32_t *dsp_frames)
3008{
3009 struct stream_out *out = (struct stream_out *)stream;
3010 *dsp_frames = 0;
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003011 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3012 return out_get_render_offload_position(out, dsp_frames);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003013 } else
3014 return -EINVAL;
3015}
3016
3017static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3018{
3019 (void)stream;
3020 (void)effect;
3021 return 0;
3022}
3023
3024static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
3025{
3026 (void)stream;
3027 (void)effect;
3028 return 0;
3029}
3030
3031static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
3032 int64_t *timestamp)
3033{
3034 (void)stream;
3035 (void)timestamp;
3036 return -EINVAL;
3037}
3038
3039static int out_get_presentation_position(const struct audio_stream_out *stream,
3040 uint64_t *frames, struct timespec *timestamp)
3041{
3042 struct stream_out *out = (struct stream_out *)stream;
Victor Lourme5869cd32018-03-26 19:36:07 +02003043 int ret = -EINVAL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003044
3045 lock_output_stream(out);
3046
3047 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003048 ret = out_get_presentation_offload_position(out, frames, timestamp);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003049 } else {
3050 /* FIXME: which device to read from? */
3051 if (!list_empty(&out->pcm_dev_list)) {
Andreas Schneiderd6359182017-02-08 16:58:22 +01003052 struct pcm_device *pcm_device;
3053 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003054 unsigned int avail;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003055
Andreas Schneiderd6359182017-02-08 16:58:22 +01003056 list_for_each(node, &out->pcm_dev_list) {
3057 pcm_device = node_to_item(node,
3058 struct pcm_device,
3059 stream_list_node);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003060
Andreas Schneiderd6359182017-02-08 16:58:22 +01003061 if (pcm_device->pcm != NULL) {
3062 if (pcm_get_htimestamp(pcm_device->pcm, &avail, timestamp) == 0) {
3063 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
3064 int64_t signed_frames = out->written - kernel_buffer_size + avail;
3065 /* This adjustment accounts for buffering after app processor.
3066 It is based on estimated DSP latency per use case, rather than exact. */
3067 signed_frames -=
3068 (render_latency(out->usecase) * out->sample_rate / 1000000LL);
3069
3070 /* It would be unusual for this value to be negative, but check just in case ... */
3071 if (signed_frames >= 0) {
3072 *frames = signed_frames;
3073 ret = 0;
3074 goto done;
3075 }
Andreas Schneiderd6359182017-02-08 16:58:22 +01003076 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003077 }
3078 }
3079 }
3080 }
3081
Andreas Schneiderd6359182017-02-08 16:58:22 +01003082done:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003083 pthread_mutex_unlock(&out->lock);
3084
3085 return ret;
3086}
3087
3088static int out_set_callback(struct audio_stream_out *stream,
3089 stream_callback_t callback, void *cookie)
3090{
3091 struct stream_out *out = (struct stream_out *)stream;
3092
3093 ALOGV("%s", __func__);
3094 lock_output_stream(out);
3095 out->offload_callback = callback;
3096 out->offload_cookie = cookie;
3097 pthread_mutex_unlock(&out->lock);
3098 return 0;
3099}
3100
3101static int out_pause(struct audio_stream_out* stream)
3102{
3103 struct stream_out *out = (struct stream_out *)stream;
3104 int status = -ENOSYS;
3105 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003106 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3107 status = out_pause_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003108 return status;
3109}
3110
3111static int out_resume(struct audio_stream_out* stream)
3112{
3113 struct stream_out *out = (struct stream_out *)stream;
3114 int status = -ENOSYS;
3115 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003116 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3117 status = out_resume_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003118 return status;
3119}
3120
3121static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3122{
3123 struct stream_out *out = (struct stream_out *)stream;
3124 int status = -ENOSYS;
3125 ALOGV("%s", __func__);
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003126 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3127 status = out_drain_offload(out, type);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003128 return status;
3129}
3130
3131static int out_flush(struct audio_stream_out* stream)
3132{
3133 struct stream_out *out = (struct stream_out *)stream;
3134 ALOGV("%s", __func__);
3135 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Christopher N. Hesse757ac412017-01-28 14:42:48 +01003136 return out_flush_offload(out);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003137 }
3138 return -ENOSYS;
3139}
3140
3141/** audio_stream_in implementation **/
3142static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3143{
3144 struct stream_in *in = (struct stream_in *)stream;
3145
3146 return in->requested_rate;
3147}
3148
3149static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
3150{
3151 (void)stream;
3152 (void)rate;
3153 return -ENOSYS;
3154}
3155
3156static uint32_t in_get_channels(const struct audio_stream *stream)
3157{
3158 struct stream_in *in = (struct stream_in *)stream;
3159
3160 return in->main_channels;
3161}
3162
3163static audio_format_t in_get_format(const struct audio_stream *stream)
3164{
3165 (void)stream;
3166 return AUDIO_FORMAT_PCM_16_BIT;
3167}
3168
3169static int in_set_format(struct audio_stream *stream, audio_format_t format)
3170{
3171 (void)stream;
3172 (void)format;
3173
3174 return -ENOSYS;
3175}
3176
3177static size_t in_get_buffer_size(const struct audio_stream *stream)
3178{
3179 struct stream_in *in = (struct stream_in *)stream;
3180
3181 return get_input_buffer_size(in->requested_rate,
3182 in_get_format(stream),
3183 audio_channel_count_from_in_mask(in->main_channels),
3184 in->usecase_type,
3185 in->devices);
3186}
3187
3188static int in_close_pcm_devices(struct stream_in *in)
3189{
3190 struct pcm_device *pcm_device;
3191 struct listnode *node;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003192
3193 list_for_each(node, &in->pcm_dev_list) {
3194 pcm_device = node_to_item(node, struct pcm_device, stream_list_node);
3195 if (pcm_device) {
3196 if (pcm_device->pcm)
3197 pcm_close(pcm_device->pcm);
3198 pcm_device->pcm = NULL;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003199 }
3200 }
3201 return 0;
3202}
3203
3204
3205/* must be called with stream and hw device mutex locked */
3206static int do_in_standby_l(struct stream_in *in)
3207{
3208 int status = 0;
3209
3210#ifdef PREPROCESSING_ENABLED
3211 struct audio_device *adev = in->dev;
3212#endif
3213 if (!in->standby) {
3214
3215 in_close_pcm_devices(in);
3216
3217#ifdef PREPROCESSING_ENABLED
3218 if (in->echo_reference != NULL) {
3219 /* stop reading from echo reference */
3220 in->echo_reference->read(in->echo_reference, NULL);
3221 put_echo_reference(adev, in->echo_reference);
3222 in->echo_reference = NULL;
3223 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003224#endif // PREPROCESSING_ENABLED
3225
3226 status = stop_input_stream(in);
3227
3228 if (in->read_buf) {
3229 free(in->read_buf);
3230 in->read_buf = NULL;
3231 }
3232
3233 in->standby = 1;
3234 }
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003235
3236 in->last_read_time_us = 0;
3237
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003238 return 0;
3239}
3240
3241// called with adev->lock_inputs locked
3242static int in_standby_l(struct stream_in *in)
3243{
3244 struct audio_device *adev = in->dev;
3245 int status = 0;
3246 lock_input_stream(in);
3247 if (!in->standby) {
3248 pthread_mutex_lock(&adev->lock);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003249 amplifier_input_stream_standby((struct audio_stream_in *) in);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003250 status = do_in_standby_l(in);
3251 pthread_mutex_unlock(&adev->lock);
3252 }
3253 pthread_mutex_unlock(&in->lock);
3254 return status;
3255}
3256
3257static int in_standby(struct audio_stream *stream)
3258{
3259 struct stream_in *in = (struct stream_in *)stream;
3260 struct audio_device *adev = in->dev;
3261 int status;
3262 ALOGV("%s: enter", __func__);
3263 pthread_mutex_lock(&adev->lock_inputs);
3264 status = in_standby_l(in);
3265 pthread_mutex_unlock(&adev->lock_inputs);
3266 ALOGV("%s: exit: status(%d)", __func__, status);
3267 return status;
3268}
3269
3270static int in_dump(const struct audio_stream *stream, int fd)
3271{
3272 (void)stream;
3273 (void)fd;
3274
3275 return 0;
3276}
3277
3278static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3279{
3280 struct stream_in *in = (struct stream_in *)stream;
3281 struct audio_device *adev = in->dev;
3282 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003283 char value[32];
3284 int ret, val = 0;
3285 struct audio_usecase *uc_info;
3286 bool do_standby = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003287 struct pcm_device *pcm_device;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003288
3289 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
3290 parms = str_parms_create_str(kvpairs);
3291
3292 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3293
3294 pthread_mutex_lock(&adev->lock_inputs);
3295 lock_input_stream(in);
3296 pthread_mutex_lock(&adev->lock);
3297 if (ret >= 0) {
3298 val = atoi(value);
3299 /* no audio source uses val == 0 */
3300 if (((int)in->source != val) && (val != 0)) {
3301 in->source = val;
3302 }
3303 }
3304
3305 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3306 if (ret >= 0) {
3307 val = atoi(value);
3308 if (((int)in->devices != val) && (val != 0)) {
3309 in->devices = val;
3310 /* If recording is in progress, change the tx device to new device */
3311 if (!in->standby) {
3312 uc_info = get_usecase_from_id(adev, in->usecase);
3313 if (uc_info == NULL) {
3314 ALOGE("%s: Could not find the usecase (%d) in the list",
3315 __func__, in->usecase);
3316 } else {
3317 if (list_empty(&in->pcm_dev_list))
3318 ALOGE("%s: pcm device list empty", __func__);
3319 else {
3320 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3321 struct pcm_device, stream_list_node);
3322 if ((pcm_device->pcm_profile->devices & val & ~AUDIO_DEVICE_BIT_IN) == 0) {
3323 do_standby = true;
3324 }
3325 }
3326 }
3327 if (do_standby) {
3328 ret = do_in_standby_l(in);
3329 } else
3330 ret = select_devices(adev, in->usecase);
3331 }
3332 }
3333 }
3334 pthread_mutex_unlock(&adev->lock);
3335 pthread_mutex_unlock(&in->lock);
3336 pthread_mutex_unlock(&adev->lock_inputs);
3337 str_parms_destroy(parms);
3338
3339 if (ret > 0)
3340 ret = 0;
3341
3342 ALOGV("%s: exit: status(%d)", __func__, ret);
3343 return ret;
3344}
3345
3346static char* in_get_parameters(const struct audio_stream *stream,
3347 const char *keys)
3348{
3349 (void)stream;
3350 (void)keys;
3351
3352 return strdup("");
3353}
3354
3355static int in_set_gain(struct audio_stream_in *stream, float gain)
3356{
3357 (void)stream;
3358 (void)gain;
3359
3360 return 0;
3361}
3362
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003363static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3364 size_t bytes)
3365{
3366 struct stream_in *in = (struct stream_in *)stream;
3367 struct audio_device *adev = in->dev;
3368 ssize_t frames = -1;
3369 int ret = -1;
3370 int read_and_process_successful = false;
3371
3372 size_t frames_rq = bytes / audio_stream_in_frame_size(stream);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003373
3374 /* no need to acquire adev->lock_inputs because API contract prevents a close */
3375 lock_input_stream(in);
3376
Andreas Schneider3b643832017-01-31 11:48:22 +01003377#if SUPPORTS_IRQ_AFFINITY
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003378 if (in->usecase == USECASE_AUDIO_CAPTURE && !in->is_fastcapture_affinity_set) {
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003379 pid_t tid = gettid();
3380 int err;
3381
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003382 err = fast_set_affinity(tid);
3383 if (err < 0) {
3384 ALOGW("Couldn't set affinity for tid %d; error %d", tid, err);
3385 }
3386 in->is_fastcapture_affinity_set = true;
3387 }
Andreas Schneider3b643832017-01-31 11:48:22 +01003388#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003389
3390 if (in->standby) {
3391 pthread_mutex_unlock(&in->lock);
3392 pthread_mutex_lock(&adev->lock_inputs);
3393 lock_input_stream(in);
3394 if (!in->standby) {
3395 pthread_mutex_unlock(&adev->lock_inputs);
3396 goto false_alarm;
3397 }
3398 pthread_mutex_lock(&adev->lock);
3399 ret = start_input_stream(in);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003400 if (ret == 0) {
3401 amplifier_input_stream_start(stream);
3402 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003403 pthread_mutex_unlock(&adev->lock);
3404 pthread_mutex_unlock(&adev->lock_inputs);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003405
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003406 if (ret != 0) {
3407 goto exit;
3408 }
3409 in->standby = 0;
3410 }
3411false_alarm:
3412
3413 if (!list_empty(&in->pcm_dev_list)) {
stenkinevgeniy44335362018-05-07 18:00:13 +00003414 /*
3415 * Read PCM and:
3416 * - resample if needed
3417 * - process if pre-processors are attached
3418 * - discard unwanted channels
3419 */
3420 frames = read_and_process_frames(in, buffer, frames_rq);
3421 if (frames >= 0)
3422 read_and_process_successful = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003423 }
3424
3425 /*
3426 * Instead of writing zeroes here, we could trust the hardware
3427 * to always provide zeroes when muted.
3428 */
3429 if (read_and_process_successful == true && adev->mic_mute)
3430 memset(buffer, 0, bytes);
3431
3432exit:
3433 pthread_mutex_unlock(&in->lock);
3434
3435 if (read_and_process_successful == false) {
3436 in_standby(&in->stream.common);
3437 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Christopher N. Hessee6b3a3e2017-01-08 00:03:23 +01003438 struct timespec t = { .tv_sec = 0, .tv_nsec = 0 };
3439 clock_gettime(CLOCK_MONOTONIC, &t);
3440 const int64_t now = (t.tv_sec * 1000000000LL + t.tv_nsec) / 1000;
3441
3442 // we do a full sleep when exiting standby.
3443 const bool standby = in->last_read_time_us == 0;
3444 const int64_t elapsed_time_since_last_read = standby ?
3445 0 : now - in->last_read_time_us;
3446 int64_t sleep_time = bytes * 1000000LL / audio_stream_in_frame_size(stream) /
3447 in_get_sample_rate(&stream->common) - elapsed_time_since_last_read;
3448 if (sleep_time > 0) {
3449 usleep(sleep_time);
3450 } else {
3451 sleep_time = 0;
3452 }
3453 in->last_read_time_us = now + sleep_time;
3454 // last_read_time_us is an approximation of when the (simulated) alsa
3455 // buffer is drained by the read, and is empty.
3456 //
3457 // On the subsequent in_read(), we measure the elapsed time spent in
3458 // the recording thread. This is subtracted from the sleep estimate based on frames,
3459 // thereby accounting for fill in the alsa buffer during the interim.
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003460 memset(buffer, 0, bytes);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003461 }
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003462
3463 if (bytes > 0) {
3464 in->frames_read += bytes / audio_stream_in_frame_size(stream);
3465 }
3466
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003467 return bytes;
3468}
3469
3470static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
3471{
3472 (void)stream;
3473
3474 return 0;
3475}
3476
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01003477static int in_get_capture_position(const struct audio_stream_in *stream,
3478 int64_t *frames, int64_t *time)
3479{
3480 if (stream == NULL || frames == NULL || time == NULL) {
3481 return -EINVAL;
3482 }
3483
3484 struct stream_in *in = (struct stream_in *)stream;
3485 struct pcm_device *pcm_device;
3486 int ret = -ENOSYS;
3487
3488 pcm_device = node_to_item(list_head(&in->pcm_dev_list),
3489 struct pcm_device, stream_list_node);
3490
3491 pthread_mutex_lock(&in->lock);
3492 if (pcm_device->pcm) {
3493 struct timespec timestamp;
3494 unsigned int avail;
3495 if (pcm_get_htimestamp(pcm_device->pcm, &avail, &timestamp) == 0) {
3496 *frames = in->frames_read + avail;
3497 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3498 ret = 0;
3499 }
3500 }
3501
3502 pthread_mutex_unlock(&in->lock);
3503 return ret;
3504}
3505
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003506static int add_remove_audio_effect(const struct audio_stream *stream,
3507 effect_handle_t effect,
3508 bool enable)
3509{
3510 struct stream_in *in = (struct stream_in *)stream;
3511 struct audio_device *adev = in->dev;
3512 int status = 0;
3513 effect_descriptor_t desc;
3514#ifdef PREPROCESSING_ENABLED
3515 int i;
3516#endif
3517 status = (*effect)->get_descriptor(effect, &desc);
3518 if (status != 0)
3519 return status;
3520
3521 ALOGI("add_remove_audio_effect(), effect type: %08x, enable: %d ", desc.type.timeLow, enable);
3522
3523 pthread_mutex_lock(&adev->lock_inputs);
3524 lock_input_stream(in);
3525 pthread_mutex_lock(&in->dev->lock);
3526#ifndef PREPROCESSING_ENABLED
3527 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3528 in->enable_aec != enable &&
3529 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3530 in->enable_aec = enable;
3531 if (!in->standby)
3532 select_devices(in->dev, in->usecase);
3533 }
3534#else
3535 if ( (in->num_preprocessors > MAX_PREPROCESSORS) && (enable == true) ) {
3536 status = -ENOSYS;
3537 goto exit;
3538 }
3539 if ( enable == true ) {
3540 in->preprocessors[in->num_preprocessors].effect_itfe = effect;
3541 /* add the supported channel of the effect in the channel_configs */
3542 in_read_audio_effect_channel_configs(in, &in->preprocessors[in->num_preprocessors]);
3543 in->num_preprocessors ++;
3544 /* check compatibility between main channel supported and possible auxiliary channels */
3545 in_update_aux_channels(in, effect);//wesley crash
3546 in->aux_channels_changed = true;
3547 } else {
3548 /* if ( enable == false ) */
3549 if (in->num_preprocessors <= 0) {
3550 status = -ENOSYS;
3551 goto exit;
3552 }
3553 status = -EINVAL;
3554 for (i=0; i < in->num_preprocessors; i++) {
3555 if (status == 0) { /* status == 0 means an effect was removed from a previous slot */
3556 in->preprocessors[i - 1].effect_itfe = in->preprocessors[i].effect_itfe;
3557 in->preprocessors[i - 1].channel_configs = in->preprocessors[i].channel_configs;
3558 in->preprocessors[i - 1].num_channel_configs =
3559 in->preprocessors[i].num_channel_configs;
3560 ALOGV("add_remove_audio_effect moving fx from %d to %d", i, i-1);
3561 continue;
3562 }
3563 if ( in->preprocessors[i].effect_itfe == effect ) {
3564 ALOGV("add_remove_audio_effect found fx at index %d", i);
3565 free(in->preprocessors[i].channel_configs);
3566 status = 0;
3567 }
3568 }
3569 if (status != 0)
3570 goto exit;
3571 in->num_preprocessors--;
3572 /* if we remove one effect, at least the last proproc should be reset */
3573 in->preprocessors[in->num_preprocessors].num_channel_configs = 0;
3574 in->preprocessors[in->num_preprocessors].effect_itfe = NULL;
3575 in->preprocessors[in->num_preprocessors].channel_configs = NULL;
3576 in->aux_channels_changed = false;
3577 ALOGV("%s: enable(%d), in->aux_channels_changed(%d)", __func__, enable, in->aux_channels_changed);
3578 }
3579 ALOGI("%s: num_preprocessors = %d", __func__, in->num_preprocessors);
3580
3581 if ( memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
3582 in->enable_aec = enable;
3583 ALOGV("add_remove_audio_effect(), FX_IID_AEC, enable: %d", enable);
3584 if (!in->standby) {
3585 select_devices(in->dev, in->usecase);
3586 do_in_standby_l(in);
3587 }
3588 if (in->enable_aec == true) {
3589 in_configure_reverse(in);
3590 }
3591 }
3592exit:
3593#endif
3594 ALOGW_IF(status != 0, "add_remove_audio_effect() error %d", status);
3595 pthread_mutex_unlock(&in->dev->lock);
3596 pthread_mutex_unlock(&in->lock);
3597 pthread_mutex_unlock(&adev->lock_inputs);
3598 return status;
3599}
3600
3601static int in_add_audio_effect(const struct audio_stream *stream,
3602 effect_handle_t effect)
3603{
3604 ALOGV("%s: effect %p", __func__, effect);
3605 return add_remove_audio_effect(stream, effect, true);
3606}
3607
3608static int in_remove_audio_effect(const struct audio_stream *stream,
3609 effect_handle_t effect)
3610{
3611 ALOGV("%s: effect %p", __func__, effect);
3612 return add_remove_audio_effect(stream, effect, false);
3613}
3614
3615static int adev_open_output_stream(struct audio_hw_device *dev,
3616 audio_io_handle_t handle,
3617 audio_devices_t devices,
3618 audio_output_flags_t flags,
3619 struct audio_config *config,
3620 struct audio_stream_out **stream_out,
3621 const char *address __unused)
3622{
3623 struct audio_device *adev = (struct audio_device *)dev;
3624 struct stream_out *out;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003625 int ret = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003626 struct pcm_device_profile *pcm_profile;
3627
3628 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3629 __func__, config->sample_rate, config->channel_mask, devices, flags);
3630 *stream_out = NULL;
3631 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
Andreas Schneider56204f62017-01-31 08:17:32 +01003632 if (out == NULL) {
3633 ret = -ENOMEM;
3634 goto error_config;
3635 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003636
3637 if (devices == AUDIO_DEVICE_NONE)
3638 devices = AUDIO_DEVICE_OUT_SPEAKER;
3639
3640 out->flags = flags;
3641 out->devices = devices;
3642 out->dev = adev;
3643 out->format = config->format;
3644 out->sample_rate = config->sample_rate;
3645 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3646 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
3647 out->handle = handle;
3648
3649 pcm_profile = get_pcm_device(PCM_PLAYBACK, devices);
3650 if (pcm_profile == NULL) {
3651 ret = -EINVAL;
3652 goto error_open;
3653 }
3654 out->config = pcm_profile->config;
3655
3656 /* Init use case and pcm_config */
3657 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3658 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3659 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3660 ALOGE("%s: Unsupported Offload information", __func__);
3661 ret = -EINVAL;
3662 goto error_open;
3663 }
3664 if (!is_supported_format(config->offload_info.format)) {
3665 ALOGE("%s: Unsupported audio format", __func__);
3666 ret = -EINVAL;
3667 goto error_open;
3668 }
3669
3670 out->compr_config.codec = (struct snd_codec *)
3671 calloc(1, sizeof(struct snd_codec));
Andreas Schneider56204f62017-01-31 08:17:32 +01003672 if (out->compr_config.codec == NULL) {
3673 ret = -ENOMEM;
3674 goto error_open;
3675 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003676
3677 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3678 if (config->offload_info.channel_mask)
3679 out->channel_mask = config->offload_info.channel_mask;
3680 else if (config->channel_mask)
3681 out->channel_mask = config->channel_mask;
3682 out->format = config->offload_info.format;
3683 out->sample_rate = config->offload_info.sample_rate;
3684
3685 out->stream.set_callback = out_set_callback;
3686 out->stream.pause = out_pause;
3687 out->stream.resume = out_resume;
3688 out->stream.drain = out_drain;
3689 out->stream.flush = out_flush;
3690
3691 out->compr_config.codec->id =
3692 get_snd_codec_id(config->offload_info.format);
3693 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3694 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
3695 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
3696 out->compr_config.codec->bit_rate =
3697 config->offload_info.bit_rate;
3698 out->compr_config.codec->ch_in =
3699 audio_channel_count_from_out_mask(config->channel_mask);
3700 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3701
3702 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3703 out->non_blocking = 1;
3704
3705 out->send_new_metadata = 1;
3706 create_offload_callback_thread(out);
3707 out->offload_state = OFFLOAD_STATE_IDLE;
3708
3709 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3710 __func__, config->offload_info.version,
3711 config->offload_info.bit_rate);
3712 } else if (out->flags & (AUDIO_OUTPUT_FLAG_DEEP_BUFFER)) {
3713 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
Christopher N. Hesse8414bd22017-01-30 18:57:20 +01003714 out->config = pcm_device_deep_buffer.config;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003715 out->sample_rate = out->config.rate;
3716 ALOGV("%s: use AUDIO_PLAYBACK_DEEP_BUFFER",__func__);
3717 } else {
3718 out->usecase = USECASE_AUDIO_PLAYBACK;
3719 out->sample_rate = out->config.rate;
3720 }
3721
3722 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
3723 if (adev->primary_output == NULL)
3724 adev->primary_output = out;
3725 else {
3726 ALOGE("%s: Primary output is already opened", __func__);
3727 ret = -EEXIST;
3728 goto error_open;
3729 }
3730 }
3731
3732 /* Check if this usecase is already existing */
3733 pthread_mutex_lock(&adev->lock);
3734 if (get_usecase_from_id(adev, out->usecase) != NULL) {
3735 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
3736 pthread_mutex_unlock(&adev->lock);
3737 ret = -EEXIST;
3738 goto error_open;
3739 }
3740 pthread_mutex_unlock(&adev->lock);
3741
3742 out->stream.common.get_sample_rate = out_get_sample_rate;
3743 out->stream.common.set_sample_rate = out_set_sample_rate;
3744 out->stream.common.get_buffer_size = out_get_buffer_size;
3745 out->stream.common.get_channels = out_get_channels;
3746 out->stream.common.get_format = out_get_format;
3747 out->stream.common.set_format = out_set_format;
3748 out->stream.common.standby = out_standby;
3749 out->stream.common.dump = out_dump;
3750 out->stream.common.set_parameters = out_set_parameters;
3751 out->stream.common.get_parameters = out_get_parameters;
3752 out->stream.common.add_audio_effect = out_add_audio_effect;
3753 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3754 out->stream.get_latency = out_get_latency;
3755 out->stream.set_volume = out_set_volume;
3756 out->stream.write = out_write;
3757 out->stream.get_render_position = out_get_render_position;
3758 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
3759 out->stream.get_presentation_position = out_get_presentation_position;
3760
3761 out->standby = 1;
3762 /* out->muted = false; by calloc() */
3763 /* out->written = 0; by calloc() */
3764
3765 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3766 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
3767 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3768
3769 config->format = out->stream.common.get_format(&out->stream.common);
3770 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3771 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3772
3773 out->is_fastmixer_affinity_set = false;
3774
3775 *stream_out = &out->stream;
3776 ALOGV("%s: exit", __func__);
3777 return 0;
3778
3779error_open:
3780 free(out);
3781 *stream_out = NULL;
Andreas Schneider56204f62017-01-31 08:17:32 +01003782error_config:
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003783 ALOGV("%s: exit: ret %d", __func__, ret);
3784 return ret;
3785}
3786
3787static void adev_close_output_stream(struct audio_hw_device *dev,
3788 struct audio_stream_out *stream)
3789{
3790 struct stream_out *out = (struct stream_out *)stream;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003791 (void)dev;
3792
3793 ALOGV("%s: enter", __func__);
3794 out_standby(&stream->common);
3795 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3796 destroy_offload_callback_thread(out);
3797
3798 if (out->compr_config.codec != NULL)
3799 free(out->compr_config.codec);
3800 }
3801 pthread_cond_destroy(&out->cond);
3802 pthread_mutex_destroy(&out->lock);
3803 free(stream);
3804 ALOGV("%s: exit", __func__);
3805}
3806
3807static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3808{
3809 struct audio_device *adev = (struct audio_device *)dev;
3810 struct str_parms *parms;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003811 char value[32];
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003812#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003813 int val;
Andreas Schneider5a2f1002017-02-09 10:59:04 +01003814#endif
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003815 int ret;
3816
3817 ALOGV("%s: enter: %s", __func__, kvpairs);
3818
3819 parms = str_parms_create_str(kvpairs);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003820
Andreas Schneider05bc1882017-02-09 14:03:11 +01003821 /******************************************************
3822 *** BT SCO
3823 ******************************************************/
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003824 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3825 if (ret >= 0) {
3826 /* When set to false, HAL should disable EC and NS
3827 * But it is currently not supported.
3828 */
3829 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003830 adev->voice.bluetooth_nrec = true;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003831 else
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003832 adev->voice.bluetooth_nrec = false;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003833 }
3834
Andreas Schneider05bc1882017-02-09 14:03:11 +01003835 ret = str_parms_get_str(parms,
3836 AUDIO_PARAMETER_KEY_BT_SCO_WB,
3837 value,
3838 sizeof(value));
3839 if (ret >= 0) {
Andreas Schneider05bc1882017-02-09 14:03:11 +01003840 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0) {
3841 adev->voice.bluetooth_wb = true;
Andreas Schneider05bc1882017-02-09 14:03:11 +01003842 } else {
3843 adev->voice.bluetooth_wb = false;
3844 }
3845 }
3846
Andreas Schneiderecd17ce2017-02-09 10:45:21 +01003847 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3848 if (ret >= 0) {
3849 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3850 adev->screen_off = false;
3851 else
3852 adev->screen_off = true;
3853 }
3854
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003855#if SWAP_SPEAKER_ON_SCREEN_ROTATION
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003856 ret = str_parms_get_int(parms, "rotation", &val);
3857 if (ret >= 0) {
3858 bool reverse_speakers = false;
3859 switch(val) {
3860 /* FIXME: note that the code below assumes that the speakers are in the correct placement
3861 relative to the user when the device is rotated 90deg from its default rotation. This
3862 assumption is device-specific, not platform-specific like this code. */
3863 case 270:
3864 reverse_speakers = true;
3865 break;
3866 case 0:
3867 case 90:
3868 case 180:
3869 break;
3870 default:
3871 ALOGE("%s: unexpected rotation of %d", __func__, val);
3872 }
3873 pthread_mutex_lock(&adev->lock);
3874 if (adev->speaker_lr_swap != reverse_speakers) {
3875 adev->speaker_lr_swap = reverse_speakers;
3876 /* only update the selected device if there is active pcm playback */
3877 struct audio_usecase *usecase;
3878 struct listnode *node;
3879 list_for_each(node, &adev->usecase_list) {
3880 usecase = node_to_item(node, struct audio_usecase, adev_list_node);
3881 if (usecase->type == PCM_PLAYBACK) {
3882 select_devices(adev, usecase->id);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003883 break;
3884 }
3885 }
3886 }
3887 pthread_mutex_unlock(&adev->lock);
3888 }
Andreas Schneiderdc15cec2017-01-30 22:36:25 +01003889#endif /* SWAP_SPEAKER_ON_SCREEN_ROTATION */
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003890
3891 str_parms_destroy(parms);
3892
3893 if (ret > 0)
3894 ret = 0;
3895
3896 ALOGV("%s: exit with code(%d)", __func__, ret);
3897 return ret;
3898}
3899
3900static char* adev_get_parameters(const struct audio_hw_device *dev,
3901 const char *keys)
3902{
3903 (void)dev;
3904 (void)keys;
3905
3906 return strdup("");
3907}
3908
3909static int adev_init_check(const struct audio_hw_device *dev)
3910{
3911 (void)dev;
3912
3913 return 0;
3914}
3915
3916static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3917{
3918 int ret = 0;
3919 struct audio_device *adev = (struct audio_device *)dev;
3920 pthread_mutex_lock(&adev->lock);
3921 /* cache volume */
Andreas Schneider74ef3a12017-02-02 18:29:12 +01003922 adev->voice.volume = volume;
3923 ret = set_voice_volume_l(adev, adev->voice.volume);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003924 pthread_mutex_unlock(&adev->lock);
3925 return ret;
3926}
3927
3928static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
3929{
3930 (void)dev;
3931 (void)volume;
3932
3933 return -ENOSYS;
3934}
3935
3936static int adev_get_master_volume(struct audio_hw_device *dev,
3937 float *volume)
3938{
3939 (void)dev;
3940 (void)volume;
3941
3942 return -ENOSYS;
3943}
3944
3945static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
3946{
3947 (void)dev;
3948 (void)muted;
3949
3950 return -ENOSYS;
3951}
3952
3953static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
3954{
3955 (void)dev;
3956 (void)muted;
3957
3958 return -ENOSYS;
3959}
3960
3961static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3962{
3963 struct audio_device *adev = (struct audio_device *)dev;
3964
3965 pthread_mutex_lock(&adev->lock);
3966 if (adev->mode != mode) {
3967 ALOGI("%s mode = %d", __func__, mode);
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02003968 if (amplifier_set_mode(mode) != 0) {
3969 ALOGE("Failed setting amplifier mode");
3970 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003971 adev->mode = mode;
Christopher N. Hesse6c0020c2017-11-17 20:41:11 +01003972
3973 if ((mode == AUDIO_MODE_NORMAL) && adev->voice.in_call) {
3974 stop_voice_call(adev);
3975 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003976 }
3977 pthread_mutex_unlock(&adev->lock);
3978 return 0;
3979}
3980
3981static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3982{
3983 struct audio_device *adev = (struct audio_device *)dev;
3984 int err = 0;
3985
3986 pthread_mutex_lock(&adev->lock);
3987 adev->mic_mute = state;
3988
3989 if (adev->mode == AUDIO_MODE_IN_CALL) {
Andreas Schneider107a8482017-02-06 12:36:31 +01003990 set_voice_session_mic_mute(adev->voice.session, state);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01003991 }
3992
3993 pthread_mutex_unlock(&adev->lock);
3994 return err;
3995}
3996
3997static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3998{
3999 struct audio_device *adev = (struct audio_device *)dev;
4000
4001 *state = adev->mic_mute;
4002
4003 return 0;
4004}
4005
4006static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
4007 const struct audio_config *config)
4008{
4009 (void)dev;
4010
4011 /* NOTE: we default to built in mic which may cause a mismatch between what we
4012 * report here and the actual buffer size
4013 */
4014 return get_input_buffer_size(config->sample_rate,
4015 config->format,
4016 audio_channel_count_from_in_mask(config->channel_mask),
4017 PCM_CAPTURE /* usecase_type */,
4018 AUDIO_DEVICE_IN_BUILTIN_MIC);
4019}
4020
4021static int adev_open_input_stream(struct audio_hw_device *dev,
4022 audio_io_handle_t handle __unused,
4023 audio_devices_t devices,
4024 struct audio_config *config,
4025 struct audio_stream_in **stream_in,
4026 audio_input_flags_t flags,
4027 const char *address __unused,
4028 audio_source_t source)
4029{
4030 struct audio_device *adev = (struct audio_device *)dev;
4031 struct stream_in *in;
4032 struct pcm_device_profile *pcm_profile;
4033
4034 ALOGV("%s: enter", __func__);
4035
4036 *stream_in = NULL;
4037 if (check_input_parameters(config->sample_rate, config->format,
4038 audio_channel_count_from_in_mask(config->channel_mask)) != 0)
4039 return -EINVAL;
4040
stenkinevgeniy44335362018-05-07 18:00:13 +00004041 usecase_type_t usecase_type = flags & AUDIO_INPUT_FLAG_FAST ?
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004042 PCM_CAPTURE_LOW_LATENCY : PCM_CAPTURE;
4043 pcm_profile = get_pcm_device(usecase_type, devices);
4044 if (pcm_profile == NULL && usecase_type == PCM_CAPTURE_LOW_LATENCY) {
4045 // a low latency profile may not exist for that device, fall back
4046 // to regular capture. the MixerThread automatically changes
4047 // to non-fast capture based on the buffer size.
4048 flags &= ~AUDIO_INPUT_FLAG_FAST;
4049 usecase_type = PCM_CAPTURE;
4050 pcm_profile = get_pcm_device(usecase_type, devices);
4051 }
4052 if (pcm_profile == NULL)
4053 return -EINVAL;
4054
4055 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Andreas Schneider56204f62017-01-31 08:17:32 +01004056 if (in == NULL) {
4057 return -ENOMEM;
4058 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004059
4060 in->stream.common.get_sample_rate = in_get_sample_rate;
4061 in->stream.common.set_sample_rate = in_set_sample_rate;
4062 in->stream.common.get_buffer_size = in_get_buffer_size;
4063 in->stream.common.get_channels = in_get_channels;
4064 in->stream.common.get_format = in_get_format;
4065 in->stream.common.set_format = in_set_format;
4066 in->stream.common.standby = in_standby;
4067 in->stream.common.dump = in_dump;
4068 in->stream.common.set_parameters = in_set_parameters;
4069 in->stream.common.get_parameters = in_get_parameters;
4070 in->stream.common.add_audio_effect = in_add_audio_effect;
4071 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4072 in->stream.set_gain = in_set_gain;
4073 in->stream.read = in_read;
4074 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004075 in->stream.get_capture_position = in_get_capture_position;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004076
4077 in->devices = devices;
4078 in->source = source;
4079 in->dev = adev;
4080 in->standby = 1;
4081 in->main_channels = config->channel_mask;
4082 in->requested_rate = config->sample_rate;
4083 if (config->sample_rate != CAPTURE_DEFAULT_SAMPLING_RATE)
4084 flags = flags & ~AUDIO_INPUT_FLAG_FAST;
4085 in->input_flags = flags;
Christopher N. Hessece6d5af2017-01-12 11:40:30 +01004086 // in->frames_read = 0;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004087 /* HW codec is limited to default channels. No need to update with
4088 * requested channels */
4089 in->config = pcm_profile->config;
4090
4091 /* Update config params with the requested sample rate and channels */
stenkinevgeniy44335362018-05-07 18:00:13 +00004092 in->usecase = USECASE_AUDIO_CAPTURE;
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004093 in->usecase_type = usecase_type;
4094
4095 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
4096 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
4097
4098 in->is_fastcapture_affinity_set = false;
4099
4100 *stream_in = &in->stream;
4101 ALOGV("%s: exit", __func__);
4102 return 0;
4103}
4104
4105static void adev_close_input_stream(struct audio_hw_device *dev,
4106 struct audio_stream_in *stream)
4107{
4108 struct audio_device *adev = (struct audio_device *)dev;
4109 struct stream_in *in = (struct stream_in*)stream;
4110 ALOGV("%s", __func__);
4111
4112 /* prevent concurrent out_set_parameters, or out_write from standby */
4113 pthread_mutex_lock(&adev->lock_inputs);
4114
Andreas Schneidercabe5e62017-01-30 10:57:06 +01004115 if (in->read_buf) {
4116 free(in->read_buf);
4117 in->read_buf = NULL;
4118 }
4119
4120 if (in->resampler) {
4121 release_resampler(in->resampler);
4122 in->resampler = NULL;
4123 }
4124
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004125#ifdef PREPROCESSING_ENABLED
4126 int i;
4127
4128 for (i=0; i<in->num_preprocessors; i++) {
4129 free(in->preprocessors[i].channel_configs);
4130 }
4131
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004132 if (in->proc_buf_in) {
4133 free(in->proc_buf_in);
4134 in->proc_buf_in = NULL;
4135 }
4136
4137 if (in->proc_buf_out) {
4138 free(in->proc_buf_out);
4139 in->proc_buf_out = NULL;
4140 }
4141
4142 if (in->ref_buf) {
4143 free(in->ref_buf);
4144 in->ref_buf = NULL;
4145 }
4146
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004147#endif
4148
4149 in_standby_l(in);
4150 free(stream);
4151
4152 pthread_mutex_unlock(&adev->lock_inputs);
4153
4154 return;
4155}
4156
4157static int adev_dump(const audio_hw_device_t *device, int fd)
4158{
4159 (void)device;
4160 (void)fd;
4161
4162 return 0;
4163}
4164
4165static int adev_close(hw_device_t *device)
4166{
4167 struct audio_device *adev = (struct audio_device *)device;
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004168 voice_session_deinit(adev->voice.session);
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004169 audio_device_ref_count--;
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004170 if (audio_device_ref_count == 0) {
4171 if (amplifier_close() != 0) {
4172 ALOGE("Amplifier close failed");
4173 }
4174 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004175 free(adev->snd_dev_ref_cnt);
4176 free_mixer_list(adev);
4177 free(device);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004178
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004179 adev = NULL;
4180
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004181 return 0;
4182}
4183
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004184/* This returns true if the input parameter looks at all plausible as a low latency period size,
4185 * or false otherwise. A return value of true doesn't mean the value is guaranteed to work,
4186 * just that it _might_ work.
4187 */
4188static bool period_size_is_plausible_for_low_latency(int period_size)
4189{
4190 switch (period_size) {
4191 case 64:
4192 case 96:
4193 case 128:
4194 case 192:
4195 case 256:
4196 return true;
4197 default:
4198 return false;
4199 }
4200}
4201
4202static int adev_open(const hw_module_t *module, const char *name,
4203 hw_device_t **device)
4204{
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004205 ALOGV("%s: enter", __func__);
4206 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
4207
Andreas Schneider56204f62017-01-31 08:17:32 +01004208 *device = NULL;
4209
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004210 adev = calloc(1, sizeof(struct audio_device));
Andreas Schneider56204f62017-01-31 08:17:32 +01004211 if (adev == NULL) {
4212 return -ENOMEM;
4213 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004214
4215 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4216 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4217 adev->device.common.module = (struct hw_module_t *)module;
4218 adev->device.common.close = adev_close;
4219
4220 adev->device.init_check = adev_init_check;
4221 adev->device.set_voice_volume = adev_set_voice_volume;
4222 adev->device.set_master_volume = adev_set_master_volume;
4223 adev->device.get_master_volume = adev_get_master_volume;
4224 adev->device.set_master_mute = adev_set_master_mute;
4225 adev->device.get_master_mute = adev_get_master_mute;
4226 adev->device.set_mode = adev_set_mode;
4227 adev->device.set_mic_mute = adev_set_mic_mute;
4228 adev->device.get_mic_mute = adev_get_mic_mute;
4229 adev->device.set_parameters = adev_set_parameters;
4230 adev->device.get_parameters = adev_get_parameters;
4231 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4232 adev->device.open_output_stream = adev_open_output_stream;
4233 adev->device.close_output_stream = adev_close_output_stream;
4234 adev->device.open_input_stream = adev_open_input_stream;
4235 adev->device.close_input_stream = adev_close_input_stream;
4236 adev->device.dump = adev_dump;
4237
4238 /* Set the default route before the PCM stream is opened */
4239 adev->mode = AUDIO_MODE_NORMAL;
4240 adev->active_input = NULL;
4241 adev->primary_output = NULL;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004242
4243 adev->voice.volume = 1.0f;
4244 adev->voice.bluetooth_nrec = true;
4245 adev->voice.in_call = false;
Christopher N. Hessee4a1c592018-01-16 18:33:38 +01004246 adev->voice.bluetooth_wb = false;
Andreas Schneider74ef3a12017-02-02 18:29:12 +01004247
stenkinevgeniy53929f72018-07-09 11:20:36 +00004248 adev->bt_sco_active = false;
4249
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004250 /* adev->cur_hdmi_channels = 0; by calloc() */
4251 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Andreas Schneider56204f62017-01-31 08:17:32 +01004252 if (adev->snd_dev_ref_cnt == NULL) {
4253 free(adev);
4254 return -ENOMEM;
4255 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004256
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004257 adev->ns_in_voice_rec = false;
4258
4259 list_init(&adev->usecase_list);
4260
4261 if (mixer_init(adev) != 0) {
4262 free(adev->snd_dev_ref_cnt);
4263 free(adev);
4264 ALOGE("%s: Failed to init, aborting.", __func__);
4265 *device = NULL;
4266 return -EINVAL;
4267 }
4268
4269 if (access(OFFLOAD_FX_LIBRARY_PATH, R_OK) == 0) {
4270 adev->offload_fx_lib = dlopen(OFFLOAD_FX_LIBRARY_PATH, RTLD_NOW);
4271 if (adev->offload_fx_lib == NULL) {
4272 ALOGE("%s: DLOPEN failed for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4273 } else {
4274 ALOGV("%s: DLOPEN successful for %s", __func__, OFFLOAD_FX_LIBRARY_PATH);
4275 adev->offload_fx_start_output =
4276 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4277 "visualizer_hal_start_output");
4278 adev->offload_fx_stop_output =
4279 (int (*)(audio_io_handle_t))dlsym(adev->offload_fx_lib,
4280 "visualizer_hal_stop_output");
4281 }
4282 }
4283
Christopher N. Hesse696959d2017-02-02 20:49:55 +01004284 adev->voice.session = voice_session_init(adev);
Christopher N. Hesse41c9f3d2017-02-02 20:48:56 +01004285 if (adev->voice.session == NULL) {
4286 ALOGE("%s: Failed to initialize voice session data", __func__);
4287
4288 free(adev->snd_dev_ref_cnt);
4289 free(adev);
4290
4291 *device = NULL;
4292 return -EINVAL;
4293 }
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004294
Christopher N. Hessec487bbe2018-07-12 13:51:43 +02004295 if (amplifier_open() != -ENOENT) {
Christopher N. Hesse6a2a3072017-08-04 21:17:55 +02004296 ALOGE("Amplifier initialization failed");
4297 }
4298
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004299 *device = &adev->device.common;
4300
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004301 audio_device_ref_count++;
4302
4303 char value[PROPERTY_VALUE_MAX];
4304 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4305 int trial = atoi(value);
4306 if (period_size_is_plausible_for_low_latency(trial)) {
4307
4308 pcm_device_playback.config.period_size = trial;
4309 pcm_device_playback.config.start_threshold =
4310 PLAYBACK_START_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4311 pcm_device_playback.config.stop_threshold =
4312 PLAYBACK_STOP_THRESHOLD(trial, PLAYBACK_PERIOD_COUNT);
4313
4314 pcm_device_capture_low_latency.config.period_size = trial;
4315 }
4316 }
4317
4318 ALOGV("%s: exit", __func__);
4319 return 0;
4320}
4321
4322static struct hw_module_methods_t hal_module_methods = {
4323 .open = adev_open,
4324};
4325
4326struct audio_module HAL_MODULE_INFO_SYM = {
4327 .common = {
4328 .tag = HARDWARE_MODULE_TAG,
4329 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4330 .hal_api_version = HARDWARE_HAL_API_VERSION,
4331 .id = AUDIO_HARDWARE_MODULE_ID,
Christopher N. Hessec8502b92017-01-28 14:02:15 +01004332 .name = "Samsung Audio HAL",
4333 .author = "The LineageOS Project",
Christopher N. Hesse297a6362017-01-28 12:40:45 +01004334 .methods = &hal_module_methods,
4335 },
4336};