blob: c7341ef583d047bfd092229ea7875d5d494c0eae [file] [log] [blame]
Amit Pundirc738b812019-06-19 16:13:49 +05301/*
Amit Pundirfec74f62020-09-28 12:43:59 +05302 * Copyright (C) 2016 The Android Open Source Project
Amit Pundirc738b812019-06-19 16:13:49 +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 Pundir648e1d02020-02-18 22:44:16 +053015 *
Amit Pundirfec74f62020-09-28 12:43:59 +053016 * Copied as it is from device/amlogic/generic/hal/audio/
Amit Pundirc738b812019-06-19 16:13:49 +053017 */
18
19#define LOG_TAG "audio_hw_generic"
Amit Pundirfec74f62020-09-28 12:43:59 +053020//#define LOG_NDEBUG 0
Amit Pundirc738b812019-06-19 16:13:49 +053021
22#include <errno.h>
Amit Pundir648e1d02020-02-18 22:44:16 +053023#include <inttypes.h>
Amit Pundirfec74f62020-09-28 12:43:59 +053024#include <malloc.h>
Amit Pundirc738b812019-06-19 16:13:49 +053025#include <pthread.h>
26#include <stdint.h>
Amit Pundirc738b812019-06-19 16:13:49 +053027#include <stdlib.h>
Amit Pundir648e1d02020-02-18 22:44:16 +053028#include <sys/time.h>
Amit Pundirc738b812019-06-19 16:13:49 +053029#include <unistd.h>
30
31#include <log/log.h>
32#include <cutils/str_parms.h>
Amit Pundirfec74f62020-09-28 12:43:59 +053033#include <cutils/properties.h>
Amit Pundirc738b812019-06-19 16:13:49 +053034
35#include <hardware/hardware.h>
36#include <system/audio.h>
37#include <hardware/audio.h>
Amit Pundirfec74f62020-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 Pundirc738b812019-06-19 16:13:49 +053047#include <tinyalsa/asoundlib.h>
Amit Pundir648e1d02020-02-18 22:44:16 +053048
Amit Pundirfec74f62020-09-28 12:43:59 +053049#include <sys/ioctl.h>
Amit Pundirc738b812019-06-19 16:13:49 +053050
Amit Pundirfec74f62020-09-28 12:43:59 +053051#include "audio_aec.h"
52#include "audio_hw.h"
Amit Pundirc738b812019-06-19 16:13:49 +053053
Amit Pundirfec74f62020-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 Pundirc738b812019-06-19 16:13:49 +053059
Alden DSouza0f4cb5f2021-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 Pundirfec74f62020-09-28 12:43:59 +053070static int get_audio_output_port(audio_devices_t devices) {
71 /* Default to internal speaker */
72 int port = PORT_INTERNAL_SPEAKER;
Caleb Connolly6e92e452021-08-10 09:54:18 +010073 if (devices & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
74 port = PORT_HEADSET;
75 }
76
Caleb Connolly1f0c1382021-08-10 11:41:23 +010077 ALOGI("CA:: %s: port = %d", __func__, port);
Amit Pundirfec74f62020-09-28 12:43:59 +053078 return port;
Amit Pundirc738b812019-06-19 16:13:49 +053079}
80
Caleb Connolly1f0c1382021-08-10 11:41:23 +010081static char* get_mixer_path_for_port(int port) {
82 switch (port)
83 {
84 case PORT_INTERNAL_SPEAKER:
85 return "speaker";
86 break;
87 case PORT_HEADSET:
88 return "headset";
89 break;
90 default:
91 return NULL;
92 break;
93 }
94}
95
Amit Pundirfec74f62020-09-28 12:43:59 +053096static void timestamp_adjust(struct timespec* ts, ssize_t frames, uint32_t sampling_rate) {
97 /* This function assumes the adjustment (in nsec) is less than the max value of long,
98 * which for 32-bit long this is 2^31 * 1e-9 seconds, slightly over 2 seconds.
99 * For 64-bit long it is 9e+9 seconds. */
100 long adj_nsec = (frames / (float) sampling_rate) * 1E9L;
101 ts->tv_nsec += adj_nsec;
102 while (ts->tv_nsec > 1E9L) {
103 ts->tv_sec++;
104 ts->tv_nsec -= 1E9L;
Amit Pundir648e1d02020-02-18 22:44:16 +0530105 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530106 if (ts->tv_nsec < 0) {
107 ts->tv_sec--;
108 ts->tv_nsec += 1E9L;
109 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530110}
111
Amit Pundirfec74f62020-09-28 12:43:59 +0530112/* Helper function to get PCM hardware timestamp.
113 * Only the field 'timestamp' of argument 'ts' is updated. */
114static int get_pcm_timestamp(struct pcm* pcm, uint32_t sample_rate, struct aec_info* info,
115 bool isOutput) {
116 int ret = 0;
117 if (pcm_get_htimestamp(pcm, &info->available, &info->timestamp) < 0) {
118 ALOGE("Error getting PCM timestamp!");
119 info->timestamp.tv_sec = 0;
120 info->timestamp.tv_nsec = 0;
Amit Pundir648e1d02020-02-18 22:44:16 +0530121 return -EINVAL;
122 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530123 ssize_t frames;
124 if (isOutput) {
125 frames = pcm_get_buffer_size(pcm) - info->available;
126 } else {
127 frames = -info->available; /* rewind timestamp */
128 }
129 timestamp_adjust(&info->timestamp, frames, sample_rate);
130 return ret;
Amit Pundir648e1d02020-02-18 22:44:16 +0530131}
132
Amit Pundirfec74f62020-09-28 12:43:59 +0530133static int read_filter_from_file(const char* filename, int16_t* filter, int max_length) {
134 FILE* fp = fopen(filename, "r");
135 if (fp == NULL) {
136 ALOGI("%s: File %s not found.", __func__, filename);
137 return 0;
138 }
139 int num_taps = 0;
140 char* line = NULL;
141 size_t len = 0;
142 while (!feof(fp)) {
143 size_t size = getline(&line, &len, fp);
144 if ((line[0] == '#') || (size < 2)) {
145 continue;
146 }
147 int n = sscanf(line, "%" SCNd16 "\n", &filter[num_taps++]);
148 if (n < 1) {
149 ALOGE("Could not find coefficient %d! Exiting...", num_taps - 1);
150 return 0;
151 }
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100152 ALOGI("CA:: Coeff %d : %" PRId16, num_taps, filter[num_taps - 1]);
Amit Pundirfec74f62020-09-28 12:43:59 +0530153 if (num_taps == max_length) {
154 ALOGI("%s: max tap length %d reached.", __func__, max_length);
Amit Pundir648e1d02020-02-18 22:44:16 +0530155 break;
156 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530157 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530158 free(line);
159 fclose(fp);
160 return num_taps;
Amit Pundir648e1d02020-02-18 22:44:16 +0530161}
162
Amit Pundirfec74f62020-09-28 12:43:59 +0530163static void out_set_eq(struct alsa_stream_out* out) {
164 out->speaker_eq = NULL;
165 int16_t* speaker_eq_coeffs = (int16_t*)calloc(SPEAKER_MAX_EQ_LENGTH, sizeof(int16_t));
166 if (speaker_eq_coeffs == NULL) {
167 ALOGE("%s: Failed to allocate speaker EQ", __func__);
168 return;
169 }
170 int num_taps = read_filter_from_file(SPEAKER_EQ_FILE, speaker_eq_coeffs, SPEAKER_MAX_EQ_LENGTH);
171 if (num_taps == 0) {
172 ALOGI("%s: Empty filter file or 0 taps set.", __func__);
173 free(speaker_eq_coeffs);
174 return;
175 }
176 out->speaker_eq = fir_init(
177 out->config.channels, FIR_SINGLE_FILTER, num_taps,
178 out_get_buffer_size(&out->stream.common) / out->config.channels / sizeof(int16_t),
179 speaker_eq_coeffs);
180 free(speaker_eq_coeffs);
181}
Amit Pundir648e1d02020-02-18 22:44:16 +0530182
Amit Pundirfec74f62020-09-28 12:43:59 +0530183/* must be called with hw device and output stream mutexes locked */
184static int start_output_stream(struct alsa_stream_out *out)
185{
186 struct alsa_audio_device *adev = out->dev;
187
188 /* default to low power: will be corrected in out_write if necessary before first write to
189 * tinyalsa.
190 */
191 out->write_threshold = PLAYBACK_PERIOD_COUNT * PLAYBACK_PERIOD_SIZE;
192 out->config.start_threshold = PLAYBACK_PERIOD_START_THRESHOLD * PLAYBACK_PERIOD_SIZE;
193 out->config.avail_min = PLAYBACK_PERIOD_SIZE;
194 out->unavailable = true;
195 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
196 int out_port = get_audio_output_port(out->devices);
197
198 while (1) {
199 out->pcm = pcm_open(CARD_OUT, out_port, PCM_OUT | PCM_MONOTONIC, &out->config);
200 if ((out->pcm != NULL) && pcm_is_ready(out->pcm)) {
Amit Pundir648e1d02020-02-18 22:44:16 +0530201 break;
Amit Pundirfec74f62020-09-28 12:43:59 +0530202 } else {
203 ALOGE("cannot open pcm_out driver: %s", pcm_get_error(out->pcm));
204 if (out->pcm != NULL) {
205 pcm_close(out->pcm);
206 out->pcm = NULL;
207 }
208 if (--pcm_retry_count == 0) {
209 ALOGE("Failed to open pcm_out after %d tries", PCM_OPEN_RETRIES);
210 return -ENODEV;
211 }
212 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
Amit Pundir648e1d02020-02-18 22:44:16 +0530213 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530214 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530215 out->unavailable = false;
216 adev->active_output = out;
217 return 0;
Amit Pundir648e1d02020-02-18 22:44:16 +0530218}
219
Amit Pundirc738b812019-06-19 16:13:49 +0530220static uint32_t out_get_sample_rate(const struct audio_stream *stream)
221{
Amit Pundirfec74f62020-09-28 12:43:59 +0530222 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
223 return out->config.rate;
Amit Pundirc738b812019-06-19 16:13:49 +0530224}
225
226static int out_set_sample_rate(struct audio_stream *stream, uint32_t rate)
227{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100228 ALOGI("CA:: out_set_sample_rate: %d", 0);
Amit Pundirc738b812019-06-19 16:13:49 +0530229 return -ENOSYS;
230}
231
232static size_t out_get_buffer_size(const struct audio_stream *stream)
233{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100234 ALOGI("CA:: out_get_buffer_size: %d", 4096);
Amit Pundirc738b812019-06-19 16:13:49 +0530235
Amit Pundirfec74f62020-09-28 12:43:59 +0530236 /* return the closest majoring multiple of 16 frames, as
237 * audioflinger expects audio buffers to be a multiple of 16 frames */
238 size_t size = PLAYBACK_PERIOD_SIZE;
239 size = ((size + 15) / 16) * 16;
240 return size * audio_stream_out_frame_size((struct audio_stream_out *)stream);
Amit Pundirc738b812019-06-19 16:13:49 +0530241}
242
243static audio_channel_mask_t out_get_channels(const struct audio_stream *stream)
244{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100245 ALOGI("CA:: out_get_channels");
Amit Pundirfec74f62020-09-28 12:43:59 +0530246 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
247 return audio_channel_out_mask_from_count(out->config.channels);
Amit Pundirc738b812019-06-19 16:13:49 +0530248}
249
250static audio_format_t out_get_format(const struct audio_stream *stream)
251{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100252 ALOGI("CA:: out_get_format");
Amit Pundirfec74f62020-09-28 12:43:59 +0530253 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
254 return audio_format_from_pcm_format(out->config.format);
Amit Pundirc738b812019-06-19 16:13:49 +0530255}
256
257static int out_set_format(struct audio_stream *stream, audio_format_t format)
258{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100259 ALOGI("CA:: out_set_format: %d",format);
Amit Pundirc738b812019-06-19 16:13:49 +0530260 return -ENOSYS;
261}
262
Amit Pundirfec74f62020-09-28 12:43:59 +0530263static int do_output_standby(struct alsa_stream_out *out)
264{
265 struct alsa_audio_device *adev = out->dev;
266
267 fir_reset(out->speaker_eq);
268
269 if (!out->standby) {
270 pcm_close(out->pcm);
271 out->pcm = NULL;
272 adev->active_output = NULL;
273 out->standby = 1;
274 }
275 aec_set_spk_running(adev->aec, false);
276 return 0;
277}
278
279static int out_standby(struct audio_stream *stream)
280{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100281 ALOGI("CA:: out_standby");
Amit Pundirfec74f62020-09-28 12:43:59 +0530282 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
283 int status;
284
285 pthread_mutex_lock(&out->dev->lock);
286 pthread_mutex_lock(&out->lock);
287 status = do_output_standby(out);
288 pthread_mutex_unlock(&out->lock);
289 pthread_mutex_unlock(&out->dev->lock);
290 return status;
291}
292
Amit Pundirc738b812019-06-19 16:13:49 +0530293static int out_dump(const struct audio_stream *stream, int fd)
294{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100295 ALOGI("CA:: out_dump");
Amit Pundirc738b812019-06-19 16:13:49 +0530296 return 0;
297}
298
299static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
300{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100301 ALOGI("CA:: out_set_parameters");
Amit Pundirfec74f62020-09-28 12:43:59 +0530302 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
303 struct alsa_audio_device *adev = out->dev;
Amit Pundirc738b812019-06-19 16:13:49 +0530304 struct str_parms *parms;
305 char value[32];
Amit Pundirfec74f62020-09-28 12:43:59 +0530306 int ret, val = 0;
Amit Pundirc738b812019-06-19 16:13:49 +0530307
308 parms = str_parms_create_str(kvpairs);
309
Amit Pundirfec74f62020-09-28 12:43:59 +0530310 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
311 if (ret >= 0) {
312 val = atoi(value);
313 pthread_mutex_lock(&adev->lock);
314 pthread_mutex_lock(&out->lock);
315 if (((out->devices & AUDIO_DEVICE_OUT_ALL) != val) && (val != 0)) {
316 out->devices &= ~AUDIO_DEVICE_OUT_ALL;
317 out->devices |= val;
318 }
319 pthread_mutex_unlock(&out->lock);
320 pthread_mutex_unlock(&adev->lock);
Amit Pundirc738b812019-06-19 16:13:49 +0530321 }
322
323 str_parms_destroy(parms);
Amit Pundirfec74f62020-09-28 12:43:59 +0530324 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +0530325}
326
327static char * out_get_parameters(const struct audio_stream *stream, const char *keys)
328{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100329 ALOGI("CA:: out_get_parameters");
Amit Pundirfec74f62020-09-28 12:43:59 +0530330 return strdup("");
Amit Pundirc738b812019-06-19 16:13:49 +0530331}
332
333static uint32_t out_get_latency(const struct audio_stream_out *stream)
334{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100335 ALOGI("CA:: out_get_latency");
Amit Pundirfec74f62020-09-28 12:43:59 +0530336 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
337 return (PLAYBACK_PERIOD_SIZE * PLAYBACK_PERIOD_COUNT * 1000) / out->config.rate;
Amit Pundirc738b812019-06-19 16:13:49 +0530338}
339
340static int out_set_volume(struct audio_stream_out *stream, float left,
Amit Pundirfec74f62020-09-28 12:43:59 +0530341 float right)
Amit Pundirc738b812019-06-19 16:13:49 +0530342{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100343 ALOGI("CA:: out_set_volume: Left:%f Right:%f", left, right);
Amit Pundir648e1d02020-02-18 22:44:16 +0530344 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530345}
346
Amit Pundirfec74f62020-09-28 12:43:59 +0530347static ssize_t out_write(struct audio_stream_out *stream, const void* buffer,
348 size_t bytes)
Amit Pundirc738b812019-06-19 16:13:49 +0530349{
Amit Pundirfec74f62020-09-28 12:43:59 +0530350 int ret;
351 struct alsa_stream_out *out = (struct alsa_stream_out *)stream;
352 struct alsa_audio_device *adev = out->dev;
353 size_t frame_size = audio_stream_out_frame_size(stream);
354 size_t out_frames = bytes / frame_size;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100355 int out_port = get_audio_output_port(out->devices);
356 char* route_active_path_name = get_mixer_path_for_port(out_port);
Amit Pundir648e1d02020-02-18 22:44:16 +0530357
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100358 if (out_port != adev->active_port) {
Caleb Connollyd59c9062021-08-10 13:50:39 +0100359 audio_route_reset(adev->audio_route);
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100360 ret = audio_route_reset_and_update_path(adev->audio_route, route_active_path_name);
361 adev->active_port = out_port;
362 if (ret < 0) {
363 ALOGE("CA:: %s() failed to set path %s", __func__, route_active_path_name);
364 }
365 }
366
367 ALOGI("CA:: %s: devices: %d, bytes %zu", __func__, out->devices, bytes);
Amit Pundir648e1d02020-02-18 22:44:16 +0530368
Amit Pundirfec74f62020-09-28 12:43:59 +0530369 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
370 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
371 * mutex
372 */
373 pthread_mutex_lock(&adev->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530374 pthread_mutex_lock(&out->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530375 if (out->standby) {
Amit Pundirfec74f62020-09-28 12:43:59 +0530376 ret = start_output_stream(out);
377 if (ret != 0) {
378 pthread_mutex_unlock(&adev->lock);
379 goto exit;
380 }
381 out->standby = 0;
382 aec_set_spk_running(adev->aec, true);
Amit Pundir648e1d02020-02-18 22:44:16 +0530383 }
384
Amit Pundirfec74f62020-09-28 12:43:59 +0530385 pthread_mutex_unlock(&adev->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530386
Amit Pundirfec74f62020-09-28 12:43:59 +0530387 if (out->speaker_eq != NULL) {
388 fir_process_interleaved(out->speaker_eq, (int16_t*)buffer, (int16_t*)buffer, out_frames);
Amit Pundir648e1d02020-02-18 22:44:16 +0530389 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530390
Amit Pundirfec74f62020-09-28 12:43:59 +0530391 ret = pcm_write(out->pcm, buffer, out_frames * frame_size);
392 if (ret == 0) {
393 out->frames_written += out_frames;
394
395 struct aec_info info;
396 get_pcm_timestamp(out->pcm, out->config.rate, &info, true /*isOutput*/);
397 out->timestamp = info.timestamp;
398 info.bytes = out_frames * frame_size;
399 int aec_ret = write_to_reference_fifo(adev->aec, (void *)buffer, &info);
400 if (aec_ret) {
401 ALOGE("AEC: Write to speaker loopback FIFO failed!");
402 }
403 }
404
405exit:
Amit Pundirc738b812019-06-19 16:13:49 +0530406 pthread_mutex_unlock(&out->lock);
407
Amit Pundirfec74f62020-09-28 12:43:59 +0530408 if (ret != 0) {
409 usleep((int64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
410 out_get_sample_rate(&stream->common));
Amit Pundirc738b812019-06-19 16:13:49 +0530411 }
412
Amit Pundir648e1d02020-02-18 22:44:16 +0530413 return bytes;
Amit Pundirc738b812019-06-19 16:13:49 +0530414}
415
Amit Pundirfec74f62020-09-28 12:43:59 +0530416static int out_get_render_position(const struct audio_stream_out *stream,
417 uint32_t *dsp_frames)
418{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100419 ALOGI("CA:: out_get_render_position: dsp_frames: %p", dsp_frames);
Amit Pundirfec74f62020-09-28 12:43:59 +0530420 return -ENOSYS;
421}
422
Amit Pundirc738b812019-06-19 16:13:49 +0530423static int out_get_presentation_position(const struct audio_stream_out *stream,
424 uint64_t *frames, struct timespec *timestamp)
425{
Amit Pundir648e1d02020-02-18 22:44:16 +0530426 if (stream == NULL || frames == NULL || timestamp == NULL) {
427 return -EINVAL;
428 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530429 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
Amit Pundirc738b812019-06-19 16:13:49 +0530430
Amit Pundirfec74f62020-09-28 12:43:59 +0530431 *frames = out->frames_written;
432 *timestamp = out->timestamp;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100433 ALOGI("CA:: %s: frames: %" PRIu64 ", timestamp (nsec): %" PRIu64, __func__, *frames,
Amit Pundirfec74f62020-09-28 12:43:59 +0530434 audio_utils_ns_from_timespec(timestamp));
Amit Pundirc738b812019-06-19 16:13:49 +0530435
Amit Pundir648e1d02020-02-18 22:44:16 +0530436 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +0530437}
438
439
440static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
441{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100442 ALOGI("CA:: out_add_audio_effect: %p", effect);
Amit Pundirc738b812019-06-19 16:13:49 +0530443 return 0;
444}
445
446static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
447{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100448 ALOGI("CA:: out_remove_audio_effect: %p", effect);
Amit Pundirc738b812019-06-19 16:13:49 +0530449 return 0;
450}
451
452static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
Amit Pundirfec74f62020-09-28 12:43:59 +0530453 int64_t *timestamp)
Amit Pundirc738b812019-06-19 16:13:49 +0530454{
Amit Pundirfec74f62020-09-28 12:43:59 +0530455 *timestamp = 0;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100456 ALOGI("CA:: out_get_next_write_timestamp: %ld", (long int)(*timestamp));
Amit Pundir648e1d02020-02-18 22:44:16 +0530457 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530458}
459
Amit Pundirfec74f62020-09-28 12:43:59 +0530460/** audio_stream_in implementation **/
461
462/* must be called with hw device and input stream mutexes locked */
463static int start_input_stream(struct alsa_stream_in *in)
464{
465 struct alsa_audio_device *adev = in->dev;
466 in->unavailable = true;
467 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
468
469 while (1) {
470 in->pcm = pcm_open(CARD_IN, PORT_BUILTIN_MIC, PCM_IN | PCM_MONOTONIC, &in->config);
471 if ((in->pcm != NULL) && pcm_is_ready(in->pcm)) {
472 break;
473 } else {
474 ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
475 if (in->pcm != NULL) {
476 pcm_close(in->pcm);
477 in->pcm = NULL;
478 }
479 if (--pcm_retry_count == 0) {
480 ALOGE("Failed to open pcm_in after %d tries", PCM_OPEN_RETRIES);
481 return -ENODEV;
482 }
483 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
484 }
485 }
486 in->unavailable = false;
487 adev->active_input = in;
488 return 0;
489}
490
491static void get_mic_characteristics(struct audio_microphone_characteristic_t* mic_data,
492 size_t* mic_count) {
493 *mic_count = 1;
494 memset(mic_data, 0, sizeof(struct audio_microphone_characteristic_t));
495 strlcpy(mic_data->device_id, "builtin_mic", AUDIO_MICROPHONE_ID_MAX_LEN - 1);
496 strlcpy(mic_data->address, "top", AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
497 memset(mic_data->channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
498 sizeof(mic_data->channel_mapping));
499 mic_data->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
500 mic_data->sensitivity = -37.0;
501 mic_data->max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
502 mic_data->min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
503 mic_data->orientation.x = 0.0f;
504 mic_data->orientation.y = 0.0f;
505 mic_data->orientation.z = 0.0f;
506 mic_data->geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
507 mic_data->geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
508 mic_data->geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
509}
510
Amit Pundirc738b812019-06-19 16:13:49 +0530511static uint32_t in_get_sample_rate(const struct audio_stream *stream)
512{
Amit Pundirfec74f62020-09-28 12:43:59 +0530513 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
514 return in->config.rate;
Amit Pundirc738b812019-06-19 16:13:49 +0530515}
516
517static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
518{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100519 ALOGI("CA:: in_set_sample_rate: %d", rate);
Amit Pundirc738b812019-06-19 16:13:49 +0530520 return -ENOSYS;
521}
522
Amit Pundirfec74f62020-09-28 12:43:59 +0530523static size_t get_input_buffer_size(size_t frames, audio_format_t format,
524 audio_channel_mask_t channel_mask) {
525 /* return the closest majoring multiple of 16 frames, as
526 * audioflinger expects audio buffers to be a multiple of 16 frames */
527 frames = ((frames + 15) / 16) * 16;
528 size_t bytes_per_frame = audio_channel_count_from_in_mask(channel_mask) *
529 audio_bytes_per_sample(format);
530 size_t buffer_size = frames * bytes_per_frame;
531 return buffer_size;
Amit Pundirc738b812019-06-19 16:13:49 +0530532}
533
534static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
535{
Amit Pundirfec74f62020-09-28 12:43:59 +0530536 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100537 ALOGI("CA:: in_get_channels: %d", in->config.channels);
Amit Pundirfec74f62020-09-28 12:43:59 +0530538 return audio_channel_in_mask_from_count(in->config.channels);
Amit Pundirc738b812019-06-19 16:13:49 +0530539}
540
541static audio_format_t in_get_format(const struct audio_stream *stream)
542{
Amit Pundirfec74f62020-09-28 12:43:59 +0530543 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100544 ALOGI("CA:: in_get_format: %d", in->config.format);
Amit Pundirfec74f62020-09-28 12:43:59 +0530545 return audio_format_from_pcm_format(in->config.format);
Amit Pundirc738b812019-06-19 16:13:49 +0530546}
547
548static int in_set_format(struct audio_stream *stream, audio_format_t format)
549{
550 return -ENOSYS;
551}
552
Amit Pundirfec74f62020-09-28 12:43:59 +0530553static size_t in_get_buffer_size(const struct audio_stream *stream)
Amit Pundirc738b812019-06-19 16:13:49 +0530554{
Amit Pundirfec74f62020-09-28 12:43:59 +0530555 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
556 size_t frames = CAPTURE_PERIOD_SIZE;
557 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
558 frames = CAPTURE_PERIOD_SIZE * PLAYBACK_CODEC_SAMPLING_RATE / CAPTURE_CODEC_SAMPLING_RATE;
559 }
560
561 size_t buffer_size =
562 get_input_buffer_size(frames, stream->get_format(stream), stream->get_channels(stream));
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100563 ALOGI("CA:: in_get_buffer_size: %zu", buffer_size);
Amit Pundirfec74f62020-09-28 12:43:59 +0530564 return buffer_size;
565}
566
567static int in_get_active_microphones(const struct audio_stream_in* stream,
568 struct audio_microphone_characteristic_t* mic_array,
569 size_t* mic_count) {
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100570 ALOGI("CA:: in_get_active_microphones");
Amit Pundirfec74f62020-09-28 12:43:59 +0530571 if ((mic_array == NULL) || (mic_count == NULL)) {
572 return -EINVAL;
573 }
574 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
575 struct audio_hw_device* dev = (struct audio_hw_device*)in->dev;
576 bool mic_muted = false;
577 adev_get_mic_mute(dev, &mic_muted);
578 if ((in->source == AUDIO_SOURCE_ECHO_REFERENCE) || mic_muted) {
579 *mic_count = 0;
580 return 0;
581 }
582 adev_get_microphones(dev, mic_array, mic_count);
583 return 0;
584}
585
586static int do_input_standby(struct alsa_stream_in *in)
587{
588 struct alsa_audio_device *adev = in->dev;
589
590 if (!in->standby) {
591 pcm_close(in->pcm);
592 in->pcm = NULL;
593 adev->active_input = NULL;
594 in->standby = true;
595 }
596 return 0;
597}
598
599static int in_standby(struct audio_stream *stream)
600{
601 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
602 int status;
Amit Pundir648e1d02020-02-18 22:44:16 +0530603
604 pthread_mutex_lock(&in->lock);
Amit Pundirfec74f62020-09-28 12:43:59 +0530605 pthread_mutex_lock(&in->dev->lock);
606 status = do_input_standby(in);
607 pthread_mutex_unlock(&in->dev->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530608 pthread_mutex_unlock(&in->lock);
Amit Pundirfec74f62020-09-28 12:43:59 +0530609 return status;
610}
611
612static int in_dump(const struct audio_stream *stream, int fd)
613{
614 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
615 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
616 return 0;
617 }
618
619 struct audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
620 size_t mic_count;
621
622 get_mic_characteristics(mic_array, &mic_count);
623
624 dprintf(fd, " Microphone count: %zd\n", mic_count);
625 size_t idx;
626 for (idx = 0; idx < mic_count; idx++) {
627 dprintf(fd, " Microphone: %zd\n", idx);
628 dprintf(fd, " Address: %s\n", mic_array[idx].address);
629 dprintf(fd, " Device: %d\n", mic_array[idx].device);
630 dprintf(fd, " Sensitivity (dB): %.2f\n", mic_array[idx].sensitivity);
631 }
632
Amit Pundirc738b812019-06-19 16:13:49 +0530633 return 0;
634}
635
636static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
637{
Amit Pundirfec74f62020-09-28 12:43:59 +0530638 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +0530639}
640
641static char * in_get_parameters(const struct audio_stream *stream,
Amit Pundirfec74f62020-09-28 12:43:59 +0530642 const char *keys)
Amit Pundirc738b812019-06-19 16:13:49 +0530643{
Amit Pundirfec74f62020-09-28 12:43:59 +0530644 return strdup("");
Amit Pundirc738b812019-06-19 16:13:49 +0530645}
646
647static int in_set_gain(struct audio_stream_in *stream, float gain)
648{
649 return 0;
650}
651
Amit Pundir648e1d02020-02-18 22:44:16 +0530652static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
Amit Pundirfec74f62020-09-28 12:43:59 +0530653 size_t bytes)
Amit Pundir648e1d02020-02-18 22:44:16 +0530654{
Amit Pundirfec74f62020-09-28 12:43:59 +0530655 int ret;
656 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
657 struct alsa_audio_device *adev = in->dev;
658 size_t frame_size = audio_stream_in_frame_size(stream);
659 size_t in_frames = bytes / frame_size;
Amit Pundir648e1d02020-02-18 22:44:16 +0530660
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100661 ALOGI("CA:: in_read: stream: %d, bytes %zu", in->source, bytes);
Amit Pundir648e1d02020-02-18 22:44:16 +0530662
Amit Pundirfec74f62020-09-28 12:43:59 +0530663 /* Special handling for Echo Reference: simply get the reference from FIFO.
664 * The format and sample rate should be specified by arguments to adev_open_input_stream. */
665 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
666 struct aec_info info;
667 info.bytes = bytes;
Amit Pundir648e1d02020-02-18 22:44:16 +0530668
Amit Pundirfec74f62020-09-28 12:43:59 +0530669 const uint64_t time_increment_nsec = (uint64_t)bytes * NANOS_PER_SECOND /
670 audio_stream_in_frame_size(stream) /
671 in_get_sample_rate(&stream->common);
672 if (!aec_get_spk_running(adev->aec)) {
673 if (in->timestamp_nsec == 0) {
674 struct timespec now;
675 clock_gettime(CLOCK_MONOTONIC, &now);
676 const uint64_t timestamp_nsec = audio_utils_ns_from_timespec(&now);
677 in->timestamp_nsec = timestamp_nsec;
678 } else {
679 in->timestamp_nsec += time_increment_nsec;
680 }
681 memset(buffer, 0, bytes);
682 const uint64_t time_increment_usec = time_increment_nsec / 1000;
683 usleep(time_increment_usec);
684 } else {
685 int ref_ret = get_reference_samples(adev->aec, buffer, &info);
686 if ((ref_ret) || (info.timestamp_usec == 0)) {
687 memset(buffer, 0, bytes);
688 in->timestamp_nsec += time_increment_nsec;
689 } else {
690 in->timestamp_nsec = 1000 * info.timestamp_usec;
Amit Pundir648e1d02020-02-18 22:44:16 +0530691 }
692 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530693 in->frames_read += in_frames;
Amit Pundir648e1d02020-02-18 22:44:16 +0530694
Amit Pundirfec74f62020-09-28 12:43:59 +0530695#if DEBUG_AEC
696 FILE* fp_ref = fopen("/data/local/traces/aec_ref.pcm", "a+");
697 if (fp_ref) {
698 fwrite((char*)buffer, 1, bytes, fp_ref);
699 fclose(fp_ref);
700 } else {
701 ALOGE("AEC debug: Could not open file aec_ref.pcm!");
Amit Pundir648e1d02020-02-18 22:44:16 +0530702 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530703 FILE* fp_ref_ts = fopen("/data/local/traces/aec_ref_timestamps.txt", "a+");
704 if (fp_ref_ts) {
705 fprintf(fp_ref_ts, "%" PRIu64 "\n", in->timestamp_nsec);
706 fclose(fp_ref_ts);
707 } else {
708 ALOGE("AEC debug: Could not open file aec_ref_timestamps.txt!");
709 }
710#endif
711 return info.bytes;
712 }
713
714 /* Microphone input stream read */
715
716 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
717 * on the input stream mutex - e.g. executing select_mode() while holding the hw device
718 * mutex
719 */
720 pthread_mutex_lock(&in->lock);
721 pthread_mutex_lock(&adev->lock);
722 if (in->standby) {
723 ret = start_input_stream(in);
724 if (ret != 0) {
725 pthread_mutex_unlock(&adev->lock);
726 ALOGE("start_input_stream failed with code %d", ret);
727 goto exit;
728 }
729 in->standby = false;
730 }
731
732 pthread_mutex_unlock(&adev->lock);
733
734 ret = pcm_read(in->pcm, buffer, in_frames * frame_size);
735 struct aec_info info;
736 get_pcm_timestamp(in->pcm, in->config.rate, &info, false /*isOutput*/);
737 if (ret == 0) {
738 in->frames_read += in_frames;
739 in->timestamp_nsec = audio_utils_ns_from_timespec(&info.timestamp);
740 }
741 else {
742 ALOGE("pcm_read failed with code %d", ret);
Amit Pundir648e1d02020-02-18 22:44:16 +0530743 }
744
745exit:
Amit Pundir648e1d02020-02-18 22:44:16 +0530746 pthread_mutex_unlock(&in->lock);
747
Amit Pundirfec74f62020-09-28 12:43:59 +0530748 bool mic_muted = false;
749 adev_get_mic_mute((struct audio_hw_device*)adev, &mic_muted);
750 if (mic_muted) {
751 memset(buffer, 0, bytes);
752 }
753
754 if (ret != 0) {
755 usleep((int64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
756 in_get_sample_rate(&stream->common));
757 } else {
758 /* Process AEC if available */
759 /* TODO move to a separate thread */
760 if (!mic_muted) {
761 info.bytes = bytes;
762 int aec_ret = process_aec(adev->aec, buffer, &info);
763 if (aec_ret) {
764 ALOGE("process_aec returned error code %d", aec_ret);
765 }
766 }
767 }
768
769#if DEBUG_AEC && !defined(AEC_HAL)
770 FILE* fp_in = fopen("/data/local/traces/aec_in.pcm", "a+");
771 if (fp_in) {
772 fwrite((char*)buffer, 1, bytes, fp_in);
773 fclose(fp_in);
774 } else {
775 ALOGE("AEC debug: Could not open file aec_in.pcm!");
776 }
777 FILE* fp_mic_ts = fopen("/data/local/traces/aec_in_timestamps.txt", "a+");
778 if (fp_mic_ts) {
779 fprintf(fp_mic_ts, "%" PRIu64 "\n", in->timestamp_nsec);
780 fclose(fp_mic_ts);
781 } else {
782 ALOGE("AEC debug: Could not open file aec_in_timestamps.txt!");
783 }
784#endif
785
Amit Pundirc738b812019-06-19 16:13:49 +0530786 return bytes;
787}
788
Amit Pundirfec74f62020-09-28 12:43:59 +0530789static int in_get_capture_position(const struct audio_stream_in* stream, int64_t* frames,
790 int64_t* time) {
791 if (stream == NULL || frames == NULL || time == NULL) {
792 return -EINVAL;
793 }
794 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
795
796 *frames = in->frames_read;
797 *time = in->timestamp_nsec;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100798 ALOGI("CA:: %s: source: %d, timestamp (nsec): %" PRIu64, __func__, in->source, *time);
Amit Pundirfec74f62020-09-28 12:43:59 +0530799
800 return 0;
801}
802
Amit Pundirc738b812019-06-19 16:13:49 +0530803static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
804{
805 return 0;
806}
807
808static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
809{
810 return 0;
811}
812
813static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
814{
815 return 0;
816}
817
818static int adev_open_output_stream(struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +0530819 audio_io_handle_t handle,
820 audio_devices_t devices,
821 audio_output_flags_t flags,
822 struct audio_config *config,
823 struct audio_stream_out **stream_out,
824 const char *address __unused)
Amit Pundirc738b812019-06-19 16:13:49 +0530825{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100826 ALOGI("CA:: adev_open_output_stream...");
827
Amit Pundirfec74f62020-09-28 12:43:59 +0530828 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundirfec74f62020-09-28 12:43:59 +0530829 int out_port = get_audio_output_port(devices);
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100830 char* route_active_path_name = get_mixer_path_for_port(out_port);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800831 struct pcm_params* params = pcm_params_get(CARD_OUT, out_port, PCM_OUT);
832 if (!params) {
Amit Pundirfec74f62020-09-28 12:43:59 +0530833 return -ENOSYS;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800834 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530835
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100836 if (audio_route_apply_and_update_path(ladev->audio_route, route_active_path_name) < 0) {
837 ALOGE("CA:: %s() Failed to apply path %s", __func__, route_active_path_name);
838 }
839 ladev->active_port = out_port;
840
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800841 struct alsa_stream_out* out =
842 (struct alsa_stream_out*)calloc(1, sizeof(struct alsa_stream_out));
843 if (!out) {
Amit Pundirc738b812019-06-19 16:13:49 +0530844 return -ENOMEM;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800845 }
Amit Pundirc738b812019-06-19 16:13:49 +0530846
847 out->stream.common.get_sample_rate = out_get_sample_rate;
848 out->stream.common.set_sample_rate = out_set_sample_rate;
849 out->stream.common.get_buffer_size = out_get_buffer_size;
850 out->stream.common.get_channels = out_get_channels;
851 out->stream.common.get_format = out_get_format;
852 out->stream.common.set_format = out_set_format;
853 out->stream.common.standby = out_standby;
854 out->stream.common.dump = out_dump;
855 out->stream.common.set_parameters = out_set_parameters;
856 out->stream.common.get_parameters = out_get_parameters;
857 out->stream.common.add_audio_effect = out_add_audio_effect;
858 out->stream.common.remove_audio_effect = out_remove_audio_effect;
859 out->stream.get_latency = out_get_latency;
860 out->stream.set_volume = out_set_volume;
861 out->stream.write = out_write;
862 out->stream.get_render_position = out_get_render_position;
Amit Pundir648e1d02020-02-18 22:44:16 +0530863 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Amit Pundirfec74f62020-09-28 12:43:59 +0530864 out->stream.get_presentation_position = out_get_presentation_position;
Amit Pundirc738b812019-06-19 16:13:49 +0530865
Amit Pundirfec74f62020-09-28 12:43:59 +0530866 out->config.channels = CHANNEL_STEREO;
867 out->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
868 out->config.format = PCM_FORMAT_S16_LE;
869 out->config.period_size = PLAYBACK_PERIOD_SIZE;
870 out->config.period_count = PLAYBACK_PERIOD_COUNT;
Amit Pundirc738b812019-06-19 16:13:49 +0530871
Amit Pundirfec74f62020-09-28 12:43:59 +0530872 if (out->config.rate != config->sample_rate ||
873 audio_channel_count_from_out_mask(config->channel_mask) != CHANNEL_STEREO ||
874 out->config.format != pcm_format_from_audio_format(config->format) ) {
875 config->sample_rate = out->config.rate;
876 config->format = audio_format_from_pcm_format(out->config.format);
877 config->channel_mask = audio_channel_out_mask_from_count(CHANNEL_STEREO);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800878 goto error_1;
Amit Pundirc738b812019-06-19 16:13:49 +0530879 }
880
Amit Pundirfec74f62020-09-28 12:43:59 +0530881 ALOGI("adev_open_output_stream selects channels=%d rate=%d format=%d, devices=%d",
882 out->config.channels, out->config.rate, out->config.format, devices);
883
884 out->dev = ladev;
885 out->standby = 1;
886 out->unavailable = false;
887 out->devices = devices;
888
889 config->format = out_get_format(&out->stream.common);
890 config->channel_mask = out_get_channels(&out->stream.common);
891 config->sample_rate = out_get_sample_rate(&out->stream.common);
Amit Pundirc738b812019-06-19 16:13:49 +0530892
Amit Pundirfec74f62020-09-28 12:43:59 +0530893 out->speaker_eq = NULL;
894 if (out_port == PORT_INTERNAL_SPEAKER) {
895 out_set_eq(out);
896 if (out->speaker_eq == NULL) {
897 ALOGE("%s: Failed to initialize speaker EQ", __func__);
898 }
899 }
900
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800901 int aec_ret = init_aec_reference_config(ladev->aec, out);
902 if (aec_ret) {
903 ALOGE("AEC: Speaker config init failed!");
904 goto error_2;
Amit Pundirfec74f62020-09-28 12:43:59 +0530905 }
Amit Pundirc738b812019-06-19 16:13:49 +0530906
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800907 *stream_out = &out->stream;
908 return 0;
909
910error_2:
911 fir_release(out->speaker_eq);
912error_1:
913 free(out);
914 return -EINVAL;
Amit Pundirc738b812019-06-19 16:13:49 +0530915}
916
917static void adev_close_output_stream(struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +0530918 struct audio_stream_out *stream)
Amit Pundirc738b812019-06-19 16:13:49 +0530919{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100920 ALOGI("CA:: adev_close_output_stream...");
Amit Pundirfec74f62020-09-28 12:43:59 +0530921 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
922 destroy_aec_reference_config(adev->aec);
923 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
924 fir_release(out->speaker_eq);
Amit Pundirc738b812019-06-19 16:13:49 +0530925 free(stream);
926}
927
928static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
929{
Caleb Connollyd59c9062021-08-10 13:50:39 +0100930 ALOGI("CA:: adev_set_parameters: %s", kvpairs);
Amit Pundirfec74f62020-09-28 12:43:59 +0530931 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530932}
933
934static char * adev_get_parameters(const struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +0530935 const char *keys)
Amit Pundirc738b812019-06-19 16:13:49 +0530936{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100937 ALOGI("CA:: adev_get_parameters");
Amit Pundirc738b812019-06-19 16:13:49 +0530938 return strdup("");
939}
940
Amit Pundirfec74f62020-09-28 12:43:59 +0530941static int adev_get_microphones(const struct audio_hw_device* dev,
942 struct audio_microphone_characteristic_t* mic_array,
943 size_t* mic_count) {
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100944 ALOGI("CA:: adev_get_microphones");
Amit Pundirfec74f62020-09-28 12:43:59 +0530945 if ((mic_array == NULL) || (mic_count == NULL)) {
946 return -EINVAL;
947 }
948 get_mic_characteristics(mic_array, mic_count);
949 return 0;
950}
951
Amit Pundirc738b812019-06-19 16:13:49 +0530952static int adev_init_check(const struct audio_hw_device *dev)
953{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100954 ALOGI("CA:: adev_init_check");
Amit Pundirc738b812019-06-19 16:13:49 +0530955 return 0;
956}
957
958static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
959{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100960 ALOGI("CA:: adev_set_voice_volume: %f", volume);
Amit Pundirfec74f62020-09-28 12:43:59 +0530961 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530962}
963
964static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
965{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100966 ALOGI("CA:: adev_set_master_volume: %f", volume);
Amit Pundirc738b812019-06-19 16:13:49 +0530967 return -ENOSYS;
968}
969
970static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
971{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100972 ALOGI("CA:: adev_get_master_volume: %f", *volume);
Amit Pundirc738b812019-06-19 16:13:49 +0530973 return -ENOSYS;
974}
975
976static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
977{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100978 ALOGI("CA:: adev_set_master_mute: %d", muted);
Amit Pundirc738b812019-06-19 16:13:49 +0530979 return -ENOSYS;
980}
981
982static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
983{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100984 ALOGI("CA:: adev_get_master_mute: %d", *muted);
Amit Pundirc738b812019-06-19 16:13:49 +0530985 return -ENOSYS;
986}
987
988static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
989{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100990 ALOGI("CA:: adev_set_mode: %d", mode);
Amit Pundirc738b812019-06-19 16:13:49 +0530991 return 0;
992}
993
994static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
995{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100996 ALOGI("CA:: adev_set_mic_mute: %d",state);
Amit Pundirfec74f62020-09-28 12:43:59 +0530997 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir648e1d02020-02-18 22:44:16 +0530998 pthread_mutex_lock(&adev->lock);
999 adev->mic_mute = state;
1000 pthread_mutex_unlock(&adev->lock);
1001 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +05301002}
1003
1004static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1005{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001006 ALOGI("CA:: adev_get_mic_mute");
Amit Pundirfec74f62020-09-28 12:43:59 +05301007 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir648e1d02020-02-18 22:44:16 +05301008 pthread_mutex_lock(&adev->lock);
1009 *state = adev->mic_mute;
1010 pthread_mutex_unlock(&adev->lock);
1011 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +05301012}
1013
1014static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +05301015 const struct audio_config *config)
Amit Pundirc738b812019-06-19 16:13:49 +05301016{
Amit Pundirfec74f62020-09-28 12:43:59 +05301017 size_t buffer_size =
1018 get_input_buffer_size(CAPTURE_PERIOD_SIZE, config->format, config->channel_mask);
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001019 ALOGI("CA:: adev_get_input_buffer_size: %zu", buffer_size);
Amit Pundirfec74f62020-09-28 12:43:59 +05301020 return buffer_size;
Amit Pundirc738b812019-06-19 16:13:49 +05301021}
1022
Amit Pundirfec74f62020-09-28 12:43:59 +05301023static int adev_open_input_stream(struct audio_hw_device* dev, audio_io_handle_t handle,
1024 audio_devices_t devices, struct audio_config* config,
1025 struct audio_stream_in** stream_in,
1026 audio_input_flags_t flags __unused, const char* address __unused,
1027 audio_source_t source) {
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001028 ALOGI("CA:: adev_open_input_stream...");
Amit Pundir648e1d02020-02-18 22:44:16 +05301029
Amit Pundirfec74f62020-09-28 12:43:59 +05301030 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundir648e1d02020-02-18 22:44:16 +05301031
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001032 struct pcm_params* params = pcm_params_get(CARD_IN, PORT_BUILTIN_MIC, PCM_IN);
1033 if (!params) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301034 return -ENOSYS;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001035 }
Amit Pundirfec74f62020-09-28 12:43:59 +05301036
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001037 struct alsa_stream_in* in = (struct alsa_stream_in*)calloc(1, sizeof(struct alsa_stream_in));
1038 if (!in) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301039 return -ENOMEM;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001040 }
Amit Pundirc738b812019-06-19 16:13:49 +05301041
1042 in->stream.common.get_sample_rate = in_get_sample_rate;
Amit Pundirfec74f62020-09-28 12:43:59 +05301043 in->stream.common.set_sample_rate = in_set_sample_rate;
Amit Pundirc738b812019-06-19 16:13:49 +05301044 in->stream.common.get_buffer_size = in_get_buffer_size;
1045 in->stream.common.get_channels = in_get_channels;
1046 in->stream.common.get_format = in_get_format;
Amit Pundirfec74f62020-09-28 12:43:59 +05301047 in->stream.common.set_format = in_set_format;
Amit Pundirc738b812019-06-19 16:13:49 +05301048 in->stream.common.standby = in_standby;
1049 in->stream.common.dump = in_dump;
1050 in->stream.common.set_parameters = in_set_parameters;
1051 in->stream.common.get_parameters = in_get_parameters;
Amit Pundirfec74f62020-09-28 12:43:59 +05301052 in->stream.common.add_audio_effect = in_add_audio_effect;
1053 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1054 in->stream.set_gain = in_set_gain;
Amit Pundirc738b812019-06-19 16:13:49 +05301055 in->stream.read = in_read;
Amit Pundirfec74f62020-09-28 12:43:59 +05301056 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Amit Pundir648e1d02020-02-18 22:44:16 +05301057 in->stream.get_capture_position = in_get_capture_position;
1058 in->stream.get_active_microphones = in_get_active_microphones;
1059
Amit Pundirfec74f62020-09-28 12:43:59 +05301060 in->config.channels = CHANNEL_STEREO;
1061 if (source == AUDIO_SOURCE_ECHO_REFERENCE) {
1062 in->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
1063 } else {
1064 in->config.rate = CAPTURE_CODEC_SAMPLING_RATE;
1065 }
1066 in->config.format = PCM_FORMAT_S32_LE;
1067 in->config.period_size = CAPTURE_PERIOD_SIZE;
1068 in->config.period_count = CAPTURE_PERIOD_COUNT;
Amit Pundir648e1d02020-02-18 22:44:16 +05301069
Amit Pundirfec74f62020-09-28 12:43:59 +05301070 if (in->config.rate != config->sample_rate ||
1071 audio_channel_count_from_in_mask(config->channel_mask) != CHANNEL_STEREO ||
1072 in->config.format != pcm_format_from_audio_format(config->format) ) {
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001073 config->format = in_get_format(&in->stream.common);
1074 config->channel_mask = in_get_channels(&in->stream.common);
1075 config->sample_rate = in_get_sample_rate(&in->stream.common);
1076 goto error_1;
Amit Pundirfec74f62020-09-28 12:43:59 +05301077 }
Amit Pundir648e1d02020-02-18 22:44:16 +05301078
Amit Pundirfec74f62020-09-28 12:43:59 +05301079 ALOGI("adev_open_input_stream selects channels=%d rate=%d format=%d source=%d",
1080 in->config.channels, in->config.rate, in->config.format, source);
1081
1082 in->dev = ladev;
Amit Pundir648e1d02020-02-18 22:44:16 +05301083 in->standby = true;
Amit Pundirfec74f62020-09-28 12:43:59 +05301084 in->unavailable = false;
1085 in->source = source;
1086 in->devices = devices;
Amit Pundir648e1d02020-02-18 22:44:16 +05301087
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001088 if (is_aec_input(in)) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301089 int aec_ret = init_aec_mic_config(ladev->aec, in);
1090 if (aec_ret) {
1091 ALOGE("AEC: Mic config init failed!");
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001092 goto error_1;
Amit Pundir648e1d02020-02-18 22:44:16 +05301093 }
Amit Pundirfec74f62020-09-28 12:43:59 +05301094 }
1095
Amit Pundirfec74f62020-09-28 12:43:59 +05301096#if DEBUG_AEC
1097 remove("/data/local/traces/aec_ref.pcm");
1098 remove("/data/local/traces/aec_in.pcm");
1099 remove("/data/local/traces/aec_ref_timestamps.txt");
1100 remove("/data/local/traces/aec_in_timestamps.txt");
1101#endif
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001102
1103 *stream_in = &in->stream;
1104 return 0;
1105
1106error_1:
1107 free(in);
1108 return -EINVAL;
Amit Pundirfec74f62020-09-28 12:43:59 +05301109}
Amit Pundir648e1d02020-02-18 22:44:16 +05301110
Amit Pundirfec74f62020-09-28 12:43:59 +05301111static void adev_close_input_stream(struct audio_hw_device *dev,
1112 struct audio_stream_in *stream)
1113{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001114 ALOGI("CA:: adev_close_input_stream...");
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001115 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
1116 if (is_aec_input(in)) {
1117 destroy_aec_mic_config(in->dev->aec);
1118 }
Amit Pundirfec74f62020-09-28 12:43:59 +05301119 free(stream);
1120 return;
1121}
Amit Pundir648e1d02020-02-18 22:44:16 +05301122
Amit Pundirfec74f62020-09-28 12:43:59 +05301123static int adev_dump(const audio_hw_device_t *device, int fd)
1124{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001125 ALOGI("CA:: adev_dump");
Amit Pundirc738b812019-06-19 16:13:49 +05301126 return 0;
1127}
1128
Amit Pundirfec74f62020-09-28 12:43:59 +05301129static int adev_close(hw_device_t *device)
Amit Pundir648e1d02020-02-18 22:44:16 +05301130{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001131 ALOGI("CA:: adev_close");
Amit Pundir648e1d02020-02-18 22:44:16 +05301132
Amit Pundirfec74f62020-09-28 12:43:59 +05301133 struct alsa_audio_device *adev = (struct alsa_audio_device *)device;
1134 release_aec(adev->aec);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001135 audio_route_free(adev->audio_route);
1136 mixer_close(adev->mixer);
Amit Pundirfec74f62020-09-28 12:43:59 +05301137 free(device);
1138 return 0;
Amit Pundir648e1d02020-02-18 22:44:16 +05301139}
1140
Amit Pundirc738b812019-06-19 16:13:49 +05301141static int adev_open(const hw_module_t* module, const char* name,
Amit Pundirfec74f62020-09-28 12:43:59 +05301142 hw_device_t** device)
Amit Pundirc738b812019-06-19 16:13:49 +05301143{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001144 ALOGI("CA:: adev_open: %s", name);
Amit Pundirc738b812019-06-19 16:13:49 +05301145
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001146 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
Amit Pundirc738b812019-06-19 16:13:49 +05301147 return -EINVAL;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001148 }
Amit Pundirc738b812019-06-19 16:13:49 +05301149
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001150 struct alsa_audio_device* adev = calloc(1, sizeof(struct alsa_audio_device));
1151 if (!adev) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301152 return -ENOMEM;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001153 }
Amit Pundirc738b812019-06-19 16:13:49 +05301154
Amit Pundirfec74f62020-09-28 12:43:59 +05301155 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
1156 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1157 adev->hw_device.common.module = (struct hw_module_t *) module;
1158 adev->hw_device.common.close = adev_close;
1159 adev->hw_device.init_check = adev_init_check;
1160 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1161 adev->hw_device.set_master_volume = adev_set_master_volume;
1162 adev->hw_device.get_master_volume = adev_get_master_volume;
1163 adev->hw_device.set_master_mute = adev_set_master_mute;
1164 adev->hw_device.get_master_mute = adev_get_master_mute;
1165 adev->hw_device.set_mode = adev_set_mode;
1166 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1167 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1168 adev->hw_device.set_parameters = adev_set_parameters;
1169 adev->hw_device.get_parameters = adev_get_parameters;
1170 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1171 adev->hw_device.open_output_stream = adev_open_output_stream;
1172 adev->hw_device.close_output_stream = adev_close_output_stream;
1173 adev->hw_device.open_input_stream = adev_open_input_stream;
1174 adev->hw_device.close_input_stream = adev_close_input_stream;
1175 adev->hw_device.dump = adev_dump;
1176 adev->hw_device.get_microphones = adev_get_microphones;
Amit Pundirc738b812019-06-19 16:13:49 +05301177
Amit Pundirfec74f62020-09-28 12:43:59 +05301178 *device = &adev->hw_device.common;
Amit Pundirc738b812019-06-19 16:13:49 +05301179
Amit Pundirfec74f62020-09-28 12:43:59 +05301180 adev->mixer = mixer_open(CARD_OUT);
Amit Pundirfec74f62020-09-28 12:43:59 +05301181 if (!adev->mixer) {
1182 ALOGE("Unable to open the mixer, aborting.");
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001183 goto error_1;
Amit Pundir648e1d02020-02-18 22:44:16 +05301184 }
1185
Amit Pundirfec74f62020-09-28 12:43:59 +05301186 adev->audio_route = audio_route_init(CARD_OUT, MIXER_XML_PATH);
1187 if (!adev->audio_route) {
1188 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001189 goto error_2;
Amit Pundirfec74f62020-09-28 12:43:59 +05301190 }
Amit Pundir648e1d02020-02-18 22:44:16 +05301191
Amit Pundirfec74f62020-09-28 12:43:59 +05301192 pthread_mutex_lock(&adev->lock);
1193 if (init_aec(CAPTURE_CODEC_SAMPLING_RATE, NUM_AEC_REFERENCE_CHANNELS,
1194 CHANNEL_STEREO, &adev->aec)) {
1195 pthread_mutex_unlock(&adev->lock);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001196 goto error_3;
Amit Pundirfec74f62020-09-28 12:43:59 +05301197 }
1198 pthread_mutex_unlock(&adev->lock);
1199
Amit Pundirc738b812019-06-19 16:13:49 +05301200 return 0;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001201
1202error_3:
1203 audio_route_free(adev->audio_route);
1204error_2:
1205 mixer_close(adev->mixer);
1206error_1:
1207 free(adev);
1208 return -EINVAL;
Amit Pundirc738b812019-06-19 16:13:49 +05301209}
1210
1211static struct hw_module_methods_t hal_module_methods = {
1212 .open = adev_open,
1213};
1214
1215struct audio_module HAL_MODULE_INFO_SYM = {
1216 .common = {
1217 .tag = HARDWARE_MODULE_TAG,
1218 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1219 .hal_api_version = HARDWARE_HAL_API_VERSION,
1220 .id = AUDIO_HARDWARE_MODULE_ID,
Amit Pundir648e1d02020-02-18 22:44:16 +05301221 .name = "Generic audio HW HAL",
Amit Pundirc738b812019-06-19 16:13:49 +05301222 .author = "The Android Open Source Project",
1223 .methods = &hal_module_methods,
1224 },
1225};