From ec647fa1db61806a334fc883fb98679768ac4d0b Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Wed, 13 Jan 2016 18:09:37 -0800 Subject: [PATCH] A2DP audio HAL: fix write error behavior Do not return -1 status in case of write error but emulate normal timing and return the number of bytes written as if no error had occured. This is because audio flinger does not take any recovery action in case of write error anyway but does not increment the number of frames written to the HAL. In case of persisting error, active audio tracks will not finish playback and a wakelock will be held indefinitely. Bug: 25488825 Change-Id: I4f00ba8d7a5c55f70520d448d894240c54685027 --- audio_a2dp_hw/audio_a2dp_hw.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c index 6c8e30c7a..97acc63a6 100644 --- a/audio_a2dp_hw/audio_a2dp_hw.c +++ b/audio_a2dp_hw/audio_a2dp_hw.c @@ -189,7 +189,7 @@ static int calc_audiotime(struct a2dp_config cfg, int bytes) ASSERTC(cfg.format == AUDIO_FORMAT_PCM_16_BIT, "unsupported sample sz", cfg.format); - return bytes*(1000000/(chan_count*2))/cfg.rate; + return (int)(((int64_t)bytes * (1000000 / (chan_count * 2))) / cfg.rate); } /***************************************************************************** @@ -550,6 +550,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, { struct a2dp_stream_out *out = (struct a2dp_stream_out *)stream; int sent; + int us_delay; DEBUG("write %zu bytes (fd %d)", bytes, out->common.audio_fd); @@ -559,7 +560,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, { DEBUG("stream suspended"); pthread_mutex_unlock(&out->common.lock); - return -1; + goto error; } /* only allow autostarting if we are in stopped or standby */ @@ -568,23 +569,15 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, { if (start_audio_datapath(&out->common) < 0) { - /* emulate time this write represents to avoid very fast write - failures during transition periods or remote suspend */ - - int us_delay = calc_audiotime(out->common.cfg, bytes); - - DEBUG("emulate a2dp write delay (%d us)", us_delay); - - usleep(us_delay); pthread_mutex_unlock(&out->common.lock); - return -1; + goto error; } } else if (out->common.state != AUDIO_A2DP_STATE_STARTED) { ERROR("stream not in stopped or standby"); pthread_mutex_unlock(&out->common.lock); - return -1; + goto error; } pthread_mutex_unlock(&out->common.lock); @@ -597,14 +590,21 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, out->common.state = AUDIO_A2DP_STATE_STOPPED; else ERROR("write failed : stream suspended, avoid resetting state"); - } else { - const size_t frames = bytes / audio_stream_out_frame_size(stream); - out->frames_rendered += frames; - out->frames_presented += frames; + goto error; } - DEBUG("wrote %d bytes out of %zu bytes", sent, bytes); - return sent; + const size_t frames = bytes / audio_stream_out_frame_size(stream); + out->frames_rendered += frames; + out->frames_presented += frames; + return bytes; + +error: + us_delay = calc_audiotime(out->common.cfg, bytes); + + DEBUG("emulate a2dp write delay (%d us)", us_delay); + + usleep(us_delay); + return bytes; } -- 2.11.0