diff options
author | Paul McLean <pmclean@google.com> | 2014-08-28 20:44:42 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-08-28 20:44:42 +0000 |
commit | 0f519a9e5ede300ba9fe5f307700585d33564982 (patch) | |
tree | fcb8acba20b352a431d540dd7faa8064a7150ceb | |
parent | c48cdc8ec0a07bca5e387041d58e9926c8b7c3de (diff) | |
parent | 2c6196f20c2ca25f6e7f8e0f752c2cbc00113538 (diff) | |
download | hardware_libhardware-0f519a9e5ede300ba9fe5f307700585d33564982.zip hardware_libhardware-0f519a9e5ede300ba9fe5f307700585d33564982.tar.gz hardware_libhardware-0f519a9e5ede300ba9fe5f307700585d33564982.tar.bz2 |
Merge "Fix problem with dropouts with multiple USB audio streams." into lmp-dev
-rw-r--r-- | include/hardware/audio.h | 2 | ||||
-rw-r--r-- | modules/usbaudio/alsa_device_profile.c | 8 | ||||
-rw-r--r-- | modules/usbaudio/alsa_device_profile.h | 2 | ||||
-rw-r--r-- | modules/usbaudio/alsa_device_proxy.c | 23 | ||||
-rw-r--r-- | modules/usbaudio/audio_hw.c | 48 |
5 files changed, 60 insertions, 23 deletions
diff --git a/include/hardware/audio.h b/include/hardware/audio.h index 59fb9a3..763ca58 100644 --- a/include/hardware/audio.h +++ b/include/hardware/audio.h @@ -124,6 +124,8 @@ __BEGIN_DECLS #define AUDIO_PARAMETER_STREAM_INPUT_SOURCE "input_source" /* audio_source_t */ #define AUDIO_PARAMETER_STREAM_SAMPLING_RATE "sampling_rate" /* uint32_t */ +#define AUDIO_PARAMETER_DEVICE_DISCONNECT "disconnect" /* audio_devices_t */ + /* Query supported formats. The response is a '|' separated list of strings from * audio_format_t enum e.g: "sup_formats=AUDIO_FORMAT_PCM_16_BIT" */ #define AUDIO_PARAMETER_STREAM_SUP_FORMATS "sup_formats" diff --git a/modules/usbaudio/alsa_device_profile.c b/modules/usbaudio/alsa_device_profile.c index 9deedce..c7df00c 100644 --- a/modules/usbaudio/alsa_device_profile.c +++ b/modules/usbaudio/alsa_device_profile.c @@ -92,6 +92,14 @@ bool profile_is_valid(alsa_device_profile* profile) { return profile->is_valid; } +bool profile_is_cached_for(alsa_device_profile* profile, int card, int device) { + return card == profile->card && device == profile->device; +} + +void profile_decache(alsa_device_profile* profile) { + profile->card = profile->device = -1; +} + /* * Returns the supplied value rounded up to the next even multiple of 16 */ diff --git a/modules/usbaudio/alsa_device_profile.h b/modules/usbaudio/alsa_device_profile.h index b75e1dc..2c0da39 100644 --- a/modules/usbaudio/alsa_device_profile.h +++ b/modules/usbaudio/alsa_device_profile.h @@ -61,6 +61,8 @@ typedef struct { void profile_init(alsa_device_profile* profile, int direction); bool profile_is_initialized(alsa_device_profile* profile); bool profile_is_valid(alsa_device_profile* profile); +bool profile_is_cached_for(alsa_device_profile* profile, int card, int device); +void profile_decache(alsa_device_profile* profile); bool profile_read_device_info(alsa_device_profile* profile); diff --git a/modules/usbaudio/alsa_device_proxy.c b/modules/usbaudio/alsa_device_proxy.c index e15f093..081c05b 100644 --- a/modules/usbaudio/alsa_device_proxy.c +++ b/modules/usbaudio/alsa_device_proxy.c @@ -27,20 +27,6 @@ #define DEFAULT_PERIOD_SIZE 1024 #define DEFAULT_PERIOD_COUNT 2 -//void proxy_init(alsa_device_proxy * proxy) -//{ -// proxy->profile = NULL; -// -// proxy->alsa_config.format = DEFAULT_SAMPLE_FORMAT; -// proxy->alsa_config.rate = DEFAULT_SAMPLE_RATE; -// proxy->alsa_config.channels = DEFAULT_CHANNEL_COUNT; -// -// proxy->alsa_config.period_size = DEFAULT_PERIOD_SIZE; -// proxy->alsa_config.period_count = DEFAULT_PERIOD_COUNT; -// -// proxy->pcm = NULL; -//} - void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile, struct pcm_config * config) { @@ -79,7 +65,6 @@ void proxy_prepare(alsa_device_proxy * proxy, alsa_device_profile* profile, int proxy_open(alsa_device_proxy * proxy) { alsa_device_profile* profile = proxy->profile; - ALOGV("proxy_open(card:%d device:%d %s)", profile->card, profile->device, profile->direction == PCM_OUT ? "PCM_OUT" : "PCM_IN"); @@ -103,8 +88,12 @@ int proxy_open(alsa_device_proxy * proxy) void proxy_close(alsa_device_proxy * proxy) { - pcm_close(proxy->pcm); - proxy->pcm = NULL; + ALOGV("proxy_close() [pcm:%p]", proxy->pcm); + + if (proxy->pcm != NULL) { + pcm_close(proxy->pcm); + proxy->pcm = NULL; + } } /* diff --git a/modules/usbaudio/audio_hw.c b/modules/usbaudio/audio_hw.c index 4310855..caddf97 100644 --- a/modules/usbaudio/audio_hw.c +++ b/modules/usbaudio/audio_hw.c @@ -253,7 +253,6 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) const struct stream_out* out = (const struct stream_out*)stream; size_t buffer_size = proxy_get_period_size(&out->proxy) * audio_stream_out_frame_size(&(out->stream)); - ALOGV("out_get_buffer_size() = %zu", buffer_size); return buffer_size; } @@ -327,7 +326,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) if (param_val >= 0) device = atoi(value); - if (card >= 0 && device >= 0) { + if (card >= 0 && device >= 0 && !profile_is_cached_for(out->profile, card, device)) { /* cannot read pcm device info if playback is active */ if (!out->standby) ret_value = -ENOSYS; @@ -343,6 +342,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) } } } + pthread_mutex_unlock(&out->lock); pthread_mutex_unlock(&out->dev->lock); str_parms_destroy(parms); @@ -401,7 +401,6 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, si } pthread_mutex_unlock(&out->dev->lock); - alsa_device_proxy* proxy = &out->proxy; const void * write_buff = buffer; int num_write_buff_bytes = bytes; @@ -516,6 +515,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, // build this to hand to the alsa_device_proxy struct pcm_config proxy_config; + memset(&proxy_config, 0, sizeof(proxy_config)); int ret = 0; @@ -704,7 +704,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) pthread_mutex_lock(&in->dev->lock); pthread_mutex_lock(&in->lock); - /* Card/Device */ + /* Device Connection Message ("card=1,device=0") */ param_val = str_parms_get_str(parms, "card", value, sizeof(value)); if (param_val >= 0) card = atoi(value); @@ -713,7 +713,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) if (param_val >= 0) device = atoi(value); - if (card >= 0 && device >= 0) { + if (card >= 0 && device >= 0 && !profile_is_cached_for(in->profile, card, device)) { /* cannot read pcm device info if playback is active */ if (!in->standby) ret_value = -ENOSYS; @@ -728,7 +728,7 @@ static int in_set_parameters(struct audio_stream *stream, const char *kvpairs) in->profile->device = saved_device; } } - } + } pthread_mutex_unlock(&in->lock); pthread_mutex_unlock(&in->dev->lock); @@ -923,6 +923,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->profile = &in->dev->in_profile; struct pcm_config proxy_config; + memset(&proxy_config, 0, sizeof(proxy_config)); /* Rate */ if (config->sample_rate == 0) { @@ -995,6 +996,41 @@ static void adev_close_input_stream(struct audio_hw_device *dev, struct audio_st */ static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) { + ALOGV("audio_hw:usb adev_set_parameters(%s)", kvpairs); + + struct audio_device * adev = (struct audio_device *)dev; + + char value[32]; + int param_val; + + struct str_parms * parms = str_parms_create_str(kvpairs); + + /* Check for the "disconnect" message */ + param_val = str_parms_get_str(parms, "disconnect", value, sizeof(value)); + if (param_val >= 0) { + audio_devices_t device = (audio_devices_t)atoi(value); + + param_val = str_parms_get_str(parms, "card", value, sizeof(value)); + int alsa_card = param_val >= 0 ? atoi(value) : -1; + + param_val = str_parms_get_str(parms, "device", value, sizeof(value)); + int alsa_device = param_val >= 0 ? atoi(value) : -1; + + if (alsa_card >= 0 && alsa_device >= 0) { + /* "decache" the profile */ + pthread_mutex_lock(&adev->lock); + if (device == AUDIO_DEVICE_OUT_USB_DEVICE && + profile_is_cached_for(&adev->out_profile, alsa_card, alsa_device)) { + profile_decache(&adev->out_profile); + } + if (device == AUDIO_DEVICE_IN_USB_DEVICE && + profile_is_cached_for(&adev->in_profile, alsa_card, alsa_device)) { + profile_decache(&adev->in_profile); + } + pthread_mutex_unlock(&adev->lock); + } + } + return 0; } |