blob: c0cd55dd6de1077d8be23d48b73ae7e2145cf8c0 [file] [log] [blame]
Amit Pundir4e375822019-04-18 16:46:10 +05301/*
Amit Pundire6732bb2020-09-28 12:43:59 +05302 * Copyright (C) 2016 The Android Open Source Project
Amit Pundir4e375822019-04-18 16:46:10 +05303 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Amit Pundir456949d2020-02-18 22:44:16 +053015 *
Amit Pundire6732bb2020-09-28 12:43:59 +053016 * Copied as it is from device/amlogic/generic/hal/audio/
Amit Pundir4e375822019-04-18 16:46:10 +053017 */
18
Amit Pundire6732bb2020-09-28 12:43:59 +053019#define LOG_TAG "audio_hw_yukawa"
20//#define LOG_NDEBUG 0
Amit Pundir4e375822019-04-18 16:46:10 +053021
22#include <errno.h>
Amit Pundir456949d2020-02-18 22:44:16 +053023#include <inttypes.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053024#include <malloc.h>
Amit Pundir4e375822019-04-18 16:46:10 +053025#include <pthread.h>
26#include <stdint.h>
Amit Pundir4e375822019-04-18 16:46:10 +053027#include <stdlib.h>
Amit Pundir456949d2020-02-18 22:44:16 +053028#include <sys/time.h>
Amit Pundir4e375822019-04-18 16:46:10 +053029#include <unistd.h>
30
31#include <log/log.h>
32#include <cutils/str_parms.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053033#include <cutils/properties.h>
Amit Pundir4e375822019-04-18 16:46:10 +053034
35#include <hardware/hardware.h>
36#include <system/audio.h>
37#include <hardware/audio.h>
Amit Pundire6732bb2020-09-28 12:43:59 +053038
39#include <audio_effects/effect_aec.h>
40#include <audio_route/audio_route.h>
41#include <audio_utils/clock.h>
42#include <audio_utils/echo_reference.h>
43#include <audio_utils/resampler.h>
44#include <hardware/audio_alsaops.h>
45#include <hardware/audio_effect.h>
46#include <sound/asound.h>
Amit Pundir4e375822019-04-18 16:46:10 +053047#include <tinyalsa/asoundlib.h>
Amit Pundir456949d2020-02-18 22:44:16 +053048
Amit Pundire6732bb2020-09-28 12:43:59 +053049#include <sys/ioctl.h>
Amit Pundir4e375822019-04-18 16:46:10 +053050
Amit Pundire6732bb2020-09-28 12:43:59 +053051#include "audio_aec.h"
52#include "audio_hw.h"
Amit Pundir4e375822019-04-18 16:46:10 +053053
Amit Pundire6732bb2020-09-28 12:43:59 +053054static int adev_get_mic_mute(const struct audio_hw_device* dev, bool* state);
55static int adev_get_microphones(const struct audio_hw_device* dev,
56 struct audio_microphone_characteristic_t* mic_array,
57 size_t* mic_count);
58static size_t out_get_buffer_size(const struct audio_stream* stream);
Amit Pundir4e375822019-04-18 16:46:10 +053059
Alden DSouzae44e0672021-02-11 17:07:01 -080060static bool is_aec_input(const struct alsa_stream_in* in) {
61 /* If AEC is in the app, only configure based on ECHO_REFERENCE spec.
62 * If AEC is in the HAL, configure using the given mic stream. */
63 bool aec_input = true;
64#if !defined(AEC_HAL)
65 aec_input = (in->source == AUDIO_SOURCE_ECHO_REFERENCE);
66#endif
67 return aec_input;
68}
69
Amit Pundire6732bb2020-09-28 12:43:59 +053070static int get_audio_output_port(audio_devices_t devices) {
71 /* Only HDMI out for now #FIXME */
72 return PORT_HDMI;
Amit Pundir4e375822019-04-18 16:46:10 +053073}
74
John Stultz57a02362021-09-02 03:26:56 +000075static int get_audio_card(int direction, int port) {
76 struct pcm_params* params = NULL;
77 int card = 0;
78
79 while (!params && card < 8) {
80 /* Find the first input/output device that works */
81 params = pcm_params_get(card, port, direction);
82 card++;
83 }
84 pcm_params_free(params);
85
86 return card - 1;
87}
88
Amit Pundire6732bb2020-09-28 12:43:59 +053089static void timestamp_adjust(struct timespec* ts, ssize_t frames, uint32_t sampling_rate) {
90 /* This function assumes the adjustment (in nsec) is less than the max value of long,
91 * which for 32-bit long this is 2^31 * 1e-9 seconds, slightly over 2 seconds.
92 * For 64-bit long it is 9e+9 seconds. */
93 long adj_nsec = (frames / (float) sampling_rate) * 1E9L;
94 ts->tv_nsec += adj_nsec;
95 while (ts->tv_nsec > 1E9L) {
96 ts->tv_sec++;
97 ts->tv_nsec -= 1E9L;
Amit Pundir456949d2020-02-18 22:44:16 +053098 }
Amit Pundire6732bb2020-09-28 12:43:59 +053099 if (ts->tv_nsec < 0) {
100 ts->tv_sec--;
101 ts->tv_nsec += 1E9L;
102 }
Amit Pundir456949d2020-02-18 22:44:16 +0530103}
104
Amit Pundire6732bb2020-09-28 12:43:59 +0530105/* Helper function to get PCM hardware timestamp.
106 * Only the field 'timestamp' of argument 'ts' is updated. */
107static int get_pcm_timestamp(struct pcm* pcm, uint32_t sample_rate, struct aec_info* info,
108 bool isOutput) {
109 int ret = 0;
110 if (pcm_get_htimestamp(pcm, &info->available, &info->timestamp) < 0) {
111 ALOGE("Error getting PCM timestamp!");
112 info->timestamp.tv_sec = 0;
113 info->timestamp.tv_nsec = 0;
Amit Pundir456949d2020-02-18 22:44:16 +0530114 return -EINVAL;
115 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530116 ssize_t frames;
117 if (isOutput) {
118 frames = pcm_get_buffer_size(pcm) - info->available;
119 } else {
120 frames = -info->available; /* rewind timestamp */
121 }
122 timestamp_adjust(&info->timestamp, frames, sample_rate);
123 return ret;
Amit Pundir456949d2020-02-18 22:44:16 +0530124}
125
Amit Pundire6732bb2020-09-28 12:43:59 +0530126static int read_filter_from_file(const char* filename, int16_t* filter, int max_length) {
127 FILE* fp = fopen(filename, "r");
128 if (fp == NULL) {
129 ALOGI("%s: File %s not found.", __func__, filename);
130 return 0;
131 }
132 int num_taps = 0;
133 char* line = NULL;
134 size_t len = 0;
135 while (!feof(fp)) {
136 size_t size = getline(&line, &len, fp);
137 if ((line[0] == '#') || (size < 2)) {
138 continue;
139 }
140 int n = sscanf(line, "%" SCNd16 "\n", &filter[num_taps++]);
141 if (n < 1) {
142 ALOGE("Could not find coefficient %d! Exiting...", num_taps - 1);
143 return 0;
144 }
145 ALOGV("Coeff %d : %" PRId16, num_taps, filter[num_taps - 1]);
146 if (num_taps == max_length) {
147 ALOGI("%s: max tap length %d reached.", __func__, max_length);
Amit Pundir456949d2020-02-18 22:44:16 +0530148 break;
149 }
Amit Pundir456949d2020-02-18 22:44:16 +0530150 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530151 free(line);
152 fclose(fp);
153 return num_taps;
Amit Pundir456949d2020-02-18 22:44:16 +0530154}
155
Amit Pundire6732bb2020-09-28 12:43:59 +0530156static void out_set_eq(struct alsa_stream_out* out) {
157 out->speaker_eq = NULL;
158 int16_t* speaker_eq_coeffs = (int16_t*)calloc(SPEAKER_MAX_EQ_LENGTH, sizeof(int16_t));
159 if (speaker_eq_coeffs == NULL) {
160 ALOGE("%s: Failed to allocate speaker EQ", __func__);
161 return;
162 }
163 int num_taps = read_filter_from_file(SPEAKER_EQ_FILE, speaker_eq_coeffs, SPEAKER_MAX_EQ_LENGTH);
164 if (num_taps == 0) {
165 ALOGI("%s: Empty filter file or 0 taps set.", __func__);
166 free(speaker_eq_coeffs);
167 return;
168 }
169 out->speaker_eq = fir_init(
170 out->config.channels, FIR_SINGLE_FILTER, num_taps,
171 out_get_buffer_size(&out->stream.common) / out->config.channels / sizeof(int16_t),
172 speaker_eq_coeffs);
173 free(speaker_eq_coeffs);
174}
Amit Pundir456949d2020-02-18 22:44:16 +0530175
Amit Pundire6732bb2020-09-28 12:43:59 +0530176/* must be called with hw device and output stream mutexes locked */
177static int start_output_stream(struct alsa_stream_out *out)
178{
179 struct alsa_audio_device *adev = out->dev;
180
181 /* default to low power: will be corrected in out_write if necessary before first write to
182 * tinyalsa.
183 */
184 out->write_threshold = PLAYBACK_PERIOD_COUNT * PLAYBACK_PERIOD_SIZE;
185 out->config.start_threshold = PLAYBACK_PERIOD_START_THRESHOLD * PLAYBACK_PERIOD_SIZE;
186 out->config.avail_min = PLAYBACK_PERIOD_SIZE;
187 out->unavailable = true;
188 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
189 int out_port = get_audio_output_port(out->devices);
John Stultz57a02362021-09-02 03:26:56 +0000190 int out_card = get_audio_card(PCM_OUT, out_port);
Amit Pundire6732bb2020-09-28 12:43:59 +0530191
192 while (1) {
John Stultz57a02362021-09-02 03:26:56 +0000193 out->pcm = pcm_open(out_card, out_port, PCM_OUT | PCM_MONOTONIC, &out->config);
Amit Pundire6732bb2020-09-28 12:43:59 +0530194 if ((out->pcm != NULL) && pcm_is_ready(out->pcm)) {
Amit Pundir456949d2020-02-18 22:44:16 +0530195 break;
Amit Pundire6732bb2020-09-28 12:43:59 +0530196 } else {
197 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm));
198 if (out->pcm != NULL) {
199 pcm_close(out->pcm);
200 out->pcm = NULL;
201 }
202 if (--pcm_retry_count == 0) {
203 ALOGE("Failed to open pcm_out after %d tries", PCM_OPEN_RETRIES);
204 return -ENODEV;
205 }
206 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
Amit Pundir456949d2020-02-18 22:44:16 +0530207 }
Amit Pundir456949d2020-02-18 22:44:16 +0530208 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530209 out->unavailable = false;
210 adev->active_output = out;
211 return 0;
Amit Pundir456949d2020-02-18 22:44:16 +0530212}
213
Amit Pundir4e375822019-04-18 16:46:10 +0530214static uint32_t out_get_sample_rate(const struct audio_stream *stream)
215{
Amit Pundire6732bb2020-09-28 12:43:59 +0530216 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
217 return out->config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530218}
219
220static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
221{
Amit Pundire6732bb2020-09-28 12:43:59 +0530222 ALOGV("out_set_sample_rate: %d", 0);
Amit Pundir4e375822019-04-18 16:46:10 +0530223 return -ENOSYS;
224}
225
226static size_t out_get_buffer_size(const struct audio_stream *stream)
227{
Amit Pundire6732bb2020-09-28 12:43:59 +0530228 ALOGV("out_get_buffer_size: %d", 4096);
Amit Pundir4e375822019-04-18 16:46:10 +0530229
Amit Pundire6732bb2020-09-28 12:43:59 +0530230 /* return the closest majoring multiple of 16 frames, as
231 * audioflinger expects audio buffers to be a multiple of 16 frames */
232 size_t size = PLAYBACK_PERIOD_SIZE;
233 size = ((size + 15) / 16) * 16;
234 return size * audio_stream_out_frame_size((struct audio_stream_out *)stream);
Amit Pundir4e375822019-04-18 16:46:10 +0530235}
236
237static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
238{
Amit Pundire6732bb2020-09-28 12:43:59 +0530239 ALOGV("out_get_channels");
240 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
241 return audio_channel_out_mask_from_count(out->config.channels);
Amit Pundir4e375822019-04-18 16:46:10 +0530242}
243
244static audio_format_t out_get_format(const struct audio_stream *stream)
245{
Amit Pundire6732bb2020-09-28 12:43:59 +0530246 ALOGV("out_get_format");
247 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
248 return audio_format_from_pcm_format(out->config.format);
Amit Pundir4e375822019-04-18 16:46:10 +0530249}
250
251static int out_set_format(struct audio_stream *stream, audio_format_t format)
252{
Amit Pundire6732bb2020-09-28 12:43:59 +0530253 ALOGV("out_set_format: %d",format);
Amit Pundir4e375822019-04-18 16:46:10 +0530254 return -ENOSYS;
255}
256
Amit Pundire6732bb2020-09-28 12:43:59 +0530257static int do_output_standby(struct alsa_stream_out *out)
258{
259 struct alsa_audio_device *adev = out->dev;
260
261 fir_reset(out->speaker_eq);
262
263 if (!out->standby) {
264 pcm_close(out->pcm);
265 out->pcm = NULL;
266 adev->active_output = NULL;
267 out->standby = 1;
268 }
269 aec_set_spk_running(adev->aec, false);
270 return 0;
271}
272
273static int out_standby(struct audio_stream *stream)
274{
275 ALOGV("out_standby");
276 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
277 int status;
278
279 pthread_mutex_lock(&out->dev->lock);
280 pthread_mutex_lock(&out->lock);
281 status = do_output_standby(out);
282 pthread_mutex_unlock(&out->lock);
283 pthread_mutex_unlock(&out->dev->lock);
284 return status;
285}
286
Amit Pundir4e375822019-04-18 16:46:10 +0530287static int out_dump(const struct audio_stream *stream, int fd)
288{
Amit Pundire6732bb2020-09-28 12:43:59 +0530289 ALOGV("out_dump");
Amit Pundir4e375822019-04-18 16:46:10 +0530290 return 0;
291}
292
293static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
294{
Amit Pundire6732bb2020-09-28 12:43:59 +0530295 ALOGV("out_set_parameters");
296 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
297 struct alsa_audio_device *adev = out->dev;
Amit Pundir4e375822019-04-18 16:46:10 +0530298 struct str_parms *parms;
299 char value[32];
Amit Pundire6732bb2020-09-28 12:43:59 +0530300 int ret, val = 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530301
302 parms = str_parms_create_str(kvpairs);
303
Amit Pundire6732bb2020-09-28 12:43:59 +0530304 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
305 if (ret >= 0) {
306 val = atoi(value);
307 pthread_mutex_lock(&adev->lock);
308 pthread_mutex_lock(&out->lock);
309 if (((out->devices & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) {
310 out->devices &= ~AUDIO_DEVICE_OUT_ALL;
311 out->devices |= val;
312 }
313 pthread_mutex_unlock(&out->lock);
314 pthread_mutex_unlock(&adev->lock);
Amit Pundir4e375822019-04-18 16:46:10 +0530315 }
316
317 str_parms_destroy(parms);
Amit Pundire6732bb2020-09-28 12:43:59 +0530318 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530319}
320
321static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
322{
Amit Pundire6732bb2020-09-28 12:43:59 +0530323 ALOGV("out_get_parameters");
324 return strdup("");
Amit Pundir4e375822019-04-18 16:46:10 +0530325}
326
327static uint32_t out_get_latency(const struct audio_stream_out *stream)
328{
Amit Pundire6732bb2020-09-28 12:43:59 +0530329 ALOGV("out_get_latency");
330 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
331 return (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT * 1000) / out->config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530332}
333
334static int out_set_volume(struct audio_stream_out *stream, float left,
Amit Pundire6732bb2020-09-28 12:43:59 +0530335 float right)
Amit Pundir4e375822019-04-18 16:46:10 +0530336{
Amit Pundire6732bb2020-09-28 12:43:59 +0530337 ALOGV("out_set_volume: Left:%f Right:%f", left, right);
Amit Pundir456949d2020-02-18 22:44:16 +0530338 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530339}
340
Amit Pundire6732bb2020-09-28 12:43:59 +0530341static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
342 size_t bytes)
Amit Pundir4e375822019-04-18 16:46:10 +0530343{
Amit Pundire6732bb2020-09-28 12:43:59 +0530344 int ret;
345 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
346 struct alsa_audio_device *adev = out->dev;
347 size_t frame_size = audio_stream_out_frame_size(stream);
348 size_t out_frames = bytes / frame_size;
Amit Pundir456949d2020-02-18 22:44:16 +0530349
Amit Pundire6732bb2020-09-28 12:43:59 +0530350 ALOGV("%s: devices: %d, bytes %zu", __func__, out->devices, bytes);
Amit Pundir456949d2020-02-18 22:44:16 +0530351
Amit Pundire6732bb2020-09-28 12:43:59 +0530352 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
353 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
354 * mutex
355 */
356 pthread_mutex_lock(&adev->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530357 pthread_mutex_lock(&out->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530358 if (out->standby) {
Amit Pundire6732bb2020-09-28 12:43:59 +0530359 ret = start_output_stream(out);
360 if (ret != 0) {
361 pthread_mutex_unlock(&adev->lock);
362 goto exit;
363 }
364 out->standby = 0;
365 aec_set_spk_running(adev->aec, true);
Amit Pundir456949d2020-02-18 22:44:16 +0530366 }
367
Amit Pundire6732bb2020-09-28 12:43:59 +0530368 pthread_mutex_unlock(&adev->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530369
Amit Pundire6732bb2020-09-28 12:43:59 +0530370 if (out->speaker_eq != NULL) {
371 fir_process_interleaved(out->speaker_eq, (int16_t*)buffer, (int16_t*)buffer, out_frames);
Amit Pundir456949d2020-02-18 22:44:16 +0530372 }
Amit Pundir456949d2020-02-18 22:44:16 +0530373
Amit Pundire6732bb2020-09-28 12:43:59 +0530374 ret = pcm_write(out->pcm, buffer, out_frames * frame_size);
375 if (ret == 0) {
376 out->frames_written += out_frames;
377
378 struct aec_info info;
379 get_pcm_timestamp(out->pcm, out->config.rate, &info, true /*isOutput*/);
380 out->timestamp = info.timestamp;
381 info.bytes = out_frames * frame_size;
382 int aec_ret = write_to_reference_fifo(adev->aec, (void *)buffer, &info);
383 if (aec_ret) {
384 ALOGE("AEC: Write to speaker loopback FIFO failed!");
385 }
386 }
387
388exit:
Amit Pundir4e375822019-04-18 16:46:10 +0530389 pthread_mutex_unlock(&out->lock);
390
Amit Pundire6732bb2020-09-28 12:43:59 +0530391 if (ret != 0) {
392 usleep((int64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
393 out_get_sample_rate(&stream->common));
Amit Pundir4e375822019-04-18 16:46:10 +0530394 }
395
Amit Pundir456949d2020-02-18 22:44:16 +0530396 return bytes;
Amit Pundir4e375822019-04-18 16:46:10 +0530397}
398
Amit Pundire6732bb2020-09-28 12:43:59 +0530399static int out_get_render_position(const struct audio_stream_out *stream,
400 uint32_t *dsp_frames)
401{
402 ALOGV("out_get_render_position: dsp_frames: %p", dsp_frames);
403 return -ENOSYS;
404}
405
Amit Pundir4e375822019-04-18 16:46:10 +0530406static int out_get_presentation_position(const struct audio_stream_out *stream,
407 uint64_t *frames, struct timespec *timestamp)
408{
Amit Pundir456949d2020-02-18 22:44:16 +0530409 if (stream == NULL || frames == NULL || timestamp == NULL) {
410 return -EINVAL;
411 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530412 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
Amit Pundir4e375822019-04-18 16:46:10 +0530413
Amit Pundire6732bb2020-09-28 12:43:59 +0530414 *frames = out->frames_written;
415 *timestamp = out->timestamp;
416 ALOGV("%s: frames: %" PRIu64 ", timestamp (nsec): %" PRIu64, __func__, *frames,
417 audio_utils_ns_from_timespec(timestamp));
Amit Pundir4e375822019-04-18 16:46:10 +0530418
Amit Pundir456949d2020-02-18 22:44:16 +0530419 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530420}
421
422
423static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
424{
Amit Pundire6732bb2020-09-28 12:43:59 +0530425 ALOGV("out_add_audio_effect: %p", effect);
Amit Pundir4e375822019-04-18 16:46:10 +0530426 return 0;
427}
428
429static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
430{
Amit Pundire6732bb2020-09-28 12:43:59 +0530431 ALOGV("out_remove_audio_effect: %p", effect);
Amit Pundir4e375822019-04-18 16:46:10 +0530432 return 0;
433}
434
435static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
Amit Pundire6732bb2020-09-28 12:43:59 +0530436 int64_t *timestamp)
Amit Pundir4e375822019-04-18 16:46:10 +0530437{
Amit Pundire6732bb2020-09-28 12:43:59 +0530438 *timestamp = 0;
439 ALOGV("out_get_next_write_timestamp: %ld", (long int)(*timestamp));
Amit Pundir456949d2020-02-18 22:44:16 +0530440 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530441}
442
Amit Pundire6732bb2020-09-28 12:43:59 +0530443/** audio_stream_in implementation **/
444
445/* must be called with hw device and input stream mutexes locked */
446static int start_input_stream(struct alsa_stream_in *in)
447{
448 struct alsa_audio_device *adev = in->dev;
449 in->unavailable = true;
450 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
John Stultz57a02362021-09-02 03:26:56 +0000451 int in_card = get_audio_card(PCM_IN, PORT_BUILTIN_MIC);
Amit Pundire6732bb2020-09-28 12:43:59 +0530452
453 while (1) {
John Stultz57a02362021-09-02 03:26:56 +0000454 in->pcm = pcm_open(in_card, PORT_BUILTIN_MIC, PCM_IN | PCM_MONOTONIC, &in->config);
Amit Pundire6732bb2020-09-28 12:43:59 +0530455 if ((in->pcm != NULL) && pcm_is_ready(in->pcm)) {
456 break;
457 } else {
458 ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
459 if (in->pcm != NULL) {
460 pcm_close(in->pcm);
461 in->pcm = NULL;
462 }
463 if (--pcm_retry_count == 0) {
464 ALOGE("Failed to open pcm_in after %d tries", PCM_OPEN_RETRIES);
465 return -ENODEV;
466 }
467 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
468 }
469 }
470 in->unavailable = false;
471 adev->active_input = in;
472 return 0;
473}
474
475static void get_mic_characteristics(struct audio_microphone_characteristic_t* mic_data,
476 size_t* mic_count) {
477 *mic_count = 1;
478 memset(mic_data, 0, sizeof(struct audio_microphone_characteristic_t));
479 strlcpy(mic_data->device_id, "builtin_mic", AUDIO_MICROPHONE_ID_MAX_LEN - 1);
480 strlcpy(mic_data->address, "top", AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
481 memset(mic_data->channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
482 sizeof(mic_data->channel_mapping));
483 mic_data->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
484 mic_data->sensitivity = -37.0;
485 mic_data->max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
486 mic_data->min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
487 mic_data->orientation.x = 0.0f;
488 mic_data->orientation.y = 0.0f;
489 mic_data->orientation.z = 0.0f;
490 mic_data->geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
491 mic_data->geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
492 mic_data->geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
493}
494
Amit Pundir4e375822019-04-18 16:46:10 +0530495static uint32_t in_get_sample_rate(const struct audio_stream *stream)
496{
Amit Pundire6732bb2020-09-28 12:43:59 +0530497 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
498 return in->config.rate;
Amit Pundir4e375822019-04-18 16:46:10 +0530499}
500
501static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
502{
Amit Pundire6732bb2020-09-28 12:43:59 +0530503 ALOGV("in_set_sample_rate: %d", rate);
Amit Pundir4e375822019-04-18 16:46:10 +0530504 return -ENOSYS;
505}
506
Amit Pundire6732bb2020-09-28 12:43:59 +0530507static size_t get_input_buffer_size(size_t frames, audio_format_t format,
508 audio_channel_mask_t channel_mask) {
509 /* return the closest majoring multiple of 16 frames, as
510 * audioflinger expects audio buffers to be a multiple of 16 frames */
511 frames = ((frames + 15) / 16) * 16;
512 size_t bytes_per_frame = audio_channel_count_from_in_mask(channel_mask) *
513 audio_bytes_per_sample(format);
514 size_t buffer_size = frames * bytes_per_frame;
515 return buffer_size;
Amit Pundir4e375822019-04-18 16:46:10 +0530516}
517
518static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
519{
Amit Pundire6732bb2020-09-28 12:43:59 +0530520 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
521 ALOGV("in_get_channels: %d", in->config.channels);
522 return audio_channel_in_mask_from_count(in->config.channels);
Amit Pundir4e375822019-04-18 16:46:10 +0530523}
524
525static audio_format_t in_get_format(const struct audio_stream *stream)
526{
Amit Pundire6732bb2020-09-28 12:43:59 +0530527 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
528 ALOGV("in_get_format: %d", in->config.format);
529 return audio_format_from_pcm_format(in->config.format);
Amit Pundir4e375822019-04-18 16:46:10 +0530530}
531
532static int in_set_format(struct audio_stream *stream, audio_format_t format)
533{
534 return -ENOSYS;
535}
536
Amit Pundire6732bb2020-09-28 12:43:59 +0530537static size_t in_get_buffer_size(const struct audio_stream *stream)
Amit Pundir4e375822019-04-18 16:46:10 +0530538{
Amit Pundire6732bb2020-09-28 12:43:59 +0530539 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
540 size_t frames = CAPTURE_PERIOD_SIZE;
541 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
542 frames = CAPTURE_PERIOD_SIZE * PLAYBACK_CODEC_SAMPLING_RATE / CAPTURE_CODEC_SAMPLING_RATE;
543 }
544
545 size_t buffer_size =
546 get_input_buffer_size(frames, stream->get_format(stream), stream->get_channels(stream));
547 ALOGV("in_get_buffer_size: %zu", buffer_size);
548 return buffer_size;
549}
550
551static int in_get_active_microphones(const struct audio_stream_in* stream,
552 struct audio_microphone_characteristic_t* mic_array,
553 size_t* mic_count) {
554 ALOGV("in_get_active_microphones");
555 if ((mic_array == NULL) || (mic_count == NULL)) {
556 return -EINVAL;
557 }
558 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
559 struct audio_hw_device* dev = (struct audio_hw_device*)in->dev;
560 bool mic_muted = false;
561 adev_get_mic_mute(dev, &mic_muted);
562 if ((in->source == AUDIO_SOURCE_ECHO_REFERENCE) || mic_muted) {
563 *mic_count = 0;
564 return 0;
565 }
566 adev_get_microphones(dev, mic_array, mic_count);
567 return 0;
568}
569
570static int do_input_standby(struct alsa_stream_in *in)
571{
572 struct alsa_audio_device *adev = in->dev;
573
574 if (!in->standby) {
575 pcm_close(in->pcm);
576 in->pcm = NULL;
577 adev->active_input = NULL;
578 in->standby = true;
579 }
580 return 0;
581}
582
583static int in_standby(struct audio_stream *stream)
584{
585 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
586 int status;
Amit Pundir456949d2020-02-18 22:44:16 +0530587
588 pthread_mutex_lock(&in->lock);
Amit Pundire6732bb2020-09-28 12:43:59 +0530589 pthread_mutex_lock(&in->dev->lock);
590 status = do_input_standby(in);
591 pthread_mutex_unlock(&in->dev->lock);
Amit Pundir456949d2020-02-18 22:44:16 +0530592 pthread_mutex_unlock(&in->lock);
Amit Pundire6732bb2020-09-28 12:43:59 +0530593 return status;
594}
595
596static int in_dump(const struct audio_stream *stream, int fd)
597{
598 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
599 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
600 return 0;
601 }
602
603 struct audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
604 size_t mic_count;
605
606 get_mic_characteristics(mic_array, &mic_count);
607
608 dprintf(fd, " Microphone count: %zd\n", mic_count);
609 size_t idx;
610 for (idx = 0; idx < mic_count; idx++) {
611 dprintf(fd, " Microphone: %zd\n", idx);
612 dprintf(fd, " Address: %s\n", mic_array[idx].address);
613 dprintf(fd, " Device: %d\n", mic_array[idx].device);
614 dprintf(fd, " Sensitivity (dB): %.2f\n", mic_array[idx].sensitivity);
615 }
616
Amit Pundir4e375822019-04-18 16:46:10 +0530617 return 0;
618}
619
620static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
621{
Amit Pundire6732bb2020-09-28 12:43:59 +0530622 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530623}
624
625static char * in_get_parameters(const struct audio_stream *stream,
Amit Pundire6732bb2020-09-28 12:43:59 +0530626 const char *keys)
Amit Pundir4e375822019-04-18 16:46:10 +0530627{
Amit Pundire6732bb2020-09-28 12:43:59 +0530628 return strdup("");
Amit Pundir4e375822019-04-18 16:46:10 +0530629}
630
631static int in_set_gain(struct audio_stream_in *stream, float gain)
632{
633 return 0;
634}
635
Amit Pundir456949d2020-02-18 22:44:16 +0530636static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
Amit Pundire6732bb2020-09-28 12:43:59 +0530637 size_t bytes)
Amit Pundir456949d2020-02-18 22:44:16 +0530638{
Amit Pundire6732bb2020-09-28 12:43:59 +0530639 int ret;
640 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
641 struct alsa_audio_device *adev = in->dev;
642 size_t frame_size = audio_stream_in_frame_size(stream);
643 size_t in_frames = bytes / frame_size;
Amit Pundir456949d2020-02-18 22:44:16 +0530644
Amit Pundire6732bb2020-09-28 12:43:59 +0530645 ALOGV("in_read: stream: %d, bytes %zu", in->source, bytes);
Amit Pundir456949d2020-02-18 22:44:16 +0530646
Amit Pundire6732bb2020-09-28 12:43:59 +0530647 /* Special handling for Echo Reference: simply get the reference from FIFO.
648 * The format and sample rate should be specified by arguments to adev_open_input_stream. */
649 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
650 struct aec_info info;
651 info.bytes = bytes;
Amit Pundir456949d2020-02-18 22:44:16 +0530652
Amit Pundire6732bb2020-09-28 12:43:59 +0530653 const uint64_t time_increment_nsec = (uint64_t)bytes * NANOS_PER_SECOND /
654 audio_stream_in_frame_size(stream) /
655 in_get_sample_rate(&stream->common);
656 if (!aec_get_spk_running(adev->aec)) {
657 if (in->timestamp_nsec == 0) {
658 struct timespec now;
659 clock_gettime(CLOCK_MONOTONIC, &now);
660 const uint64_t timestamp_nsec = audio_utils_ns_from_timespec(&now);
661 in->timestamp_nsec = timestamp_nsec;
662 } else {
663 in->timestamp_nsec += time_increment_nsec;
664 }
665 memset(buffer, 0, bytes);
666 const uint64_t time_increment_usec = time_increment_nsec / 1000;
667 usleep(time_increment_usec);
668 } else {
669 int ref_ret = get_reference_samples(adev->aec, buffer, &info);
670 if ((ref_ret) || (info.timestamp_usec == 0)) {
671 memset(buffer, 0, bytes);
672 in->timestamp_nsec += time_increment_nsec;
673 } else {
674 in->timestamp_nsec = 1000 * info.timestamp_usec;
Amit Pundir456949d2020-02-18 22:44:16 +0530675 }
676 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530677 in->frames_read += in_frames;
Amit Pundir456949d2020-02-18 22:44:16 +0530678
Amit Pundire6732bb2020-09-28 12:43:59 +0530679#if DEBUG_AEC
680 FILE* fp_ref = fopen("/data/local/traces/aec_ref.pcm", "a+");
681 if (fp_ref) {
682 fwrite((char*)buffer, 1, bytes, fp_ref);
683 fclose(fp_ref);
684 } else {
685 ALOGE("AEC debug: Could not open file aec_ref.pcm!");
Amit Pundir456949d2020-02-18 22:44:16 +0530686 }
Amit Pundire6732bb2020-09-28 12:43:59 +0530687 FILE* fp_ref_ts = fopen("/data/local/traces/aec_ref_timestamps.txt", "a+");
688 if (fp_ref_ts) {
689 fprintf(fp_ref_ts, "%" PRIu64 "\n", in->timestamp_nsec);
690 fclose(fp_ref_ts);
691 } else {
692 ALOGE("AEC debug: Could not open file aec_ref_timestamps.txt!");
693 }
694#endif
695 return info.bytes;
696 }
697
698 /* Microphone input stream read */
699
700 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
701 * on the input stream mutex - e.g. executing select_mode() while holding the hw device
702 * mutex
703 */
704 pthread_mutex_lock(&in->lock);
705 pthread_mutex_lock(&adev->lock);
706 if (in->standby) {
707 ret = start_input_stream(in);
708 if (ret != 0) {
709 pthread_mutex_unlock(&adev->lock);
710 ALOGE("start_input_stream failed with code %d", ret);
711 goto exit;
712 }
713 in->standby = false;
714 }
715
716 pthread_mutex_unlock(&adev->lock);
717
718 ret = pcm_read(in->pcm, buffer, in_frames * frame_size);
719 struct aec_info info;
720 get_pcm_timestamp(in->pcm, in->config.rate, &info, false /*isOutput*/);
721 if (ret == 0) {
722 in->frames_read += in_frames;
723 in->timestamp_nsec = audio_utils_ns_from_timespec(&info.timestamp);
724 }
725 else {
726 ALOGE("pcm_read failed with code %d", ret);
Amit Pundir456949d2020-02-18 22:44:16 +0530727 }
728
729exit:
Amit Pundir456949d2020-02-18 22:44:16 +0530730 pthread_mutex_unlock(&in->lock);
731
Amit Pundire6732bb2020-09-28 12:43:59 +0530732 bool mic_muted = false;
733 adev_get_mic_mute((struct audio_hw_device*)adev, &mic_muted);
734 if (mic_muted) {
735 memset(buffer, 0, bytes);
736 }
737
738 if (ret != 0) {
739 usleep((int64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
740 in_get_sample_rate(&stream->common));
741 } else {
742 /* Process AEC if available */
743 /* TODO move to a separate thread */
744 if (!mic_muted) {
745 info.bytes = bytes;
746 int aec_ret = process_aec(adev->aec, buffer, &info);
747 if (aec_ret) {
748 ALOGE("process_aec returned error code %d", aec_ret);
749 }
750 }
751 }
752
753#if DEBUG_AEC && !defined(AEC_HAL)
754 FILE* fp_in = fopen("/data/local/traces/aec_in.pcm", "a+");
755 if (fp_in) {
756 fwrite((char*)buffer, 1, bytes, fp_in);
757 fclose(fp_in);
758 } else {
759 ALOGE("AEC debug: Could not open file aec_in.pcm!");
760 }
761 FILE* fp_mic_ts = fopen("/data/local/traces/aec_in_timestamps.txt", "a+");
762 if (fp_mic_ts) {
763 fprintf(fp_mic_ts, "%" PRIu64 "\n", in->timestamp_nsec);
764 fclose(fp_mic_ts);
765 } else {
766 ALOGE("AEC debug: Could not open file aec_in_timestamps.txt!");
767 }
768#endif
769
Amit Pundir4e375822019-04-18 16:46:10 +0530770 return bytes;
771}
772
Amit Pundire6732bb2020-09-28 12:43:59 +0530773static int in_get_capture_position(const struct audio_stream_in* stream, int64_t* frames,
774 int64_t* time) {
775 if (stream == NULL || frames == NULL || time == NULL) {
776 return -EINVAL;
777 }
778 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
779
780 *frames = in->frames_read;
781 *time = in->timestamp_nsec;
782 ALOGV("%s: source: %d, timestamp (nsec): %" PRIu64, __func__, in->source, *time);
783
784 return 0;
785}
786
Amit Pundir4e375822019-04-18 16:46:10 +0530787static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
788{
789 return 0;
790}
791
792static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
793{
794 return 0;
795}
796
797static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
798{
799 return 0;
800}
801
802static int adev_open_output_stream(struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530803 audio_io_handle_t handle,
804 audio_devices_t devices,
805 audio_output_flags_t flags,
806 struct audio_config *config,
807 struct audio_stream_out **stream_out,
808 const char *address __unused)
Amit Pundir4e375822019-04-18 16:46:10 +0530809{
Amit Pundire6732bb2020-09-28 12:43:59 +0530810 ALOGV("adev_open_output_stream...");
811
812 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundire6732bb2020-09-28 12:43:59 +0530813 int out_port = get_audio_output_port(devices);
John Stultz57a02362021-09-02 03:26:56 +0000814 int out_card = get_audio_card(PCM_OUT, out_port);
815 struct pcm_params* params = pcm_params_get(out_card, out_port, PCM_OUT);
Alden DSouzae44e0672021-02-11 17:07:01 -0800816 if (!params) {
Amit Pundire6732bb2020-09-28 12:43:59 +0530817 return -ENOSYS;
Alden DSouzae44e0672021-02-11 17:07:01 -0800818 }
Amit Pundir456949d2020-02-18 22:44:16 +0530819
Alden DSouzae44e0672021-02-11 17:07:01 -0800820 struct alsa_stream_out* out =
821 (struct alsa_stream_out*)calloc(1, sizeof(struct alsa_stream_out));
822 if (!out) {
Amit Pundir4e375822019-04-18 16:46:10 +0530823 return -ENOMEM;
Alden DSouzae44e0672021-02-11 17:07:01 -0800824 }
Amit Pundir4e375822019-04-18 16:46:10 +0530825
826 out->stream.common.get_sample_rate = out_get_sample_rate;
827 out->stream.common.set_sample_rate = out_set_sample_rate;
828 out->stream.common.get_buffer_size = out_get_buffer_size;
829 out->stream.common.get_channels = out_get_channels;
830 out->stream.common.get_format = out_get_format;
831 out->stream.common.set_format = out_set_format;
832 out->stream.common.standby = out_standby;
833 out->stream.common.dump = out_dump;
834 out->stream.common.set_parameters = out_set_parameters;
835 out->stream.common.get_parameters = out_get_parameters;
836 out->stream.common.add_audio_effect = out_add_audio_effect;
837 out->stream.common.remove_audio_effect = out_remove_audio_effect;
838 out->stream.get_latency = out_get_latency;
839 out->stream.set_volume = out_set_volume;
840 out->stream.write = out_write;
841 out->stream.get_render_position = out_get_render_position;
Amit Pundir456949d2020-02-18 22:44:16 +0530842 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Amit Pundire6732bb2020-09-28 12:43:59 +0530843 out->stream.get_presentation_position = out_get_presentation_position;
Amit Pundir4e375822019-04-18 16:46:10 +0530844
Amit Pundire6732bb2020-09-28 12:43:59 +0530845 out->config.channels = CHANNEL_STEREO;
846 out->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
847 out->config.format = PCM_FORMAT_S16_LE;
848 out->config.period_size = PLAYBACK_PERIOD_SIZE;
849 out->config.period_count = PLAYBACK_PERIOD_COUNT;
Amit Pundir4e375822019-04-18 16:46:10 +0530850
Amit Pundire6732bb2020-09-28 12:43:59 +0530851 if (out->config.rate != config->sample_rate ||
852 audio_channel_count_from_out_mask(config->channel_mask) != CHANNEL_STEREO ||
853 out->config.format != pcm_format_from_audio_format(config->format) ) {
854 config->sample_rate = out->config.rate;
855 config->format = audio_format_from_pcm_format(out->config.format);
856 config->channel_mask = audio_channel_out_mask_from_count(CHANNEL_STEREO);
Alden DSouzae44e0672021-02-11 17:07:01 -0800857 goto error_1;
Amit Pundir4e375822019-04-18 16:46:10 +0530858 }
859
Amit Pundire6732bb2020-09-28 12:43:59 +0530860 ALOGI("adev_open_output_stream selects channels=%d rate=%d format=%d, devices=%d",
861 out->config.channels, out->config.rate, out->config.format, devices);
862
863 out->dev = ladev;
864 out->standby = 1;
865 out->unavailable = false;
866 out->devices = devices;
867
868 config->format = out_get_format(&out->stream.common);
869 config->channel_mask = out_get_channels(&out->stream.common);
870 config->sample_rate = out_get_sample_rate(&out->stream.common);
Amit Pundir4e375822019-04-18 16:46:10 +0530871
Amit Pundire6732bb2020-09-28 12:43:59 +0530872 out->speaker_eq = NULL;
873 if (out_port == PORT_INTERNAL_SPEAKER) {
874 out_set_eq(out);
875 if (out->speaker_eq == NULL) {
876 ALOGE("%s: Failed to initialize speaker EQ", __func__);
877 }
878 }
879
Alden DSouzae44e0672021-02-11 17:07:01 -0800880 int aec_ret = init_aec_reference_config(ladev->aec, out);
881 if (aec_ret) {
882 ALOGE("AEC: Speaker config init failed!");
883 goto error_2;
Amit Pundire6732bb2020-09-28 12:43:59 +0530884 }
Amit Pundir4e375822019-04-18 16:46:10 +0530885
Alden DSouzae44e0672021-02-11 17:07:01 -0800886 *stream_out = &out->stream;
887 return 0;
888
889error_2:
890 fir_release(out->speaker_eq);
891error_1:
892 free(out);
893 return -EINVAL;
Amit Pundir4e375822019-04-18 16:46:10 +0530894}
895
896static void adev_close_output_stream(struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530897 struct audio_stream_out *stream)
Amit Pundir4e375822019-04-18 16:46:10 +0530898{
Amit Pundire6732bb2020-09-28 12:43:59 +0530899 ALOGV("adev_close_output_stream...");
900 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
901 destroy_aec_reference_config(adev->aec);
902 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
903 fir_release(out->speaker_eq);
Amit Pundir4e375822019-04-18 16:46:10 +0530904 free(stream);
905}
906
907static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
908{
Amit Pundire6732bb2020-09-28 12:43:59 +0530909 ALOGV("adev_set_parameters");
910 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530911}
912
913static char * adev_get_parameters(const struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530914 const char *keys)
Amit Pundir4e375822019-04-18 16:46:10 +0530915{
Amit Pundire6732bb2020-09-28 12:43:59 +0530916 ALOGV("adev_get_parameters");
Amit Pundir4e375822019-04-18 16:46:10 +0530917 return strdup("");
918}
919
Amit Pundire6732bb2020-09-28 12:43:59 +0530920static int adev_get_microphones(const struct audio_hw_device* dev,
921 struct audio_microphone_characteristic_t* mic_array,
922 size_t* mic_count) {
923 ALOGV("adev_get_microphones");
924 if ((mic_array == NULL) || (mic_count == NULL)) {
925 return -EINVAL;
926 }
927 get_mic_characteristics(mic_array, mic_count);
928 return 0;
929}
930
Amit Pundir4e375822019-04-18 16:46:10 +0530931static int adev_init_check(const struct audio_hw_device *dev)
932{
Amit Pundire6732bb2020-09-28 12:43:59 +0530933 ALOGV("adev_init_check");
Amit Pundir4e375822019-04-18 16:46:10 +0530934 return 0;
935}
936
937static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
938{
Amit Pundire6732bb2020-09-28 12:43:59 +0530939 ALOGV("adev_set_voice_volume: %f", volume);
940 return -ENOSYS;
Amit Pundir4e375822019-04-18 16:46:10 +0530941}
942
943static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
944{
Amit Pundire6732bb2020-09-28 12:43:59 +0530945 ALOGV("adev_set_master_volume: %f", volume);
Amit Pundir4e375822019-04-18 16:46:10 +0530946 return -ENOSYS;
947}
948
949static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
950{
Amit Pundire6732bb2020-09-28 12:43:59 +0530951 ALOGV("adev_get_master_volume: %f", *volume);
Amit Pundir4e375822019-04-18 16:46:10 +0530952 return -ENOSYS;
953}
954
955static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
956{
Amit Pundire6732bb2020-09-28 12:43:59 +0530957 ALOGV("adev_set_master_mute: %d", muted);
Amit Pundir4e375822019-04-18 16:46:10 +0530958 return -ENOSYS;
959}
960
961static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
962{
Amit Pundire6732bb2020-09-28 12:43:59 +0530963 ALOGV("adev_get_master_mute: %d", *muted);
Amit Pundir4e375822019-04-18 16:46:10 +0530964 return -ENOSYS;
965}
966
967static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
968{
Amit Pundire6732bb2020-09-28 12:43:59 +0530969 ALOGV("adev_set_mode: %d", mode);
Amit Pundir4e375822019-04-18 16:46:10 +0530970 return 0;
971}
972
973static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
974{
Amit Pundire6732bb2020-09-28 12:43:59 +0530975 ALOGV("adev_set_mic_mute: %d",state);
976 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir456949d2020-02-18 22:44:16 +0530977 pthread_mutex_lock(&adev->lock);
978 adev->mic_mute = state;
979 pthread_mutex_unlock(&adev->lock);
980 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530981}
982
983static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
984{
Amit Pundire6732bb2020-09-28 12:43:59 +0530985 ALOGV("adev_get_mic_mute");
986 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir456949d2020-02-18 22:44:16 +0530987 pthread_mutex_lock(&adev->lock);
988 *state = adev->mic_mute;
989 pthread_mutex_unlock(&adev->lock);
990 return 0;
Amit Pundir4e375822019-04-18 16:46:10 +0530991}
992
993static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Amit Pundire6732bb2020-09-28 12:43:59 +0530994 const struct audio_config *config)
Amit Pundir4e375822019-04-18 16:46:10 +0530995{
Amit Pundire6732bb2020-09-28 12:43:59 +0530996 size_t buffer_size =
997 get_input_buffer_size(CAPTURE_PERIOD_SIZE, config->format, config->channel_mask);
998 ALOGV("adev_get_input_buffer_size: %zu", buffer_size);
999 return buffer_size;
Amit Pundir4e375822019-04-18 16:46:10 +05301000}
1001
Amit Pundire6732bb2020-09-28 12:43:59 +05301002static int adev_open_input_stream(struct audio_hw_device* dev, audio_io_handle_t handle,
1003 audio_devices_t devices, struct audio_config* config,
1004 struct audio_stream_in** stream_in,
1005 audio_input_flags_t flags __unused, const char* address __unused,
1006 audio_source_t source) {
1007 ALOGV("adev_open_input_stream...");
Amit Pundir456949d2020-02-18 22:44:16 +05301008
Amit Pundire6732bb2020-09-28 12:43:59 +05301009 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundir456949d2020-02-18 22:44:16 +05301010
John Stultz57a02362021-09-02 03:26:56 +00001011 int in_card = get_audio_card(PCM_IN, PORT_BUILTIN_MIC);
1012 struct pcm_params* params = pcm_params_get(in_card, PORT_BUILTIN_MIC, PCM_IN);
Alden DSouzae44e0672021-02-11 17:07:01 -08001013 if (!params) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301014 return -ENOSYS;
Alden DSouzae44e0672021-02-11 17:07:01 -08001015 }
Amit Pundire6732bb2020-09-28 12:43:59 +05301016
Alden DSouzae44e0672021-02-11 17:07:01 -08001017 struct alsa_stream_in* in = (struct alsa_stream_in*)calloc(1, sizeof(struct alsa_stream_in));
1018 if (!in) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301019 return -ENOMEM;
Alden DSouzae44e0672021-02-11 17:07:01 -08001020 }
Amit Pundir4e375822019-04-18 16:46:10 +05301021
1022 in->stream.common.get_sample_rate = in_get_sample_rate;
Amit Pundire6732bb2020-09-28 12:43:59 +05301023 in->stream.common.set_sample_rate = in_set_sample_rate;
Amit Pundir4e375822019-04-18 16:46:10 +05301024 in->stream.common.get_buffer_size = in_get_buffer_size;
1025 in->stream.common.get_channels = in_get_channels;
1026 in->stream.common.get_format = in_get_format;
Amit Pundire6732bb2020-09-28 12:43:59 +05301027 in->stream.common.set_format = in_set_format;
Amit Pundir4e375822019-04-18 16:46:10 +05301028 in->stream.common.standby = in_standby;
1029 in->stream.common.dump = in_dump;
1030 in->stream.common.set_parameters = in_set_parameters;
1031 in->stream.common.get_parameters = in_get_parameters;
Amit Pundire6732bb2020-09-28 12:43:59 +05301032 in->stream.common.add_audio_effect = in_add_audio_effect;
1033 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1034 in->stream.set_gain = in_set_gain;
Amit Pundir4e375822019-04-18 16:46:10 +05301035 in->stream.read = in_read;
Amit Pundire6732bb2020-09-28 12:43:59 +05301036 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Amit Pundir456949d2020-02-18 22:44:16 +05301037 in->stream.get_capture_position = in_get_capture_position;
1038 in->stream.get_active_microphones = in_get_active_microphones;
1039
Amit Pundire6732bb2020-09-28 12:43:59 +05301040 in->config.channels = CHANNEL_STEREO;
1041 if (source == AUDIO_SOURCE_ECHO_REFERENCE) {
1042 in->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
1043 } else {
1044 in->config.rate = CAPTURE_CODEC_SAMPLING_RATE;
1045 }
1046 in->config.format = PCM_FORMAT_S32_LE;
1047 in->config.period_size = CAPTURE_PERIOD_SIZE;
1048 in->config.period_count = CAPTURE_PERIOD_COUNT;
Amit Pundir456949d2020-02-18 22:44:16 +05301049
Amit Pundire6732bb2020-09-28 12:43:59 +05301050 if (in->config.rate != config->sample_rate ||
1051 audio_channel_count_from_in_mask(config->channel_mask) != CHANNEL_STEREO ||
1052 in->config.format != pcm_format_from_audio_format(config->format) ) {
Alden DSouzae44e0672021-02-11 17:07:01 -08001053 config->format = in_get_format(&in->stream.common);
1054 config->channel_mask = in_get_channels(&in->stream.common);
1055 config->sample_rate = in_get_sample_rate(&in->stream.common);
1056 goto error_1;
Amit Pundire6732bb2020-09-28 12:43:59 +05301057 }
Amit Pundir456949d2020-02-18 22:44:16 +05301058
Amit Pundire6732bb2020-09-28 12:43:59 +05301059 ALOGI("adev_open_input_stream selects channels=%d rate=%d format=%d source=%d",
1060 in->config.channels, in->config.rate, in->config.format, source);
1061
1062 in->dev = ladev;
Amit Pundir456949d2020-02-18 22:44:16 +05301063 in->standby = true;
Amit Pundire6732bb2020-09-28 12:43:59 +05301064 in->unavailable = false;
1065 in->source = source;
1066 in->devices = devices;
Amit Pundir456949d2020-02-18 22:44:16 +05301067
Alden DSouzae44e0672021-02-11 17:07:01 -08001068 if (is_aec_input(in)) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301069 int aec_ret = init_aec_mic_config(ladev->aec, in);
1070 if (aec_ret) {
1071 ALOGE("AEC: Mic config init failed!");
Alden DSouzae44e0672021-02-11 17:07:01 -08001072 goto error_1;
Amit Pundir456949d2020-02-18 22:44:16 +05301073 }
Amit Pundire6732bb2020-09-28 12:43:59 +05301074 }
1075
Amit Pundire6732bb2020-09-28 12:43:59 +05301076#if DEBUG_AEC
1077 remove("/data/local/traces/aec_ref.pcm");
1078 remove("/data/local/traces/aec_in.pcm");
1079 remove("/data/local/traces/aec_ref_timestamps.txt");
1080 remove("/data/local/traces/aec_in_timestamps.txt");
1081#endif
Alden DSouzae44e0672021-02-11 17:07:01 -08001082
1083 *stream_in = &in->stream;
1084 return 0;
1085
1086error_1:
1087 free(in);
1088 return -EINVAL;
Amit Pundire6732bb2020-09-28 12:43:59 +05301089}
Amit Pundir456949d2020-02-18 22:44:16 +05301090
Amit Pundire6732bb2020-09-28 12:43:59 +05301091static void adev_close_input_stream(struct audio_hw_device *dev,
1092 struct audio_stream_in *stream)
1093{
1094 ALOGV("adev_close_input_stream...");
Alden DSouzae44e0672021-02-11 17:07:01 -08001095 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
1096 if (is_aec_input(in)) {
1097 destroy_aec_mic_config(in->dev->aec);
1098 }
Amit Pundire6732bb2020-09-28 12:43:59 +05301099 free(stream);
1100 return;
1101}
Amit Pundir456949d2020-02-18 22:44:16 +05301102
Amit Pundire6732bb2020-09-28 12:43:59 +05301103static int adev_dump(const audio_hw_device_t *device, int fd)
1104{
1105 ALOGV("adev_dump");
Amit Pundir4e375822019-04-18 16:46:10 +05301106 return 0;
1107}
1108
Amit Pundire6732bb2020-09-28 12:43:59 +05301109static int adev_close(hw_device_t *device)
Amit Pundir456949d2020-02-18 22:44:16 +05301110{
Amit Pundire6732bb2020-09-28 12:43:59 +05301111 ALOGV("adev_close");
Amit Pundir456949d2020-02-18 22:44:16 +05301112
Amit Pundire6732bb2020-09-28 12:43:59 +05301113 struct alsa_audio_device *adev = (struct alsa_audio_device *)device;
1114 release_aec(adev->aec);
Alden DSouzae44e0672021-02-11 17:07:01 -08001115 audio_route_free(adev->audio_route);
1116 mixer_close(adev->mixer);
Amit Pundire6732bb2020-09-28 12:43:59 +05301117 free(device);
1118 return 0;
Amit Pundir456949d2020-02-18 22:44:16 +05301119}
1120
Amit Pundir4e375822019-04-18 16:46:10 +05301121static int adev_open(const hw_module_t* module, const char* name,
Amit Pundire6732bb2020-09-28 12:43:59 +05301122 hw_device_t** device)
Amit Pundir4e375822019-04-18 16:46:10 +05301123{
Amit Pundire6732bb2020-09-28 12:43:59 +05301124 ALOGV("adev_open: %s", name);
Amit Pundir4e375822019-04-18 16:46:10 +05301125
Alden DSouzae44e0672021-02-11 17:07:01 -08001126 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
Amit Pundir4e375822019-04-18 16:46:10 +05301127 return -EINVAL;
Alden DSouzae44e0672021-02-11 17:07:01 -08001128 }
Amit Pundir4e375822019-04-18 16:46:10 +05301129
Alden DSouzae44e0672021-02-11 17:07:01 -08001130 struct alsa_audio_device* adev = calloc(1, sizeof(struct alsa_audio_device));
1131 if (!adev) {
Amit Pundire6732bb2020-09-28 12:43:59 +05301132 return -ENOMEM;
Alden DSouzae44e0672021-02-11 17:07:01 -08001133 }
Amit Pundir4e375822019-04-18 16:46:10 +05301134
Amit Pundire6732bb2020-09-28 12:43:59 +05301135 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
1136 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1137 adev->hw_device.common.module = (struct hw_module_t *) module;
1138 adev->hw_device.common.close = adev_close;
1139 adev->hw_device.init_check = adev_init_check;
1140 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1141 adev->hw_device.set_master_volume = adev_set_master_volume;
1142 adev->hw_device.get_master_volume = adev_get_master_volume;
1143 adev->hw_device.set_master_mute = adev_set_master_mute;
1144 adev->hw_device.get_master_mute = adev_get_master_mute;
1145 adev->hw_device.set_mode = adev_set_mode;
1146 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1147 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1148 adev->hw_device.set_parameters = adev_set_parameters;
1149 adev->hw_device.get_parameters = adev_get_parameters;
1150 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1151 adev->hw_device.open_output_stream = adev_open_output_stream;
1152 adev->hw_device.close_output_stream = adev_close_output_stream;
1153 adev->hw_device.open_input_stream = adev_open_input_stream;
1154 adev->hw_device.close_input_stream = adev_close_input_stream;
1155 adev->hw_device.dump = adev_dump;
1156 adev->hw_device.get_microphones = adev_get_microphones;
Amit Pundir4e375822019-04-18 16:46:10 +05301157
Amit Pundire6732bb2020-09-28 12:43:59 +05301158 *device = &adev->hw_device.common;
Amit Pundir4e375822019-04-18 16:46:10 +05301159
John Stultz57a02362021-09-02 03:26:56 +00001160 int out_card = get_audio_card(PCM_OUT, 0);
1161 adev->mixer = mixer_open(out_card);
Amit Pundire6732bb2020-09-28 12:43:59 +05301162 if (!adev->mixer) {
1163 ALOGE("Unable to open the mixer, aborting.");
Alden DSouzae44e0672021-02-11 17:07:01 -08001164 goto error_1;
Amit Pundir456949d2020-02-18 22:44:16 +05301165 }
1166
John Stultz57a02362021-09-02 03:26:56 +00001167 adev->audio_route = audio_route_init(out_card, MIXER_XML_PATH);
Amit Pundire6732bb2020-09-28 12:43:59 +05301168 if (!adev->audio_route) {
1169 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
Alden DSouzae44e0672021-02-11 17:07:01 -08001170 goto error_2;
Amit Pundire6732bb2020-09-28 12:43:59 +05301171 }
Amit Pundir456949d2020-02-18 22:44:16 +05301172
Amit Pundire6732bb2020-09-28 12:43:59 +05301173 pthread_mutex_lock(&adev->lock);
1174 if (init_aec(CAPTURE_CODEC_SAMPLING_RATE, NUM_AEC_REFERENCE_CHANNELS,
1175 CHANNEL_STEREO, &adev->aec)) {
1176 pthread_mutex_unlock(&adev->lock);
Alden DSouzae44e0672021-02-11 17:07:01 -08001177 goto error_3;
Amit Pundire6732bb2020-09-28 12:43:59 +05301178 }
1179 pthread_mutex_unlock(&adev->lock);
1180
Amit Pundir4e375822019-04-18 16:46:10 +05301181 return 0;
Alden DSouzae44e0672021-02-11 17:07:01 -08001182
1183error_3:
1184 audio_route_free(adev->audio_route);
1185error_2:
1186 mixer_close(adev->mixer);
1187error_1:
1188 free(adev);
1189 return -EINVAL;
Amit Pundir4e375822019-04-18 16:46:10 +05301190}
1191
1192static struct hw_module_methods_t hal_module_methods = {
1193 .open = adev_open,
1194};
1195
1196struct audio_module HAL_MODULE_INFO_SYM = {
1197 .common = {
1198 .tag = HARDWARE_MODULE_TAG,
1199 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1200 .hal_api_version = HARDWARE_HAL_API_VERSION,
1201 .id = AUDIO_HARDWARE_MODULE_ID,
Amit Pundire6732bb2020-09-28 12:43:59 +05301202 .name = "Yukawa audio HW HAL",
Amit Pundir4e375822019-04-18 16:46:10 +05301203 .author = "The Android Open Source Project",
1204 .methods = &hal_module_methods,
1205 },
1206};