Merge "hal: Change FB speaker protection to use new cal driver"
diff --git a/hal/Android.mk b/hal/Android.mk
index 0ec3e3d..53b4a09 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -35,7 +35,8 @@
platform_info.c \
$(AUDIO_PLATFORM)/platform.c
-LOCAL_SRC_FILES += audio_extn/audio_extn.c
+LOCAL_SRC_FILES += audio_extn/audio_extn.c \
+ audio_extn/utils.c
ifneq ($(strip $(AUDIO_FEATURE_DISABLED_PCM_OFFLOAD)),true)
LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
@@ -91,6 +92,11 @@
LOCAL_CFLAGS += -DCOMPRESS_VOIP_ENABLED
LOCAL_SRC_FILES += voice_extn/compress_voip.c
endif
+
+endif
+
+ifneq ($(strip $(AUDIO_FEATURE_DISABLED_FORMATS)),true)
+LOCAL_CFLAGS += -DFORMATS_ENABLED
endif
ifneq ($(strip, $(AUDIO_FEATURE_DISABLED_SPKR_PROTECTION)),true)
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 80bc434..771d913 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -61,6 +61,8 @@
#endif
+#define MAX_LENGTH_MIXER_CONTROL_IN_INT (128)
+
void audio_extn_set_parameters(struct audio_device *adev,
struct str_parms *parms);
@@ -182,11 +184,15 @@
#define audio_extn_spkr_prot_start_processing(snd_device) (-EINVAL)
#define audio_extn_spkr_prot_stop_processing() (0)
#define audio_extn_spkr_prot_is_enabled() (false)
+#define audio_extn_spkr_prot_get_acdb_id(snd_device) (-EINVAL)
+#define audio_extn_get_spkr_prot_snd_device(snd_device) (SND_DEVICE_OUT_SPEAKER)
#else
void audio_extn_spkr_prot_init(void *adev);
int audio_extn_spkr_prot_start_processing(snd_device_t snd_device);
void audio_extn_spkr_prot_stop_processing();
bool audio_extn_spkr_prot_is_enabled();
+int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device);
+int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device);
#endif
#ifndef COMPRESS_CAPTURE_ENABLED
@@ -211,8 +217,10 @@
#if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS1_DOLBY_DAP_ENABLED)
void audio_extn_dolby_set_dmid(struct audio_device *adev);
+void audio_extn_dolby_set_license(struct audio_device *adev);
#else
#define audio_extn_dolby_set_dmid(adev) (0)
+#define audio_extn_dolby_set_license(adev) (0)
#endif
#ifndef DS1_DOLBY_DDP_ENABLED
@@ -244,4 +252,17 @@
audio_usecase_t audio_extn_hfp_get_usecase();
#endif
+void audio_extn_utils_update_streams_output_cfg_list(void *platform,
+ struct mixer *mixer,
+ struct listnode *streams_output_cfg_list);
+void audio_extn_utils_dump_streams_output_cfg_list(
+ struct listnode *streams_output_cfg_list);
+void audio_extn_utils_release_streams_output_cfg_list(
+ struct listnode *streams_output_cfg_list);
+void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+ struct listnode *streams_output_cfg_list,
+ audio_output_flags_t flags,
+ audio_format_t format,
+ struct stream_app_type_cfg *app_type_cfg);
+int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase);
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/dolby.c b/hal/audio_extn/dolby.c
index 99fa2b7..cb74715 100644
--- a/hal/audio_extn/dolby.c
+++ b/hal/audio_extn/dolby.c
@@ -287,6 +287,15 @@
int ddp_dev, dev_ch_cap;
int val, ret;
char value[32]={0};
+
+ ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
+ sizeof(value));
+ if (ret >= 0) {
+ char *snd_card_status = value + 2;
+ if (strncmp(snd_card_status, "ONLINE", sizeof("ONLINE")) == 0)
+ audio_extn_dolby_set_license(adev);
+ }
+
ret = str_parms_get_str(parms, AUDIO_PARAMETER_DDP_DEV, value,
sizeof(value));
if (ret >= 0) {
@@ -470,4 +479,29 @@
return;
}
+
+void audio_extn_dolby_set_license(struct audio_device *adev)
+{
+ int ret, key=0;
+ char value[128] = {0};
+ struct mixer_ctl *ctl;
+ const char *mixer_ctl_name = "DS1 License";
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return;
+ }
+
+ property_get("audio.ds1.metainfo.key",value,"0");
+ key = atoi(value);
+
+ ALOGV("%s Setting DS1 License, key:0x%x",__func__, key);
+ ret = mixer_ctl_set_value(ctl, 0, key);
+ if (ret)
+ ALOGE("%s: cannot set license, error:%d",__func__, ret);
+
+ return;
+}
#endif /* DS1_DOLBY_DDP_ENABLED || DS1_DOLBY_DAP_ENABLED */
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 690d893..91f69f3 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -653,6 +653,25 @@
}
}
+int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device)
+{
+ int acdb_id;
+
+ acdb_id = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+ platform_get_snd_device_acdb_id(SND_DEVICE_OUT_SPEAKER_PROTECTED) :
+ -EINVAL;
+
+ return acdb_id;
+}
+
+int audio_extn_get_spkr_prot_snd_device(snd_device_t snd_device)
+{
+ if ((snd_device == SND_DEVICE_OUT_SPEAKER) && handle.spkr_prot_enable)
+ return SND_DEVICE_OUT_SPEAKER_PROTECTED;
+ else
+ return snd_device;
+}
+
int audio_extn_spkr_prot_start_processing(snd_device_t snd_device)
{
struct audio_usecase uc_info_tx;
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
new file mode 100644
index 0000000..bb34bf0
--- /dev/null
+++ b/hal/audio_extn/utils.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "audio_hw_utils"
+/* #define LOG_NDEBUG 0 */
+
+#include <errno.h>
+#include <cutils/properties.h>
+#include <cutils/config_utils.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/str_parms.h>
+#include <cutils/log.h>
+#include <cutils/misc.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include "audio_extn.h"
+
+#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
+
+#define OUTPUTS_TAG "outputs"
+
+#define DYNAMIC_VALUE_TAG "dynamic"
+#define FLAGS_TAG "flags"
+#define FORMATS_TAG "formats"
+#define SAMPLING_RATES_TAG "sampling_rates"
+#define BIT_WIDTH_TAG "bit_width"
+#define APP_TYPE_TAG "app_type"
+
+#define STRING_TO_ENUM(string) { #string, string }
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+struct string_to_enum {
+ const char *name;
+ uint32_t value;
+};
+
+const struct string_to_enum s_flag_name_to_enum_table[] = {
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DIRECT),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_PRIMARY),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_FAST),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING),
+#ifdef INCALL_MUSIC_ENABLED
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC),
+#endif
+#ifdef COMPRESS_VOIP_ENABLED
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+#endif
+};
+
+const struct string_to_enum s_format_name_to_enum_table[] = {
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
+ STRING_TO_ENUM(AUDIO_FORMAT_MP3),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC),
+ STRING_TO_ENUM(AUDIO_FORMAT_VORBIS),
+#ifdef FORMATS_ENABLED
+ STRING_TO_ENUM(AUDIO_FORMAT_AC3),
+ STRING_TO_ENUM(AUDIO_FORMAT_EAC3),
+ STRING_TO_ENUM(AUDIO_FORMAT_DTS),
+ STRING_TO_ENUM(AUDIO_FORMAT_DTS_LBR),
+ STRING_TO_ENUM(AUDIO_FORMAT_WMA),
+ STRING_TO_ENUM(AUDIO_FORMAT_WMA_PRO),
+ STRING_TO_ENUM(AUDIO_FORMAT_AAC_ADIF),
+ STRING_TO_ENUM(AUDIO_FORMAT_AMR_NB),
+ STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB),
+ STRING_TO_ENUM(AUDIO_FORMAT_AMR_WB_PLUS),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRC),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRCB),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRCWB),
+ STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
+ STRING_TO_ENUM(AUDIO_FORMAT_MP2),
+ STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
+ STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
+#endif
+};
+
+static uint32_t string_to_enum(const struct string_to_enum *table, size_t size,
+ const char *name)
+{
+ size_t i;
+ for (i = 0; i < size; i++) {
+ if (strcmp(table[i].name, name) == 0) {
+ ALOGV("%s found %s", __func__, table[i].name);
+ return table[i].value;
+ }
+ }
+ return 0;
+}
+
+static audio_output_flags_t parse_flag_names(char *name)
+{
+ uint32_t flag = 0;
+ char *flag_name = strtok(name, "|");
+ while (flag_name != NULL) {
+ if (strlen(flag_name) != 0) {
+ flag |= string_to_enum(s_flag_name_to_enum_table,
+ ARRAY_SIZE(s_flag_name_to_enum_table),
+ flag_name);
+ }
+ flag_name = strtok(NULL, "|");
+ }
+
+ ALOGV("parse_flag_names: flag - %d", flag);
+ return (audio_output_flags_t)flag;
+}
+
+static void parse_format_names(char *name, struct streams_output_cfg *so_info)
+{
+ struct stream_format *sf_info = NULL;
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG) == 0)
+ return;
+
+ list_init(&so_info->format_list);
+ while (str != NULL) {
+ audio_format_t format = (audio_format_t)string_to_enum(s_format_name_to_enum_table,
+ ARRAY_SIZE(s_format_name_to_enum_table), str);
+ ALOGV("%s: format - %d", __func__, format);
+ if (format != 0) {
+ sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
+ sf_info->format = format;
+ list_add_tail(&so_info->format_list, &sf_info->list);
+ }
+ str = strtok(NULL, "|");
+ }
+}
+
+static int parse_sample_rate_names(char *name)
+{
+ int sample_rate = 48000;
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+ sample_rate = (int)strtol(str, (char **)NULL, 10);
+
+ ALOGV("%s: sample_rate - %d", __func__, sample_rate);
+ return sample_rate;
+}
+
+static int parse_bit_width_names(char *name)
+{
+ int bit_width = 16;
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+ bit_width = (int)strtol(str, (char **)NULL, 10);
+
+ ALOGV("%s: bit_width - %d", __func__, bit_width);
+ return bit_width;
+}
+
+static int parse_app_type_names(void *platform, char *name)
+{
+ int app_type = 0; /* TODO: default app type from acdb when exposed using "platform" */
+ char *str = strtok(name, "|");
+
+ if (str != NULL && strcmp(str, DYNAMIC_VALUE_TAG))
+ app_type = (int)strtol(str, (char **)NULL, 10);
+
+ ALOGV("%s: app_type - %d", __func__, app_type);
+ return app_type;
+}
+
+static void update_streams_output_cfg_list(cnode *root, void *platform,
+ struct listnode *streams_output_cfg_list)
+{
+ cnode *node = root->first_child;
+ struct streams_output_cfg *so_info;
+
+ ALOGV("%s", __func__);
+ so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
+ while (node) {
+ if (strcmp(node->name, FLAGS_TAG) == 0) {
+ so_info->flags = parse_flag_names((char *)node->value);
+ } else if (strcmp(node->name, FORMATS_TAG) == 0) {
+ parse_format_names((char *)node->value, so_info);
+ } else if (strcmp(node->name, SAMPLING_RATES_TAG) == 0) {
+ so_info->app_type_cfg.sample_rate = parse_sample_rate_names((char *)node->value);
+ } else if (strcmp(node->name, BIT_WIDTH_TAG) == 0) {
+ so_info->app_type_cfg.bit_width = parse_bit_width_names((char *)node->value);
+ } else if (strcmp(node->name, APP_TYPE_TAG) == 0) {
+ so_info->app_type_cfg.app_type = parse_app_type_names(platform, (char *)node->value);
+ }
+ node = node->next;
+ }
+ list_add_tail(streams_output_cfg_list, &so_info->list);
+}
+
+static void load_output(cnode *root, void *platform,
+ struct listnode *streams_output_cfg_list)
+{
+ cnode *node = config_find(root, OUTPUTS_TAG);
+ if (node == NULL) {
+ ALOGE("%s: could not load output, node is NULL", __func__);
+ return;
+ }
+
+ node = node->first_child;
+ while (node) {
+ ALOGV("%s: loading output %s", __func__, node->name);
+ update_streams_output_cfg_list(node, platform, streams_output_cfg_list);
+ node = node->next;
+ }
+}
+
+static void send_app_type_cfg(void *platform, struct mixer *mixer,
+ struct listnode *streams_output_cfg_list)
+{
+ int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT] = {-1};
+ int length = 0, i, num_app_types = 0;
+ struct listnode *node;
+ bool update;
+ struct mixer_ctl *ctl = NULL;
+ const char *mixer_ctl_name = "App Type Config";
+ struct streams_output_cfg *so_info;
+
+ if (!mixer) {
+ ALOGE("%s: mixer is null",__func__);
+ return;
+ }
+ ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",__func__, mixer_ctl_name);
+ return;
+ }
+ if (streams_output_cfg_list == NULL) {
+ app_type_cfg[length++] = 1;
+ app_type_cfg[length++] = 0; /* TODO: default app type from acdb when exposed from "platform" */
+ app_type_cfg[length++] = 48000;
+ app_type_cfg[length++] = 16;
+ mixer_ctl_set_array(ctl, app_type_cfg, length);
+ return;
+ }
+
+ app_type_cfg[length++] = num_app_types;
+ list_for_each(node, streams_output_cfg_list) {
+ so_info = node_to_item(node, struct streams_output_cfg, list);
+ update = true;
+ for (i=0; i<length; i=i+3) {
+ if (app_type_cfg[i+1] == -1)
+ break;
+ else if (app_type_cfg[i+1] == so_info->app_type_cfg.app_type) {
+ update = false;
+ break;
+ }
+ }
+ if (update && ((length + 3) <= MAX_LENGTH_MIXER_CONTROL_IN_INT)) {
+ num_app_types += 1 ;
+ app_type_cfg[length++] = so_info->app_type_cfg.app_type;
+ app_type_cfg[length++] = so_info->app_type_cfg.sample_rate;
+ app_type_cfg[length++] = so_info->app_type_cfg.bit_width;
+ }
+ }
+ ALOGV("%s: num_app_types: %d", __func__, num_app_types);
+ if (num_app_types) {
+ app_type_cfg[0] = num_app_types;
+ mixer_ctl_set_array(ctl, app_type_cfg, length);
+ }
+}
+
+void audio_extn_utils_update_streams_output_cfg_list(void *platform,
+ struct mixer *mixer,
+ struct listnode *streams_output_cfg_list)
+{
+ cnode *root;
+ char *data;
+
+ ALOGV("%s", __func__);
+ list_init(streams_output_cfg_list);
+ data = (char *)load_file(AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE, NULL);
+ if (data == NULL) {
+ send_app_type_cfg(platform, mixer, NULL);
+ ALOGE("%s: could not load output policy config file", __func__);
+ return;
+ }
+
+ root = config_node("", "");
+ config_load(root, data);
+ load_output(root, platform, streams_output_cfg_list);
+
+ send_app_type_cfg(platform, mixer, streams_output_cfg_list);
+}
+
+void audio_extn_utils_dump_streams_output_cfg_list(
+ struct listnode *streams_output_cfg_list)
+{
+ int i=0;
+ struct listnode *node_i, *node_j;
+ struct streams_output_cfg *so_info;
+ struct stream_format *sf_info;
+ ALOGV("%s", __func__);
+ list_for_each(node_i, streams_output_cfg_list) {
+ so_info = node_to_item(node_i, struct streams_output_cfg, list);
+ ALOGV("%d: flags-%d, output_sample_rate-%d, output_bit_width-%d, app_type-%d",
+ i++, so_info->flags, so_info->app_type_cfg.sample_rate,
+ so_info->app_type_cfg.bit_width, so_info->app_type_cfg.app_type);
+ list_for_each(node_j, &so_info->format_list) {
+ sf_info = node_to_item(node_j, struct stream_format, list);
+ ALOGV("format-%x", sf_info->format);
+ }
+ }
+}
+
+void audio_extn_utils_release_streams_output_cfg_list(
+ struct listnode *streams_output_cfg_list)
+{
+ struct listnode *node_i, *node_j;
+ struct streams_output_cfg *so_info;
+ struct stream_format *sf_info;
+
+ ALOGV("%s", __func__);
+ while (!list_empty(streams_output_cfg_list)) {
+ node_i = list_head(streams_output_cfg_list);
+ so_info = node_to_item(node_i, struct streams_output_cfg, list);
+ while (!list_empty(&so_info->format_list)) {
+ node_j = list_head(&so_info->format_list);
+ list_remove(node_j);
+ free(node_to_item(node_j, struct stream_format, list));
+ }
+ list_remove(node_i);
+ free(node_to_item(node_i, struct streams_output_cfg, list));
+ }
+}
+
+void audio_extn_utils_update_stream_app_type_cfg(void *platform,
+ struct listnode *streams_output_cfg_list,
+ audio_output_flags_t flags,
+ audio_format_t format,
+ struct stream_app_type_cfg *app_type_cfg)
+{
+ struct listnode *node_i, *node_j;
+ struct streams_output_cfg *so_info;
+ struct stream_format *sf_info;
+
+ ALOGV("%s: flags: %x, format: %x", __func__, flags, format);
+ list_for_each(node_i, streams_output_cfg_list) {
+ so_info = node_to_item(node_i, struct streams_output_cfg, list);
+ if (so_info->flags == flags) {
+ list_for_each(node_j, &so_info->format_list) {
+ sf_info = node_to_item(node_j, struct stream_format, list);
+ if (sf_info->format == format) {
+ ALOGV("App type: %d", so_info->app_type_cfg.app_type);
+ app_type_cfg->app_type = so_info->app_type_cfg.app_type;
+ app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
+ app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+ return;
+ }
+ }
+ }
+ }
+ list_for_each(node_i, streams_output_cfg_list) {
+ so_info = node_to_item(node_i, struct streams_output_cfg, list);
+ if (so_info->flags == AUDIO_OUTPUT_FLAG_PRIMARY) {
+ ALOGV("Compatible output profile not found.");
+ ALOGV("App type default to primary output: %d", so_info->app_type_cfg.app_type);
+ app_type_cfg->app_type = so_info->app_type_cfg.app_type;
+ app_type_cfg->sample_rate = so_info->app_type_cfg.sample_rate;
+ app_type_cfg->bit_width = so_info->app_type_cfg.bit_width;
+ return;
+ }
+ }
+ ALOGW("%s: App type could not be selected. Falling back to default", __func__);
+ app_type_cfg->app_type = 0; /* TODO: default app type from acdb when exposed from "platform" */
+ app_type_cfg->sample_rate = 48000;
+ app_type_cfg->bit_width = 16;
+}
+
+int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase)
+{
+ char mixer_ctl_name[MAX_LENGTH_MIXER_CONTROL_IN_INT];
+ int app_type_cfg[MAX_LENGTH_MIXER_CONTROL_IN_INT], len = 0, rc;
+ struct stream_out *out = usecase->stream.out;
+ struct audio_device *adev = out->dev;
+ struct mixer_ctl *ctl;
+ int pcm_device_id, acdb_dev_id, snd_device = usecase->out_snd_device;
+
+ ALOGV("%s", __func__);
+
+ if (usecase->type != PCM_PLAYBACK) {
+ ALOGV("%s: not a playback path, no need to cfg app type", __func__);
+ rc = 0;
+ goto exit_send_app_type_cfg;
+ }
+ if ((usecase->id != USECASE_AUDIO_PLAYBACK_DEEP_BUFFER) &&
+ (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) &&
+ (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
+ (usecase->id != USECASE_AUDIO_PLAYBACK_OFFLOAD)) {
+ ALOGV("%s: a playback path where app type cfg is not required", __func__);
+ rc = 0;
+ goto exit_send_app_type_cfg;
+ }
+
+ snd_device = usecase->out_snd_device;
+
+ pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
+
+ snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
+ "Audio Stream %d App Type Cfg", pcm_device_id);
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__,
+ mixer_ctl_name);
+ rc = -EINVAL;
+ goto exit_send_app_type_cfg;
+ }
+ snd_device = (snd_device == SND_DEVICE_OUT_SPEAKER) ?
+ audio_extn_get_spkr_prot_snd_device(snd_device) : snd_device;
+ acdb_dev_id = platform_get_snd_device_acdb_id(snd_device);
+ if (acdb_dev_id < 0) {
+ ALOGE("%s: Couldn't get the acdb dev id", __func__);
+ rc = -EINVAL;
+ goto exit_send_app_type_cfg;
+ }
+ app_type_cfg[len++] = out->app_type_cfg.app_type;
+ app_type_cfg[len++] = acdb_dev_id;
+
+ mixer_ctl_set_array(ctl, app_type_cfg, len);
+
+ rc = 0;
+exit_send_app_type_cfg:
+ return rc;
+}
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1a4ce0a..e93abdb 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -257,6 +257,7 @@
audio_extn_dolby_set_dmid(adev);
audio_extn_dolby_set_endpoint(adev);
#endif
+ audio_extn_utils_send_app_type_cfg(usecase);
strcpy(mixer_path, use_case_table[usecase->id]);
platform_add_backend_name(mixer_path, snd_device);
ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
@@ -790,6 +791,15 @@
ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
__func__, &in->stream, in->usecase, use_case_table[in->usecase]);
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state) {
+ ALOGE("%s: sound card is not active/SSR returning error", __func__);
+ ret = -ENETRESET;
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+ goto error_config;
+ }
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+
/* Check if source matches incall recording usecase criteria */
ret = voice_check_and_set_incall_rec_usecase(adev, in);
if (ret)
@@ -827,8 +837,11 @@
pcm_close(in->pcm);
in->pcm = NULL;
ret = -EIO;
+ in->pcm_error_type = PCM_ERROR_EIO;
goto error_open;
}
+
+ in->pcm_error_type = PCM_ERROR_NONE;
ALOGV("%s: exit", __func__);
return ret;
@@ -1169,6 +1182,16 @@
ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
__func__, &out->stream, out->usecase, use_case_table[out->usecase],
out->devices);
+
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state) {
+ ALOGE("%s: sound card is not active/SSR returning error", __func__);
+ ret = -ENETRESET;
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+ goto error_config;
+ }
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+
out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
if (out->pcm_device_id < 0) {
ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
@@ -1215,8 +1238,10 @@
pcm_close(out->pcm);
out->pcm = NULL;
ret = -EIO;
+ out->pcm_error_type = PCM_ERROR_EIO;
goto error_open;
}
+ out->pcm_error_type = PCM_ERROR_NONE;
} else {
out->pcm = NULL;
out->compr = compress_open(adev->snd_card,
@@ -1642,9 +1667,28 @@
{
struct stream_out *out = (struct stream_out *)stream;
struct audio_device *adev = out->dev;
+ int scard_state = SND_CARD_STATE_ONLINE;
ssize_t ret = 0;
pthread_mutex_lock(&out->lock);
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ scard_state = adev->snd_card_status.state;
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+
+ if (out->pcm) {
+ if (SND_CARD_STATE_OFFLINE == scard_state) {
+ ALOGD(" %s: sound card is not active/SSR state", __func__);
+ ret= -ENETRESET;
+ goto exit;
+ } else if (PCM_ERROR_ENETRESET == out->pcm_error_type) {
+ ALOGD(" %s restarting pcm session on post SSR", __func__);
+ out->standby = false;
+ pthread_mutex_unlock(&out->lock);
+ out_standby(&out->stream.common);
+ pthread_mutex_lock(&out->lock);
+ }
+ }
+
if (out->standby) {
out->standby = false;
pthread_mutex_lock(&adev->lock);
@@ -1693,6 +1737,15 @@
}
exit:
+
+ if (-ENETRESET == ret) {
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
+ out->pcm_error_type = PCM_ERROR_ENETRESET;
+ out->standby = true; /*standby will be called on post SSR */
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+ }
+
pthread_mutex_unlock(&out->lock);
if (ret != 0) {
@@ -1700,7 +1753,8 @@
ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
out_standby(&out->stream.common);
usleep(bytes * 1000000 / audio_stream_frame_size(&out->stream.common) /
- out_get_sample_rate(&out->stream.common));
+ out_get_sample_rate(&out->stream.common));
+
}
return bytes;
}
@@ -2032,8 +2086,27 @@
struct stream_in *in = (struct stream_in *)stream;
struct audio_device *adev = in->dev;
int i, ret = -1;
+ int scard_state = SND_CARD_STATE_ONLINE;
pthread_mutex_lock(&in->lock);
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ scard_state = adev->snd_card_status.state;
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+
+ if (in->pcm) {
+ if(SND_CARD_STATE_OFFLINE == scard_state) {
+ ALOGD(" %s: sound card is not active/SSR state", __func__);
+ ret= -ENETRESET;
+ goto exit;
+ } else if (PCM_ERROR_ENETRESET == in->pcm_error_type) {
+ ALOGD(" %s restarting pcm session on post SSR", __func__);
+ in->standby = false;
+ pthread_mutex_unlock(&in->lock);
+ in_standby(&in->stream.common);
+ pthread_mutex_lock(&in->lock);
+ }
+ }
+
if (in->standby) {
pthread_mutex_lock(&adev->lock);
if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
@@ -2064,13 +2137,22 @@
memset(buffer, 0, bytes);
exit:
+
+ if (-ENETRESET == ret) {
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
+ in->pcm_error_type = PCM_ERROR_ENETRESET;
+ memset(buffer, 0, bytes);
+ in->standby = true; /*standby will be called on post SSR */
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+ }
pthread_mutex_unlock(&in->lock);
if (ret != 0) {
in_standby(&in->stream.common);
ALOGV("%s: read failed - sleeping for buffer duration", __func__);
usleep(bytes * 1000000 / audio_stream_frame_size(&in->stream.common) /
- in_get_sample_rate(&in->stream.common));
+ in_get_sample_rate(&in->stream.common));
}
return bytes;
}
@@ -2137,6 +2219,7 @@
struct audio_device *adev = (struct audio_device *)dev;
struct stream_out *out;
int i, ret = 0;
+ audio_format_t format;
*stream_out = NULL;
out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
@@ -2159,7 +2242,7 @@
out->flags = flags;
out->devices = devices;
out->dev = adev;
- out->format = config->format;
+ format = out->format = config->format;
out->sample_rate = config->sample_rate;
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
@@ -2225,7 +2308,7 @@
out->channel_mask = config->channel_mask;
config->offload_info.channel_mask = config->channel_mask;
}
- out->format = config->offload_info.format;
+ format = out->format = config->offload_info.format;
out->sample_rate = config->offload_info.sample_rate;
out->stream.set_callback = out_set_callback;
@@ -2285,16 +2368,21 @@
goto error_open;
}
} else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
+ format = AUDIO_FORMAT_PCM_16_BIT;
out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
out->config = pcm_config_low_latency;
out->sample_rate = out->config.rate;
} else {
/* primary path is the default path selected if no other outputs are available/suitable */
+ format = AUDIO_FORMAT_PCM_16_BIT;
out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
out->config = pcm_config_deep_buffer;
out->sample_rate = out->config.rate;
}
+ audio_extn_utils_update_stream_app_type_cfg(adev->platform,
+ &adev->streams_output_cfg_list,
+ flags, format, &out->app_type_cfg);
if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
(flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
/* Ensure the default output is not selected twice */
@@ -2398,10 +2486,23 @@
int ret = 0, err;
ALOGD("%s: enter: %s", __func__, kvpairs);
-
- pthread_mutex_lock(&adev->lock);
parms = str_parms_create_str(kvpairs);
+ err = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
+ if (err >= 0) {
+ char *snd_card_status = value+2;
+ pthread_mutex_lock(&adev->snd_card_status.lock);
+ if (strstr(snd_card_status, "OFFLINE")) {
+ ALOGD("Received sound card OFFLINE status");
+ adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
+ } else if (strstr(snd_card_status, "ONLINE")) {
+ ALOGD("Received sound card ONLINE status");
+ adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
+ }
+ pthread_mutex_unlock(&adev->snd_card_status.lock);
+ }
+
+ pthread_mutex_lock(&adev->lock);
ret = voice_set_parameters(adev, parms);
if (ret != 0)
goto done;
@@ -2694,6 +2795,7 @@
if ((--audio_device_ref_count) == 0) {
audio_extn_listen_deinit(adev);
+ audio_extn_utils_release_streams_output_cfg_list(&adev->streams_output_cfg_list);
audio_route_free(adev->audio_route);
free(adev->snd_dev_ref_cnt);
platform_deinit(adev->platform);
@@ -2762,6 +2864,9 @@
list_init(&adev->usecase_list);
adev->cur_wfd_channels = 2;
adev->offload_usecases_state = 0;
+
+ pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
+ adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
/* Loads platform specific libraries dynamically */
adev->platform = platform_init(adev);
if (!adev->platform) {
@@ -2773,6 +2878,8 @@
return -EINVAL;
}
+ adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
+
if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
if (adev->visualizer_lib == NULL) {
@@ -2808,6 +2915,9 @@
*device = &adev->device.common;
+ audio_extn_utils_update_streams_output_cfg_list(adev->platform, adev->mixer,
+ &adev->streams_output_cfg_list);
+
audio_device_ref_count++;
pthread_mutex_unlock(&adev_init_lock);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 3115f1a..7d8d924 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -52,6 +52,8 @@
#define MAX_SUPPORTED_CHANNEL_MASKS 2
#define DEFAULT_HDMI_OUT_CHANNELS 2
+#define SND_CARD_STATE_OFFLINE 0
+#define SND_CARD_STATE_ONLINE 1
typedef int snd_device_t;
/* These are the supported use cases by the hardware.
@@ -138,12 +140,24 @@
OFFLOAD_STATE_PAUSED,
};
+enum {
+ PCM_ERROR_NONE,
+ PCM_ERROR_EIO,
+ PCM_ERROR_ENETRESET, /* For SSR */
+};
+
struct offload_cmd {
struct listnode node;
int cmd;
int data[];
};
+struct stream_app_type_cfg {
+ int sample_rate;
+ int bit_width;
+ int app_type;
+};
+
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -165,6 +179,7 @@
bool muted;
uint64_t written; /* total frames written, not cleared when entering standby */
audio_io_handle_t handle;
+ struct stream_app_type_cfg app_type_cfg;
int non_blocking;
int playback_started;
@@ -178,6 +193,7 @@
void *offload_cookie;
struct compr_gapless_mdata gapless_mdata;
int send_new_metadata;
+ int pcm_error_type;
struct audio_device *dev;
};
@@ -196,6 +212,7 @@
bool enable_aec;
bool enable_ns;
audio_format_t format;
+ int pcm_error_type;
struct audio_device *dev;
};
@@ -223,6 +240,23 @@
union stream_ptr stream;
};
+struct sound_card_status {
+ pthread_mutex_t lock;
+ int state;
+};
+
+struct stream_format {
+ struct listnode list;
+ audio_format_t format;
+};
+
+struct streams_output_cfg {
+ struct listnode list;
+ audio_output_flags_t flags;
+ struct listnode format_list;
+ struct stream_app_type_cfg app_type_cfg;
+};
+
struct audio_device {
struct audio_hw_device device;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
@@ -235,6 +269,7 @@
bool screen_off;
int *snd_dev_ref_cnt;
struct listnode usecase_list;
+ struct listnode streams_output_cfg_list;
struct audio_route *audio_route;
int acdb_settings;
bool speaker_lr_swap;
@@ -251,6 +286,8 @@
void *offload_effects_lib;
int (*offload_effects_start_output)(audio_io_handle_t, int);
int (*offload_effects_stop_output)(audio_io_handle_t, int);
+
+ struct sound_card_status snd_card_status;
};
int select_devices(struct audio_device *adev,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 4ca7ce7..d2a6807 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -34,6 +34,8 @@
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define MIXER_XML_PATH_MTP "/system/etc/mixer_paths_mtp.xml"
+#define MIXER_XML_PATH_QRD_SKUH "/system/etc/mixer_paths_qrd_skuh.xml"
+#define MIXER_XML_PATH_QRD_SKUI "/system/etc/mixer_paths_qrd_skui.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
#define PLATFORM_INFO_XML_PATH "/system/etc/audio_platform_info.xml"
#define LIB_ACDB_LOADER "libacdbloader.so"
@@ -402,6 +404,14 @@
sizeof("msm8x16-snd-card-mtp"))) {
strlcpy(mixer_xml_path, MIXER_XML_PATH_MTP,
sizeof(MIXER_XML_PATH_MTP));
+ } else if (!strncmp(snd_card_name, "msm8x16-skuh-snd-card",
+ sizeof("msm8x16-skuh-snd-card"))) {
+ strlcpy(mixer_xml_path, MIXER_XML_PATH_QRD_SKUH,
+ sizeof(MIXER_XML_PATH_QRD_SKUH));
+ } else if (!strncmp(snd_card_name, "msm8x16-skui-snd-card",
+ sizeof("msm8x16-skui-snd-card"))) {
+ strlcpy(mixer_xml_path, MIXER_XML_PATH_QRD_SKUI,
+ sizeof(MIXER_XML_PATH_QRD_SKUI));
} else {
strlcpy(mixer_xml_path, MIXER_XML_PATH,
sizeof(MIXER_XML_PATH));
@@ -706,6 +716,9 @@
/* Read one time ssr property */
audio_extn_ssr_update_enabled();
audio_extn_spkr_prot_init(adev);
+
+ audio_extn_dolby_set_license(adev);
+
return my_data;
}
@@ -881,6 +894,15 @@
return ret;
}
+int platform_get_snd_device_acdb_id(snd_device_t snd_device)
+{
+ if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+ return -EINVAL;
+ }
+ return acdb_device_table[snd_device];
+}
+
int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 64e090b..dae686e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -785,6 +785,9 @@
/* Read one time ssr property */
audio_extn_ssr_update_enabled();
audio_extn_spkr_prot_init(adev);
+
+ audio_extn_dolby_set_license(adev);
+
return my_data;
}
@@ -967,6 +970,15 @@
return ret;
}
+int platform_get_snd_device_acdb_id(snd_device_t snd_device)
+{
+ if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+ return -EINVAL;
+ }
+ return acdb_device_table[snd_device];
+}
+
int platform_send_audio_calibration(void *platform, snd_device_t snd_device)
{
struct platform_data *my_data = (struct platform_data *)platform;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index bf6bdcb..15deea5 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -31,6 +31,7 @@
int platform_set_fluence_type(void *platform, char *value);
int platform_get_fluence_type(void *platform, char *value, uint32_t len);
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
+int platform_get_snd_device_acdb_id(snd_device_t snd_device);
int platform_send_audio_calibration(void *platform, snd_device_t snd_device);
int platform_switch_voice_call_device_pre(void *platform);
int platform_switch_voice_call_enable_device_config(void *platform,
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index 74dc426..d42cc53 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -302,12 +302,6 @@
no_of_calls_active++;
}
- /* When there is only one call active, wait for audio policy manager to set
- * the mode to AUDIO_MODE_NORMAL and trigger routing to end the last call.
- */
- if (no_of_calls_active == 1 && call_state == CALL_INACTIVE)
- return 0;
-
if (session) {
session->state.new = call_state;
voice_extn_is_in_call(adev, &is_in_call);
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index 303540c..b679fdb 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -233,8 +233,16 @@
// do not force device change on duplicated output because if device is 0, it will
// also force a device 0 for the two outputs it is duplicated to which may override
// a valid device selection on those outputs.
+ audio_devices_t cachedDevice = getNewDevice(mOutputs.keyAt(i), true /*fromCache*/);
+ AudioOutputDescriptor *desc = mOutputs.valueFor(mOutputs.keyAt(i));
+ if (cachedDevice == AUDIO_DEVICE_OUT_SPEAKER &&
+ device == AUDIO_DEVICE_OUT_PROXY &&
+ (desc->mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
+ ALOGI("Avoid routing touch tone to spkr as proxy is being disconnected");
+ break;
+ }
setOutputDevice(mOutputs.keyAt(i),
- getNewDevice(mOutputs.keyAt(i), true /*fromCache*/),
+ cachedDevice,
!mOutputs.valueAt(i)->isDuplicated(),
0);
}
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index 8d96e90..1c96280 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -156,6 +156,7 @@
(device == AUDIO_DEVICE_OUT_PROXY) ||
#endif
(device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
+ (device == AUDIO_DEVICE_OUT_USB_ACCESSORY) ||
(device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
if (offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass))) {
offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index b11a700..a0d9fcb 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -201,6 +201,11 @@
output_context_t *out_ctxt = (output_context_t *)
malloc(sizeof(output_context_t));
+ if (!out_ctxt) {
+ ALOGE("%s fail to allocate for output context", __func__);
+ ret = -ENOMEM;
+ goto exit;
+ }
out_ctxt->handle = output;
out_ctxt->pcm_device_id = pcm_id;
@@ -334,6 +339,9 @@
sizeof(effect_uuid_t)) == 0) {
equalizer_context_t *eq_ctxt = (equalizer_context_t *)
calloc(1, sizeof(equalizer_context_t));
+ if (eq_ctxt == NULL) {
+ return -ENOMEM;
+ }
context = (effect_context_t *)eq_ctxt;
context->ops.init = equalizer_init;
context->ops.reset = equalizer_reset;
@@ -351,6 +359,9 @@
sizeof(effect_uuid_t)) == 0) {
bassboost_context_t *bass_ctxt = (bassboost_context_t *)
calloc(1, sizeof(bassboost_context_t));
+ if (bass_ctxt == NULL) {
+ return -ENOMEM;
+ }
context = (effect_context_t *)bass_ctxt;
context->ops.init = bassboost_init;
context->ops.reset = bassboost_reset;
@@ -368,6 +379,9 @@
sizeof(effect_uuid_t)) == 0) {
virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)
calloc(1, sizeof(virtualizer_context_t));
+ if (virt_ctxt == NULL) {
+ return -ENOMEM;
+ }
context = (effect_context_t *)virt_ctxt;
context->ops.init = virtualizer_init;
context->ops.reset = virtualizer_reset;
@@ -391,6 +405,9 @@
sizeof(effect_uuid_t)) == 0)) {
reverb_context_t *reverb_ctxt = (reverb_context_t *)
calloc(1, sizeof(reverb_context_t));
+ if (reverb_ctxt == NULL) {
+ return -ENOMEM;
+ }
context = (effect_context_t *)reverb_ctxt;
context->ops.init = reverb_init;
context->ops.reset = reverb_reset;
diff --git a/post_proc/effect_api.c b/post_proc/effect_api.c
index bad6ee1..971b67f 100644
--- a/post_proc/effect_api.c
+++ b/post_proc/effect_api.c
@@ -318,7 +318,8 @@
uint32_t i;
ALOGV("%s: flags 0x%x", __func__, param_send_flags);
- if (eq.config.preset_id < -1 ) {
+ if ((eq.config.preset_id < -1) ||
+ ((param_send_flags & OFFLOAD_SEND_EQ_PRESET) && (eq.config.preset_id == -1))) {
ALOGV("No Valid preset to set");
return 0;
}
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index bd52062..96828a0 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -155,6 +155,7 @@
(device == AUDIO_DEVICE_OUT_PROXY) ||
#endif
(device == AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
+ (device == AUDIO_DEVICE_OUT_USB_ACCESSORY) ||
(device == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET)) {
if (offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt))) {
offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false);
diff --git a/visualizer/offload_visualizer.c b/visualizer/offload_visualizer.c
index 95b4687..94c44a5 100644
--- a/visualizer/offload_visualizer.c
+++ b/visualizer/offload_visualizer.c
@@ -431,6 +431,11 @@
}
output_context_t *out_ctxt = (output_context_t *)malloc(sizeof(output_context_t));
+ if (out_ctxt == NULL) {
+ ALOGE("%s fail to allocate memory", __func__);
+ ret = -ENOMEM;
+ goto exit;
+ }
out_ctxt->handle = output;
list_init(&out_ctxt->effects_list);
@@ -927,6 +932,10 @@
if (memcmp(uuid, &visualizer_descriptor.uuid, sizeof(effect_uuid_t)) == 0) {
visualizer_context_t *visu_ctxt = (visualizer_context_t *)calloc(1,
sizeof(visualizer_context_t));
+ if (visu_ctxt == NULL) {
+ ALOGE("%s fail to allocate memory", __func__);
+ return -ENOMEM;
+ }
context = (effect_context_t *)visu_ctxt;
context->ops.init = visualizer_init;
context->ops.reset = visualizer_reset;
diff --git a/voice_processing/voice_processing.c b/voice_processing/voice_processing.c
index b8b1e1b..1d18a3d 100644
--- a/voice_processing/voice_processing.c
+++ b/voice_processing/voice_processing.c
@@ -408,6 +408,10 @@
}
session = (struct session_s *)calloc(1, sizeof(struct session_s));
+ if (session == NULL) {
+ ALOGE("get_session() fail to allocate memory");
+ return NULL;
+ }
session_init(session);
session->id = sessionId;
session->io = ioId;
@@ -682,6 +686,10 @@
return -EINVAL;
}
id = uuid_to_id(&desc->type);
+ if (id >= NUM_ID) {
+ ALOGW("lib_create: fx not found type: %08x", desc->type.timeLow);
+ return -EINVAL;
+ }
session = get_session(id, sessionId, ioId);