/* * Copyright (c) 2015, 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 "source_track" /*#define LOG_NDEBUG 0*/ #define LOG_NDDEBUG 0 #include #include #include #include "audio_hw.h" #include "platform.h" #include "platform_api.h" #include "voice_extn.h" #include #include #ifdef SOURCE_TRACKING_ENABLED /* Audio Paramater Key to identify the list of start angles. * Starting angle (in degrees) defines the boundary starting angle for each sector. */ #define AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES "SoundFocus.start_angles" /* Audio Paramater Key to identify the list of enable flags corresponding to each sector. */ #define AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS "SoundFocus.enable_sectors" /* Audio Paramater Key to identify the gain step value to be applied to all enabled sectors. */ #define AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP "SoundFocus.gain_step" /* Audio Paramater Key to identify the list of voice activity detector outputs corresponding * to each sector. */ #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD "SourceTrack.vad" /* Audio Paramater Key to identify the direction (in degrees) of arrival for desired talker * (dominant source of speech). */ #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH "SourceTrack.doa_speech" /* Audio Paramater Key to identify the list of directions (in degrees) of arrival for * interferers (interfering noise sources). */ #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE "SourceTrack.doa_noise" /* Audio Paramater Key to identify the list of sound strength indicators at each degree * of the horizontal plane referred to by a full circle (360 degrees). */ #define AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY "SourceTrack.polar_activity" #define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES 0x1 #define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS 0x2 #define BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP 0x4 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD 0x8 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH 0x10 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE 0x20 #define BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY 0x40 #define BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS \ (BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES |\ BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS |\ BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP) #define BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING \ (BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD |\ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH |\ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE |\ BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) #define MAX_SECTORS 8 #define MAX_STR_SIZE 2048 struct audio_device_to_audio_interface audio_device_to_interface_table[]; int audio_device_to_interface_table_len; struct sound_focus_param { uint16_t start_angle[MAX_SECTORS]; uint8_t enable[MAX_SECTORS]; uint16_t gain_step; }; struct source_tracking_param { uint8_t vad[MAX_SECTORS]; uint16_t doa_speech; uint16_t doa_noise[3]; uint8_t polar_activity[360]; }; static int add_audio_intf_name_to_mixer_ctl(audio_devices_t device, char *mixer_ctl_name, struct audio_device_to_audio_interface *table, int len) { int ret = 0; int i; if (table == NULL) { ALOGE("%s: table is NULL", __func__); ret = -EINVAL; goto done; } if (mixer_ctl_name == NULL) { ret = -EINVAL; goto done; } for (i=0; i < len; i++) { if (device == table[i].device) { strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH); strlcat(mixer_ctl_name, table[i].interface_name, MIXER_PATH_MAX_LENGTH); break; } } if (i == len) { ALOGE("%s: Audio Device not found in the table", __func__); ret = -EINVAL; } done: return ret; } static bool is_stt_supported_snd_device(snd_device_t snd_device) { bool ret = false; switch (snd_device) { case SND_DEVICE_IN_HANDSET_DMIC: case SND_DEVICE_IN_HANDSET_DMIC_AEC: case SND_DEVICE_IN_HANDSET_DMIC_NS: case SND_DEVICE_IN_HANDSET_DMIC_AEC_NS: case SND_DEVICE_IN_HANDSET_STEREO_DMIC: case SND_DEVICE_IN_HANDSET_QMIC: case SND_DEVICE_IN_VOICE_DMIC: case SND_DEVICE_IN_VOICE_REC_DMIC_FLUENCE: case SND_DEVICE_IN_HEADSET_MIC_FLUENCE: case SND_DEVICE_IN_SPEAKER_DMIC: case SND_DEVICE_IN_SPEAKER_DMIC_AEC: case SND_DEVICE_IN_SPEAKER_DMIC_NS: case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS: case SND_DEVICE_IN_SPEAKER_DMIC_AEC_NS_BROADSIDE: case SND_DEVICE_IN_SPEAKER_DMIC_AEC_BROADSIDE: case SND_DEVICE_IN_SPEAKER_DMIC_NS_BROADSIDE: case SND_DEVICE_IN_SPEAKER_QMIC_AEC: case SND_DEVICE_IN_SPEAKER_QMIC_NS: case SND_DEVICE_IN_SPEAKER_QMIC_AEC_NS: case SND_DEVICE_IN_VOICE_SPEAKER_DMIC: case SND_DEVICE_IN_VOICE_SPEAKER_DMIC_BROADSIDE: case SND_DEVICE_IN_VOICE_SPEAKER_QMIC: ret = true; break; default: break; } return ret; } audio_devices_t get_input_audio_device(audio_devices_t device) { audio_devices_t in_device = device; switch (device) { case AUDIO_DEVICE_OUT_EARPIECE: case AUDIO_DEVICE_OUT_WIRED_HEADPHONE: in_device = AUDIO_DEVICE_IN_BUILTIN_MIC; break; case AUDIO_DEVICE_OUT_SPEAKER: in_device = AUDIO_DEVICE_IN_BACK_MIC; break; case AUDIO_DEVICE_OUT_WIRED_HEADSET: in_device = AUDIO_DEVICE_IN_WIRED_HEADSET; break; case AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET: in_device = AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET; break; default: break; } return in_device; } static int derive_mixer_ctl_from_usecase_intf(struct audio_device *adev, char *mixer_ctl_name) { struct audio_usecase *usecase = NULL; audio_devices_t in_device; int ret = 0; if (mixer_ctl_name == NULL) { ALOGE("%s: mixer_ctl_name is NULL", __func__); ret = -EINVAL; goto done; } if (voice_is_in_call(adev)) { strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH); strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH); usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, VOICE_CALL)); } else if (voice_extn_compress_voip_is_active(adev)) { strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH); strlcat(mixer_ctl_name, "Voice Tx", MIXER_PATH_MAX_LENGTH); usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL); } else { strlcat(mixer_ctl_name, " ", MIXER_PATH_MAX_LENGTH); strlcat(mixer_ctl_name, "Audio Tx", MIXER_PATH_MAX_LENGTH); usecase = get_usecase_from_list(adev, get_usecase_id_from_usecase_type(adev, PCM_CAPTURE)); } if (usecase && (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) { if (is_stt_supported_snd_device(usecase->in_snd_device)) { in_device = get_input_audio_device(usecase->devices); ret = add_audio_intf_name_to_mixer_ctl(in_device, mixer_ctl_name, audio_device_to_interface_table, audio_device_to_interface_table_len); } else { ALOGE("%s: Sound Focus/Source Tracking not supported on the input sound device (%s)", __func__, platform_get_snd_device_name(usecase->in_snd_device)); ret = -EINVAL; } } else { ALOGE("%s: No use case is active which supports Sound Focus/Source Tracking", __func__); ret = -EINVAL; } done: return ret; } static int parse_soundfocus_sourcetracking_keys(struct str_parms *parms) { char *str; char *value = NULL; int val, len; int ret = 0, err; char *kv_pairs = str_parms_to_str(parms); ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs); len = strlen(kv_pairs); value = (char*)calloc(len, sizeof(char)); if(value == NULL) { ret = -ENOMEM; ALOGE("%s: failed to allocate memory", __func__); goto done; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE; } err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value, len); if (err >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY); ret = ret | BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY; } done: free(kv_pairs); if(value != NULL) free(value); ALOGV("%s: returning bitmask = %d", __func__, ret); return ret; } static int get_soundfocus_sourcetracking_data(struct audio_device *adev, const int bitmask, struct sound_focus_param *sound_focus_data, struct source_tracking_param *source_tracking_data) { struct mixer_ctl *ctl; char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus"; char source_tracking_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Source Tracking"; int ret = -EINVAL; int i, count; if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOUND_FOCUS) { /* Derive the mixer control name based on the use case and the audio interface * for the corresponding audio device */ ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name); if (ret != 0) { ALOGE("%s: Could not get Sound Focus Params", __func__); goto done; } else { ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name); } ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, sound_focus_mixer_ctl_name); ret = -EINVAL; goto done; } else { ALOGV("%s: Getting Sound Focus Params", __func__); mixer_ctl_update(ctl); count = mixer_ctl_get_num_values(ctl); if (count != sizeof(struct sound_focus_param)) { ALOGE("%s: mixer_ctl_get_num_values() invalid sound focus data size", __func__); ret = -EINVAL; goto done; } ret = mixer_ctl_get_array(ctl, (void *)sound_focus_data, count); if (ret != 0) { ALOGE("%s: mixer_ctl_get_array() failed to get Sound Focus Params", __func__); ret = -EINVAL; goto done; } } } if (bitmask & BITMASK_AUDIO_PARAMETER_KEYS_SOURCE_TRACKING) { /* Derive the mixer control name based on the use case and the audio interface * for the corresponding audio device */ ret = derive_mixer_ctl_from_usecase_intf(adev, source_tracking_mixer_ctl_name); if (ret != 0) { ALOGE("%s: Could not get Source Tracking Params", __func__); goto done; } else { ALOGV("%s: Mixer Ctl name: %s", __func__, source_tracking_mixer_ctl_name); } ctl = mixer_get_ctl_by_name(adev->mixer, source_tracking_mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, source_tracking_mixer_ctl_name); ret = -EINVAL; goto done; } else { ALOGV("%s: Getting Source Tracking Params", __func__); mixer_ctl_update(ctl); count = mixer_ctl_get_num_values(ctl); if (count != sizeof(struct source_tracking_param)) { ALOGE("%s: mixer_ctl_get_num_values() invalid source tracking data size", __func__); ret = -EINVAL; goto done; } ret = mixer_ctl_get_array(ctl, (void *)source_tracking_data, count); if (ret != 0) { ALOGE("%s: mixer_ctl_get_array() failed to get Source Tracking Params", __func__); ret = -EINVAL; goto done; } } } done: return ret; } static void send_soundfocus_sourcetracking_params(struct str_parms *reply, const int bitmask, const struct sound_focus_param sound_focus_data, const struct source_tracking_param source_tracking_data) { int i = 0, len = 0; char value[MAX_STR_SIZE] = ""; if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES) { for (i = 0; i < MAX_SECTORS; i++) { if ((i >=4) && (sound_focus_data.start_angle[i] == 0xFFFF)) continue; if (i) snprintf(value + strlen(value), MAX_STR_SIZE, ","); snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.start_angle[i]); } str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value); } strlcpy(value, "", sizeof("")); if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS) { for (i = 0; i < MAX_SECTORS; i++) { if ((i >=4) && (sound_focus_data.enable[i] == 0xFF)) continue; if (i) snprintf(value + strlen(value), MAX_STR_SIZE, ","); snprintf(value + strlen(value), MAX_STR_SIZE, "%d", sound_focus_data.enable[i]); } str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value); } if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP) str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, sound_focus_data.gain_step); strlcpy(value, "", sizeof("")); if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD) { for (i = 0; i < MAX_SECTORS; i++) { if ((i >=4) && (source_tracking_data.vad[i] == 0xFF)) continue; if (i) snprintf(value + strlen(value), MAX_STR_SIZE, ","); snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.vad[i]); } str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_VAD, value); } if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH) str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_SPEECH, source_tracking_data.doa_speech); strlcpy(value, "", sizeof("")); if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE) { snprintf(value, MAX_STR_SIZE, "%d,%d,%d", source_tracking_data.doa_noise[0], source_tracking_data.doa_noise[1], source_tracking_data.doa_noise[2]); str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_DOA_NOISE, value); } strlcpy(value, "", sizeof("")); if (bitmask & BITMASK_AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY) { for (i = 0; i < 360; i++) { if (i) snprintf(value + strlen(value), MAX_STR_SIZE, ","); snprintf(value + strlen(value), MAX_STR_SIZE, "%d", source_tracking_data.polar_activity[i]); } str_parms_add_str(reply, AUDIO_PARAMETER_KEY_SOURCE_TRACK_POLAR_ACTIVITY, value); } } void audio_extn_source_track_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { int bitmask = 0, ret = 0; struct sound_focus_param sound_focus_data; struct source_tracking_param source_tracking_data; memset(&sound_focus_data, 0xFF, sizeof(struct sound_focus_param)); memset(&source_tracking_data, 0xFF, sizeof(struct source_tracking_param)); // Parse the input parameters string for Source Tracking keys bitmask = parse_soundfocus_sourcetracking_keys(query); if (bitmask) { // Get the parameter values from the backend ret = get_soundfocus_sourcetracking_data(adev, bitmask, &sound_focus_data, &source_tracking_data); if (ret == 0) { // Construct the return string with key, value pairs send_soundfocus_sourcetracking_params(reply, bitmask, sound_focus_data, source_tracking_data); } } } void audio_extn_source_track_set_parameters(struct audio_device *adev, struct str_parms *parms) { int len, ret, count;; struct mixer_ctl *ctl; char sound_focus_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Sound Focus"; char *value = NULL; char *kv_pairs = str_parms_to_str(parms); len = strlen(kv_pairs); value = (char*)calloc(len, sizeof(char)); if(value == NULL) { ret = -ENOMEM; ALOGE("%s: failed to allocate memory", __func__); goto done; } // Parse the input parameter string for Source Tracking key, value pairs ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES, value, len); if (ret >= 0) { char *saveptr, *tok; int i = 0, val; struct sound_focus_param sound_focus_param; memset(&sound_focus_param, 0xFF, sizeof(struct sound_focus_param)); str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_START_ANGLES); tok = strtok_r(value, ",", &saveptr); while ((i < MAX_SECTORS) && (tok != NULL)) { if (sscanf(tok, "%d", &val) == 1) { sound_focus_param.start_angle[i++] = (uint16_t)val; } tok = strtok_r(NULL, ",", &saveptr); } ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS, value, len); if (ret >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_ENABLE_SECTORS); tok = strtok_r(value, ",", &saveptr); i = 0; while ((i < MAX_SECTORS) && (tok != NULL)) { if (sscanf(tok, "%d", &val) == 1) { sound_focus_param.enable[i++] = (uint8_t)val; } tok = strtok_r(NULL, ",", &saveptr); } } else { ALOGE("%s: SoundFocus.enable_sectors key not found", __func__); goto done; } ret = str_parms_get_int(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP, &val); if (ret >= 0) { str_parms_del(parms, AUDIO_PARAMETER_KEY_SOUND_FOCUS_GAIN_STEP); sound_focus_param.gain_step = (uint16_t)val; } else { ALOGE("%s: SoundFocus.gain_step key not found", __func__); goto done; } /* Derive the mixer control name based on the use case and the audio h/w * interface name for the corresponding audio device */ ret = derive_mixer_ctl_from_usecase_intf(adev, sound_focus_mixer_ctl_name); if (ret != 0) { ALOGE("%s: Could not set Sound Focus Params", __func__); goto done; } else { ALOGV("%s: Mixer Ctl name: %s", __func__, sound_focus_mixer_ctl_name); } ctl = mixer_get_ctl_by_name(adev->mixer, sound_focus_mixer_ctl_name); if (!ctl) { ALOGE("%s: Could not get ctl for mixer cmd - %s", __func__, sound_focus_mixer_ctl_name); goto done; } else { ALOGV("%s: Setting Sound Focus Params", __func__); for (i = 0; i < MAX_SECTORS;i++) { ALOGV("%s: start_angles[%d] = %d", __func__, i, sound_focus_param.start_angle[i]); } for (i = 0; i < MAX_SECTORS;i++) { ALOGV("%s: enable_sectors[%d] = %d", __func__, i, sound_focus_param.enable[i]); } ALOGV("%s: gain_step = %d", __func__, sound_focus_param.gain_step); mixer_ctl_update(ctl); count = mixer_ctl_get_num_values(ctl); if (count != sizeof(struct sound_focus_param)) { ALOGE("%s: mixer_ctl_get_num_values() invalid data size", __func__); goto done; } // Set the parameters on the mixer control derived above ret = mixer_ctl_set_array(ctl, (void *)&sound_focus_param, count); if (ret != 0) { ALOGE("%s: mixer_ctl_set_array() failed to set Sound Focus Params", __func__); goto done; } } } done: free(kv_pairs); if(value != NULL) free(value); return; } #endif /* SOURCE_TRACKING_ENABLED end */