Merge "hal: fix missing calibration issue for playback on speaker"
diff --git a/hal/Android.mk b/hal/Android.mk
index e7ba38f..72042d1 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -256,6 +256,14 @@
LOCAL_SRC_FILES += audio_extn/listen.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_HDMI)),true)
+ LOCAL_CFLAGS += -DAUDIO_EXTERNAL_HDMI_ENABLED
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH)),true)
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/mm-audio/audio-parsers
+ LOCAL_SHARED_LIBRARIES += libaudioparsers
+endif
+endif
+
ifeq ($(strip $(BOARD_SUPPORTS_SOUND_TRIGGER)),true)
LOCAL_CFLAGS += -DSOUND_TRIGGER_ENABLED
LOCAL_CFLAGS += -DSOUND_TRIGGER_PLATFORM_NAME=$(TARGET_BOARD_PLATFORM)
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 9d80112..1c5da54 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -101,4 +101,6 @@
/* Query if Proxy can be Opend */
#define AUDIO_PARAMETER_KEY_CAN_OPEN_PROXY "can_open_proxy"
+#define AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED "is_hw_dec_session_allowed"
+
#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index dca965a..3645cdb 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -510,4 +510,10 @@
void audio_extn_perf_lock_acquire(void);
void audio_extn_perf_lock_release(void);
#endif /* KPI_OPTIMIZE_ENABLED */
+
+#ifndef AUDIO_EXTERNAL_HDMI_ENABLED
+#define audio_utils_set_hdmi_channel_status(out, buffer, bytes) (0)
+#else
+void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes);
+#endif
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index a39c8aa..a114b30 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -35,6 +35,12 @@
#include "audio_extn.h"
#include "voice.h"
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#ifdef HDMI_PASSTHROUGH_ENABLED
+#include "audio_parsers.h"
+#endif
+#endif
+
#define AUDIO_OUTPUT_POLICY_VENDOR_CONFIG_FILE "/vendor/etc/audio_output_policy.conf"
#define OUTPUTS_TAG "outputs"
@@ -52,6 +58,21 @@
#define BASE_TABLE_SIZE 64
#define MAX_BASEINDEX_LEN 256
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+#define PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */
+#define NON_LPCM (1<<1) /* 0 = audio, 1 = non-audio */
+#define SR_44100 (0<<0) /* 44.1kHz */
+#define SR_NOTID (1<<0) /* non indicated */
+#define SR_48000 (2<<0) /* 48kHz */
+#define SR_32000 (3<<0) /* 32kHz */
+#define SR_22050 (4<<0) /* 22.05kHz */
+#define SR_24000 (6<<0) /* 24kHz */
+#define SR_88200 (8<<0) /* 88.2kHz */
+#define SR_96000 (10<<0) /* 96kHz */
+#define SR_176400 (12<<0) /* 176.4kHz */
+#define SR_192000 (14<<0) /* 192kHz */
+
+#endif
struct string_to_enum {
const char *name;
uint32_t value;
@@ -764,3 +785,136 @@
outp[k] = '\0';
return k;
}
+
+#ifdef AUDIO_EXTERNAL_HDMI_ENABLED
+
+void get_default_compressed_channel_status(
+ unsigned char *channel_status)
+{
+ int32_t status = 0;
+ unsigned char bit_index;
+ memset(channel_status,0,24);
+
+ /* block start bit in preamble bit 3 */
+ channel_status[0] |= PROFESSIONAL;
+ //compre out
+ channel_status[0] |= NON_LPCM;
+ // sample rate; fixed 48K for default/transcode
+ channel_status[3] |= SR_48000;
+}
+
+#ifdef HDMI_PASSTHROUGH_ENABLED
+int32_t get_compressed_channel_status(void *audio_stream_data,
+ uint32_t audio_frame_size,
+ unsigned char *channel_status,
+ enum audio_parser_code_type codec_type)
+ // codec_type - AUDIO_PARSER_CODEC_AC3
+ // - AUDIO_PARSER_CODEC_DTS
+{
+ unsigned char *stream;
+ int ret = 0;
+ stream = (unsigned char *)audio_stream_data;
+
+ if (audio_stream_data == NULL || audio_frame_size == 0) {
+ ALOGW("no buffer to get channel status, return default for compress");
+ get_default_compressed_channel_status(channel_status);
+ return ret;
+ }
+
+ memset(channel_status,0,24);
+ if(init_audio_parser(stream, audio_frame_size, codec_type) == -1)
+ {
+ ALOGE("init audio parser failed");
+ return -1;
+ }
+ ret = get_channel_status(channel_status, codec_type);
+ return ret;
+
+}
+
+#endif
+
+void get_lpcm_channel_status(uint32_t sampleRate,
+ unsigned char *channel_status)
+{
+ int32_t status = 0;
+ unsigned char bit_index;
+ memset(channel_status,0,24);
+ /* block start bit in preamble bit 3 */
+ channel_status[0] |= PROFESSIONAL;
+ //LPCM OUT
+ channel_status[0] &= ~NON_LPCM;
+
+ switch (sampleRate) {
+ case 8000:
+ case 11025:
+ case 12000:
+ case 16000:
+ case 22050:
+ channel_status[3] |= SR_NOTID;
+ case 24000:
+ channel_status[3] |= SR_24000;
+ break;
+ case 32000:
+ channel_status[3] |= SR_32000;
+ break;
+ case 44100:
+ channel_status[3] |= SR_44100;
+ break;
+ case 48000:
+ channel_status[3] |= SR_48000;
+ break;
+ case 88200:
+ channel_status[3] |= SR_88200;
+ break;
+ case 96000:
+ channel_status[3] |= SR_96000;
+ break;
+ case 176400:
+ channel_status[3] |= SR_176400;
+ break;
+ case 192000:
+ channel_status[3] |= SR_192000;
+ break;
+ default:
+ ALOGV("Invalid sample_rate %u\n", sampleRate);
+ status = -1;
+ break;
+ }
+}
+
+void audio_utils_set_hdmi_channel_status(struct stream_out *out, char * buffer, size_t bytes)
+{
+ unsigned char channel_status[24]={0};
+ struct snd_aes_iec958 iec958;
+ const char *mixer_ctl_name = "IEC958 Playback PCM Stream";
+ struct mixer_ctl *ctl;
+ int i=0;
+#ifdef HDMI_PASSTHROUGH_ENABLED
+ if (audio_extn_is_dolby_format(out->format) &&
+ /*TODO:Extend code to support DTS passthrough*/
+ /*set compressed channel status bits*/
+ audio_extn_dolby_is_passthrough_stream(out->flags)){
+ get_compressed_channel_status(buffer, bytes, channel_status, AUDIO_PARSER_CODEC_AC3);
+ } else
+#endif
+ {
+ /*set channel status bit for LPCM*/
+ get_lpcm_channel_status(out->sample_rate, channel_status);
+ }
+
+ memcpy(iec958.status, channel_status,sizeof(iec958.status));
+ ctl = mixer_get_ctl_by_name(out->dev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return;
+ }
+ if (mixer_ctl_set_array(ctl, &iec958, sizeof(iec958)) < 0) {
+ ALOGE("%s: Could not set channel status for ext HDMI ",
+ __func__);
+ return;
+ }
+
+}
+#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 1c11484..e637a97 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -601,6 +601,9 @@
audio_route_reset_and_update_path(adev->audio_route, device_name);
}
+ if (snd_device == SND_DEVICE_OUT_HDMI)
+ adev->is_channel_status_set = false;
+
audio_extn_dev_arbi_release(snd_device);
audio_extn_sound_trigger_update_device_status(snd_device,
ST_EVENT_SND_DEVICE_FREE);
@@ -1190,6 +1193,20 @@
return ret;
}
+void lock_input_stream(struct stream_in *in)
+{
+ pthread_mutex_lock(&in->pre_lock);
+ pthread_mutex_lock(&in->lock);
+ pthread_mutex_unlock(&in->pre_lock);
+}
+
+void lock_output_stream(struct stream_out *out)
+{
+ pthread_mutex_lock(&out->pre_lock);
+ pthread_mutex_lock(&out->lock);
+ pthread_mutex_unlock(&out->pre_lock);
+}
+
/* must be called with out->lock locked */
static int send_offload_cmd_l(struct stream_out* out, int command)
{
@@ -1278,7 +1295,7 @@
prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
ALOGV("%s", __func__);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
for (;;) {
struct offload_cmd *cmd = NULL;
stream_callback_event_t event;
@@ -1357,7 +1374,7 @@
ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
break;
}
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
out->offload_thread_blocked = false;
pthread_cond_signal(&out->cond);
if (send_callback && out->offload_callback) {
@@ -1389,7 +1406,7 @@
static int destroy_offload_callback_thread(struct stream_out *out)
{
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
stop_compressed_output_l(out);
send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
@@ -1848,7 +1865,7 @@
return 0;
}
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (!out->standby) {
if (adev->adm_deregister_stream)
adev->adm_deregister_stream(adev->adm_data, out->handle);
@@ -1937,7 +1954,7 @@
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
if (err >= 0) {
val = atoi(value);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
pthread_mutex_lock(&adev->lock);
/*
@@ -2001,7 +2018,7 @@
pthread_mutex_unlock(&adev->lock);
}
if (is_offload_usecase(out->usecase)) {
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
parse_compress_metadata(out, parms);
audio_extn_dts_create_state_notifier_node(out->usecase);
@@ -2157,7 +2174,7 @@
int snd_scard_state = get_snd_card_state(adev);
ssize_t ret = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
// increase written size during SSR to avoid mismatch
@@ -2194,6 +2211,11 @@
adev->adm_register_output_stream(adev->adm_data, out->handle, out->flags);
}
+ if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
+ audio_utils_set_hdmi_channel_status(out, buffer, bytes);
+ adev->is_channel_status_set = true;
+ }
+
if (is_offload_usecase(out->usecase)) {
ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
if (out->send_new_metadata) {
@@ -2297,7 +2319,7 @@
*dsp_frames = 0;
if (is_offload_usecase(out->usecase)) {
ssize_t ret = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL) {
ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
&out->sample_rate);
@@ -2356,7 +2378,7 @@
int ret = -1;
unsigned long dsp_frames;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (is_offload_usecase(out->usecase)) {
if (out->compr != NULL) {
@@ -2408,7 +2430,7 @@
struct stream_out *out = (struct stream_out *)stream;
ALOGV("%s", __func__);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
out->offload_callback = callback;
out->offload_cookie = cookie;
pthread_mutex_unlock(&out->lock);
@@ -2422,7 +2444,7 @@
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):pause compress driver", out);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
struct audio_device *adev = out->dev;
int snd_scard_state = get_snd_card_state(adev);
@@ -2450,7 +2472,7 @@
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):resume compress driver", out);
status = 0;
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
struct audio_device *adev = out->dev;
int snd_scard_state = get_snd_card_state(adev);
@@ -2475,7 +2497,7 @@
int status = -ENOSYS;
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
if (type == AUDIO_DRAIN_EARLY_NOTIFY)
status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
else
@@ -2491,7 +2513,7 @@
ALOGV("%s", __func__);
if (is_offload_usecase(out->usecase)) {
ALOGD("copl(%p):calling compress flush", out);
- pthread_mutex_lock(&out->lock);
+ lock_output_stream(out);
stop_compressed_output_l(out);
pthread_mutex_unlock(&out->lock);
ALOGD("copl(%p):out of compress flush", out);
@@ -2563,7 +2585,7 @@
return status;
}
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
if (!in->standby && in->is_st_session) {
ALOGD("%s: sound trigger pcm stop lab", __func__);
audio_extn_sound_trigger_stop_lab(in);
@@ -2608,7 +2630,7 @@
if (!parms)
goto error;
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
pthread_mutex_lock(&adev->lock);
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
@@ -2692,7 +2714,7 @@
int i, ret = -1;
int snd_scard_state = get_snd_card_state(adev);
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
if (in->is_st_session) {
ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
@@ -2792,7 +2814,7 @@
if (status != 0)
return status;
- pthread_mutex_lock(&in->lock);
+ lock_input_stream(in);
pthread_mutex_lock(&in->dev->lock);
if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
in->enable_aec != enable &&
@@ -2860,6 +2882,7 @@
}
pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
if (devices == AUDIO_DEVICE_NONE)
@@ -3524,6 +3547,7 @@
devices, &in->stream, handle, source);
pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
+ pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
in->stream.common.get_sample_rate = in_get_sample_rate;
in->stream.common.set_sample_rate = in_set_sample_rate;
@@ -3781,6 +3805,7 @@
list_init(&adev->usecase_list);
adev->cur_wfd_channels = 2;
adev->offload_usecases_state = 0;
+ adev->is_channel_status_set = false;
pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 5c1ea1d..dc0970f 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -184,6 +184,7 @@
struct stream_out {
struct audio_stream_out stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
+ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
pthread_cond_t cond;
struct pcm_config config;
struct compr_config compr_config;
@@ -228,6 +229,7 @@
struct stream_in {
struct audio_stream_in stream;
pthread_mutex_t lock; /* see note below on mutex acquisition order */
+ pthread_mutex_t pre_lock; /* acquire before lock to avoid DOS by playback thread */
struct pcm_config config;
struct pcm *pcm;
int standby;
@@ -327,6 +329,7 @@
int snd_card;
unsigned int cur_codec_backend_samplerate;
unsigned int cur_codec_backend_bit_width;
+ bool is_channel_status_set;
void *platform;
unsigned int offload_usecases_state;
void *visualizer_lib;
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index baec1e0..b5f56c1 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -138,6 +138,17 @@
#define AUDIO_PARAMETER_KEY_REC_PLAY_CONC "rec_play_conc_on"
+#define AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED "is_hw_dec_session_allowed"
+
+char * dsp_only_decoders_mime[] = {
+ "audio/x-ms-wma" /* wma*/ ,
+ "audio/x-ms-wma-lossless" /* wma lossless */ ,
+ "audio/x-ms-wma-pro" /* wma prop */ ,
+ "audio/amr-wb-plus" /* amr wb plus */ ,
+ "audio/alac" /*alac */ ,
+ "audio/x-ape" /*ape */,
+};
+
enum {
VOICE_FEATURE_SET_DEFAULT,
VOICE_FEATURE_SET_VOLUME_BOOST
@@ -3435,6 +3446,8 @@
char value[512] = {0};
int ret;
char *kv_pairs = NULL;
+ char propValue[PROPERTY_VALUE_MAX]={0};
+ bool prop_playback_enabled = false;
ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK,
value, sizeof(value));
@@ -3463,6 +3476,37 @@
}
native_audio_get_params(query, reply, value, sizeof(value));
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED,
+ value, sizeof(value));
+ if (ret >= 0) {
+ int isallowed = 1; /*true*/
+
+ if (property_get("voice.playback.conc.disabled", propValue, NULL)) {
+ prop_playback_enabled = atoi(propValue) ||
+ !strncmp("true", propValue, 4);
+ }
+
+ if (prop_playback_enabled && (voice_is_in_call(my_data->adev) ||
+ (SND_CARD_STATE_OFFLINE == get_snd_card_state(my_data->adev)))) {
+ char *decoder_mime_type = value;
+
+ //check if unsupported mime type or not
+ if(decoder_mime_type) {
+ int i = 0;
+ for (i = 0; i < sizeof(dsp_only_decoders_mime)/sizeof(dsp_only_decoders_mime[0]); i++) {
+ if (!strncmp(decoder_mime_type, dsp_only_decoders_mime[i],
+ strlen(dsp_only_decoders_mime[i]))) {
+ ALOGD("Rejecting request for DSP only session from HAL during voice call/SSR state");
+ isallowed = 0;
+ break;
+ }
+ }
+ }
+ }
+ str_parms_add_int(reply, AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED, isallowed);
+ }
+
+
/* Handle audio calibration keys */
kv_pairs = str_parms_to_str(reply);
ALOGV("%s: exit: returns - %s", __func__, kv_pairs);
@@ -4146,15 +4190,12 @@
}
edid_data[0] = count;
memcpy(&edid_data[1], block, count);
-
-#ifdef AUDIO_FEATURE_ENABLED_HDMI_EDID
if (!edid_get_sink_caps(info, edid_data)) {
ALOGE("%s: Failed to get HDMI sink capabilities", __func__);
goto fail;
}
my_data->edid_valid = true;
return 0;
-#endif
fail:
if (my_data->edid_info) {
free(my_data->edid_info);
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index b72cae9..8d5004d 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -374,7 +374,7 @@
}
void platform_add_backend_name(char *mixer_path, snd_device_t snd_device,
- struct audio_usecase *usecase)
+ struct audio_usecase *usecase __unused)
{
if (snd_device == SND_DEVICE_IN_BT_SCO_MIC)
strlcat(mixer_path, " bt-sco", MIXER_PATH_MAX_LENGTH);
@@ -1172,3 +1172,8 @@
{
return 0;
}
+
+void platform_set_gsm_mode(void *platform __unused, bool enable __unused)
+{
+ ALOGE("%s: Not implemented", __func__);
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 5cb18fd..1c8e812 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -133,6 +133,18 @@
[WCD9XXX_VBAT_CAL] = "vbat_cal",
};
+#define AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED "is_hw_dec_session_allowed"
+
+char * dsp_only_decoders_mime[] = {
+ "audio/x-ms-wma" /* wma*/ ,
+ "audio/x-ms-wma-lossless" /* wma lossless */ ,
+ "audio/x-ms-wma-pro" /* wma prop */ ,
+ "audio/amr-wb-plus" /* amr wb plus */ ,
+ "audio/alac" /*alac */ ,
+ "audio/x-ape" /*ape */,
+};
+
+
enum {
VOICE_FEATURE_SET_DEFAULT,
VOICE_FEATURE_SET_VOLUME_BOOST
@@ -1148,7 +1160,7 @@
ret = 0;
- if((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
+ if ((plat_data->is_vbat_speaker) && (WCD9XXX_VBAT_CAL == type)) {
ret = send_vbat_adc_data_to_acdb(plat_data, cal_name_info[type]);
if (ret < 0)
ALOGE("%s error in sending vbat adc data to acdb", __func__);
@@ -1286,7 +1298,12 @@
continue;
}
- snd_card_name = mixer_get_name(adev->mixer);
+ snd_card_name = strdup(mixer_get_name(adev->mixer));
+ if (!snd_card_name) {
+ ALOGE("failed to allocate memory for snd_card_name\n");
+ free(my_data);
+ return NULL;
+ }
ALOGV("%s: snd_card_name: %s", __func__, snd_card_name);
my_data->hw_info = hw_info_init(snd_card_name);
@@ -1348,6 +1365,7 @@
ALOGE("%s: Failed to init audio route controls, aborting.",
__func__);
free(my_data);
+ free(snd_card_name);
return NULL;
}
adev->snd_card = snd_card_num;
@@ -1361,6 +1379,7 @@
if (snd_card_num >= MAX_SND_CARD) {
ALOGE("%s: Unable to find correct sound card, aborting.", __func__);
free(my_data);
+ free(snd_card_name);
return NULL;
}
@@ -1559,6 +1578,7 @@
strdup("SLIM_5_RX SampleRate");
my_data->edid_info = NULL;
+ free(snd_card_name);
return my_data;
}
@@ -1649,7 +1669,7 @@
return;
}
- if((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
+ if ((snd_device == SND_DEVICE_OUT_VOICE_SPEAKER_VBAT) &&
!(usecase->type == VOICE_CALL || usecase->type == VOIP_CALL)) {
ALOGI("%s: Not adding vbat speaker device to non voice use cases", __func__);
return;
@@ -3293,6 +3313,8 @@
char value[512] = {0};
int ret;
char *kv_pairs = NULL;
+ char propValue[PROPERTY_VALUE_MAX]={0};
+ bool prop_playback_enabled = false;
ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SLOWTALK,
value, sizeof(value));
@@ -3324,6 +3346,36 @@
get_audiocal(platform, query, reply);
native_audio_get_params(query, reply, value, sizeof(value));
+ ret = str_parms_get_str(query, AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED,
+ value, sizeof(value));
+ if (ret >= 0) {
+ int isallowed = 1; /*true*/
+
+ if (property_get("voice.playback.conc.disabled", propValue, NULL)) {
+ prop_playback_enabled = atoi(propValue) ||
+ !strncmp("true", propValue, 4);
+ }
+
+ if (prop_playback_enabled && (voice_is_in_call(my_data->adev) ||
+ (SND_CARD_STATE_OFFLINE == get_snd_card_state(my_data->adev)))) {
+ char *decoder_mime_type = value;
+
+ //check if unsupported mime type or not
+ if(decoder_mime_type) {
+ int i = 0;
+ for (i = 0; i < sizeof(dsp_only_decoders_mime)/sizeof(dsp_only_decoders_mime[0]); i++) {
+ if (!strncmp(decoder_mime_type, dsp_only_decoders_mime[i],
+ strlen(dsp_only_decoders_mime[i]))) {
+ ALOGD("Rejecting request for DSP only session from HAL during voice call/SSR state");
+ isallowed = 0;
+ break;
+ }
+ }
+ }
+ }
+ str_parms_add_int(reply, AUDIO_PARAMETER_IS_HW_DECODER_SESSION_ALLOWED, isallowed);
+ }
+
done:
kv_pairs = str_parms_to_str(reply);
ALOGV_IF(kv_pairs != NULL, "%s: exit: returns - %s", __func__, kv_pairs);
diff --git a/policy_hal/AudioPolicyManager.cpp b/policy_hal/AudioPolicyManager.cpp
index b0707d7..900e6cc 100644
--- a/policy_hal/AudioPolicyManager.cpp
+++ b/policy_hal/AudioPolicyManager.cpp
@@ -460,6 +460,14 @@
ALOGV("isOffloadSupported: has_video == true, returning false");
return false;
}
+
+ const bool allowOffloadStreamingWithVideo = property_get_bool("av.streaming.offload.enable",
+ false /*default value*/);
+ if(offloadInfo.has_video && offloadInfo.is_streaming && !allowOffloadStreamingWithVideo) {
+ ALOGW("offload disabled by av.streaming.offload.enable = %s ", propValue );
+ return false;
+ }
+
}
//If duration is less than minimum value defined in property, return false
@@ -977,6 +985,7 @@
// store time at which the stream was stopped - see isStreamActive()
if (outputDesc->mRefCount[stream] == 0 || forceDeviceUpdate) {
outputDesc->mStopTime[stream] = systemTime();
+ audio_devices_t prevDevice = outputDesc->device();
audio_devices_t newDevice = getNewOutputDevice(outputDesc, false /*fromCache*/);
// delay the device switch by twice the latency because stopOutput() is executed when
// the track stop() command is received and at that time the audio track buffer can
@@ -995,10 +1004,16 @@
outputDesc->sharesHwModuleWith(desc) &&
(newDevice != desc->device())) {
audio_devices_t dev = getNewOutputDevice(mOutputs.valueFor(curOutput), false /*fromCache*/);
+ uint32_t delayMs;
+ if (dev == prevDevice) {
+ delayMs = 0;
+ } else {
+ delayMs = outputDesc->mLatency*2;
+ }
setOutputDevice(desc,
dev,
true,
- outputDesc->latency()*2);
+ delayMs);
}
}
// update the outputs if stopping one with a stream that can affect notification routing
@@ -1920,6 +1935,37 @@
mHdmiAudioEvent(false),
mPrevPhoneState(0)
{
+ char ssr_enabled[PROPERTY_VALUE_MAX] = {0};
+ bool prop_ssr_enabled = false;
+
+ if (property_get("ro.qc.sdk.audio.ssr", ssr_enabled, NULL)) {
+ prop_ssr_enabled = atoi(ssr_enabled) || !strncmp("true", ssr_enabled, 4);
+ }
+
+ for (size_t i = 0; i < mHwModules.size(); i++) {
+ ALOGV("Hw module %d", i);
+ for (size_t j = 0; j < mHwModules[i]->mInputProfiles.size(); j++) {
+ const sp<IOProfile> inProfile = mHwModules[i]->mInputProfiles[j];
+ ALOGV("Input profile ", j);
+ for (size_t k = 0; k < inProfile->mChannelMasks.size(); k++) {
+ audio_channel_mask_t channelMask =
+ inProfile->mChannelMasks.itemAt(k);
+ ALOGV("Channel Mask %x size %d", channelMask,
+ inProfile->mChannelMasks.size());
+ if (AUDIO_CHANNEL_IN_5POINT1 == channelMask) {
+ if (!prop_ssr_enabled) {
+ ALOGI("removing AUDIO_CHANNEL_IN_5POINT1 from"
+ " input profile as SSR(surround sound record)"
+ " is not supported on this chipset variant");
+ inProfile->mChannelMasks.removeItemsAt(k, 1);
+ ALOGV("Channel Mask size now %d",
+ inProfile->mChannelMasks.size());
+ }
+ }
+ }
+ }
+ }
+
#ifdef RECORD_PLAY_CONCURRENCY
mIsInputRequestOnProgress = false;
#endif
diff --git a/post_proc/volume_listener.c b/post_proc/volume_listener.c
index 51f8803..d540bf5 100644
--- a/post_proc/volume_listener.c
+++ b/post_proc/volume_listener.c
@@ -344,7 +344,7 @@
if (in_buffer->raw != out_buffer->raw) {
memcpy(out_buffer->raw, in_buffer->raw, out_buffer->frameCount * 2 * sizeof(int16_t));
} else {
- ALOGW("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
+ ALOGV("%s: something wrong, didn't handle in_buffer and out_buffer same address case",
__func__);
}
@@ -432,7 +432,7 @@
// After changing the state and if device is speaker
// recalculate gain dep cal level
- if (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
check_and_set_gain_dep_cal();
}
@@ -459,7 +459,7 @@
// After changing the state and if device is speaker
// recalculate gain dep cal level
- if (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
check_and_set_gain_dep_cal();
}
@@ -490,8 +490,8 @@
__func__, context->dev_id, new_device);
// check if old or new device is speaker
- if ((context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) ||
- (new_device & AUDIO_DEVICE_OUT_SPEAKER)) {
+ if ((context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) ||
+ (new_device == AUDIO_DEVICE_OUT_SPEAKER)) {
recompute_gain_dep_cal_Level = true;
}
@@ -516,7 +516,7 @@
goto exit;
}
- if (context->dev_id & AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
recompute_gain_dep_cal_Level = true;
}
@@ -681,6 +681,11 @@
bool recompute_flag = false;
int active_stream_count = 0;
ALOGV("%s context %p", __func__, handle);
+ if (recv_contex == NULL || recv_contex->desc == NULL) {
+ ALOGE("%s: Got invalid handle while release, DO NOTHING ", __func__);
+ return status;
+ }
+
pthread_mutex_lock(&vol_listner_init_lock);
// check if the handle/context provided is valid
@@ -690,13 +695,14 @@
&& (context->session_id == recv_contex->session_id)
&& (context->stream_type == recv_contex->stream_type)) {
ALOGV("--- Found something to remove ---");
- list_remove(&context->effect_list_node);
PRINT_STREAM_TYPE(context->stream_type);
- if (context->dev_id && AUDIO_DEVICE_OUT_SPEAKER) {
+ if (context->dev_id == AUDIO_DEVICE_OUT_SPEAKER) {
recompute_flag = true;
}
+ list_remove(&context->effect_list_node);
free(context);
status = 0;
+ break;
} else {
++active_stream_count;
}