From 45f1919f3dbcf4be7b16f1a37e1fb6a0a1617a9a Mon Sep 17 00:00:00 2001 From: Divya Narayanan Poojary Date: Fri, 30 Sep 2016 18:52:13 +0530 Subject: [PATCH] hal: Restrict SSR recording to channel position representation Surround Sound Recording(SSR) supports only channel position representation while default channel mask for multi-channel recording is always index representation. Return updated channel mask in case index representation is sent for channel count 6. This ensures audio flinger reopens the session with updated position representation channel mask. And also handled the case if any client requests recording with multichannel when SSR is not enabled, will check the max_mic_count supported by the device and update the channel mask accordingly. Change-Id: Ib925a5f31d50182cd595e547f3412ed809224a5a --- hal/audio_extn/audio_extn.c | 49 +++++++++++++++++++++++++++++++ hal/audio_extn/audio_extn.h | 28 +++++++++++------- hal/audio_extn/ssr.c | 58 +++++++++++++++++++++++++------------ hal/audio_hw.c | 10 ++++++- hal/msm8916/platform.c | 5 ++++ hal/msm8974/platform.c | 5 ++++ hal/platform_api.h | 1 + 7 files changed, 127 insertions(+), 29 deletions(-) diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c index 65f516c8..e46b7369 100644 --- a/hal/audio_extn/audio_extn.c +++ b/hal/audio_extn/audio_extn.c @@ -1142,3 +1142,52 @@ void audio_extn_perf_lock_release(int *handle) } } #endif /* KPI_OPTIMIZE_ENABLED */ + +static int audio_extn_set_multichannel_mask(struct audio_device *adev, + struct stream_in *in, + struct audio_config *config, + bool *channel_mask_updated) +{ + int ret = -EINVAL; + int channel_count = audio_channel_count_from_in_mask(in->channel_mask); + *channel_mask_updated = false; + + int max_mic_count = platform_get_max_mic_count(adev->platform); + /* validate input params*/ + if ((channel_count == 6) && + (in->format == AUDIO_FORMAT_PCM_16_BIT)) { + + switch (max_mic_count) { + case 4: + config->channel_mask = AUDIO_CHANNEL_INDEX_MASK_4; + break; + case 3: + config->channel_mask = AUDIO_CHANNEL_INDEX_MASK_3; + break; + case 2: + config->channel_mask = AUDIO_CHANNEL_IN_STEREO; + break; + default: + config->channel_mask = AUDIO_CHANNEL_IN_STEREO; + break; + } + ret = 0; + *channel_mask_updated = true; + } + return ret; +} + +int audio_extn_check_and_set_multichannel_usecase(struct audio_device *adev, + struct stream_in *in, + struct audio_config *config, + bool *update_params) +{ + bool ssr_supported = false; + ssr_supported = audio_extn_ssr_check_usecase(in); + if (ssr_supported) { + return audio_extn_ssr_set_usecase(in, config, update_params); + } else { + return audio_extn_set_multichannel_mask(adev, in, config, + update_params); + } +} diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h index 069feda6..8ce06d91 100644 --- a/hal/audio_extn/audio_extn.h +++ b/hal/audio_extn/audio_extn.h @@ -189,17 +189,21 @@ void audio_extn_a2dp_set_handoff_mode(bool is_on); #endif #ifndef SSR_ENABLED -#define audio_extn_ssr_check_and_set_usecase(in) (-1) -#define audio_extn_ssr_init(in, num_out_chan) (0) -#define audio_extn_ssr_deinit() (0) -#define audio_extn_ssr_update_enabled() (0) -#define audio_extn_ssr_get_enabled() (0) -#define audio_extn_ssr_read(stream, buffer, bytes) (0) -#define audio_extn_ssr_set_parameters(adev, parms) (0) -#define audio_extn_ssr_get_parameters(adev, parms, reply) (0) -#define audio_extn_ssr_get_stream() (0) +#define audio_extn_ssr_check_usecase(in) (0) +#define audio_extn_ssr_set_usecase(in, config, channel_mask_updated) (0) +#define audio_extn_ssr_init(in, num_out_chan) (0) +#define audio_extn_ssr_deinit() (0) +#define audio_extn_ssr_update_enabled() (0) +#define audio_extn_ssr_get_enabled() (0) +#define audio_extn_ssr_read(stream, buffer, bytes) (0) +#define audio_extn_ssr_set_parameters(adev, parms) (0) +#define audio_extn_ssr_get_parameters(adev, parms, reply) (0) +#define audio_extn_ssr_get_stream() (0) #else -int audio_extn_ssr_check_and_set_usecase(struct stream_in *in); +bool audio_extn_ssr_check_usecase(struct stream_in *in); +int audio_extn_ssr_set_usecase(struct stream_in *in, + struct audio_config *config, + bool *channel_mask_updated); int32_t audio_extn_ssr_init(struct stream_in *in, int num_out_chan); int32_t audio_extn_ssr_deinit(); @@ -214,6 +218,10 @@ void audio_extn_ssr_get_parameters(const struct audio_device *adev, struct str_parms *reply); struct stream_in *audio_extn_ssr_get_stream(); #endif +int audio_extn_check_and_set_multichannel_usecase(struct audio_device *adev, + struct stream_in *in, + struct audio_config *config, + bool *update_params); #ifndef HW_VARIANTS_ENABLED #define hw_info_init(snd_card_name) (0) diff --git a/hal/audio_extn/ssr.c b/hal/audio_extn/ssr.c index f55f3ced..51a6a268 100644 --- a/hal/audio_extn/ssr.c +++ b/hal/audio_extn/ssr.c @@ -331,33 +331,55 @@ bool audio_extn_ssr_get_enabled() return false; } -int audio_extn_ssr_check_and_set_usecase(struct stream_in *in) -{ - int ret = -1; +bool audio_extn_ssr_check_usecase(struct stream_in *in) { + int ret = false; int channel_count = audio_channel_count_from_in_mask(in->channel_mask); audio_devices_t devices = in->device; audio_source_t source = in->source; - /* validate input params - * only stereo and 5:1 channel config is supported - * only AUDIO_DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BACK_MIC supports 3 mics */ - if (audio_extn_ssr_get_enabled() && - ((channel_count == 2) || (channel_count == 6)) && - ((AUDIO_SOURCE_MIC == source) || (AUDIO_SOURCE_CAMCORDER == source)) && - ((AUDIO_DEVICE_IN_BUILTIN_MIC == devices) || (AUDIO_DEVICE_IN_BACK_MIC == devices)) && - (in->format == AUDIO_FORMAT_PCM_16_BIT)) { - - ALOGD("%s: Found SSR use case starting SSR lib with channel_count :%d", + if ((audio_extn_ssr_get_enabled()) && + ((channel_count == 2) || (channel_count == 6)) && + ((AUDIO_SOURCE_MIC == source) || (AUDIO_SOURCE_CAMCORDER == source)) && + ((AUDIO_DEVICE_IN_BUILTIN_MIC == devices) || (AUDIO_DEVICE_IN_BACK_MIC == devices)) && + (in->format == AUDIO_FORMAT_PCM_16_BIT)) { + ALOGD("%s: SSR enabled with channel_count :%d", __func__, channel_count); + ret = true; + } + return ret; +} - if (!audio_extn_ssr_init(in, channel_count)) { - ALOGD("%s: Created SSR session succesfully", __func__); +int audio_extn_ssr_set_usecase(struct stream_in *in, + struct audio_config *config, + bool *update_params) +{ + int ret = -EINVAL; + int channel_count = audio_channel_count_from_in_mask(in->channel_mask); + audio_channel_representation_t representation = + audio_channel_mask_get_representation(in->channel_mask); + *update_params = false; + + if (audio_extn_ssr_check_usecase(in)) { + + if (representation == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + /* update params in case channel representation index. + * on returning error, flinger will retry with supported representation passed + */ + ALOGD("%s: SSR supports only channel representation position, channel_mask(%#x)" + ,__func__, config->channel_mask); + config->channel_mask = AUDIO_CHANNEL_IN_5POINT1; ret = 0; + *update_params = true; } else { - ALOGE("%s: Unable to start SSR record session", __func__); + if (!audio_extn_ssr_init(in, channel_count)) { + ALOGD("%s: Created SSR session succesfully", __func__); + ret = 0; + } else { + ALOGE("%s: Unable to start SSR record session", __func__); + } } - } - return ret; + } + return ret; } static void pcm_buffer_queue_push(struct pcm_buffer_queue **queue, diff --git a/hal/audio_hw.c b/hal/audio_hw.c index f6e11e81..569948a7 100644 --- a/hal/audio_hw.c +++ b/hal/audio_hw.c @@ -4348,6 +4348,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, int ret = 0, buffer_size, frame_size; int channel_count = audio_channel_count_from_in_mask(config->channel_mask); bool is_low_latency = false; + bool channel_mask_updated = false; *stream_in = NULL; if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) { @@ -4442,7 +4443,14 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->config.channels = channel_count; in->config.rate = config->sample_rate; in->sample_rate = config->sample_rate; - } else if (!audio_extn_ssr_check_and_set_usecase(in)) { + } else if (!audio_extn_check_and_set_multichannel_usecase(adev, + in, config, &channel_mask_updated)) { + if (channel_mask_updated == true) { + ALOGD("%s: return error to retry with updated channel mask (%#x)", + __func__, config->channel_mask); + ret = -EINVAL; + goto err_open; + } ALOGD("%s: created surround sound session succesfully",__func__); } else if (audio_extn_compr_cap_enabled() && audio_extn_compr_cap_format_supported(config->format) && diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c index 47f251fa..0296accc 100644 --- a/hal/msm8916/platform.c +++ b/hal/msm8916/platform.c @@ -5686,3 +5686,8 @@ int platform_retrieve_audio_cal(void* platform __unused, { return -ENOSYS; } + +int platform_get_max_mic_count(void *platform) { + struct platform_data *my_data = (struct platform_data *)platform; + return my_data->max_mic_count; +} diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c index 48bb46cd..a52e2b16 100644 --- a/hal/msm8974/platform.c +++ b/hal/msm8974/platform.c @@ -5825,3 +5825,8 @@ int platform_retrieve_audio_cal(void* platform, int acdb_dev_id, ERROR_RETURN: return ret; } + +int platform_get_max_mic_count(void *platform) { + struct platform_data *my_data = (struct platform_data *)platform; + return my_data->max_mic_count; +} diff --git a/hal/platform_api.h b/hal/platform_api.h index 7bd6756f..c3b76b0d 100644 --- a/hal/platform_api.h +++ b/hal/platform_api.h @@ -178,4 +178,5 @@ int platform_retrieve_audio_cal(void* platform, int acdb_dev_id, int acdb_device void* data, int* length); unsigned char* platform_get_license(void* platform, int* size); +int platform_get_max_mic_count(void *platform); #endif // AUDIO_PLATFORM_API_H