Merge "hal: Avoid double free while closing of VoIP driver"
diff --git a/hal/Android.mk b/hal/Android.mk
index 73ae361..32b9275 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -43,6 +43,8 @@
LOCAL_SRC_FILES += audio_extn/audio_extn.c \
audio_extn/utils.c
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PCM_OFFLOAD)),true)
LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
@@ -89,8 +91,7 @@
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MULTI_VOICE_SESSIONS)),true)
LOCAL_CFLAGS += -DMULTI_VOICE_SESSION_ENABLED
LOCAL_SRC_FILES += voice_extn/voice_extn.c
- LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
- LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_INCALL_MUSIC)),true)
LOCAL_CFLAGS += -DINCALL_MUSIC_ENABLED
endif
@@ -108,8 +109,6 @@
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_SPKR_PROTECTION)),true)
LOCAL_CFLAGS += -DSPKR_PROT_ENABLED
LOCAL_SRC_FILES += audio_extn/spkr_protection.c
- LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
- LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
ifdef MULTIPLE_HW_VARIANTS_ENABLED
@@ -124,8 +123,6 @@
ifeq ($(strip $(DOLBY_DDP)),true)
LOCAL_CFLAGS += -DDS1_DOLBY_DDP_ENABLED
- LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
- LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_SRC_FILES += audio_extn/dolby.c
endif
@@ -140,6 +137,15 @@
LOCAL_CFLAGS += -DMULTIPLE_OFFLOAD_ENABLED
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXTN_FLAC_DECODER)),true)
+ LOCAL_CFLAGS += -DQTI_FLAC_DECODER
+endif
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_DEV_ARBI)),true)
+ LOCAL_CFLAGS += -DDEV_ARBI_ENABLED
+ LOCAL_SRC_FILES += audio_extn/dev_arbi.c
+endif
+
LOCAL_SHARED_LIBRARIES := \
liblog \
libcutils \
@@ -147,8 +153,7 @@
libtinycompress \
libaudioroute \
libdl \
- libexpat \
- libmdmdetect
+ libexpat
LOCAL_C_INCLUDES += \
external/tinyalsa/include \
@@ -158,8 +163,7 @@
$(call include-path-for, audio-effects) \
$(LOCAL_PATH)/$(AUDIO_PLATFORM) \
$(LOCAL_PATH)/audio_extn \
- $(LOCAL_PATH)/voice_extn \
- $(TARGET_OUT_HEADERS)/libmdmdetect/inc
+ $(LOCAL_PATH)/voice_extn
ifeq ($(strip $(AUDIO_FEATURE_ENABLED_LISTEN)),true)
LOCAL_CFLAGS += -DAUDIO_LISTEN_ENABLED
@@ -171,6 +175,9 @@
LOCAL_CFLAGS += -DAUXPCM_BT_ENABLED
endif
+LOCAL_COPY_HEADERS_TO := mm-audio
+LOCAL_COPY_HEADERS := audio_extn/audio_defs.h
+
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_RELATIVE_PATH := hw
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index a858028..5eb650c 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -51,6 +51,16 @@
#define AUDIO_DEVICE_IN_FM_RX_A2DP (AUDIO_DEVICE_BIT_IN | 0x10000)
#endif
+#ifndef QTI_FLAC_DECODER
+#define AUDIO_FORMAT_FLAC 0x19000000UL
+#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE "music_offload_flac_min_blk_size"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE "music_offload_flac_max_blk_size"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
+#define PCM_OUTPUT_BIT_WIDTH (CODEC_BACKEND_DEFAULT_BIT_WIDTH)
+#else
+#define PCM_OUTPUT_BIT_WIDTH (config->offload_info.bit_width)
+#endif
#define MAX_LENGTH_MIXER_CONTROL_IN_INT (128)
@@ -182,7 +192,7 @@
#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)
+#define audio_extn_get_spkr_prot_snd_device(snd_device) (snd_device)
#else
void audio_extn_spkr_prot_init(void *adev);
int audio_extn_spkr_prot_start_processing(snd_device_t snd_device);
@@ -250,6 +260,18 @@
audio_usecase_t audio_extn_hfp_get_usecase();
#endif
+#ifndef DEV_ARBI_ENABLED
+#define audio_extn_dev_arbi_init() (0)
+#define audio_extn_dev_arbi_deinit() (0)
+#define audio_extn_dev_arbi_acquire(snd_device) (0)
+#define audio_extn_dev_arbi_release(snd_device) (0)
+#else
+int audio_extn_dev_arbi_init();
+int audio_extn_dev_arbi_deinit();
+int audio_extn_dev_arbi_acquire(snd_device_t snd_device);
+int audio_extn_dev_arbi_release(snd_device_t snd_device);
+#endif
+
void audio_extn_utils_update_streams_output_cfg_list(void *platform,
struct mixer *mixer,
struct listnode *streams_output_cfg_list);
diff --git a/hal/audio_extn/dev_arbi.c b/hal/audio_extn/dev_arbi.c
new file mode 100644
index 0000000..d3c01c5
--- /dev/null
+++ b/hal/audio_extn/dev_arbi.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "audio_hw_dev_arbi"
+/*#define LOG_NDEBUG 0*/
+#define LOG_NDDEBUG 0
+
+#include <errno.h>
+#include <cutils/log.h>
+#include <fcntl.h>
+#include "audio_hw.h"
+#include "platform.h"
+#include "platform_api.h"
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/properties.h>
+#include "audio_extn.h"
+
+#ifdef DEV_ARBI_ENABLED
+
+typedef int (init_fn_t)();
+typedef int (deinit_fn_t)();
+typedef int (acquire_fn_t)(audio_devices_t aud_dev);
+typedef int (release_fn_t)(audio_devices_t aud_dev);
+
+typedef struct {
+ snd_device_t snd_device;
+ audio_devices_t aud_device;
+} snd_aud_dev_mapping_t;
+
+static void* lib_handle = NULL;
+
+static init_fn_t *init_fp = NULL;
+static deinit_fn_t *deinit_fp = NULL;
+static acquire_fn_t *acquire_fp = NULL;
+static release_fn_t *release_fp = NULL;
+
+static int load_dev_arbi_lib()
+{
+ int rc = -EINVAL;
+
+ if (lib_handle != NULL) {
+ ALOGE("%s: library already loaded", __func__);
+ return rc;
+ }
+
+ lib_handle = dlopen("libaudiodevarb.so", RTLD_NOW);
+ if (lib_handle != NULL) {
+ init_fp = (init_fn_t*)dlsym(lib_handle, "aud_dev_arbi_server_init");
+ deinit_fp = (deinit_fn_t*)dlsym(lib_handle, "aud_dev_arbi_server_deinit");
+ acquire_fp = (acquire_fn_t*)dlsym(lib_handle, "aud_dev_arbi_server_acquire");
+ release_fp = (release_fn_t*)dlsym(lib_handle, "aud_dev_arbi_server_release");
+
+ if ((init_fp == NULL) ||
+ (deinit_fp == NULL) ||
+ (acquire_fp == NULL) ||
+ (release_fp == NULL)) {
+
+ ALOGE("%s: error loading symbols from library", __func__);
+
+ init_fp = NULL;
+ deinit_fp = NULL;
+ acquire_fp = NULL;
+ release_fp = NULL;
+ } else
+ return 0;
+ }
+
+ return rc;
+}
+
+int audio_extn_dev_arbi_init()
+{
+ int rc = load_dev_arbi_lib();
+ if (!rc)
+ rc = init_fp();
+
+ return rc;
+}
+
+int audio_extn_dev_arbi_deinit()
+{
+ int rc = -EINVAL;
+
+ if(deinit_fp != NULL) {
+ rc = deinit_fp();
+
+ init_fp = NULL;
+ deinit_fp = NULL;
+ acquire_fp = NULL;
+ release_fp = NULL;
+
+ dlclose(lib_handle);
+ lib_handle = NULL;
+ }
+
+ return rc;
+}
+
+static audio_devices_t get_audio_device(snd_device_t snd_device)
+{
+ static snd_aud_dev_mapping_t snd_aud_dev_map[] = {
+ {SND_DEVICE_OUT_HANDSET, AUDIO_DEVICE_OUT_EARPIECE},
+ {SND_DEVICE_OUT_VOICE_HANDSET, AUDIO_DEVICE_OUT_EARPIECE}
+ };
+
+ audio_devices_t aud_device = AUDIO_DEVICE_NONE;
+ uint32_t ind = 0;
+
+ for (ind = 0; ind < ARRAY_SIZE(snd_aud_dev_map); ++ind) {
+ if (snd_device == snd_aud_dev_map[ind].snd_device) {
+ aud_device = snd_aud_dev_map[ind].aud_device;
+ break;
+ }
+ }
+
+ return aud_device;
+}
+
+int audio_extn_dev_arbi_acquire(snd_device_t snd_device)
+{
+ int rc = -EINVAL;
+ audio_devices_t audio_device = get_audio_device(snd_device);
+
+ if ((acquire_fp != NULL) && (audio_device != AUDIO_DEVICE_NONE))
+ rc = acquire_fp(audio_device);
+
+ return rc;
+}
+
+int audio_extn_dev_arbi_release(snd_device_t snd_device)
+{
+ int rc = -EINVAL;
+ audio_devices_t audio_device = get_audio_device(snd_device);
+
+ if ((release_fp != NULL) && (audio_device != AUDIO_DEVICE_NONE))
+ rc = release_fp(audio_device);
+
+ return rc;
+}
+
+#endif /*DEV_ARBI_ENABLED*/
diff --git a/hal/audio_extn/fm.c b/hal/audio_extn/fm.c
index 1d1613a..b6f8689 100644
--- a/hal/audio_extn/fm.c
+++ b/hal/audio_extn/fm.c
@@ -148,6 +148,10 @@
ALOGD("%s: enter", __func__);
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+ if (!uc_info)
+ return -ENOMEM;
+
uc_info->id = USECASE_AUDIO_PLAYBACK_FM;
uc_info->type = PCM_PLAYBACK;
uc_info->stream.out = adev->primary_output;
diff --git a/hal/audio_extn/hfp.c b/hal/audio_extn/hfp.c
index 239c975..c94cc14 100644
--- a/hal/audio_extn/hfp.c
+++ b/hal/audio_extn/hfp.c
@@ -136,6 +136,10 @@
ALOGD("%s: enter", __func__);
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+ if (!uc_info)
+ return -ENOMEM;
+
uc_info->id = hfpmod.ucid;
uc_info->type = PCM_HFP_CALL;
uc_info->stream.out = adev->primary_output;
@@ -200,10 +204,26 @@
ret = -EIO;
goto exit;
}
- pcm_start(hfpmod.hfp_sco_rx);
- pcm_start(hfpmod.hfp_sco_tx);
- pcm_start(hfpmod.hfp_pcm_rx);
- pcm_start(hfpmod.hfp_pcm_tx);
+ if (pcm_start(hfpmod.hfp_sco_rx) < 0) {
+ ALOGE("%s: pcm start for hfp sco rx failed", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+ if (pcm_start(hfpmod.hfp_sco_tx) < 0) {
+ ALOGE("%s: pcm start for hfp sco tx failed", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+ if (pcm_start(hfpmod.hfp_pcm_rx) < 0) {
+ ALOGE("%s: pcm start for hfp pcm rx failed", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+ if (pcm_start(hfpmod.hfp_pcm_tx) < 0) {
+ ALOGE("%s: pcm start for hfp pcm tx failed", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
hfpmod.is_hfp_running = true;
hfp_set_volume(adev, hfpmod.hfp_volume);
diff --git a/hal/audio_extn/listen.c b/hal/audio_extn/listen.c
index b1ed105..4cb2d2d 100644
--- a/hal/audio_extn/listen.c
+++ b/hal/audio_extn/listen.c
@@ -200,6 +200,11 @@
listen_dev = (struct listen_audio_device*)
calloc(1, sizeof(struct listen_audio_device));
+ if (!listen_dev) {
+ ALOGE("failed to allocate listen_dev mem");
+ return -ENOMEM;
+ }
+
listen_dev->lib_handle = lib_handle;
listen_dev->adev = adev;
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c
index 7ab65c6..951dadc 100644
--- a/hal/audio_extn/spkr_protection.c
+++ b/hal/audio_extn/spkr_protection.c
@@ -668,6 +668,15 @@
handle.thermal_handle = NULL;
handle.spkr_prot_enable = false;
}
+
+ if (handle.spkr_prot_enable) {
+ char platform[PROPERTY_VALUE_MAX];
+ property_get("ro.board.platform", platform, "");
+ if (!strncmp("apq8084", platform, sizeof("apq8084"))) {
+ platform_set_snd_device_backend(SND_DEVICE_OUT_VOICE_SPEAKER,
+ "speaker-protected");
+ }
+ }
}
int audio_extn_spkr_prot_get_acdb_id(snd_device_t snd_device)
diff --git a/hal/audio_extn/ssr.c b/hal/audio_extn/ssr.c
index ac6da8b..f32d217 100644
--- a/hal/audio_extn/ssr.c
+++ b/hal/audio_extn/ssr.c
@@ -294,8 +294,8 @@
if ( ret > 0 ) {
ALOGV("%s: Allocating surroundObj size is %d", __func__, ret);
ssrmod.surround_obj = (void *)malloc(ret);
- memset(ssrmod.surround_obj,0,ret);
if (NULL != ssrmod.surround_obj) {
+ memset(ssrmod.surround_obj,0,ret);
/* initialize after allocating the memory for surround_obj */
ret = ssrmod.surround_filters_init(ssrmod.surround_obj,
6,
diff --git a/hal/audio_extn/usb.c b/hal/audio_extn/usb.c
index bc83709..a4ea134 100644
--- a/hal/audio_extn/usb.c
+++ b/hal/audio_extn/usb.c
@@ -159,12 +159,16 @@
char *buffer;
int32_t err = 1;
int32_t size = 0;
- int32_t fd, i, channels_playback;
- char *read_buf, *str_start, *channel_start, *rates_str, *rates_str_for_val,
- *rates_str_start, *next_sr_str, *test, *next_sr_string, *temp_ptr;
+ int32_t fd=-1, i, channels_playback;
+ char *str_start, *channel_start, *rates_str_start, *next_sr_str,
+ *next_sr_string, *temp_ptr;
struct stat st;
- int *rates_supported;
+ char *read_buf = NULL;
+ char *rates_str = NULL;
+ char *rates_str_for_val = NULL;
+ int *rates_supported = NULL;
char path[128];
+ int ret = 0;
memset(&st, 0x0, sizeof(struct stat));
*sample_rate = 0;
@@ -175,45 +179,49 @@
if (fd <0) {
ALOGE("%s: error failed to open config file %s error: %d\n",
__func__, path, errno);
- close(fd);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
if (fstat(fd, &st) < 0) {
ALOGE("%s: error failed to stat %s error %d\n",
__func__, path, errno);
- close(fd);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
file_size = st.st_size;
read_buf = (char *)calloc(1, USB_BUFF_SIZE + 1);
+
+ if (!read_buf) {
+ ALOGE("Failed to create read_buf");
+ ret = -ENOMEM;
+ goto done;
+ }
+
err = read(fd, read_buf, USB_BUFF_SIZE);
str_start = strstr(read_buf, type);
if (str_start == NULL) {
ALOGE("%s: error %s section not found in usb config file",
__func__, type);
- close(fd);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
channel_start = strstr(str_start, "Channels:");
if (channel_start == NULL) {
ALOGE("%s: error could not find Channels information", __func__);
- close(fd);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
channel_start = strstr(channel_start, " ");
if (channel_start == NULL) {
ALOGE("%s: error channel section not found in usb config file",
__func__);
- close(fd);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
channels_playback = atoi(channel_start);
@@ -227,44 +235,38 @@
rates_str_start = strstr(str_start, "Rates:");
if (rates_str_start == NULL) {
ALOGE("%s: error cant find rates information", __func__);
- close(fd);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
rates_str_start = strstr(rates_str_start, " ");
if (rates_str_start == NULL) {
ALOGE("%s: error channel section not found in usb config file",
__func__);
- close(fd);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
char *target = strchr(rates_str_start, '\n');
if (target == NULL) {
ALOGE("%s: error end of line not found", __func__);
- close(fd);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
size = target - rates_str_start;
if ((rates_str = (char *)malloc(size + 1)) == NULL) {
ALOGE("%s: error unable to allocate memory to hold sample rate strings",
__func__);
- close(fd);
- free(read_buf);
- return -ENOMEM;
+ ret = -EINVAL;
+ goto done;
}
if ((rates_str_for_val = (char *)malloc(size + 1)) == NULL) {
ALOGE("%s: error unable to allocate memory to hold sample rate string",
__func__);
- close(fd);
- free(rates_str);
- free(read_buf);
- return -ENOMEM;
+ ret = -EINVAL;
+ goto done;
}
memcpy(rates_str, rates_str_start, size);
@@ -275,23 +277,23 @@
size = usb_get_numof_rates(rates_str);
if (!size) {
ALOGE("%s: error could not get rate size, returning", __func__);
- close(fd);
- free(rates_str_for_val);
- free(rates_str);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
rates_supported = (int *)malloc(sizeof(int) * size);
+
+ if (!rates_supported) {
+ ALOGE("couldn't allocate mem for rates_supported");
+ ret = -EINVAL;
+ goto done;
+ }
+
next_sr_string = strtok_r(rates_str_for_val, " ,", &temp_ptr);
if (next_sr_string == NULL) {
ALOGE("%s: error could not get first rate val", __func__);
- close(fd);
- free(rates_str_for_val);
- free(rates_str);
- free(rates_supported);
- free(read_buf);
- return -EINVAL;
+ ret = -EINVAL;
+ goto done;
}
rates_supported[0] = atoi(next_sr_string);
@@ -299,6 +301,10 @@
__func__, rates_supported[0]);
for (i = 1; i<size; i++) {
next_sr_string = strtok_r(NULL, " ,.-", &temp_ptr);
+ if (next_sr_string == NULL) {
+ rates_supported[i] = -1; // fill in an invalid sr for the rest
+ continue;
+ }
rates_supported[i] = atoi(next_sr_string);
ALOGD("rates_supported[%d] for playback: %d",i, rates_supported[i]);
}
@@ -317,12 +323,13 @@
}
ALOGD("%s: sample_rate: %d", __func__, *sample_rate);
- close(fd);
- free(rates_str_for_val);
- free(rates_str);
- free(rates_supported);
- free(read_buf);
- return 0;
+done:
+ if (fd >= 0) close(fd);
+ if (rates_str_for_val) free(rates_str_for_val);
+ if (rates_str) free(rates_str);
+ if (rates_supported) free(rates_supported);
+ if (read_buf) free(read_buf);
+ return ret;
}
static int32_t usb_playback_entry(void *adev)
@@ -387,7 +394,6 @@
if(usbmod->proxy_pcm_playback_handle
&& !pcm_is_ready(usbmod->proxy_pcm_playback_handle)){
pcm_close(usbmod->proxy_pcm_playback_handle);
- usbmod->proxy_pcm_playback_handle = NULL;
proxy_open_retry_count--;
usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
ALOGE("%s: pcm_open for proxy failed retrying = %d",
@@ -507,7 +513,6 @@
if(usbmod->proxy_pcm_record_handle
&& !pcm_is_ready(usbmod->proxy_pcm_record_handle)){
pcm_close(usbmod->proxy_pcm_record_handle);
- usbmod->proxy_pcm_record_handle = NULL;
proxy_open_retry_count--;
usleep(USB_PROXY_OPEN_WAIT_TIME * 1000);
ALOGE("%s: pcm_open for proxy(recording) failed retrying = %d",
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index aa66360..e7a57c8 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -141,6 +141,9 @@
ALOGV("%s: format - %d", __func__, format);
if (format != 0) {
sf_info = (struct stream_format *)calloc(1, sizeof(struct stream_format));
+ if (sf_info == NULL)
+ break; /* return whatever was parsed */
+
sf_info->format = format;
list_add_tail(&so_info->format_list, &sf_info->list);
}
@@ -192,6 +195,12 @@
ALOGV("%s", __func__);
so_info = (struct streams_output_cfg *)calloc(1, sizeof(struct streams_output_cfg));
+
+ if (!so_info) {
+ ALOGE("failed to allocate mem for so_info list element");
+ return;
+ }
+
while (node) {
if (strcmp(node->name, FLAGS_TAG) == 0) {
so_info->flags = parse_flag_names((char *)node->value);
@@ -298,6 +307,11 @@
}
root = config_node("", "");
+ if (root == NULL) {
+ ALOGE("cfg_list, NULL config root");
+ return;
+ }
+
config_load(root, data);
load_output(root, platform, streams_output_cfg_list);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 9171d04..4d8925d 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -125,7 +125,7 @@
[USECASE_AUDIO_HFP_SCO] = "hfp-sco",
[USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
[USECASE_VOICE_CALL] = "voice-call",
-
+
[USECASE_VOICE2_CALL] = "voice2-call",
[USECASE_VOLTE_CALL] = "volte-call",
[USECASE_QCHAT_CALL] = "qchat-call",
@@ -209,7 +209,8 @@
if (format == AUDIO_FORMAT_MP3 ||
format == AUDIO_FORMAT_AAC ||
format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
- format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
+ format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
+ format == AUDIO_FORMAT_FLAC)
return true;
return false;
@@ -230,6 +231,9 @@
case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
id = SND_AUDIOCODEC_PCM;
break;
+ case AUDIO_FORMAT_FLAC:
+ id = SND_AUDIOCODEC_FLAC;
+ break;
default:
ALOGE("%s: Unsupported audio format :%x", __func__, format);
}
@@ -375,6 +379,7 @@
LISTEN_EVENT_SND_DEVICE_FREE);
return -EINVAL;
}
+ audio_extn_dev_arbi_acquire(snd_device);
audio_route_apply_and_update_path(adev->audio_route, device_name);
}
return 0;
@@ -418,9 +423,10 @@
snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
audio_extn_spkr_prot_is_enabled()) {
audio_extn_spkr_prot_stop_processing();
- } else
+ } else {
audio_route_reset_and_update_path(adev->audio_route, device_name);
-
+ audio_extn_dev_arbi_release(snd_device);
+ }
audio_extn_listen_update_device_status(snd_device,
LISTEN_EVENT_SND_DEVICE_FREE);
}
@@ -447,6 +453,15 @@
* because of the limitation that both the devices cannot be enabled
* at the same time as they share the same backend.
*/
+ /*
+ * This call is to check if we need to force routing for a particular stream
+ * If there is a backend configuration change for the device when a
+ * new stream starts, then ADM needs to be closed and re-opened with the new
+ * configuraion. This call check if we need to re-route all the streams
+ * associated with the backend. Touch tone + 24 bit playback.
+ */
+ bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
+
/* Disable all the usecases on the shared backend other than the
specified usecase */
for (i = 0; i < AUDIO_USECASE_MAX; i++)
@@ -456,7 +471,7 @@
usecase = node_to_item(node, struct audio_usecase, list);
if (usecase->type != PCM_CAPTURE &&
usecase != uc_info &&
- usecase->out_snd_device != snd_device &&
+ (usecase->out_snd_device != snd_device || force_routing) &&
usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
__func__, use_case_table[usecase->id],
@@ -657,26 +672,26 @@
* usecase. This is to avoid switching devices for voice call when
* check_usecases_codec_backend() is called below.
*/
- if (voice_is_in_call(adev)) {
+ if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
vc_usecase = get_usecase_from_list(adev,
get_voice_usecase_id_from_list(adev));
- if ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
- (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL)) {
+ if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
+ (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
in_snd_device = vc_usecase->in_snd_device;
out_snd_device = vc_usecase->out_snd_device;
}
} else if (voice_extn_compress_voip_is_active(adev)) {
voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
- if ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
+ if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
(usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
- (voip_usecase->stream.out != adev->primary_output)) {
+ (voip_usecase->stream.out != adev->primary_output))) {
in_snd_device = voip_usecase->in_snd_device;
out_snd_device = voip_usecase->out_snd_device;
}
} else if (audio_extn_hfp_is_active(adev)) {
hfp_ucid = audio_extn_hfp_get_usecase();
hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
- if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
+ if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
in_snd_device = hfp_usecase->in_snd_device;
out_snd_device = hfp_usecase->out_snd_device;
}
@@ -723,7 +738,9 @@
* and enable both RX and TX devices though one of them is same as current
* device.
*/
- if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
+ if ((usecase->type == VOICE_CALL) &&
+ (usecase->in_snd_device != SND_DEVICE_NONE) &&
+ (usecase->out_snd_device != SND_DEVICE_NONE)) {
status = platform_switch_voice_call_device_pre(adev->platform);
}
@@ -742,10 +759,13 @@
* New device information should be sent to modem before enabling
* the devices to reduce in-call device switch time.
*/
- if (usecase->type == VOICE_CALL)
+ if ((usecase->type == VOICE_CALL) &&
+ (usecase->in_snd_device != SND_DEVICE_NONE) &&
+ (usecase->out_snd_device != SND_DEVICE_NONE)) {
status = platform_switch_voice_call_enable_device_config(adev->platform,
out_snd_device,
in_snd_device);
+ }
/* Enable new sound devices */
if (out_snd_device != SND_DEVICE_NONE) {
@@ -777,7 +797,6 @@
status = platform_switch_voice_call_usecase_route_post(adev->platform,
out_snd_device,
in_snd_device);
-
ALOGD("%s: done",__func__);
return status;
@@ -852,6 +871,12 @@
adev->active_input = in;
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+ if (!uc_info) {
+ ret = -ENOMEM;
+ goto error_config;
+ }
+
uc_info->id = in->usecase;
uc_info->type = PCM_CAPTURE;
uc_info->stream.in = in;
@@ -893,6 +918,11 @@
{
struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
+ if (!cmd) {
+ ALOGE("failed to allocate mem for command 0x%x", command);
+ return -ENOMEM;
+ }
+
ALOGVV("%s %d", __func__, command);
cmd->cmd = command;
@@ -1213,6 +1243,11 @@
struct audio_device *adev = out->dev;
int snd_card_status = get_snd_card_state(adev);
+ if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
+ ret = -EINVAL;
+ goto error_config;
+ }
+
ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
__func__, &out->stream, out->usecase, use_case_table[out->usecase],
out->devices);
@@ -1232,6 +1267,12 @@
}
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+ if (!uc_info) {
+ ret = -ENOMEM;
+ goto error_config;
+ }
+
uc_info->id = out->usecase;
uc_info->type = PCM_PLAYBACK;
uc_info->stream.out = out;
@@ -1475,6 +1516,29 @@
out->send_new_metadata = 1;
}
+ if (out->format == AUDIO_FORMAT_FLAC) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
+ out->send_new_metadata = 1;
+ }
+ }
+
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
if(ret >= 0)
is_meta_data_params = true;
@@ -1566,17 +1630,18 @@
select_devices(adev, out->usecase);
if ((adev->mode == AUDIO_MODE_IN_CALL) &&
- !voice_is_in_call(adev) &&
- (out == adev->primary_output)) {
+ !adev->voice.in_call &&
+ (out == adev->primary_output)) {
ret = voice_start_call(adev);
- } else if (voice_is_in_call(adev) &&
- (out == adev->primary_output)) {
+ } else if ((adev->mode == AUDIO_MODE_IN_CALL) &&
+ adev->voice.in_call &&
+ (out == adev->primary_output)) {
voice_update_devices_for_all_voice_usecases(adev);
}
}
if ((adev->mode == AUDIO_MODE_NORMAL) &&
- voice_is_in_call(adev) &&
+ adev->voice.in_call &&
(out == adev->primary_output)) {
ret = voice_stop_call(adev);
}
@@ -1611,6 +1676,12 @@
size_t i, j;
int ret;
bool first = true;
+
+ if (!query || !reply) {
+ ALOGE("out_get_parameters: failed to allocate mem for query or reply");
+ return NULL;
+ }
+
ALOGV("%s: enter: keys - %s", __func__, keys);
ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
if (ret >= 0) {
@@ -1796,9 +1867,9 @@
uint32_t *dsp_frames)
{
struct stream_out *out = (struct stream_out *)stream;
- *dsp_frames = 0;
if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
ssize_t ret = -EINVAL;
+ *dsp_frames = 0;
pthread_mutex_lock(&out->lock);
if (out->compr != NULL) {
ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
@@ -2116,6 +2187,12 @@
char *str;
char value[256];
struct str_parms *reply = str_parms_create();
+
+ if (!query || !reply) {
+ ALOGE("in_get_parameters: failed to create query or reply");
+ return NULL;
+ }
+
ALOGV("%s: enter: keys - %s", __func__, keys);
voice_extn_in_get_parameters(in, query, reply);
@@ -2301,6 +2378,7 @@
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
out->handle = handle;
+ out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
/* Init use case and pcm_config */
if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
@@ -2355,6 +2433,11 @@
out->compr_config.codec = (struct snd_codec *)
calloc(1, sizeof(struct snd_codec));
+ if (!out->compr_config.codec) {
+ ret = -ENOMEM;
+ goto error_open;
+ }
+
out->usecase = get_offload_usecase(adev);
if (config->offload_info.channel_mask)
out->channel_mask = config->offload_info.channel_mask;
@@ -2370,6 +2453,7 @@
out->stream.resume = out_resume;
out->stream.drain = out_drain;
out->stream.flush = out_flush;
+ out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
if (audio_extn_is_dolby_format(config->offload_info.format))
out->compr_config.codec->id =
@@ -2393,13 +2477,26 @@
out->compr_config.codec->ch_in =
popcount(config->channel_mask);
out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
- out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
+ out->bit_width = PCM_OUTPUT_BIT_WIDTH;
+ if (config->offload_info.format == AUDIO_FORMAT_AAC)
+ out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
- else if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
+ if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
+ if (out->bit_width == 24) {
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
+ }
+
+ if (out->bit_width == 24 && !platform_check_24_bit_support()) {
+ ALOGW("24 bit support is not enabled, using 16 bit backend");
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
+ }
+
+ out->compr_config.codec->options.flac_dec.sample_size = out->bit_width;
+
if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
out->non_blocking = 1;
@@ -2659,6 +2756,11 @@
char value[256] = {0};
int ret = 0;
+ if (!query || !reply) {
+ ALOGE("adev_get_parameters: failed to create query or reply");
+ return NULL;
+ }
+
ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
sizeof(value));
if (ret >=0) {
@@ -2778,6 +2880,12 @@
return -EINVAL;
in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
+
+ if (!in) {
+ ALOGE("failed to allocate input stream");
+ return -ENOMEM;
+ }
+
ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
devices, &in->stream);
@@ -2923,6 +3031,11 @@
adev = calloc(1, sizeof(struct audio_device));
+ if (!adev) {
+ pthread_mutex_unlock(&adev_init_lock);
+ return -ENOMEM;
+ }
+
pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
adev->device.common.tag = HARDWARE_DEVICE_TAG;
@@ -2956,6 +3069,8 @@
adev->bluetooth_nrec = true;
adev->acdb_settings = TTY_MODE_OFF;
/* adev->cur_hdmi_channels = 0; by calloc() */
+ adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
voice_init(adev);
list_init(&adev->usecase_list);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index e537377..f1ceedc 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -188,6 +188,7 @@
void *offload_cookie;
struct compr_gapless_mdata gapless_mdata;
int send_new_metadata;
+ unsigned int bit_width;
struct audio_device *dev;
};
@@ -272,6 +273,8 @@
bool bt_wb_speech_enabled;
int snd_card;
+ unsigned int cur_codec_backend_samplerate;
+ unsigned int cur_codec_backend_bit_width;
void *platform;
unsigned int offload_usecases_state;
void *visualizer_lib;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 4360967..6cf0f65 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <dlfcn.h>
+#include <sys/ioctl.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <cutils/str_parms.h>
@@ -116,6 +117,7 @@
bool fluence_in_audio_rec;
int fluence_type;
char fluence_cap[PROPERTY_VALUE_MAX];
+ int fluence_mode;
bool slowtalk;
/* Audio calibration related functions */
void *acdb_handle;
@@ -248,6 +250,11 @@
[SND_DEVICE_IN_HANDSET_STEREO_DMIC] = "handset-stereo-dmic-ef",
[SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = "speaker-stereo-dmic-ef",
[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = "vi-feedback",
+ [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE] = "voice-speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = "speaker-dmic-broadside",
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = "speaker-dmic-broadside",
};
/* ACDB IDs (audio DSP path configuration IDs) for each sound device */
@@ -321,6 +328,11 @@
[SND_DEVICE_IN_HANDSET_STEREO_DMIC] = 34,
[SND_DEVICE_IN_SPEAKER_STEREO_DMIC] = 35,
[SND_DEVICE_IN_CAPTURE_VI_FEEDBACK] = 102,
+ [SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE] = 12,
+ [SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE] = 12,
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE] = 119,
+ [SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE] = 121,
+ [SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = 120,
};
struct snd_device_index {
@@ -549,6 +561,14 @@
__func__, dlerror());
goto error;
}
+ csd->set_lch = (set_lch_t)dlsym(csd->csd_client, "csd_client_set_lch");
+ if (csd->set_lch == NULL) {
+ ALOGE("%s: dlsym error %s for csd_client_set_lch",
+ __func__, dlerror());
+ /* Ignore the error as this is not mandatory function for
+ * basic voice call to work.
+ */
+ }
csd->start_record = (start_record_t)dlsym(csd->csd_client,
"csd_client_start_record");
if (csd->start_record == NULL) {
@@ -661,6 +681,7 @@
my_data->fluence_in_voice_rec = false;
my_data->fluence_in_audio_rec = false;
my_data->fluence_type = FLUENCE_NONE;
+ my_data->fluence_mode = FLUENCE_ENDFIRE;
property_get("ro.qc.sdk.audio.fluencetype", my_data->fluence_cap, "");
if (!strncmp("fluencepro", my_data->fluence_cap, sizeof("fluencepro"))) {
@@ -691,6 +712,11 @@
if (!strncmp("true", value, sizeof("true"))) {
my_data->fluence_in_spkr_mode = true;
}
+
+ property_get("persist.audio.fluence.mode",value,"");
+ if (!strncmp("broadside", value, sizeof("broadside"))) {
+ my_data->fluence_mode = FLUENCE_BROADSIDE;
+ }
}
my_data->voice_feature_set = VOICE_FEATURE_SET_DEFAULT;
@@ -1415,7 +1441,10 @@
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_QMIC;
} else {
adev->acdb_settings |= DMIC_FLAG;
- snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_VOICE_SPEAKER_DMIC;
}
} else {
snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
@@ -1455,7 +1484,10 @@
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
my_data->fluence_in_spkr_mode) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS;
adev->acdb_settings |= DMIC_FLAG;
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC_NS;
@@ -1471,8 +1503,12 @@
set_echo_reference(adev->mixer, EC_REF_RX);
} else if (adev->active_input->enable_aec) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
+ my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_AEC;
adev->acdb_settings |= DMIC_FLAG;
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_AEC;
@@ -1488,8 +1524,12 @@
set_echo_reference(adev->mixer, EC_REF_RX);
} else if (adev->active_input->enable_ns) {
if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
- if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
- snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
+ if (my_data->fluence_type & FLUENCE_DUAL_MIC &&
+ my_data->fluence_in_spkr_mode) {
+ if (my_data->fluence_mode == FLUENCE_BROADSIDE)
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE;
+ else
+ snd_device = SND_DEVICE_IN_SPEAKER_DMIC_NS;
adev->acdb_settings |= DMIC_FLAG;
} else
snd_device = SND_DEVICE_IN_SPEAKER_MIC_NS;
@@ -1840,6 +1880,20 @@
return ret;
}
+int platform_update_lch(void *platform, struct voice_session *session,
+ enum voice_lch_mode lch_mode)
+{
+ int ret = 0;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if ((my_data->csd != NULL) && (my_data->csd->set_lch != NULL))
+ ret = my_data->csd->set_lch(session->vsid, lch_mode);
+ else
+ ret = pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode);
+
+ return ret;
+}
+
void platform_get_parameters(void *platform,
struct str_parms *query,
struct str_parms *reply)
@@ -2018,3 +2072,28 @@
return fragment_size;
}
+bool platform_check_24_bit_support() {
+ return false;
+}
+
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase) {
+ return false;
+}
+
+int platform_get_usecase_index(const char * usecase __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
+ int32_t pcm_id __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_snd_device_backend(snd_device_t snd_device __unused,
+ const char * backend __unused)
+{
+ return -ENOSYS;
+}
+
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index f12697c..3fc8fbf 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -19,6 +19,7 @@
#ifndef QCOM_AUDIO_PLATFORM_H
#define QCOM_AUDIO_PLATFORM_H
+#include <sound/voice_params.h>
enum {
FLUENCE_NONE,
@@ -26,6 +27,11 @@
FLUENCE_QUAD_MIC = 0x2,
};
+enum {
+ FLUENCE_ENDFIRE = 0x1,
+ FLUENCE_BROADSIDE = 0x2,
+};
+
/*
* Below are the devices for which is back end is same, SLIMBUS_0_RX.
* All these devices are handled by the internal HW codec. We can
@@ -120,6 +126,11 @@
SND_DEVICE_IN_HANDSET_STEREO_DMIC,
SND_DEVICE_IN_SPEAKER_STEREO_DMIC,
SND_DEVICE_IN_CAPTURE_VI_FEEDBACK,
+ SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE,
+ SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE,
SND_DEVICE_IN_END,
SND_DEVICE_MAX = SND_DEVICE_IN_END,
@@ -205,6 +216,7 @@
typedef int (*stop_voice_t)(uint32_t);
typedef int (*start_playback_t)(uint32_t);
typedef int (*stop_playback_t)(uint32_t);
+typedef int (*set_lch_t)(uint32_t, enum voice_lch_mode);
typedef int (*start_record_t)(uint32_t, int);
typedef int (*stop_record_t)(uint32_t);
/* CSD Client structure */
@@ -222,6 +234,7 @@
stop_voice_t stop_voice;
start_playback_t start_playback;
stop_playback_t stop_playback;
+ set_lch_t set_lch;
start_record_t start_record;
stop_record_t stop_record;
};
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 4102be7..d83a93f 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -914,6 +914,14 @@
return -ENOSYS;
}
+int platform_update_lch(void *platform __unused,
+ struct voice_session *session __unused,
+ enum voice_lch_mode lch_mode __unused)
+{
+ LOGE("%s: Not implemented", __func__);
+ return -ENOSYS;
+}
+
/* Delay in Us */
int64_t platform_render_latency(audio_usecase_t usecase)
{
@@ -942,3 +950,28 @@
{
return false;
}
+
+bool platform_check_24_bit_support() {
+ return false;
+}
+
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase) {
+ return false;
+}
+
+int platform_get_usecase_index(const char * usecase __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_usecase_pcm_id(audio_usecase_t usecase __unused, int32_t type __unused,
+ int32_t pcm_id __unused)
+{
+ return -ENOSYS;
+}
+
+int platform_set_snd_device_backend(snd_device_t snd_device __unused,
+ const char * backend __unused)
+{
+ return -ENOSYS;
+}
diff --git a/hal/msm8974/hw_info.c b/hal/msm8974/hw_info.c
index 7ac5ce7..f7d19f4 100644
--- a/hal/msm8974/hw_info.c
+++ b/hal/msm8974/hw_info.c
@@ -329,6 +329,11 @@
struct hardware_info *hw_info;
hw_info = malloc(sizeof(struct hardware_info));
+ if (!hw_info) {
+ ALOGE("failed to allocate mem for hardware info");
+ return NULL;
+ }
+
hw_info->snd_devices = NULL;
hw_info->num_snd_devices = 0;
strlcpy(hw_info->dev_extn, "", sizeof(hw_info->dev_extn));
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index f853506..88a09b8 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <dlfcn.h>
+#include <sys/ioctl.h>
#include <cutils/log.h>
#include <cutils/properties.h>
#include <cutils/str_parms.h>
@@ -32,7 +33,6 @@
#include "audio_extn.h"
#include "voice_extn.h"
#include "sound/compress_params.h"
-#include "mdm_detect.h"
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define MIXER_XML_PATH_AUXPCM "/system/etc/mixer_paths_auxpcm.xml"
@@ -43,6 +43,7 @@
#define LIB_ACDB_LOADER "libacdbloader.so"
#define AUDIO_DATA_BLOCK_MIXER_CTL "HDMI EDID"
+#define CVD_VERSION_MIXER_CTL "CVD Version"
#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
@@ -71,6 +72,8 @@
#define MAX_SAD_BLOCKS 10
#define SAD_BLOCK_SIZE 3
+#define MAX_CVD_VERSION_STRING_SIZE 100
+
/* EDID format ID for LPCM audio */
#define EDID_FORMAT_LPCM 1
@@ -108,7 +111,7 @@
/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
-typedef int (*acdb_init_t)(char *);
+typedef int (*acdb_init_t)(char *, char *);
typedef void (*acdb_send_audio_cal_t)(int, int, int , int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
@@ -142,7 +145,7 @@
struct csd_data *csd;
};
-static const int pcm_device_table[AUDIO_USECASE_MAX][2] = {
+static int pcm_device_table[AUDIO_USECASE_MAX][2] = {
[USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {DEEP_BUFFER_PCM_DEVICE,
DEEP_BUFFER_PCM_DEVICE},
[USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE,
@@ -372,7 +375,7 @@
[SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE] = 120,
};
-struct snd_device_index {
+struct name_to_index {
char name[100];
unsigned int index;
};
@@ -380,7 +383,7 @@
#define TO_NAME_INDEX(X) #X, X
/* Used to get index from parsed sting */
-struct snd_device_index snd_device_name_index[SND_DEVICE_MAX] = {
+static struct name_to_index snd_device_name_index[SND_DEVICE_MAX] = {
{TO_NAME_INDEX(SND_DEVICE_OUT_HANDSET)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER)},
{TO_NAME_INDEX(SND_DEVICE_OUT_SPEAKER_EXTERNAL_1)},
@@ -460,6 +463,26 @@
{TO_NAME_INDEX(SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE)},
};
+static char * backend_table[SND_DEVICE_MAX] = {0};
+
+static struct name_to_index usecase_name_index[AUDIO_USECASE_MAX] = {
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_DEEP_BUFFER)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_LOW_LATENCY)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_MULTI_CH)},
+ {TO_NAME_INDEX(USECASE_AUDIO_PLAYBACK_OFFLOAD)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD)},
+ {TO_NAME_INDEX(USECASE_AUDIO_RECORD_LOW_LATENCY)},
+ {TO_NAME_INDEX(USECASE_VOICE_CALL)},
+ {TO_NAME_INDEX(USECASE_VOICE2_CALL)},
+ {TO_NAME_INDEX(USECASE_VOLTE_CALL)},
+ {TO_NAME_INDEX(USECASE_QCHAT_CALL)},
+ {TO_NAME_INDEX(USECASE_VOWLAN_CALL)},
+ {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK)},
+ {TO_NAME_INDEX(USECASE_INCALL_REC_DOWNLINK)},
+ {TO_NAME_INDEX(USECASE_INCALL_REC_UPLINK_AND_DOWNLINK)},
+ {TO_NAME_INDEX(USECASE_AUDIO_HFP_SCO)},
+};
+
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
@@ -477,6 +500,11 @@
{
struct csd_data *csd = calloc(1, sizeof(struct csd_data));
+ if (!csd) {
+ ALOGE("failed to allocate csd_data mem");
+ return NULL;
+ }
+
csd->csd_client = dlopen(LIB_CSD_CLIENT, RTLD_NOW);
if (csd->csd_client == NULL) {
ALOGE("%s: DLOPEN failed for %s", __func__, LIB_CSD_CLIENT);
@@ -561,6 +589,14 @@
__func__, dlerror());
goto error;
}
+ csd->set_lch = (set_lch_t)dlsym(csd->csd_client, "csd_client_set_lch");
+ if (csd->set_lch == NULL) {
+ ALOGE("%s: dlsym error %s for csd_client_set_lch",
+ __func__, dlerror());
+ /* Ignore the error as this is not mandatory function for
+ * basic voice call to work.
+ */
+ }
csd->start_record = (start_record_t)dlsym(csd->csd_client,
"csd_client_start_record");
if (csd->start_record == NULL) {
@@ -613,26 +649,6 @@
}
}
-static void platform_csd_init(struct platform_data *plat_data)
-{
- struct dev_info mdm_detect_info;
- int ret = 0;
-
- /* Call ESOC API to get the number of modems.
- * If the number of modems is not zero, load CSD Client specific
- * symbols. Voice call is handled by MDM and apps processor talks to
- * MDM through CSD Client
- */
- ret = get_system_info(&mdm_detect_info);
- if (ret > 0) {
- ALOGE("%s: Failed to get system info, ret %d", __func__, ret);
- }
- ALOGD("%s: num_modems %d\n", __func__, mdm_detect_info.num_modems);
-
- if (mdm_detect_info.num_modems > 0)
- plat_data->csd = open_csd_client(plat_data->is_i2s_ext_modem);
-}
-
static bool platform_is_i2s_ext_modem(const char *snd_card_name,
struct platform_data *plat_data)
{
@@ -649,15 +665,74 @@
return plat_data->is_i2s_ext_modem;
}
+static void set_platform_defaults(struct platform_data * my_data)
+{
+ int32_t dev;
+ for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
+ backend_table[dev] = NULL;
+ }
+
+ // TBD - do these go to the platform-info.xml file.
+ // will help in avoiding strdups here
+ backend_table[SND_DEVICE_IN_BT_SCO_MIC] = strdup("bt-sco");
+ backend_table[SND_DEVICE_IN_BT_SCO_MIC_WB] = strdup("bt-sco-wb");
+ backend_table[SND_DEVICE_OUT_BT_SCO] = strdup("bt-sco");
+ backend_table[SND_DEVICE_OUT_BT_SCO_WB] = strdup("bt-sco-wb");
+ backend_table[SND_DEVICE_OUT_HDMI] = strdup("hdmi");
+ backend_table[SND_DEVICE_OUT_SPEAKER_AND_HDMI] = strdup("speaker-and-hdmi");
+ backend_table[SND_DEVICE_OUT_AFE_PROXY] = strdup("afe-proxy");
+ backend_table[SND_DEVICE_OUT_USB_HEADSET] = strdup("usb-headphones");
+ backend_table[SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET] =
+ strdup("speaker-and-usb-headphones");
+ backend_table[SND_DEVICE_IN_USB_HEADSET_MIC] = strdup("usb-headset-mic");
+ backend_table[SND_DEVICE_IN_CAPTURE_FM] = strdup("capture-fm");
+ backend_table[SND_DEVICE_OUT_TRANSMISSION_FM] = strdup("transmission-fm");
+}
+
+void get_cvd_version(char *cvd_version, struct audio_device *adev)
+{
+ struct mixer_ctl *ctl;
+ int count;
+ int ret = 0;
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, CVD_VERSION_MIXER_CTL);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, CVD_VERSION_MIXER_CTL);
+ goto done;
+ }
+ mixer_ctl_update(ctl);
+
+ count = mixer_ctl_get_num_values(ctl);
+ if (count > MAX_CVD_VERSION_STRING_SIZE)
+ count = MAX_CVD_VERSION_STRING_SIZE;
+
+ ret = mixer_ctl_get_array(ctl, cvd_version, count);
+ if (ret != 0) {
+ ALOGE("%s: ERROR! mixer_ctl_get_array() failed to get CVD Version", __func__);
+ goto done;
+ }
+
+done:
+ return;
+}
+
void *platform_init(struct audio_device *adev)
{
+ char platform[PROPERTY_VALUE_MAX];
+ char baseband[PROPERTY_VALUE_MAX];
char value[PROPERTY_VALUE_MAX];
struct platform_data *my_data = NULL;
int retry_num = 0, snd_card_num = 0;
const char *snd_card_name;
+ char *cvd_version = NULL;
my_data = calloc(1, sizeof(struct platform_data));
+ if (!my_data) {
+ ALOGE("failed to allocate platform data");
+ return NULL;
+ }
+
while (snd_card_num < MAX_SND_CARD) {
adev->mixer = mixer_open(snd_card_num);
@@ -798,20 +873,44 @@
my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
"acdb_loader_init_v2");
- if (my_data->acdb_init == NULL)
+ if (my_data->acdb_init == NULL) {
ALOGE("%s: dlsym error %s for acdb_loader_init_v2", __func__, dlerror());
+ goto acdb_init_fail;
+ }
+
+ cvd_version = calloc(1, MAX_CVD_VERSION_STRING_SIZE);
+ if (!cvd_version)
+ ALOGE("failed to allocate cvd_version");
else
- my_data->acdb_init(snd_card_name);
+ get_cvd_version(cvd_version, adev);
+
+ my_data->acdb_init(snd_card_name, cvd_version);
+ if (cvd_version)
+ free(cvd_version);
}
+acdb_init_fail:
+
+ set_platform_defaults(my_data);
+
/* Initialize ACDB ID's */
if (my_data->is_i2s_ext_modem)
platform_info_init(PLATFORM_INFO_XML_PATH_I2S);
else
platform_info_init(PLATFORM_INFO_XML_PATH);
- /* load csd client */
- platform_csd_init(my_data);
+ /* If platform is apq8084 and baseband is MDM, load CSD Client specific
+ * symbols. Voice call is handled by MDM and apps processor talks to
+ * MDM through CSD Client
+ */
+ property_get("ro.board.platform", platform, "");
+ property_get("ro.baseband", baseband, "");
+ if (!strncmp("apq8084", platform, sizeof("apq8084")) &&
+ !strncmp("mdm", baseband, (sizeof("mdm")-1))) {
+ my_data->csd = open_csd_client(my_data->is_i2s_ext_modem);
+ } else {
+ my_data->csd = NULL;
+ }
/* init usb */
audio_extn_usb_init(adev);
@@ -824,6 +923,9 @@
audio_extn_dolby_set_license(adev);
+ /* init audio device arbitration */
+ audio_extn_dev_arbi_init();
+
return my_data;
}
@@ -834,6 +936,17 @@
hw_info_deinit(my_data->hw_info);
close_csd_client(my_data->csd);
+ int32_t dev;
+ for (dev = 0; dev < SND_DEVICE_MAX; dev++) {
+ if (backend_table[dev]) {
+ free(backend_table[dev]);
+ backend_table[dev]= NULL;
+ }
+ }
+
+ /* deinit audio device arbitration */
+ audio_extn_dev_arbi_deinit();
+
free(platform);
/* deinit usb */
audio_extn_usb_deinit();
@@ -865,37 +978,16 @@
void platform_add_backend_name(char *mixer_path, snd_device_t snd_device)
{
- if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
- strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB)
- strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
- else if(snd_device == SND_DEVICE_OUT_BT_SCO)
- strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
- else if(snd_device == SND_DEVICE_OUT_BT_SCO_WB)
- strlcat(mixer_path, " bt-sco-wb", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_OUT_HDMI)
- strlcat(mixer_path, " hdmi", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_HDMI)
- strcat(mixer_path, " speaker-and-hdmi");
- else if (snd_device == SND_DEVICE_OUT_AFE_PROXY)
- strlcat(mixer_path, " afe-proxy", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_OUT_USB_HEADSET)
- strlcat(mixer_path, " usb-headphones", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET)
- strlcat(mixer_path, " speaker-and-usb-headphones",
- MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_IN_USB_HEADSET_MIC)
- strlcat(mixer_path, " usb-headset-mic", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_IN_CAPTURE_FM)
- strlcat(mixer_path, " capture-fm", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_OUT_TRANSMISSION_FM)
- strlcat(mixer_path, " transmission-fm", MIXER_PATH_MAX_LENGTH);
- else if (snd_device == SND_DEVICE_OUT_VOICE_SPEAKER &&
- audio_extn_spkr_prot_is_enabled() ) {
- char platform[PROPERTY_VALUE_MAX];
- property_get("ro.board.platform", platform, "");
- if (!strncmp("apq8084", platform, sizeof("apq8084")))
- strlcat(mixer_path, " speaker-protected", MIXER_PATH_MAX_LENGTH);
+ if ((snd_device < SND_DEVICE_MIN) || (snd_device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d", __func__, snd_device);
+ return;
+ }
+
+ const char * suffix = backend_table[snd_device];
+
+ if (suffix != NULL) {
+ strlcat(mixer_path, " ", MIXER_PATH_MAX_LENGTH);
+ strlcat(mixer_path, suffix, MIXER_PATH_MAX_LENGTH);
}
}
@@ -909,25 +1001,36 @@
return device_id;
}
-int platform_get_snd_device_index(char *snd_device_index_name)
+static int find_index(struct name_to_index * table, int32_t len, const char * name)
{
int ret = 0;
- int i;
+ int32_t i;
- if (snd_device_index_name == NULL) {
- ALOGE("%s: snd_device_index_name is NULL", __func__);
+ if (table == NULL) {
+ ALOGE("%s: table is NULL", __func__);
ret = -ENODEV;
goto done;
}
- for (i=0; i < SND_DEVICE_MAX; i++) {
- if(strcmp(snd_device_name_index[i].name, snd_device_index_name) == 0) {
- ret = snd_device_name_index[i].index;
+ if (name == NULL) {
+ ALOGE("null key");
+ ret = -ENODEV;
+ goto done;
+ }
+
+ for (i=0; i < len; i++) {
+ const char* tn = table[i].name;
+ int32_t len = strlen(tn);
+ if (strncmp(tn, name, len) == 0) {
+ if (strlen(name) != len) {
+ continue; // substring
+ }
+ ret = table[i].index;
goto done;
}
}
- ALOGE("%s: Could not find index for snd_device_index_name = %s",
- __func__, snd_device_index_name);
+ ALOGE("%s: Could not find index for name = %s",
+ __func__, name);
ret = -ENODEV;
done:
return ret;
@@ -990,6 +1093,16 @@
return ret;
}
+int platform_get_snd_device_index(char *device_name)
+{
+ return find_index(snd_device_name_index, SND_DEVICE_MAX, device_name);
+}
+
+int platform_get_usecase_index(const char *usecase_name)
+{
+ return find_index(usecase_name_index, AUDIO_USECASE_MAX, usecase_name);
+}
+
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id)
{
int ret = 0;
@@ -1031,7 +1144,7 @@
struct platform_data *my_data = (struct platform_data *)platform;
int acdb_dev_id, acdb_dev_type;
- acdb_dev_id = acdb_device_table[snd_device];
+ acdb_dev_id = acdb_device_table[audio_extn_get_spkr_prot_snd_device(snd_device)];
if (acdb_dev_id < 0) {
ALOGE("%s: Could not find acdb id for device(%d)",
__func__, snd_device);
@@ -2035,6 +2148,20 @@
return ret;
}
+int platform_update_lch(void *platform, struct voice_session *session,
+ enum voice_lch_mode lch_mode)
+{
+ int ret = 0;
+ struct platform_data *my_data = (struct platform_data *)platform;
+
+ if ((my_data->csd != NULL) && (my_data->csd->set_lch != NULL))
+ ret = my_data->csd->set_lch(session->vsid, lch_mode);
+ else
+ ret = pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode);
+
+ return ret;
+}
+
void platform_get_parameters(void *platform,
struct str_parms *query,
struct str_parms *reply)
@@ -2121,6 +2248,14 @@
fragment_size = atoi(value) * 1024;
}
+ // For FLAC use max size since it is loss less, and has sampling rates
+ // upto 192kHZ
+ if (info != NULL && !info->has_video &&
+ info->format == AUDIO_FORMAT_FLAC) {
+ fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ ALOGV("FLAC fragment size %d", fragment_size);
+ }
+
if (info != NULL && info->has_video && info->is_streaming) {
fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
ALOGV("%s: offload fragment size reduced for AV streaming to %d",
@@ -2180,3 +2315,227 @@
return fragment_size;
}
+bool platform_check_24_bit_support() {
+
+ char value[PROPERTY_VALUE_MAX] = {0};
+ property_get("audio.offload.24bit.enable", value, "0");
+ if (atoi(value)) {
+ ALOGW("Property audio.offload.24bit.enable is set");
+ return true;
+ }
+ return false;
+}
+
+int platform_set_codec_backend_cfg(struct audio_device* adev,
+ unsigned int bit_width, unsigned int sample_rate)
+{
+ ALOGV("platform_set_codec_backend_cfg bw %d, sr %d", bit_width, sample_rate);
+
+ int ret = 0;
+ if (bit_width != adev->cur_codec_backend_bit_width) {
+ const char * mixer_ctl_name = "SLIM_0_RX Format";
+ struct mixer_ctl *ctl;
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer command - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ if (bit_width == 24) {
+ mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+ } else {
+ mixer_ctl_set_enum_by_string(ctl, "S16_LE");
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+ adev->cur_codec_backend_bit_width = bit_width;
+ ALOGE("Backend bit width is set to %d ", bit_width);
+ }
+
+ if ((adev->cur_codec_backend_bit_width == CODEC_BACKEND_DEFAULT_BIT_WIDTH &&
+ adev->cur_codec_backend_samplerate != CODEC_BACKEND_DEFAULT_SAMPLE_RATE) ||
+ (adev->cur_codec_backend_samplerate < sample_rate)) {
+
+ char *rate_str = NULL;
+ const char * mixer_ctl_name = "SLIM_0_RX SampleRate";
+ struct mixer_ctl *ctl;
+
+ switch (sample_rate) {
+ case 8000:
+ rate_str = "KHZ_8";
+ break;
+ case 11025:
+ rate_str = "KHZ_11_025";
+ break;
+ case 16000:
+ rate_str = "KHZ_16";
+ break;
+ case 22050:
+ rate_str = "KHZ_22_05";
+ break;
+ case 32000:
+ rate_str = "KHZ_32";
+ break;
+ case 44100:
+ rate_str = "KHZ_44_1";
+ break;
+ case 48000:
+ rate_str = "KHZ_48";
+ break;
+ case 64000:
+ rate_str = "KHZ_64";
+ break;
+ case 88200:
+ rate_str = "KHZ_88_2";
+ break;
+ case 96000:
+ rate_str = "KHZ_96";
+ break;
+ case 176400:
+ rate_str = "KHZ_176_4";
+ break;
+ case 192000:
+ rate_str = "KHZ_192";
+ break;
+ default:
+ rate_str = "KHZ_48";
+ break;
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if(!ctl) {
+ ALOGE("%s: Could not get ctl for mixer command - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ ALOGV("Set sample rate as rate_str = %s", rate_str);
+ mixer_ctl_set_enum_by_string(ctl, rate_str);
+ adev->cur_codec_backend_samplerate = sample_rate;
+ }
+
+ return ret;
+}
+
+bool platform_check_codec_backend_cfg(struct audio_device* adev,
+ struct audio_usecase* usecase,
+ unsigned int* new_bit_width,
+ unsigned int* new_sample_rate)
+{
+ bool backend_change = false;
+ struct listnode *node;
+ struct stream_out *out = NULL;
+
+ // For voice calls use default configuration
+ // force routing is not required here, caller will do it anyway
+ if (adev->mode == AUDIO_MODE_IN_CALL ||
+ adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+ ALOGW("%s:Use default bw and sr for voice/voip calls ",__func__);
+ *new_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ *new_sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ backend_change = true;
+ }
+
+
+ if (!backend_change) {
+ // go through all the offload usecases, and
+ // find the max bit width and samplerate
+ list_for_each(node, &adev->usecase_list) {
+ struct audio_usecase *curr_usecase;
+ curr_usecase = node_to_item(node, struct audio_usecase, list);
+ if (curr_usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ struct stream_out *out =
+ (struct stream_out*) curr_usecase->stream.out;
+ if (out != NULL ) {
+ ALOGV("Offload playback running bw %d sr %d",
+ out->bit_width, out->sample_rate);
+ if (*new_bit_width < out->bit_width) {
+ *new_bit_width = out->bit_width;
+ }
+ if (*new_sample_rate < out->sample_rate) {
+ *new_sample_rate = out->sample_rate;
+ }
+ }
+ }
+ }
+ }
+
+ // Force routing if the expected bitwdith or samplerate
+ // is not same as current backend comfiguration
+ if ((*new_bit_width != adev->cur_codec_backend_bit_width) ||
+ (*new_sample_rate != adev->cur_codec_backend_samplerate)) {
+ backend_change = true;
+ ALOGW("Codec backend needs to be updated");
+ }
+
+ return backend_change;
+}
+
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase)
+{
+ // check if 24bit configuration is enabled first
+ if (!platform_check_24_bit_support()) {
+ ALOGW("24bit not enable, no need to check for backend change");
+ return false;
+ }
+
+ ALOGV("platform_check_and_set_codec_backend_cfg usecase = %d",usecase->id );
+
+ unsigned int new_bit_width, old_bit_width;
+ unsigned int new_sample_rate, old_sample_rate;
+
+ new_bit_width = old_bit_width = adev->cur_codec_backend_bit_width;
+ new_sample_rate = old_sample_rate = adev->cur_codec_backend_samplerate;
+
+ ALOGW("Codec backend bitwidth %d, samplerate %d", old_bit_width, old_sample_rate);
+ if (platform_check_codec_backend_cfg(adev, usecase,
+ &new_bit_width, &new_sample_rate)) {
+ platform_set_codec_backend_cfg(adev, new_bit_width, new_sample_rate);
+ }
+
+ if (old_bit_width != adev->cur_codec_backend_bit_width ||
+ old_sample_rate != adev->cur_codec_backend_samplerate) {
+ ALOGW("New codec backend bit width %d, sample rate %d",
+ adev->cur_codec_backend_bit_width, adev->cur_codec_backend_samplerate);
+ return true;
+ }
+
+ return false;
+}
+
+int platform_set_snd_device_backend(snd_device_t device, const char *backend)
+{
+ int ret = 0;
+
+ if ((device < SND_DEVICE_MIN) || (device >= SND_DEVICE_MAX)) {
+ ALOGE("%s: Invalid snd_device = %d",
+ __func__, device);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (backend_table[device]) {
+ free(backend_table[device]);
+ }
+ backend_table[device] = strdup(backend);
+done:
+ return ret;
+}
+
+int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id)
+{
+ int ret = 0;
+ if ((usecase <= USECASE_INVALID) || (usecase >= AUDIO_USECASE_MAX)) {
+ ALOGE("%s: invalid usecase case idx %d", __func__, usecase);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if ((type != 0) && (type != 1)) {
+ ALOGE("%s: invalid usecase type", __func__);
+ ret = -EINVAL;
+ }
+ pcm_device_table[usecase][type] = pcm_id;
+done:
+ return ret;
+}
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 956e395..19f37c7 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -19,6 +19,7 @@
#ifndef QCOM_AUDIO_PLATFORM_H
#define QCOM_AUDIO_PLATFORM_H
+#include <sound/voice_params.h>
enum {
FLUENCE_NONE,
@@ -190,13 +191,15 @@
#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 14
#elif PLATFORM_MSM8x26
#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 16
+#elif PLATFORM_APQ8084
+#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 34
#else
#define INCALL_MUSIC_UPLINK2_PCM_DEVICE 35
#endif
#define SPKR_PROT_CALIB_RX_PCM_DEVICE 5
#ifdef PLATFORM_APQ8084
-#define SPKR_PROT_CALIB_TX_PCM_DEVICE 33
+#define SPKR_PROT_CALIB_TX_PCM_DEVICE 35
#else
#define SPKR_PROT_CALIB_TX_PCM_DEVICE 25
#endif
@@ -302,6 +305,7 @@
typedef int (*stop_voice_t)(uint32_t);
typedef int (*start_playback_t)(uint32_t);
typedef int (*stop_playback_t)(uint32_t);
+typedef int (*set_lch_t)(uint32_t, enum voice_lch_mode);
typedef int (*start_record_t)(uint32_t, int);
typedef int (*stop_record_t)(uint32_t);
typedef int (*get_sample_rate_t)(uint32_t *);
@@ -320,6 +324,7 @@
stop_voice_t stop_voice;
start_playback_t start_playback;
stop_playback_t stop_playback;
+ set_lch_t set_lch;
start_record_t start_record;
stop_record_t stop_record;
get_sample_rate_t get_sample_rate;
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 66b090e..85b3c4f 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -19,6 +19,10 @@
#ifndef AUDIO_PLATFORM_API_H
#define AUDIO_PLATFORM_API_H
+#include <sound/voice_params.h>
+
+#define CODEC_BACKEND_DEFAULT_BIT_WIDTH 16
+#define CODEC_BACKEND_DEFAULT_SAMPLE_RATE 48000
void *platform_init(struct audio_device *adev);
void platform_deinit(void *platform);
@@ -63,6 +67,8 @@
int platform_stop_incall_recording_usecase(void *platform);
int platform_start_incall_music_usecase(void *platform);
int platform_stop_incall_music_usecase(void *platform);
+int platform_update_lch(void *platform, struct voice_session *session,
+ enum voice_lch_mode lch_mode);
/* returns the latency for a usecase in Us */
int64_t platform_render_latency(audio_usecase_t usecase);
int platform_update_usecase_from_source(int source, audio_usecase_t usecase);
@@ -70,6 +76,8 @@
bool platform_listen_device_needs_event(snd_device_t snd_device);
bool platform_listen_usecase_needs_event(audio_usecase_t uc_id);
+int platform_set_snd_device_backend(snd_device_t snd_device, const char * backend);
+
/* From platform_info_parser.c */
int platform_info_init(const char *filename);
@@ -77,4 +85,9 @@
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase);
+bool platform_check_24_bit_support();
+int platform_get_usecase_index(const char * usecase);
+int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
+
#endif // AUDIO_PLATFORM_API_H
diff --git a/hal/platform_info.c b/hal/platform_info.c
index 85a05eb..615b9f3 100644
--- a/hal/platform_info.c
+++ b/hal/platform_info.c
@@ -40,7 +40,137 @@
#define BUF_SIZE 1024
-static void process_device(const XML_Char **attr)
+typedef enum {
+ ROOT,
+ ACDB,
+ PCM_ID,
+ BACKEND_NAME,
+} section_t;
+
+typedef void (* section_process_fn)(const XML_Char **attr);
+
+static void process_acdb_id(const XML_Char **attr);
+static void process_pcm_id(const XML_Char **attr);
+static void process_backend_name(const XML_Char **attr);
+static void process_root(const XML_Char **attr);
+
+static section_process_fn section_table[] = {
+ [ROOT] = process_root,
+ [ACDB] = process_acdb_id,
+ [PCM_ID] = process_pcm_id,
+ [BACKEND_NAME] = process_backend_name,
+};
+
+static section_t section;
+
+/*
+ * <audio_platform_info>
+ * <acdb_ids>
+ * <device name="???" acdb_id="???"/>
+ * ...
+ * ...
+ * </acdb_ids>
+ * <backend_names>
+ * <device name="???" backend="???"/>
+ * ...
+ * ...
+ * </backend_names>
+ * <pcm_ids>
+ * <usecase name="???" type="in/out" id="???"/>
+ * ...
+ * ...
+ * </pcm_ids>
+ * </audio_platform_info>
+ */
+
+static void process_root(const XML_Char **attr __unused)
+{
+}
+
+/* mapping from usecase to pcm dev id */
+static void process_pcm_id(const XML_Char **attr)
+{
+ int index;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
+ goto done;
+ }
+
+ index = platform_get_usecase_index((char *)attr[1]);
+ if (index < 0) {
+ ALOGE("%s: usecase %s not found!",
+ __func__, attr[1]);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "type") != 0) {
+ ALOGE("%s: usecase type not mentioned", __func__);
+ goto done;
+ }
+
+ int type = -1;
+
+ if (!strcasecmp((char *)attr[3], "in")) {
+ type = 1;
+ } else if (!strcasecmp((char *)attr[3], "out")) {
+ type = 0;
+ } else {
+ ALOGE("%s: type must be IN or OUT", __func__);
+ goto done;
+ }
+
+ if (strcmp(attr[4], "id") != 0) {
+ ALOGE("%s: usecase id not mentioned", __func__);
+ goto done;
+ }
+
+ int id = atoi((char *)attr[5]);
+
+ if (platform_set_usecase_pcm_id(index, type, id) < 0) {
+ ALOGE("%s: usecase %s type %d id %d was not set!",
+ __func__, attr[1], type, id);
+ goto done;
+ }
+
+done:
+ return;
+}
+
+/* backend to be used for a device */
+static void process_backend_name(const XML_Char **attr)
+{
+ int index;
+
+ if (strcmp(attr[0], "name") != 0) {
+ ALOGE("%s: 'name' not found, no ACDB ID set!", __func__);
+ goto done;
+ }
+
+ index = platform_get_snd_device_index((char *)attr[1]);
+ if (index < 0) {
+ ALOGE("%s: Device %s not found, no ACDB ID set!",
+ __func__, attr[1]);
+ goto done;
+ }
+
+ if (strcmp(attr[2], "backend") != 0) {
+ ALOGE("%s: Device %s has no backend set!",
+ __func__, attr[1]);
+ goto done;
+ }
+
+ if (platform_set_snd_device_backend(index, attr[3]) < 0) {
+ ALOGE("%s: Device %s backend %s was not set!",
+ __func__, attr[1], attr[3]);
+ goto done;
+ }
+
+done:
+ return;
+}
+
+static void process_acdb_id(const XML_Char **attr)
{
int index;
@@ -62,8 +192,8 @@
goto done;
}
- if(platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
- ALOGE("%s: Device %s in platform info xml ACDB ID %d was not set!",
+ if (platform_set_snd_device_acdb_id(index, atoi((char *)attr[3])) < 0) {
+ ALOGE("%s: Device %s, ACDB ID %d was not set!",
__func__, attr[1], atoi((char *)attr[3]));
goto done;
}
@@ -72,22 +202,50 @@
return;
}
-static void start_tag(void *userdata, const XML_Char *tag_name,
+static void start_tag(void *userdata __unused, const XML_Char *tag_name,
const XML_Char **attr)
{
const XML_Char *attr_name = NULL;
const XML_Char *attr_value = NULL;
unsigned int i;
- if (strcmp(tag_name, "device") == 0)
- process_device(attr);
+ if (strcmp(tag_name, "acdb_ids") == 0) {
+ section = ACDB;
+ } else if (strcmp(tag_name, "pcm_ids") == 0) {
+ section = PCM_ID;
+ } else if (strcmp(tag_name, "backend_names") == 0) {
+ section = BACKEND_NAME;
+ } else if (strcmp(tag_name, "device") == 0) {
+ if ((section != ACDB) && (section != BACKEND_NAME)) {
+ ALOGE("device tag only supported for acdb/backend names");
+ return;
+ }
+
+ /* call into process function for the current section */
+ section_process_fn fn = section_table[section];
+ fn(attr);
+ } else if (strcmp(tag_name, "usecase") == 0) {
+ if (section != PCM_ID) {
+ ALOGE("usecase tag only supported with PCM_ID section");
+ return;
+ }
+
+ section_process_fn fn = section_table[PCM_ID];
+ fn(attr);
+ }
return;
}
-static void end_tag(void *userdata, const XML_Char *tag_name)
+static void end_tag(void *userdata __unused, const XML_Char *tag_name)
{
-
+ if (strcmp(tag_name, "acdb_ids") == 0) {
+ section = ROOT;
+ } else if (strcmp(tag_name, "pcm_ids") == 0) {
+ section = ROOT;
+ } else if (strcmp(tag_name, "backend_names") == 0) {
+ section = ROOT;
+ }
}
int platform_info_init(const char *filename)
@@ -99,6 +257,8 @@
void *buf;
file = fopen(filename, "r");
+ section = ROOT;
+
if (!file) {
ALOGD("%s: Failed to open %s, using defaults.",
__func__, filename);
diff --git a/hal/voice.c b/hal/voice.c
index 449c0c2..a5826e6 100644
--- a/hal/voice.c
+++ b/hal/voice.c
@@ -66,6 +66,11 @@
ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);
session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
+ if (!session) {
+ ALOGE("stop_call: couldn't find voice session");
+ return -EINVAL;
+ }
+
session->state.current = CALL_INACTIVE;
if (adev->mode == AUDIO_MODE_NORMAL)
adev->voice.is_in_call = false;
@@ -115,7 +120,17 @@
ALOGD("%s: enter usecase:%s", __func__, use_case_table[usecase_id]);
session = (struct voice_session *)voice_get_session_from_use_case(adev, usecase_id);
+ if (!session) {
+ ALOGE("start_call: couldn't find voice session");
+ return -EINVAL;
+ }
+
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+ if (!uc_info) {
+ ALOGE("start_call: couldn't allocate mem for audio_usecase");
+ return -ENOMEM;
+ }
+
uc_info->id = usecase_id;
uc_info->type = VOICE_CALL;
uc_info->stream.out = adev->primary_output;
@@ -177,26 +192,27 @@
}
session->state.current = CALL_ACTIVE;
- return 0;
+ goto done;
error_start_voice:
stop_call(adev, usecase_id);
+done:
ALOGD("%s: exit: status(%d)", __func__, ret);
return ret;
}
-bool voice_is_in_call(struct audio_device *adev)
+bool voice_is_call_state_active(struct audio_device *adev)
{
- bool in_call = false;
+ bool call_state = false;
int ret = 0;
- ret = voice_extn_is_in_call(adev, &in_call);
+ ret = voice_extn_is_call_state_active(adev, &call_state);
if (ret == -ENOSYS) {
- in_call = (adev->voice.session[VOICE_SESS_IDX].state.current == CALL_ACTIVE) ? true : false;
+ call_state = (adev->voice.session[VOICE_SESS_IDX].state.current == CALL_ACTIVE) ? true : false;
}
- return in_call;
+ return call_state;
}
bool voice_is_in_call_rec_stream(struct stream_in *in)
@@ -232,7 +248,7 @@
int usecase_id;
int rec_mode = INCALL_REC_NONE;
- if (voice_is_in_call(adev)) {
+ if (voice_is_call_state_active(adev)) {
switch (in->source) {
case AUDIO_SOURCE_VOICE_UPLINK:
if (audio_extn_compr_cap_enabled() &&
@@ -358,6 +374,7 @@
if (ret == -ENOSYS) {
ret = start_call(adev, USECASE_VOICE_CALL);
}
+ adev->voice.in_call = true;
return ret;
}
@@ -366,6 +383,7 @@
{
int ret = 0;
+ adev->voice.in_call = false;
ret = voice_extn_stop_call(adev);
if (ret == -ENOSYS) {
ret = stop_call(adev, USECASE_VOICE_CALL);
@@ -392,12 +410,20 @@
ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);
ret = voice_extn_set_parameters(adev, parms);
- if (ret != 0)
- goto done;
+ if (ret != 0) {
+ if (ret == -ENOSYS)
+ ret = 0;
+ else
+ goto done;
+ }
ret = voice_extn_compress_voip_set_parameters(adev, parms);
- if (ret != 0)
- goto done;
+ if (ret != 0) {
+ if (ret == -ENOSYS)
+ ret = 0;
+ else
+ goto done;
+ }
err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_TTY_MODE, value, sizeof(value));
if (err >= 0) {
@@ -419,7 +445,7 @@
if (tty_mode != adev->voice.tty_mode) {
adev->voice.tty_mode = tty_mode;
adev->acdb_settings = (adev->acdb_settings & TTY_MODE_CLEAR) | tty_mode;
- if (voice_is_in_call(adev))
+ if (voice_is_call_state_active(adev))
voice_update_devices_for_all_voice_usecases(adev);
}
}
@@ -432,7 +458,7 @@
platform_start_incall_music_usecase(adev->platform);
else
platform_stop_incall_music_usecase(adev->platform);
- }
+ }
done:
ALOGV("%s: exit with code(%d)", __func__, ret);
@@ -448,7 +474,7 @@
adev->voice.tty_mode = TTY_MODE_OFF;
adev->voice.volume = 1.0f;
adev->voice.mic_mute = false;
- adev->voice.voice_device_set = false;
+ adev->voice.in_call = false;
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
adev->voice.session[i].pcm_rx = NULL;
adev->voice.session[i].pcm_tx = NULL;
diff --git a/hal/voice.h b/hal/voice.h
index 4df2d6a..5d1ae40 100644
--- a/hal/voice.h
+++ b/hal/voice.h
@@ -60,8 +60,8 @@
int tty_mode;
bool mic_mute;
float volume;
- bool voice_device_set;
bool is_in_call;
+ bool in_call;
};
enum {
@@ -77,8 +77,8 @@
void voice_get_parameters(struct audio_device *adev, struct str_parms *query,
struct str_parms *reply);
void voice_init(struct audio_device *adev);
-bool voice_is_in_call(struct audio_device *adev);
bool voice_is_in_call_rec_stream(struct stream_in *in);
+bool voice_is_call_state_active(struct audio_device *adev);
int voice_set_mic_mute(struct audio_device *dev, bool state);
bool voice_get_mic_mute(struct audio_device *dev);
int voice_set_volume(struct audio_device *adev, float volume);
diff --git a/hal/voice_extn/compress_voip.c b/hal/voice_extn/compress_voip.c
index 841f866..46aab7d 100644
--- a/hal/voice_extn/compress_voip.c
+++ b/hal/voice_extn/compress_voip.c
@@ -335,6 +335,12 @@
if (uc_info == NULL) {
ALOGV("%s: voip usecase is added to the list", __func__);
uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
+
+ if (!uc_info) {
+ ALOGE("failed to allocate voip usecase mem");
+ return -ENOMEM;
+ }
+
uc_info->id = USECASE_COMPRESS_VOIP_CALL;
uc_info->type = VOIP_CALL;
if (voip_data.out_stream)
@@ -574,8 +580,14 @@
ret = voip_start_call(adev, &out->config);
out->pcm = voip_data.pcm_rx;
uc_info = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
- uc_info->stream.out = out;
- uc_info->devices = out->devices;
+ if (uc_info) {
+ uc_info->stream.out = out;
+ uc_info->devices = out->devices;
+ } else {
+ ret = -EINVAL;
+ ALOGE("%s: exit(%d): failed to get use case info", __func__, ret);
+ goto error;
+ }
error:
ALOGV("%s: exit: status(%d)", __func__, ret);
diff --git a/hal/voice_extn/voice_extn.c b/hal/voice_extn/voice_extn.c
index ea25a4b..89abc3a 100644
--- a/hal/voice_extn/voice_extn.c
+++ b/hal/voice_extn/voice_extn.c
@@ -73,7 +73,7 @@
extern int start_call(struct audio_device *adev, audio_usecase_t usecase_id);
extern int stop_call(struct audio_device *adev, audio_usecase_t usecase_id);
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
+int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active);
static bool is_valid_call_state(int call_state)
{
@@ -153,7 +153,6 @@
struct voice_session *session = NULL;
int fd = 0;
int ret = 0;
- bool is_in_call = false;
ALOGD("%s: enter:", __func__);
@@ -187,11 +186,11 @@
case CALL_LOCAL_HOLD:
ALOGD("%s: LOCAL_HOLD -> ACTIVE vsid:%x", __func__, session->vsid);
lch_mode = VOICE_LCH_STOP;
- if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD -> ACTIVE failed");
- } else {
+ ret = platform_update_lch(adev->platform, session, lch_mode);
+ if (ret < 0)
+ ALOGE("%s: lch mode update failed, ret = %d", __func__, ret);
+ else
session->state.current = session->state.new;
- }
break;
default:
@@ -213,10 +212,6 @@
ALOGE("%s: voice_end_call() failed for usecase: %d\n",
__func__, usecase_id);
} else {
- voice_extn_is_in_call(adev, &is_in_call);
- if (!is_in_call) {
- adev->voice.voice_device_set = false;
- }
session->state.current = session->state.new;
}
break;
@@ -239,11 +234,11 @@
case CALL_LOCAL_HOLD:
ALOGD("%s: CALL_LOCAL_HOLD -> HOLD vsid:%x", __func__, session->vsid);
lch_mode = VOICE_LCH_STOP;
- if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD -> HOLD failed");
- } else {
+ ret = platform_update_lch(adev->platform, session, lch_mode);
+ if (ret < 0)
+ ALOGE("%s: lch mode update failed, ret = %d", __func__, ret);
+ else
session->state.current = session->state.new;
- }
break;
default:
@@ -261,11 +256,11 @@
ALOGD("%s: ACTIVE/CALL_HOLD -> LOCAL_HOLD vsid:%x", __func__,
session->vsid);
lch_mode = VOICE_LCH_START;
- if (pcm_ioctl(session->pcm_tx, SNDRV_VOICE_IOCTL_LCH, &lch_mode) < 0) {
- ALOGE("LOCAL_HOLD -> HOLD failed");
- } else {
+ ret = platform_update_lch(adev->platform, session, lch_mode);
+ if (ret < 0)
+ ALOGE("%s: lch mode update failed, ret = %d", __func__, ret);
+ else
session->state.current = session->state.new;
- }
break;
default:
@@ -288,8 +283,7 @@
{
struct voice_session *session = NULL;
int i = 0;
- bool is_in_call;
- int no_of_calls_active = 0;
+ bool is_call_active;
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
if (vsid == adev->voice.session[i].vsid) {
@@ -298,21 +292,16 @@
}
}
- for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
- if (CALL_INACTIVE != adev->voice.session[i].state.current)
- no_of_calls_active++;
- }
-
if (session) {
session->state.new = call_state;
- voice_extn_is_in_call(adev, &is_in_call);
- ALOGD("%s is_in_call:%d voice_device_set:%d, mode:%d\n",
- __func__, is_in_call, adev->voice.voice_device_set, adev->mode);
+ voice_extn_is_call_state_active(adev, &is_call_active);
+ ALOGD("%s is_call_active:%d in_call:%d, mode:%d\n",
+ __func__, is_call_active, adev->voice.in_call, adev->mode);
/* Dont start voice call before device routing for voice usescases has
* occured, otherwise voice calls will be started unintendedly on
* speaker.
*/
- if (is_in_call || adev->voice.voice_device_set) {
+ if (is_call_active || adev->voice.in_call) {
/* Device routing is not triggered for voice calls on the subsequent
* subs, Hence update the call states if voice call is already
* active on other sub.
@@ -334,16 +323,16 @@
return 0;
}
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
+int voice_extn_is_call_state_active(struct audio_device *adev, bool *is_call_active)
{
struct voice_session *session = NULL;
int i = 0;
- *in_call = false;
+ *is_call_active = false;
for (i = 0; i < MAX_VOICE_SESSIONS; i++) {
session = &adev->voice.session[i];
if(session->state.current != CALL_INACTIVE){
- *in_call = true;
+ *is_call_active = true;
break;
}
}
@@ -415,7 +404,6 @@
* udpated.
*/
ALOGV("%s: enter:", __func__);
- adev->voice.voice_device_set = true;
return update_calls(adev);
}
@@ -462,6 +450,7 @@
err = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_CALL_STATE, &value);
if (err >= 0) {
call_state = value;
+ str_parms_del(parms, AUDIO_PARAMETER_KEY_CALL_STATE);
} else {
ALOGE("%s: call_state key not found", __func__);
ret = -EINVAL;
diff --git a/hal/voice_extn/voice_extn.h b/hal/voice_extn/voice_extn.h
index 4a9c610..73da18a 100644
--- a/hal/voice_extn/voice_extn.h
+++ b/hal/voice_extn/voice_extn.h
@@ -32,8 +32,9 @@
void voice_extn_get_parameters(const struct audio_device *adev,
struct str_parms *query,
struct str_parms *reply);
-int voice_extn_is_in_call(struct audio_device *adev, bool *in_call);
int voice_extn_is_in_call_rec_stream(struct stream_in *in, bool *in_call_rec);
+int voice_extn_is_call_state_active(struct audio_device *adev,
+ bool *is_call_active);
int voice_extn_get_active_session_id(struct audio_device *adev,
uint32_t *session_id);
void voice_extn_in_get_parameters(struct stream_in *in,
@@ -76,7 +77,8 @@
{
}
-static int voice_extn_is_in_call(struct audio_device *adev, bool *in_call)
+static int voice_extn_is_call_state_active(struct audio_device *adev,
+ bool *is_call_active)
{
return -ENOSYS;
}
diff --git a/post_proc/bass_boost.c b/post_proc/bass_boost.c
index 1c96280..e2c6d9a 100644
--- a/post_proc/bass_boost.c
+++ b/post_proc/bass_boost.c
@@ -158,24 +158,27 @@
(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);
+ if (!bass_ctxt->temp_disabled) {
+ if (effect_is_active(&bass_ctxt->common)) {
+ offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), false);
+ if (bass_ctxt->ctl)
+ offload_bassboost_send_params(bass_ctxt->ctl,
+ bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ }
bass_ctxt->temp_disabled = true;
- if (bass_ctxt->ctl)
- offload_bassboost_send_params(bass_ctxt->ctl,
- bass_ctxt->offload_bass,
- OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
- ALOGI("%s: ctxt %p, disabled based on device", __func__, bass_ctxt);
}
+ ALOGI("%s: ctxt %p, disabled based on device", __func__, bass_ctxt);
} else {
- if (!offload_bassboost_get_enable_flag(&(bass_ctxt->offload_bass)) &&
- bass_ctxt->temp_disabled) {
- offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
+ if (bass_ctxt->temp_disabled) {
+ if (effect_is_active(&bass_ctxt->common)) {
+ offload_bassboost_set_enable_flag(&(bass_ctxt->offload_bass), true);
+ if (bass_ctxt->ctl)
+ offload_bassboost_send_params(bass_ctxt->ctl,
+ bass_ctxt->offload_bass,
+ OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
+ }
bass_ctxt->temp_disabled = false;
- if (bass_ctxt->ctl)
- offload_bassboost_send_params(bass_ctxt->ctl,
- bass_ctxt->offload_bass,
- OFFLOAD_SEND_BASSBOOST_ENABLE_FLAG);
}
}
offload_bassboost_set_device(&(bass_ctxt->offload_bass), device);
diff --git a/post_proc/bundle.c b/post_proc/bundle.c
index a0d9fcb..0db2e37 100644
--- a/post_proc/bundle.c
+++ b/post_proc/bundle.c
@@ -186,6 +186,7 @@
int ret = 0;
struct listnode *node;
char mixer_string[128];
+ output_context_t * out_ctxt = NULL;
ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
@@ -199,7 +200,7 @@
goto exit;
}
- output_context_t *out_ctxt = (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__);
@@ -217,6 +218,7 @@
ALOGE("Failed to open mixer");
out_ctxt->ctl = NULL;
ret = -EINVAL;
+ free(out_ctxt);
goto exit;
} else {
out_ctxt->ctl = mixer_get_ctl_by_name(out_ctxt->mixer, mixer_string);
@@ -225,6 +227,7 @@
mixer_close(out_ctxt->mixer);
out_ctxt->mixer = NULL;
ret = -EINVAL;
+ free(out_ctxt);
goto exit;
}
}
@@ -535,12 +538,12 @@
pthread_mutex_lock(&lock);
if (!effect_exists(context)) {
- status = -EINVAL;
+ status = -ENOSYS;
goto exit;
}
if (context->state != EFFECT_STATE_ACTIVE) {
- status = -EINVAL;
+ status = -ENODATA;
goto exit;
}
@@ -560,13 +563,13 @@
pthread_mutex_lock(&lock);
if (!effect_exists(context)) {
- status = -EINVAL;
+ status = -ENOSYS;
goto exit;
}
ALOGV("%s: ctxt %p, cmd %d", __func__, context, cmdCode);
if (context == NULL || context->state == EFFECT_STATE_UNINITIALIZED) {
- status = -EINVAL;
+ status = -ENOSYS;
goto exit;
}
@@ -752,6 +755,9 @@
return 0;
}
+bool effect_is_active(effect_context_t * ctxt) {
+ return ctxt->state == EFFECT_STATE_ACTIVE;
+}
/* effect_handle_t interface implementation for offload effects */
const struct effect_interface_s effect_interface = {
diff --git a/post_proc/bundle.h b/post_proc/bundle.h
index 7ebea92..cbe7dba 100644
--- a/post_proc/bundle.h
+++ b/post_proc/bundle.h
@@ -87,4 +87,6 @@
int set_config(effect_context_t *context, effect_config_t *config);
+bool effect_is_active(effect_context_t *context);
+
#endif /* OFFLOAD_EFFECT_BUNDLE_H */
diff --git a/post_proc/reverb.c b/post_proc/reverb.c
index 81bcb97..77ae303 100644
--- a/post_proc/reverb.c
+++ b/post_proc/reverb.c
@@ -229,7 +229,7 @@
void reverb_set_density(reverb_context_t *context, int16_t density)
{
- ALOGV("%s: ctxt %p, density: %d", __func__, density, density);
+ ALOGV("%s: ctxt %p, density: %d", __func__, context, density);
context->reverb_settings.density = density;
offload_reverb_set_density(&(context->offload_reverb), density);
if (context->ctl)
diff --git a/post_proc/virtualizer.c b/post_proc/virtualizer.c
index 96828a0..9ed1ac5 100644
--- a/post_proc/virtualizer.c
+++ b/post_proc/virtualizer.c
@@ -157,24 +157,27 @@
(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);
+ if (!virt_ctxt->temp_disabled) {
+ if (effect_is_active(&virt_ctxt->common)) {
+ offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), false);
+ if (virt_ctxt->ctl)
+ offload_virtualizer_send_params(virt_ctxt->ctl,
+ virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
+ }
virt_ctxt->temp_disabled = true;
- if (virt_ctxt->ctl)
- offload_virtualizer_send_params(virt_ctxt->ctl,
- virt_ctxt->offload_virt,
- OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
ALOGI("%s: ctxt %p, disabled based on device", __func__, virt_ctxt);
}
} else {
- if (!offload_virtualizer_get_enable_flag(&(virt_ctxt->offload_virt)) &&
- virt_ctxt->temp_disabled) {
- offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
+ if (virt_ctxt->temp_disabled) {
+ if (effect_is_active(&virt_ctxt->common)) {
+ offload_virtualizer_set_enable_flag(&(virt_ctxt->offload_virt), true);
+ if (virt_ctxt->ctl)
+ offload_virtualizer_send_params(virt_ctxt->ctl,
+ virt_ctxt->offload_virt,
+ OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
+ }
virt_ctxt->temp_disabled = false;
- if (virt_ctxt->ctl)
- offload_virtualizer_send_params(virt_ctxt->ctl,
- virt_ctxt->offload_virt,
- OFFLOAD_SEND_VIRTUALIZER_ENABLE_FLAG);
}
}
offload_virtualizer_set_device(&(virt_ctxt->offload_virt), device);
@@ -212,6 +215,7 @@
set_config(context, &context->config);
+ virt_ctxt->temp_disabled = false;
memset(&(virt_ctxt->offload_virt), 0, sizeof(struct virtualizer_params));
return 0;