audio: Clean up missing memory free's when opening devices/streams
Signed-off-by: Alden DSouza <aldend@google.com>
Change-Id: Iae726f0818464fc09d809120cbba1eb8b109e031
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 4a16ac1..5a0953c 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -57,6 +57,16 @@
size_t* mic_count);
static size_t out_get_buffer_size(const struct audio_stream* stream);
+static bool is_aec_input(const struct alsa_stream_in* in) {
+ /* If AEC is in the app, only configure based on ECHO_REFERENCE spec.
+ * If AEC is in the HAL, configure using the given mic stream. */
+ bool aec_input = true;
+#if !defined(AEC_HAL)
+ aec_input = (in->source == AUDIO_SOURCE_ECHO_REFERENCE);
+#endif
+ return aec_input;
+}
+
static int get_audio_output_port(audio_devices_t devices) {
/* Only HDMI out for now #FIXME */
return PORT_HDMI;
@@ -784,19 +794,17 @@
ALOGV("adev_open_output_stream...");
struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
- struct alsa_stream_out *out;
- struct pcm_params *params;
- int ret = 0;
-
int out_port = get_audio_output_port(devices);
-
- params = pcm_params_get(CARD_OUT, out_port, PCM_OUT);
- if (!params)
+ struct pcm_params* params = pcm_params_get(CARD_OUT, out_port, PCM_OUT);
+ if (!params) {
return -ENOSYS;
+ }
- out = (struct alsa_stream_out *)calloc(1, sizeof(struct alsa_stream_out));
- if (!out)
+ struct alsa_stream_out* out =
+ (struct alsa_stream_out*)calloc(1, sizeof(struct alsa_stream_out));
+ if (!out) {
return -ENOMEM;
+ }
out->stream.common.get_sample_rate = out_get_sample_rate;
out->stream.common.set_sample_rate = out_set_sample_rate;
@@ -829,7 +837,7 @@
config->sample_rate = out->config.rate;
config->format = audio_format_from_pcm_format(out->config.format);
config->channel_mask = audio_channel_out_mask_from_count(CHANNEL_STEREO);
- ret = -EINVAL;
+ goto error_1;
}
ALOGI("adev_open_output_stream selects channels=%d rate=%d format=%d, devices=%d",
@@ -844,8 +852,6 @@
config->channel_mask = out_get_channels(&out->stream.common);
config->sample_rate = out_get_sample_rate(&out->stream.common);
- *stream_out = &out->stream;
-
out->speaker_eq = NULL;
if (out_port == PORT_INTERNAL_SPEAKER) {
out_set_eq(out);
@@ -854,18 +860,20 @@
}
}
- /* TODO The retry mechanism isn't implemented in AudioPolicyManager/AudioFlinger. */
- ret = 0;
-
- if (ret == 0) {
- int aec_ret = init_aec_reference_config(ladev->aec, out);
- if (aec_ret) {
- ALOGE("AEC: Speaker config init failed!");
- return -EINVAL;
- }
+ int aec_ret = init_aec_reference_config(ladev->aec, out);
+ if (aec_ret) {
+ ALOGE("AEC: Speaker config init failed!");
+ goto error_2;
}
- return ret;
+ *stream_out = &out->stream;
+ return 0;
+
+error_2:
+ fir_release(out->speaker_eq);
+error_1:
+ free(out);
+ return -EINVAL;
}
static void adev_close_output_stream(struct audio_hw_device *dev,
@@ -982,17 +990,16 @@
ALOGV("adev_open_input_stream...");
struct alsa_audio_device *ladev = (struct alsa_audio_device *)dev;
- struct alsa_stream_in *in;
- struct pcm_params *params;
- int ret = 0;
- params = pcm_params_get(CARD_IN, PORT_BUILTIN_MIC, PCM_IN);
- if (!params)
+ struct pcm_params* params = pcm_params_get(CARD_IN, PORT_BUILTIN_MIC, PCM_IN);
+ if (!params) {
return -ENOSYS;
+ }
- in = (struct alsa_stream_in *)calloc(1, sizeof(struct alsa_stream_in));
- if (!in)
+ struct alsa_stream_in* in = (struct alsa_stream_in*)calloc(1, sizeof(struct alsa_stream_in));
+ if (!in) {
return -ENOMEM;
+ }
in->stream.common.get_sample_rate = in_get_sample_rate;
in->stream.common.set_sample_rate = in_set_sample_rate;
@@ -1025,7 +1032,10 @@
if (in->config.rate != config->sample_rate ||
audio_channel_count_from_in_mask(config->channel_mask) != CHANNEL_STEREO ||
in->config.format != pcm_format_from_audio_format(config->format) ) {
- ret = -EINVAL;
+ config->format = in_get_format(&in->stream.common);
+ config->channel_mask = in_get_channels(&in->stream.common);
+ config->sample_rate = in_get_sample_rate(&in->stream.common);
+ goto error_1;
}
ALOGI("adev_open_input_stream selects channels=%d rate=%d format=%d source=%d",
@@ -1037,46 +1047,37 @@
in->source = source;
in->devices = devices;
- config->format = in_get_format(&in->stream.common);
- config->channel_mask = in_get_channels(&in->stream.common);
- config->sample_rate = in_get_sample_rate(&in->stream.common);
-
- /* If AEC is in the app, only configure based on ECHO_REFERENCE spec.
- * If AEC is in the HAL, configure using the given mic stream. */
- bool aecInput = true;
-#if !defined(AEC_HAL)
- aecInput = (in->source == AUDIO_SOURCE_ECHO_REFERENCE);
-#endif
-
- if ((ret == 0) && aecInput) {
+ if (is_aec_input(in)) {
int aec_ret = init_aec_mic_config(ladev->aec, in);
if (aec_ret) {
ALOGE("AEC: Mic config init failed!");
- return -EINVAL;
+ goto error_1;
}
}
- if (ret) {
- free(in);
- } else {
- *stream_in = &in->stream;
- }
-
#if DEBUG_AEC
remove("/data/local/traces/aec_ref.pcm");
remove("/data/local/traces/aec_in.pcm");
remove("/data/local/traces/aec_ref_timestamps.txt");
remove("/data/local/traces/aec_in_timestamps.txt");
#endif
- return ret;
+
+ *stream_in = &in->stream;
+ return 0;
+
+error_1:
+ free(in);
+ return -EINVAL;
}
static void adev_close_input_stream(struct audio_hw_device *dev,
struct audio_stream_in *stream)
{
ALOGV("adev_close_input_stream...");
- struct alsa_audio_device *adev = (struct alsa_audio_device *)dev;
- destroy_aec_mic_config(adev->aec);
+ struct alsa_stream_in* in = (struct alsa_stream_in*)stream;
+ if (is_aec_input(in)) {
+ destroy_aec_mic_config(in->dev->aec);
+ }
free(stream);
return;
}
@@ -1093,6 +1094,8 @@
struct alsa_audio_device *adev = (struct alsa_audio_device *)device;
release_aec(adev->aec);
+ audio_route_free(adev->audio_route);
+ mixer_close(adev->mixer);
free(device);
return 0;
}
@@ -1100,16 +1103,16 @@
static int adev_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
- struct alsa_audio_device *adev;
-
ALOGV("adev_open: %s", name);
- if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0)
+ if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) {
return -EINVAL;
+ }
- adev = calloc(1, sizeof(struct alsa_audio_device));
- if (!adev)
+ struct alsa_audio_device* adev = calloc(1, sizeof(struct alsa_audio_device));
+ if (!adev) {
return -ENOMEM;
+ }
adev->hw_device.common.tag = HARDWARE_DEVICE_TAG;
adev->hw_device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
@@ -1137,27 +1140,34 @@
*device = &adev->hw_device.common;
adev->mixer = mixer_open(CARD_OUT);
-
if (!adev->mixer) {
ALOGE("Unable to open the mixer, aborting.");
- return -EINVAL;
+ goto error_1;
}
adev->audio_route = audio_route_init(CARD_OUT, MIXER_XML_PATH);
if (!adev->audio_route) {
ALOGE("%s: Failed to init audio route controls, aborting.", __func__);
- return -EINVAL;
+ goto error_2;
}
pthread_mutex_lock(&adev->lock);
if (init_aec(CAPTURE_CODEC_SAMPLING_RATE, NUM_AEC_REFERENCE_CHANNELS,
CHANNEL_STEREO, &adev->aec)) {
pthread_mutex_unlock(&adev->lock);
- return -EINVAL;
+ goto error_3;
}
pthread_mutex_unlock(&adev->lock);
return 0;
+
+error_3:
+ audio_route_free(adev->audio_route);
+error_2:
+ mixer_close(adev->mixer);
+error_1:
+ free(adev);
+ return -EINVAL;
}
static struct hw_module_methods_t hal_module_methods = {