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