diff options
author | Steve Kondik <steve@cyngn.com> | 2016-04-13 11:13:53 -0700 |
---|---|---|
committer | Steve Kondik <steve@cyngn.com> | 2016-04-20 09:25:29 -0700 |
commit | 45ed070d0ac61d196bfcbd0114220db3a447cfa7 (patch) | |
tree | 6233125553efd70fb7a114ddedc68b9ea214c657 | |
parent | 2a77bee753fa7b56186c0c4e848d12215b454b53 (diff) | |
download | android_hardware_qcom_audio-45ed070d0ac61d196bfcbd0114220db3a447cfa7.tar.gz android_hardware_qcom_audio-45ed070d0ac61d196bfcbd0114220db3a447cfa7.tar.bz2 android_hardware_qcom_audio-45ed070d0ac61d196bfcbd0114220db3a447cfa7.zip |
hal: Various upstream fixes and sanity checks
* Fix issues with soundtrigger and possible crashes.
Change-Id: I7a455c176b97097464592a922154a62a0aa2283e
-rw-r--r-- | hal/audio_extn/soundtrigger.c | 16 | ||||
-rw-r--r-- | hal/audio_hw.c | 103 |
2 files changed, 88 insertions, 31 deletions
diff --git a/hal/audio_extn/soundtrigger.c b/hal/audio_extn/soundtrigger.c index c502f66a..1630b2df 100644 --- a/hal/audio_extn/soundtrigger.c +++ b/hal/audio_extn/soundtrigger.c @@ -15,7 +15,7 @@ * limitations under the License. */ #define LOG_TAG "soundtrigger" -/* #define LOG_NDEBUG 0 */ +/*#define LOG_NDEBUG 0*/ #define LOG_NDDEBUG 0 #include <errno.h> @@ -134,15 +134,17 @@ int audio_extn_sound_trigger_read(struct stream_in *in, void *buffer, if (in->standby) in->standby = false; + ALOGD("audio_extn_sound_trigger_read"); + pthread_mutex_lock(&st_dev->lock); st_info = get_sound_trigger_info(in->capture_handle); - pthread_mutex_unlock(&st_dev->lock); if (st_info) { event.u.aud_info.ses_info = &st_info->st_ses; event.u.aud_info.buf = buffer; event.u.aud_info.num_bytes = bytes; ret = st_dev->st_callback(AUDIO_EVENT_READ_SAMPLES, &event); } + pthread_mutex_unlock(&st_dev->lock); exit: if (ret) { @@ -150,7 +152,7 @@ exit: in->is_st_session_active = false; memset(buffer, 0, bytes); ALOGV("%s: read failed status %d - sleep", __func__, ret); - usleep((bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) * + usleep(((int64_t)bytes * 1000000) / (audio_stream_in_frame_size((struct audio_stream_in *)in) * in->config.rate)); } return ret; @@ -165,15 +167,17 @@ void audio_extn_sound_trigger_stop_lab(struct stream_in *in) if (!st_dev || !in || !in->is_st_session_active) return; + ALOGD("audio_extn_sound_trigger_stop_lab"); + pthread_mutex_lock(&st_dev->lock); st_ses_info = get_sound_trigger_info(in->capture_handle); - pthread_mutex_unlock(&st_dev->lock); if (st_ses_info) { event.u.ses_info = st_ses_info->st_ses; ALOGV("%s: AUDIO_EVENT_STOP_LAB pcm %p", __func__, st_ses_info->st_ses.pcm); st_dev->st_callback(AUDIO_EVENT_STOP_LAB, &event); in->is_st_session_active = false; } + pthread_mutex_unlock(&st_dev->lock); } void audio_extn_sound_trigger_check_and_get_session(struct stream_in *in) { @@ -227,6 +231,7 @@ void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device, ALOGI("%s: device 0x%x of type %d for Event %d", __func__, snd_device, device_type, event); if (device_type == PCM_CAPTURE) { + pthread_mutex_lock(&st_dev->lock); switch(event) { case ST_EVENT_SND_DEVICE_FREE: st_dev->st_callback(AUDIO_EVENT_CAPTURE_DEVICE_INACTIVE, NULL); @@ -238,6 +243,7 @@ void audio_extn_sound_trigger_update_device_status(snd_device_t snd_device, ALOGW("%s:invalid event %d for device 0x%x", __func__, event, snd_device); } + pthread_mutex_unlock(&st_dev->lock); }/*Events for output device, if required can be placed here in else*/ } @@ -253,6 +259,7 @@ void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused, return; } + pthread_mutex_lock(&st_dev->lock); ret = str_parms_get_str(params, "SND_CARD_STATUS", value, sizeof(value)); if (ret > 0) { @@ -287,6 +294,7 @@ void audio_extn_sound_trigger_set_parameters(struct audio_device *adev __unused, event.u.value = val; st_dev->st_callback(AUDIO_EVENT_NUM_ST_SESSIONS, &event); } + pthread_mutex_unlock(&st_dev->lock); } int audio_extn_sound_trigger_init(struct audio_device *adev) diff --git a/hal/audio_hw.c b/hal/audio_hw.c index 06bd2b7b..ada5ecec 100644 --- a/hal/audio_hw.c +++ b/hal/audio_hw.c @@ -336,8 +336,6 @@ int enable_snd_device(struct audio_device *adev, return -EINVAL; } - platform_send_audio_calibration(adev->platform, snd_device); - adev->snd_dev_ref_cnt[snd_device]++; if (adev->snd_dev_ref_cnt[snd_device] > 1) { ALOGV("%s: snd_device(%d: %s) is already active", @@ -345,11 +343,6 @@ int enable_snd_device(struct audio_device *adev, return 0; } - /* due to the possibility of calibration overwrite between listen - and audio, notify sound trigger hal before audio calibration is sent */ - audio_extn_sound_trigger_update_device_status(snd_device, - ST_EVENT_SND_DEVICE_BUSY); - if (audio_extn_spkr_prot_is_enabled()) audio_extn_spkr_prot_calib_cancel(adev); @@ -359,12 +352,11 @@ int enable_snd_device(struct audio_device *adev, snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) && audio_extn_spkr_prot_is_enabled()) { if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) { - adev->snd_dev_ref_cnt[snd_device]--; - return -EINVAL; + goto out_error; } if (audio_extn_spkr_prot_start_processing(snd_device)) { ALOGE("%s: spkr_start_processing failed", __func__); - return -EINVAL; + goto out_error; } } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) { for (i = 0; i < num_devices; i++) { @@ -373,11 +365,21 @@ int enable_snd_device(struct audio_device *adev, platform_set_speaker_gain_in_combo(adev, snd_device, true); } else { const char * dev_path = platform_get_snd_device_name(snd_device); - ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path); + audio_extn_sound_trigger_update_device_status(snd_device, + ST_EVENT_SND_DEVICE_BUSY); + /* due to the possibility of calibration overwrite between listen + and audio, notify sound trigger hal before audio calibration is sent */ + ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, dev_path); + platform_send_audio_calibration(adev->platform, snd_device); audio_route_apply_and_update_path(adev->audio_route, dev_path); } return 0; + +out_error: + adev->snd_dev_ref_cnt[snd_device]--; + audio_extn_sound_trigger_update_device_status(snd_device, ST_EVENT_SND_DEVICE_FREE); + return -EINVAL; } int disable_snd_device(struct audio_device *adev, @@ -878,7 +880,13 @@ int start_input_stream(struct stream_in *in) } ALOGV("%s: pcm_prepare start", __func__); - pcm_prepare(in->pcm); + ret = pcm_prepare(in->pcm); + if (ret < 0) { + ALOGE("%s: pcm_prepare returned %d", __func__, ret); + pcm_close(in->pcm); + in->pcm = NULL; + goto error_open; + } audio_extn_perf_lock_release(); @@ -1250,9 +1258,15 @@ int start_output_stream(struct stream_out *out) break; } ALOGV("%s: pcm_prepare start", __func__); - if (pcm_is_ready(out->pcm)) - pcm_prepare(out->pcm); - + if (pcm_is_ready(out->pcm)) { + ret = pcm_prepare(out->pcm); + if (ret < 0) { + ALOGE("%s: pcm_prepare returned %d", __func__, ret); + pcm_close(out->pcm); + out->pcm = NULL; + goto error_open; + } + } } else { out->pcm = NULL; out->compr = compress_open(adev->snd_card, out->pcm_device_id, @@ -1655,7 +1669,7 @@ static ssize_t out_write_for_no_output(struct audio_stream_out *stream, * Sleep for the amount of buffer duration */ lock_output_stream(out); - usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) / + usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) / out_get_sample_rate(&out->stream.common)); pthread_mutex_unlock(&out->lock); return bytes; @@ -2001,11 +2015,13 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs); parms = str_parms_create_str(kvpairs); - ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value)); - + if (!parms) + goto error; lock_input_stream(in); - pthread_mutex_lock(&adev->lock); + + ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value)); + if (ret >= 0) { val = atoi(value); /* no audio source uses val == 0 */ @@ -2021,7 +2037,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) if (((int)in->device != val) && (val != 0)) { in->device = val; /* If recording is in progress, change the tx device to new device */ - if (!in->standby) + if (!in->standby && !in->is_st_session) status = select_devices(adev, in->usecase); } } @@ -2030,6 +2046,8 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_unlock(&in->lock); str_parms_destroy(parms); + +error: ALOGV("%s: exit: status(%d)", __func__, status); return status; } @@ -2037,7 +2055,20 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) static char* in_get_parameters(const struct audio_stream *stream __unused, const char *keys __unused) { - return strdup(""); + struct str_parms *reply = str_parms_create_str(keys); + char *str; + + if (!reply) { + ALOGE("in_get_parameters: failed to create query or reply"); + return NULL; + } + + ALOGV("%s: enter: keys - %s", __func__, keys); + + str = str_parms_to_str(reply); + str_parms_destroy(reply); + + return str; } static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused) @@ -2080,8 +2111,11 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, if (in->pcm) { if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) { ret = pcm_mmap_read(in->pcm, buffer, bytes); - } else + } else { + ALOGVV("%s: reading buffer (%d bytes) from pcm device (handle=%d)", __func__, + bytes, in->capture_handle); ret = pcm_read(in->pcm, buffer, bytes); + } if (ret < 0) ret = -errno; } @@ -2101,9 +2135,10 @@ exit: pthread_mutex_unlock(&in->lock); if (ret != 0) { + memset(buffer, 0, bytes); in_standby(&in->stream.common); ALOGV("%s: read failed - sleeping for buffer duration", __func__); - usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) / + usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) / in_get_sample_rate(&in->stream.common)); } return bytes; @@ -2193,6 +2228,15 @@ static int adev_open_output_stream(struct audio_hw_device *dev, *stream_out = NULL; out = (struct stream_out *)calloc(1, sizeof(struct stream_out)); + if (!out) { + return -ENOMEM; + } + + 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) devices = AUDIO_DEVICE_OUT_SPEAKER; @@ -2425,10 +2469,6 @@ static int adev_open_output_stream(struct audio_hw_device *dev, /* out->muted = false; by calloc() */ /* out->written = 0; by calloc() */ - 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); - config->format = out->stream.common.get_format(&out->stream.common); config->channel_mask = out->stream.common.get_channels(&out->stream.common); config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common); @@ -2534,6 +2574,8 @@ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) } audio_extn_hfp_set_parameters(adev, parms); + audio_extn_sound_trigger_set_parameters(adev, parms); + done: str_parms_destroy(parms); pthread_mutex_unlock(&adev->lock); @@ -2758,9 +2800,16 @@ err_open: static void adev_close_input_stream(struct audio_hw_device *dev __unused, struct audio_stream_in *stream) { + struct stream_in *in = (struct stream_in *)stream; + ALOGV("%s", __func__); in_standby(&stream->common); + + if (in->is_st_session) { + ALOGV("%s: sound trigger pcm stop lab", __func__); + audio_extn_sound_trigger_stop_lab(in); + } free(stream); return; |