blob: cf4928cbd5a95e76ff9471d5ddc0dacb9b16db49 [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) {
359 ret = audio_route_reset_and_update_path(adev->audio_route, route_active_path_name);
360 adev->active_port = out_port;
361 if (ret < 0) {
362 ALOGE("CA:: %s() failed to set path %s", __func__, route_active_path_name);
363 }
364 }
365
366 ALOGI("CA:: %s: devices: %d, bytes %zu", __func__, out->devices, bytes);
Amit Pundir648e1d02020-02-18 22:44:16 +0530367
Amit Pundirfec74f62020-09-28 12:43:59 +0530368 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
369 * on the output stream mutex - e.g. executing select_mode() while holding the hw device
370 * mutex
371 */
372 pthread_mutex_lock(&adev->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530373 pthread_mutex_lock(&out->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530374 if (out->standby) {
Amit Pundirfec74f62020-09-28 12:43:59 +0530375 ret = start_output_stream(out);
376 if (ret != 0) {
377 pthread_mutex_unlock(&adev->lock);
378 goto exit;
379 }
380 out->standby = 0;
381 aec_set_spk_running(adev->aec, true);
Amit Pundir648e1d02020-02-18 22:44:16 +0530382 }
383
Amit Pundirfec74f62020-09-28 12:43:59 +0530384 pthread_mutex_unlock(&adev->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530385
Amit Pundirfec74f62020-09-28 12:43:59 +0530386 if (out->speaker_eq != NULL) {
387 fir_process_interleaved(out->speaker_eq, (int16_t*)buffer, (int16_t*)buffer, out_frames);
Amit Pundir648e1d02020-02-18 22:44:16 +0530388 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530389
Amit Pundirfec74f62020-09-28 12:43:59 +0530390 ret = pcm_write(out->pcm, buffer, out_frames * frame_size);
391 if (ret == 0) {
392 out->frames_written += out_frames;
393
394 struct aec_info info;
395 get_pcm_timestamp(out->pcm, out->config.rate, &info, true /*isOutput*/);
396 out->timestamp = info.timestamp;
397 info.bytes = out_frames * frame_size;
398 int aec_ret = write_to_reference_fifo(adev->aec, (void *)buffer, &info);
399 if (aec_ret) {
400 ALOGE("AEC: Write to speaker loopback FIFO failed!");
401 }
402 }
403
404exit:
Amit Pundirc738b812019-06-19 16:13:49 +0530405 pthread_mutex_unlock(&out->lock);
406
Amit Pundirfec74f62020-09-28 12:43:59 +0530407 if (ret != 0) {
408 usleep((int64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
409 out_get_sample_rate(&stream->common));
Amit Pundirc738b812019-06-19 16:13:49 +0530410 }
411
Amit Pundir648e1d02020-02-18 22:44:16 +0530412 return bytes;
Amit Pundirc738b812019-06-19 16:13:49 +0530413}
414
Amit Pundirfec74f62020-09-28 12:43:59 +0530415static int out_get_render_position(const struct audio_stream_out *stream,
416 uint32_t *dsp_frames)
417{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100418 ALOGI("CA:: out_get_render_position: dsp_frames: %p", dsp_frames);
Amit Pundirfec74f62020-09-28 12:43:59 +0530419 return -ENOSYS;
420}
421
Amit Pundirc738b812019-06-19 16:13:49 +0530422static int out_get_presentation_position(const struct audio_stream_out *stream,
423 uint64_t *frames, struct timespec *timestamp)
424{
Amit Pundir648e1d02020-02-18 22:44:16 +0530425 if (stream == NULL || frames == NULL || timestamp == NULL) {
426 return -EINVAL;
427 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530428 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
Amit Pundirc738b812019-06-19 16:13:49 +0530429
Amit Pundirfec74f62020-09-28 12:43:59 +0530430 *frames = out->frames_written;
431 *timestamp = out->timestamp;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100432 ALOGI("CA:: %s: frames: %" PRIu64 ", timestamp (nsec): %" PRIu64, __func__, *frames,
Amit Pundirfec74f62020-09-28 12:43:59 +0530433 audio_utils_ns_from_timespec(timestamp));
Amit Pundirc738b812019-06-19 16:13:49 +0530434
Amit Pundir648e1d02020-02-18 22:44:16 +0530435 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +0530436}
437
438
439static int out_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
440{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100441 ALOGI("CA:: out_add_audio_effect: %p", effect);
Amit Pundirc738b812019-06-19 16:13:49 +0530442 return 0;
443}
444
445static int out_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
446{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100447 ALOGI("CA:: out_remove_audio_effect: %p", effect);
Amit Pundirc738b812019-06-19 16:13:49 +0530448 return 0;
449}
450
451static int out_get_next_write_timestamp(const struct audio_stream_out *stream,
Amit Pundirfec74f62020-09-28 12:43:59 +0530452 int64_t *timestamp)
Amit Pundirc738b812019-06-19 16:13:49 +0530453{
Amit Pundirfec74f62020-09-28 12:43:59 +0530454 *timestamp = 0;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100455 ALOGI("CA:: out_get_next_write_timestamp: %ld", (long int)(*timestamp));
Amit Pundir648e1d02020-02-18 22:44:16 +0530456 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530457}
458
Amit Pundirfec74f62020-09-28 12:43:59 +0530459/** audio_stream_in implementation **/
460
461/* must be called with hw device and input stream mutexes locked */
462static int start_input_stream(struct alsa_stream_in *in)
463{
464 struct alsa_audio_device *adev = in->dev;
465 in->unavailable = true;
466 unsigned int pcm_retry_count = PCM_OPEN_RETRIES;
467
468 while (1) {
469 in->pcm = pcm_open(CARD_IN, PORT_BUILTIN_MIC, PCM_IN | PCM_MONOTONIC, &in->config);
470 if ((in->pcm != NULL) && pcm_is_ready(in->pcm)) {
471 break;
472 } else {
473 ALOGE("cannot open pcm_in driver: %s", pcm_get_error(in->pcm));
474 if (in->pcm != NULL) {
475 pcm_close(in->pcm);
476 in->pcm = NULL;
477 }
478 if (--pcm_retry_count == 0) {
479 ALOGE("Failed to open pcm_in after %d tries", PCM_OPEN_RETRIES);
480 return -ENODEV;
481 }
482 usleep(PCM_OPEN_WAIT_TIME_MS * 1000);
483 }
484 }
485 in->unavailable = false;
486 adev->active_input = in;
487 return 0;
488}
489
490static void get_mic_characteristics(struct audio_microphone_characteristic_t* mic_data,
491 size_t* mic_count) {
492 *mic_count = 1;
493 memset(mic_data, 0, sizeof(struct audio_microphone_characteristic_t));
494 strlcpy(mic_data->device_id, "builtin_mic", AUDIO_MICROPHONE_ID_MAX_LEN - 1);
495 strlcpy(mic_data->address, "top", AUDIO_DEVICE_MAX_ADDRESS_LEN - 1);
496 memset(mic_data->channel_mapping, AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED,
497 sizeof(mic_data->channel_mapping));
498 mic_data->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
499 mic_data->sensitivity = -37.0;
500 mic_data->max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
501 mic_data->min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
502 mic_data->orientation.x = 0.0f;
503 mic_data->orientation.y = 0.0f;
504 mic_data->orientation.z = 0.0f;
505 mic_data->geometric_location.x = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
506 mic_data->geometric_location.y = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
507 mic_data->geometric_location.z = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
508}
509
Amit Pundirc738b812019-06-19 16:13:49 +0530510static uint32_t in_get_sample_rate(const struct audio_stream *stream)
511{
Amit Pundirfec74f62020-09-28 12:43:59 +0530512 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
513 return in->config.rate;
Amit Pundirc738b812019-06-19 16:13:49 +0530514}
515
516static int in_set_sample_rate(struct audio_stream *stream, uint32_t rate)
517{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100518 ALOGI("CA:: in_set_sample_rate: %d", rate);
Amit Pundirc738b812019-06-19 16:13:49 +0530519 return -ENOSYS;
520}
521
Amit Pundirfec74f62020-09-28 12:43:59 +0530522static size_t get_input_buffer_size(size_t frames, audio_format_t format,
523 audio_channel_mask_t channel_mask) {
524 /* return the closest majoring multiple of 16 frames, as
525 * audioflinger expects audio buffers to be a multiple of 16 frames */
526 frames = ((frames + 15) / 16) * 16;
527 size_t bytes_per_frame = audio_channel_count_from_in_mask(channel_mask) *
528 audio_bytes_per_sample(format);
529 size_t buffer_size = frames * bytes_per_frame;
530 return buffer_size;
Amit Pundirc738b812019-06-19 16:13:49 +0530531}
532
533static audio_channel_mask_t in_get_channels(const struct audio_stream *stream)
534{
Amit Pundirfec74f62020-09-28 12:43:59 +0530535 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100536 ALOGI("CA:: in_get_channels: %d", in->config.channels);
Amit Pundirfec74f62020-09-28 12:43:59 +0530537 return audio_channel_in_mask_from_count(in->config.channels);
Amit Pundirc738b812019-06-19 16:13:49 +0530538}
539
540static audio_format_t in_get_format(const struct audio_stream *stream)
541{
Amit Pundirfec74f62020-09-28 12:43:59 +0530542 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100543 ALOGI("CA:: in_get_format: %d", in->config.format);
Amit Pundirfec74f62020-09-28 12:43:59 +0530544 return audio_format_from_pcm_format(in->config.format);
Amit Pundirc738b812019-06-19 16:13:49 +0530545}
546
547static int in_set_format(struct audio_stream *stream, audio_format_t format)
548{
549 return -ENOSYS;
550}
551
Amit Pundirfec74f62020-09-28 12:43:59 +0530552static size_t in_get_buffer_size(const struct audio_stream *stream)
Amit Pundirc738b812019-06-19 16:13:49 +0530553{
Amit Pundirfec74f62020-09-28 12:43:59 +0530554 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
555 size_t frames = CAPTURE_PERIOD_SIZE;
556 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
557 frames = CAPTURE_PERIOD_SIZE * PLAYBACK_CODEC_SAMPLING_RATE / CAPTURE_CODEC_SAMPLING_RATE;
558 }
559
560 size_t buffer_size =
561 get_input_buffer_size(frames, stream->get_format(stream), stream->get_channels(stream));
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100562 ALOGI("CA:: in_get_buffer_size: %zu", buffer_size);
Amit Pundirfec74f62020-09-28 12:43:59 +0530563 return buffer_size;
564}
565
566static int in_get_active_microphones(const struct audio_stream_in* stream,
567 struct audio_microphone_characteristic_t* mic_array,
568 size_t* mic_count) {
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100569 ALOGI("CA:: in_get_active_microphones");
Amit Pundirfec74f62020-09-28 12:43:59 +0530570 if ((mic_array == NULL) || (mic_count == NULL)) {
571 return -EINVAL;
572 }
573 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
574 struct audio_hw_device* dev = (struct audio_hw_device*)in->dev;
575 bool mic_muted = false;
576 adev_get_mic_mute(dev, &mic_muted);
577 if ((in->source == AUDIO_SOURCE_ECHO_REFERENCE) || mic_muted) {
578 *mic_count = 0;
579 return 0;
580 }
581 adev_get_microphones(dev, mic_array, mic_count);
582 return 0;
583}
584
585static int do_input_standby(struct alsa_stream_in *in)
586{
587 struct alsa_audio_device *adev = in->dev;
588
589 if (!in->standby) {
590 pcm_close(in->pcm);
591 in->pcm = NULL;
592 adev->active_input = NULL;
593 in->standby = true;
594 }
595 return 0;
596}
597
598static int in_standby(struct audio_stream *stream)
599{
600 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
601 int status;
Amit Pundir648e1d02020-02-18 22:44:16 +0530602
603 pthread_mutex_lock(&in->lock);
Amit Pundirfec74f62020-09-28 12:43:59 +0530604 pthread_mutex_lock(&in->dev->lock);
605 status = do_input_standby(in);
606 pthread_mutex_unlock(&in->dev->lock);
Amit Pundir648e1d02020-02-18 22:44:16 +0530607 pthread_mutex_unlock(&in->lock);
Amit Pundirfec74f62020-09-28 12:43:59 +0530608 return status;
609}
610
611static int in_dump(const struct audio_stream *stream, int fd)
612{
613 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
614 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
615 return 0;
616 }
617
618 struct audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
619 size_t mic_count;
620
621 get_mic_characteristics(mic_array, &mic_count);
622
623 dprintf(fd, " Microphone count: %zd\n", mic_count);
624 size_t idx;
625 for (idx = 0; idx < mic_count; idx++) {
626 dprintf(fd, " Microphone: %zd\n", idx);
627 dprintf(fd, " Address: %s\n", mic_array[idx].address);
628 dprintf(fd, " Device: %d\n", mic_array[idx].device);
629 dprintf(fd, " Sensitivity (dB): %.2f\n", mic_array[idx].sensitivity);
630 }
631
Amit Pundirc738b812019-06-19 16:13:49 +0530632 return 0;
633}
634
635static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
636{
Amit Pundirfec74f62020-09-28 12:43:59 +0530637 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +0530638}
639
640static char * in_get_parameters(const struct audio_stream *stream,
Amit Pundirfec74f62020-09-28 12:43:59 +0530641 const char *keys)
Amit Pundirc738b812019-06-19 16:13:49 +0530642{
Amit Pundirfec74f62020-09-28 12:43:59 +0530643 return strdup("");
Amit Pundirc738b812019-06-19 16:13:49 +0530644}
645
646static int in_set_gain(struct audio_stream_in *stream, float gain)
647{
648 return 0;
649}
650
Amit Pundir648e1d02020-02-18 22:44:16 +0530651static ssize_t in_read(struct audio_stream_in *stream, void* buffer,
Amit Pundirfec74f62020-09-28 12:43:59 +0530652 size_t bytes)
Amit Pundir648e1d02020-02-18 22:44:16 +0530653{
Amit Pundirfec74f62020-09-28 12:43:59 +0530654 int ret;
655 struct alsa_stream_in *in = (struct alsa_stream_in *)stream;
656 struct alsa_audio_device *adev = in->dev;
657 size_t frame_size = audio_stream_in_frame_size(stream);
658 size_t in_frames = bytes / frame_size;
Amit Pundir648e1d02020-02-18 22:44:16 +0530659
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100660 ALOGI("CA:: in_read: stream: %d, bytes %zu", in->source, bytes);
Amit Pundir648e1d02020-02-18 22:44:16 +0530661
Amit Pundirfec74f62020-09-28 12:43:59 +0530662 /* Special handling for Echo Reference: simply get the reference from FIFO.
663 * The format and sample rate should be specified by arguments to adev_open_input_stream. */
664 if (in->source == AUDIO_SOURCE_ECHO_REFERENCE) {
665 struct aec_info info;
666 info.bytes = bytes;
Amit Pundir648e1d02020-02-18 22:44:16 +0530667
Amit Pundirfec74f62020-09-28 12:43:59 +0530668 const uint64_t time_increment_nsec = (uint64_t)bytes * NANOS_PER_SECOND /
669 audio_stream_in_frame_size(stream) /
670 in_get_sample_rate(&stream->common);
671 if (!aec_get_spk_running(adev->aec)) {
672 if (in->timestamp_nsec == 0) {
673 struct timespec now;
674 clock_gettime(CLOCK_MONOTONIC, &now);
675 const uint64_t timestamp_nsec = audio_utils_ns_from_timespec(&now);
676 in->timestamp_nsec = timestamp_nsec;
677 } else {
678 in->timestamp_nsec += time_increment_nsec;
679 }
680 memset(buffer, 0, bytes);
681 const uint64_t time_increment_usec = time_increment_nsec / 1000;
682 usleep(time_increment_usec);
683 } else {
684 int ref_ret = get_reference_samples(adev->aec, buffer, &info);
685 if ((ref_ret) || (info.timestamp_usec == 0)) {
686 memset(buffer, 0, bytes);
687 in->timestamp_nsec += time_increment_nsec;
688 } else {
689 in->timestamp_nsec = 1000 * info.timestamp_usec;
Amit Pundir648e1d02020-02-18 22:44:16 +0530690 }
691 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530692 in->frames_read += in_frames;
Amit Pundir648e1d02020-02-18 22:44:16 +0530693
Amit Pundirfec74f62020-09-28 12:43:59 +0530694#if DEBUG_AEC
695 FILE* fp_ref = fopen("/data/local/traces/aec_ref.pcm", "a+");
696 if (fp_ref) {
697 fwrite((char*)buffer, 1, bytes, fp_ref);
698 fclose(fp_ref);
699 } else {
700 ALOGE("AEC debug: Could not open file aec_ref.pcm!");
Amit Pundir648e1d02020-02-18 22:44:16 +0530701 }
Amit Pundirfec74f62020-09-28 12:43:59 +0530702 FILE* fp_ref_ts = fopen("/data/local/traces/aec_ref_timestamps.txt", "a+");
703 if (fp_ref_ts) {
704 fprintf(fp_ref_ts, "%" PRIu64 "\n", in->timestamp_nsec);
705 fclose(fp_ref_ts);
706 } else {
707 ALOGE("AEC debug: Could not open file aec_ref_timestamps.txt!");
708 }
709#endif
710 return info.bytes;
711 }
712
713 /* Microphone input stream read */
714
715 /* acquiring hw device mutex systematically is useful if a low priority thread is waiting
716 * on the input stream mutex - e.g. executing select_mode() while holding the hw device
717 * mutex
718 */
719 pthread_mutex_lock(&in->lock);
720 pthread_mutex_lock(&adev->lock);
721 if (in->standby) {
722 ret = start_input_stream(in);
723 if (ret != 0) {
724 pthread_mutex_unlock(&adev->lock);
725 ALOGE("start_input_stream failed with code %d", ret);
726 goto exit;
727 }
728 in->standby = false;
729 }
730
731 pthread_mutex_unlock(&adev->lock);
732
733 ret = pcm_read(in->pcm, buffer, in_frames * frame_size);
734 struct aec_info info;
735 get_pcm_timestamp(in->pcm, in->config.rate, &info, false /*isOutput*/);
736 if (ret == 0) {
737 in->frames_read += in_frames;
738 in->timestamp_nsec = audio_utils_ns_from_timespec(&info.timestamp);
739 }
740 else {
741 ALOGE("pcm_read failed with code %d", ret);
Amit Pundir648e1d02020-02-18 22:44:16 +0530742 }
743
744exit:
Amit Pundir648e1d02020-02-18 22:44:16 +0530745 pthread_mutex_unlock(&in->lock);
746
Amit Pundirfec74f62020-09-28 12:43:59 +0530747 bool mic_muted = false;
748 adev_get_mic_mute((struct audio_hw_device*)adev, &mic_muted);
749 if (mic_muted) {
750 memset(buffer, 0, bytes);
751 }
752
753 if (ret != 0) {
754 usleep((int64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
755 in_get_sample_rate(&stream->common));
756 } else {
757 /* Process AEC if available */
758 /* TODO move to a separate thread */
759 if (!mic_muted) {
760 info.bytes = bytes;
761 int aec_ret = process_aec(adev->aec, buffer, &info);
762 if (aec_ret) {
763 ALOGE("process_aec returned error code %d", aec_ret);
764 }
765 }
766 }
767
768#if DEBUG_AEC && !defined(AEC_HAL)
769 FILE* fp_in = fopen("/data/local/traces/aec_in.pcm", "a+");
770 if (fp_in) {
771 fwrite((char*)buffer, 1, bytes, fp_in);
772 fclose(fp_in);
773 } else {
774 ALOGE("AEC debug: Could not open file aec_in.pcm!");
775 }
776 FILE* fp_mic_ts = fopen("/data/local/traces/aec_in_timestamps.txt", "a+");
777 if (fp_mic_ts) {
778 fprintf(fp_mic_ts, "%" PRIu64 "\n", in->timestamp_nsec);
779 fclose(fp_mic_ts);
780 } else {
781 ALOGE("AEC debug: Could not open file aec_in_timestamps.txt!");
782 }
783#endif
784
Amit Pundirc738b812019-06-19 16:13:49 +0530785 return bytes;
786}
787
Amit Pundirfec74f62020-09-28 12:43:59 +0530788static int in_get_capture_position(const struct audio_stream_in* stream, int64_t* frames,
789 int64_t* time) {
790 if (stream == NULL || frames == NULL || time == NULL) {
791 return -EINVAL;
792 }
793 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
794
795 *frames = in->frames_read;
796 *time = in->timestamp_nsec;
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100797 ALOGI("CA:: %s: source: %d, timestamp (nsec): %" PRIu64, __func__, in->source, *time);
Amit Pundirfec74f62020-09-28 12:43:59 +0530798
799 return 0;
800}
801
Amit Pundirc738b812019-06-19 16:13:49 +0530802static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream)
803{
804 return 0;
805}
806
807static int in_add_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
808{
809 return 0;
810}
811
812static int in_remove_audio_effect(const struct audio_stream *stream, effect_handle_t effect)
813{
814 return 0;
815}
816
817static int adev_open_output_stream(struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +0530818 audio_io_handle_t handle,
819 audio_devices_t devices,
820 audio_output_flags_t flags,
821 struct audio_config *config,
822 struct audio_stream_out **stream_out,
823 const char *address __unused)
Amit Pundirc738b812019-06-19 16:13:49 +0530824{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100825 ALOGI("CA:: adev_open_output_stream...");
826
Amit Pundirfec74f62020-09-28 12:43:59 +0530827 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundirfec74f62020-09-28 12:43:59 +0530828 int out_port = get_audio_output_port(devices);
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100829 char* route_active_path_name = get_mixer_path_for_port(out_port);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800830 struct pcm_params* params = pcm_params_get(CARD_OUT, out_port, PCM_OUT);
831 if (!params) {
Amit Pundirfec74f62020-09-28 12:43:59 +0530832 return -ENOSYS;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800833 }
Amit Pundir648e1d02020-02-18 22:44:16 +0530834
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100835 if (audio_route_apply_and_update_path(ladev->audio_route, route_active_path_name) < 0) {
836 ALOGE("CA:: %s() Failed to apply path %s", __func__, route_active_path_name);
837 }
838 ladev->active_port = out_port;
839
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800840 struct alsa_stream_out* out =
841 (struct alsa_stream_out*)calloc(1, sizeof(struct alsa_stream_out));
842 if (!out) {
Amit Pundirc738b812019-06-19 16:13:49 +0530843 return -ENOMEM;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800844 }
Amit Pundirc738b812019-06-19 16:13:49 +0530845
846 out->stream.common.get_sample_rate = out_get_sample_rate;
847 out->stream.common.set_sample_rate = out_set_sample_rate;
848 out->stream.common.get_buffer_size = out_get_buffer_size;
849 out->stream.common.get_channels = out_get_channels;
850 out->stream.common.get_format = out_get_format;
851 out->stream.common.set_format = out_set_format;
852 out->stream.common.standby = out_standby;
853 out->stream.common.dump = out_dump;
854 out->stream.common.set_parameters = out_set_parameters;
855 out->stream.common.get_parameters = out_get_parameters;
856 out->stream.common.add_audio_effect = out_add_audio_effect;
857 out->stream.common.remove_audio_effect = out_remove_audio_effect;
858 out->stream.get_latency = out_get_latency;
859 out->stream.set_volume = out_set_volume;
860 out->stream.write = out_write;
861 out->stream.get_render_position = out_get_render_position;
Amit Pundir648e1d02020-02-18 22:44:16 +0530862 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Amit Pundirfec74f62020-09-28 12:43:59 +0530863 out->stream.get_presentation_position = out_get_presentation_position;
Amit Pundirc738b812019-06-19 16:13:49 +0530864
Amit Pundirfec74f62020-09-28 12:43:59 +0530865 out->config.channels = CHANNEL_STEREO;
866 out->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
867 out->config.format = PCM_FORMAT_S16_LE;
868 out->config.period_size = PLAYBACK_PERIOD_SIZE;
869 out->config.period_count = PLAYBACK_PERIOD_COUNT;
Amit Pundirc738b812019-06-19 16:13:49 +0530870
Amit Pundirfec74f62020-09-28 12:43:59 +0530871 if (out->config.rate != config->sample_rate ||
872 audio_channel_count_from_out_mask(config->channel_mask) != CHANNEL_STEREO ||
873 out->config.format != pcm_format_from_audio_format(config->format) ) {
874 config->sample_rate = out->config.rate;
875 config->format = audio_format_from_pcm_format(out->config.format);
876 config->channel_mask = audio_channel_out_mask_from_count(CHANNEL_STEREO);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800877 goto error_1;
Amit Pundirc738b812019-06-19 16:13:49 +0530878 }
879
Amit Pundirfec74f62020-09-28 12:43:59 +0530880 ALOGI("adev_open_output_stream selects channels=%d rate=%d format=%d, devices=%d",
881 out->config.channels, out->config.rate, out->config.format, devices);
882
883 out->dev = ladev;
884 out->standby = 1;
885 out->unavailable = false;
886 out->devices = devices;
887
888 config->format = out_get_format(&out->stream.common);
889 config->channel_mask = out_get_channels(&out->stream.common);
890 config->sample_rate = out_get_sample_rate(&out->stream.common);
Amit Pundirc738b812019-06-19 16:13:49 +0530891
Amit Pundirfec74f62020-09-28 12:43:59 +0530892 out->speaker_eq = NULL;
893 if (out_port == PORT_INTERNAL_SPEAKER) {
894 out_set_eq(out);
895 if (out->speaker_eq == NULL) {
896 ALOGE("%s: Failed to initialize speaker EQ", __func__);
897 }
898 }
899
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800900 int aec_ret = init_aec_reference_config(ladev->aec, out);
901 if (aec_ret) {
902 ALOGE("AEC: Speaker config init failed!");
903 goto error_2;
Amit Pundirfec74f62020-09-28 12:43:59 +0530904 }
Amit Pundirc738b812019-06-19 16:13:49 +0530905
Alden DSouza0f4cb5f2021-02-11 17:07:01 -0800906 *stream_out = &out->stream;
907 return 0;
908
909error_2:
910 fir_release(out->speaker_eq);
911error_1:
912 free(out);
913 return -EINVAL;
Amit Pundirc738b812019-06-19 16:13:49 +0530914}
915
916static void adev_close_output_stream(struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +0530917 struct audio_stream_out *stream)
Amit Pundirc738b812019-06-19 16:13:49 +0530918{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100919 ALOGI("CA:: adev_close_output_stream...");
Amit Pundirfec74f62020-09-28 12:43:59 +0530920 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
921 destroy_aec_reference_config(adev->aec);
922 struct alsa_stream_out* out = (struct alsa_stream_out*)stream;
923 fir_release(out->speaker_eq);
Amit Pundirc738b812019-06-19 16:13:49 +0530924 free(stream);
925}
926
927static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
928{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100929 ALOGI("CA:: adev_set_parameters");
Amit Pundirfec74f62020-09-28 12:43:59 +0530930 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530931}
932
933static char * adev_get_parameters(const struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +0530934 const char *keys)
Amit Pundirc738b812019-06-19 16:13:49 +0530935{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100936 ALOGI("CA:: adev_get_parameters");
Amit Pundirc738b812019-06-19 16:13:49 +0530937 return strdup("");
938}
939
Amit Pundirfec74f62020-09-28 12:43:59 +0530940static int adev_get_microphones(const struct audio_hw_device* dev,
941 struct audio_microphone_characteristic_t* mic_array,
942 size_t* mic_count) {
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100943 ALOGI("CA:: adev_get_microphones");
Amit Pundirfec74f62020-09-28 12:43:59 +0530944 if ((mic_array == NULL) || (mic_count == NULL)) {
945 return -EINVAL;
946 }
947 get_mic_characteristics(mic_array, mic_count);
948 return 0;
949}
950
Amit Pundirc738b812019-06-19 16:13:49 +0530951static int adev_init_check(const struct audio_hw_device *dev)
952{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100953 ALOGI("CA:: adev_init_check");
Amit Pundirc738b812019-06-19 16:13:49 +0530954 return 0;
955}
956
957static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
958{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100959 ALOGI("CA:: adev_set_voice_volume: %f", volume);
Amit Pundirfec74f62020-09-28 12:43:59 +0530960 return -ENOSYS;
Amit Pundirc738b812019-06-19 16:13:49 +0530961}
962
963static int adev_set_master_volume(struct audio_hw_device *dev, float volume)
964{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100965 ALOGI("CA:: adev_set_master_volume: %f", volume);
Amit Pundirc738b812019-06-19 16:13:49 +0530966 return -ENOSYS;
967}
968
969static int adev_get_master_volume(struct audio_hw_device *dev, float *volume)
970{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100971 ALOGI("CA:: adev_get_master_volume: %f", *volume);
Amit Pundirc738b812019-06-19 16:13:49 +0530972 return -ENOSYS;
973}
974
975static int adev_set_master_mute(struct audio_hw_device *dev, bool muted)
976{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100977 ALOGI("CA:: adev_set_master_mute: %d", muted);
Amit Pundirc738b812019-06-19 16:13:49 +0530978 return -ENOSYS;
979}
980
981static int adev_get_master_mute(struct audio_hw_device *dev, bool *muted)
982{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100983 ALOGI("CA:: adev_get_master_mute: %d", *muted);
Amit Pundirc738b812019-06-19 16:13:49 +0530984 return -ENOSYS;
985}
986
987static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
988{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100989 ALOGI("CA:: adev_set_mode: %d", mode);
Amit Pundirc738b812019-06-19 16:13:49 +0530990 return 0;
991}
992
993static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
994{
Caleb Connolly1f0c1382021-08-10 11:41:23 +0100995 ALOGI("CA:: adev_set_mic_mute: %d",state);
Amit Pundirfec74f62020-09-28 12:43:59 +0530996 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir648e1d02020-02-18 22:44:16 +0530997 pthread_mutex_lock(&adev->lock);
998 adev->mic_mute = state;
999 pthread_mutex_unlock(&adev->lock);
1000 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +05301001}
1002
1003static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
1004{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001005 ALOGI("CA:: adev_get_mic_mute");
Amit Pundirfec74f62020-09-28 12:43:59 +05301006 struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
Amit Pundir648e1d02020-02-18 22:44:16 +05301007 pthread_mutex_lock(&adev->lock);
1008 *state = adev->mic_mute;
1009 pthread_mutex_unlock(&adev->lock);
1010 return 0;
Amit Pundirc738b812019-06-19 16:13:49 +05301011}
1012
1013static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev,
Amit Pundirfec74f62020-09-28 12:43:59 +05301014 const struct audio_config *config)
Amit Pundirc738b812019-06-19 16:13:49 +05301015{
Amit Pundirfec74f62020-09-28 12:43:59 +05301016 size_t buffer_size =
1017 get_input_buffer_size(CAPTURE_PERIOD_SIZE, config->format, config->channel_mask);
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001018 ALOGI("CA:: adev_get_input_buffer_size: %zu", buffer_size);
Amit Pundirfec74f62020-09-28 12:43:59 +05301019 return buffer_size;
Amit Pundirc738b812019-06-19 16:13:49 +05301020}
1021
Amit Pundirfec74f62020-09-28 12:43:59 +05301022static int adev_open_input_stream(struct audio_hw_device* dev, audio_io_handle_t handle,
1023 audio_devices_t devices, struct audio_config* config,
1024 struct audio_stream_in** stream_in,
1025 audio_input_flags_t flags __unused, const char* address __unused,
1026 audio_source_t source) {
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001027 ALOGI("CA:: adev_open_input_stream...");
Amit Pundir648e1d02020-02-18 22:44:16 +05301028
Amit Pundirfec74f62020-09-28 12:43:59 +05301029 struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
Amit Pundir648e1d02020-02-18 22:44:16 +05301030
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001031 struct pcm_params* params = pcm_params_get(CARD_IN, PORT_BUILTIN_MIC, PCM_IN);
1032 if (!params) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301033 return -ENOSYS;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001034 }
Amit Pundirfec74f62020-09-28 12:43:59 +05301035
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001036 struct alsa_stream_in* in = (struct alsa_stream_in*)calloc(1, sizeof(struct alsa_stream_in));
1037 if (!in) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301038 return -ENOMEM;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001039 }
Amit Pundirc738b812019-06-19 16:13:49 +05301040
1041 in->stream.common.get_sample_rate = in_get_sample_rate;
Amit Pundirfec74f62020-09-28 12:43:59 +05301042 in->stream.common.set_sample_rate = in_set_sample_rate;
Amit Pundirc738b812019-06-19 16:13:49 +05301043 in->stream.common.get_buffer_size = in_get_buffer_size;
1044 in->stream.common.get_channels = in_get_channels;
1045 in->stream.common.get_format = in_get_format;
Amit Pundirfec74f62020-09-28 12:43:59 +05301046 in->stream.common.set_format = in_set_format;
Amit Pundirc738b812019-06-19 16:13:49 +05301047 in->stream.common.standby = in_standby;
1048 in->stream.common.dump = in_dump;
1049 in->stream.common.set_parameters = in_set_parameters;
1050 in->stream.common.get_parameters = in_get_parameters;
Amit Pundirfec74f62020-09-28 12:43:59 +05301051 in->stream.common.add_audio_effect = in_add_audio_effect;
1052 in->stream.common.remove_audio_effect = in_remove_audio_effect;
1053 in->stream.set_gain = in_set_gain;
Amit Pundirc738b812019-06-19 16:13:49 +05301054 in->stream.read = in_read;
Amit Pundirfec74f62020-09-28 12:43:59 +05301055 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Amit Pundir648e1d02020-02-18 22:44:16 +05301056 in->stream.get_capture_position = in_get_capture_position;
1057 in->stream.get_active_microphones = in_get_active_microphones;
1058
Amit Pundirfec74f62020-09-28 12:43:59 +05301059 in->config.channels = CHANNEL_STEREO;
1060 if (source == AUDIO_SOURCE_ECHO_REFERENCE) {
1061 in->config.rate = PLAYBACK_CODEC_SAMPLING_RATE;
1062 } else {
1063 in->config.rate = CAPTURE_CODEC_SAMPLING_RATE;
1064 }
1065 in->config.format = PCM_FORMAT_S32_LE;
1066 in->config.period_size = CAPTURE_PERIOD_SIZE;
1067 in->config.period_count = CAPTURE_PERIOD_COUNT;
Amit Pundir648e1d02020-02-18 22:44:16 +05301068
Amit Pundirfec74f62020-09-28 12:43:59 +05301069 if (in->config.rate != config->sample_rate ||
1070 audio_channel_count_from_in_mask(config->channel_mask) != CHANNEL_STEREO ||
1071 in->config.format != pcm_format_from_audio_format(config->format) ) {
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001072 config->format = in_get_format(&in->stream.common);
1073 config->channel_mask = in_get_channels(&in->stream.common);
1074 config->sample_rate = in_get_sample_rate(&in->stream.common);
1075 goto error_1;
Amit Pundirfec74f62020-09-28 12:43:59 +05301076 }
Amit Pundir648e1d02020-02-18 22:44:16 +05301077
Amit Pundirfec74f62020-09-28 12:43:59 +05301078 ALOGI("adev_open_input_stream selects channels=%d rate=%d format=%d source=%d",
1079 in->config.channels, in->config.rate, in->config.format, source);
1080
1081 in->dev = ladev;
Amit Pundir648e1d02020-02-18 22:44:16 +05301082 in->standby = true;
Amit Pundirfec74f62020-09-28 12:43:59 +05301083 in->unavailable = false;
1084 in->source = source;
1085 in->devices = devices;
Amit Pundir648e1d02020-02-18 22:44:16 +05301086
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001087 if (is_aec_input(in)) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301088 int aec_ret = init_aec_mic_config(ladev->aec, in);
1089 if (aec_ret) {
1090 ALOGE("AEC: Mic config init failed!");
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001091 goto error_1;
Amit Pundir648e1d02020-02-18 22:44:16 +05301092 }
Amit Pundirfec74f62020-09-28 12:43:59 +05301093 }
1094
Amit Pundirfec74f62020-09-28 12:43:59 +05301095#if DEBUG_AEC
1096 remove("/data/local/traces/aec_ref.pcm");
1097 remove("/data/local/traces/aec_in.pcm");
1098 remove("/data/local/traces/aec_ref_timestamps.txt");
1099 remove("/data/local/traces/aec_in_timestamps.txt");
1100#endif
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001101
1102 *stream_in = &in->stream;
1103 return 0;
1104
1105error_1:
1106 free(in);
1107 return -EINVAL;
Amit Pundirfec74f62020-09-28 12:43:59 +05301108}
Amit Pundir648e1d02020-02-18 22:44:16 +05301109
Amit Pundirfec74f62020-09-28 12:43:59 +05301110static void adev_close_input_stream(struct audio_hw_device *dev,
1111 struct audio_stream_in *stream)
1112{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001113 ALOGI("CA:: adev_close_input_stream...");
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001114 struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
1115 if (is_aec_input(in)) {
1116 destroy_aec_mic_config(in->dev->aec);
1117 }
Amit Pundirfec74f62020-09-28 12:43:59 +05301118 free(stream);
1119 return;
1120}
Amit Pundir648e1d02020-02-18 22:44:16 +05301121
Amit Pundirfec74f62020-09-28 12:43:59 +05301122static int adev_dump(const audio_hw_device_t *device, int fd)
1123{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001124 ALOGI("CA:: adev_dump");
Amit Pundirc738b812019-06-19 16:13:49 +05301125 return 0;
1126}
1127
Amit Pundirfec74f62020-09-28 12:43:59 +05301128static int adev_close(hw_device_t *device)
Amit Pundir648e1d02020-02-18 22:44:16 +05301129{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001130 ALOGI("CA:: adev_close");
Amit Pundir648e1d02020-02-18 22:44:16 +05301131
Amit Pundirfec74f62020-09-28 12:43:59 +05301132 struct alsa_audio_device *adev = (struct alsa_audio_device *)device;
1133 release_aec(adev->aec);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001134 audio_route_free(adev->audio_route);
1135 mixer_close(adev->mixer);
Amit Pundirfec74f62020-09-28 12:43:59 +05301136 free(device);
1137 return 0;
Amit Pundir648e1d02020-02-18 22:44:16 +05301138}
1139
Amit Pundirc738b812019-06-19 16:13:49 +05301140static int adev_open(const hw_module_t* module, const char* name,
Amit Pundirfec74f62020-09-28 12:43:59 +05301141 hw_device_t** device)
Amit Pundirc738b812019-06-19 16:13:49 +05301142{
Caleb Connolly1f0c1382021-08-10 11:41:23 +01001143 ALOGI("CA:: adev_open: %s", name);
Amit Pundirc738b812019-06-19 16:13:49 +05301144
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001145 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
Amit Pundirc738b812019-06-19 16:13:49 +05301146 return -EINVAL;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001147 }
Amit Pundirc738b812019-06-19 16:13:49 +05301148
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001149 struct alsa_audio_device* adev = calloc(1, sizeof(struct alsa_audio_device));
1150 if (!adev) {
Amit Pundirfec74f62020-09-28 12:43:59 +05301151 return -ENOMEM;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001152 }
Amit Pundirc738b812019-06-19 16:13:49 +05301153
Amit Pundirfec74f62020-09-28 12:43:59 +05301154 adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
1155 adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
1156 adev->hw_device.common.module = (struct hw_module_t *) module;
1157 adev->hw_device.common.close = adev_close;
1158 adev->hw_device.init_check = adev_init_check;
1159 adev->hw_device.set_voice_volume = adev_set_voice_volume;
1160 adev->hw_device.set_master_volume = adev_set_master_volume;
1161 adev->hw_device.get_master_volume = adev_get_master_volume;
1162 adev->hw_device.set_master_mute = adev_set_master_mute;
1163 adev->hw_device.get_master_mute = adev_get_master_mute;
1164 adev->hw_device.set_mode = adev_set_mode;
1165 adev->hw_device.set_mic_mute = adev_set_mic_mute;
1166 adev->hw_device.get_mic_mute = adev_get_mic_mute;
1167 adev->hw_device.set_parameters = adev_set_parameters;
1168 adev->hw_device.get_parameters = adev_get_parameters;
1169 adev->hw_device.get_input_buffer_size = adev_get_input_buffer_size;
1170 adev->hw_device.open_output_stream = adev_open_output_stream;
1171 adev->hw_device.close_output_stream = adev_close_output_stream;
1172 adev->hw_device.open_input_stream = adev_open_input_stream;
1173 adev->hw_device.close_input_stream = adev_close_input_stream;
1174 adev->hw_device.dump = adev_dump;
1175 adev->hw_device.get_microphones = adev_get_microphones;
Amit Pundirc738b812019-06-19 16:13:49 +05301176
Amit Pundirfec74f62020-09-28 12:43:59 +05301177 *device = &adev->hw_device.common;
Amit Pundirc738b812019-06-19 16:13:49 +05301178
Amit Pundirfec74f62020-09-28 12:43:59 +05301179 adev->mixer = mixer_open(CARD_OUT);
Amit Pundirfec74f62020-09-28 12:43:59 +05301180 if (!adev->mixer) {
1181 ALOGE("Unable to open the mixer, aborting.");
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001182 goto error_1;
Amit Pundir648e1d02020-02-18 22:44:16 +05301183 }
1184
Amit Pundirfec74f62020-09-28 12:43:59 +05301185 adev->audio_route = audio_route_init(CARD_OUT, MIXER_XML_PATH);
1186 if (!adev->audio_route) {
1187 ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001188 goto error_2;
Amit Pundirfec74f62020-09-28 12:43:59 +05301189 }
Amit Pundir648e1d02020-02-18 22:44:16 +05301190
Amit Pundirfec74f62020-09-28 12:43:59 +05301191 pthread_mutex_lock(&adev->lock);
1192 if (init_aec(CAPTURE_CODEC_SAMPLING_RATE, NUM_AEC_REFERENCE_CHANNELS,
1193 CHANNEL_STEREO, &adev->aec)) {
1194 pthread_mutex_unlock(&adev->lock);
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001195 goto error_3;
Amit Pundirfec74f62020-09-28 12:43:59 +05301196 }
1197 pthread_mutex_unlock(&adev->lock);
1198
Amit Pundirc738b812019-06-19 16:13:49 +05301199 return 0;
Alden DSouza0f4cb5f2021-02-11 17:07:01 -08001200
1201error_3:
1202 audio_route_free(adev->audio_route);
1203error_2:
1204 mixer_close(adev->mixer);
1205error_1:
1206 free(adev);
1207 return -EINVAL;
Amit Pundirc738b812019-06-19 16:13:49 +05301208}
1209
1210static struct hw_module_methods_t hal_module_methods = {
1211 .open = adev_open,
1212};
1213
1214struct audio_module HAL_MODULE_INFO_SYM = {
1215 .common = {
1216 .tag = HARDWARE_MODULE_TAG,
1217 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
1218 .hal_api_version = HARDWARE_HAL_API_VERSION,
1219 .id = AUDIO_HARDWARE_MODULE_ID,
Amit Pundir648e1d02020-02-18 22:44:16 +05301220 .name = "Generic audio HW HAL",
Amit Pundirc738b812019-06-19 16:13:49 +05301221 .author = "The Android Open Source Project",
1222 .methods = &hal_module_methods,
1223 },
1224};