diff options
Diffstat (limited to 'hal')
-rw-r--r-- | hal/audio/6.0/audio_hw.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/hal/audio/6.0/audio_hw.c b/hal/audio/6.0/audio_hw.c index 09ed827..317d77e 100644 --- a/hal/audio/6.0/audio_hw.c +++ b/hal/audio/6.0/audio_hw.c @@ -61,6 +61,11 @@ // Max tone frequency to auto assign, don't want to generate too high of a pitch #define MAX_TONE_FREQUENCY 500 +// The average interval with which notifications come from the device (1 ms or 1000 us) +#define NOTIFICATION_AVR_INTERVAL_US 1000 +// The amount of times we try to read a notification from the device +#define MAX_READ_ATTEMPTS 100 + #define _bool_str(x) ((x)?"true":"false") static const char * const PROP_KEY_SIMULATE_MULTI_ZONE_AUDIO = "ro.aae.simulateMultiZoneAudio"; @@ -899,6 +904,25 @@ static bool is_tone_generator_device(struct generic_stream_in *in) { address_has_tone_keyword(in->bus_address)); } +static size_t read_frames_from_stream(void* dst, struct generic_stream_in* in, size_t frames_cnt) { + size_t frames_read = 0; + void *cur_dst = NULL; + audio_vbuffer_t *src = &in->buffer; + size_t frame_size = in->buffer.frame_size; + for (int attempt = 0; attempt < MAX_READ_ATTEMPTS; attempt++) { + cur_dst = &((uint8_t *)dst)[frames_read * frame_size]; + frames_read += audio_vbuffer_read(src, cur_dst, frames_cnt - frames_read); + if (frames_read == frames_cnt) + break; + // The next notification from the device informs about new available frames. + // Wait for a time of the order of one notification interval. + pthread_mutex_unlock(&in->lock); + usleep(NOTIFICATION_AVR_INTERVAL_US / 2); + pthread_mutex_lock(&in->lock); + } + return frames_read; +} + static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t bytes) { struct generic_stream_in *in = (struct generic_stream_in *)stream; struct generic_audio_device *adev = in->dev; @@ -945,7 +969,7 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte } pthread_mutex_lock(&in->lock); - int read_frames = 0; + size_t read_frames = 0; if (in->standby) { ALOGW("Input put to sleep while read in progress"); goto exit; @@ -966,7 +990,12 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte } } - read_frames = audio_vbuffer_read(&in->buffer, in->stereo_to_mono_buf, frames); + read_frames = read_frames_from_stream(in->stereo_to_mono_buf, in, frames); + if (read_frames != frames) { + ALOGE("Failed to read all the frames! Is the device dead?"); + goto exit; + } + // Currently only pcm 16 is supported. uint16_t *src = (uint16_t *)in->stereo_to_mono_buf; @@ -980,7 +1009,11 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, size_t byte dst += 1; } } else { - read_frames = audio_vbuffer_read(&in->buffer, buffer, frames); + read_frames = read_frames_from_stream(buffer, in, frames); + if (read_frames != frames) { + ALOGE("Failed to read all the frames! Is the device dead?"); + goto exit; + } } exit: |