diff options
author | Narayan Kamath <narayan@google.com> | 2011-07-19 12:43:17 +0100 |
---|---|---|
committer | Narayan Kamath <narayan@google.com> | 2011-07-19 12:43:17 +0100 |
commit | a36cce06a63ff0eb1c3a765ceb3863195732b4bf (patch) | |
tree | 6343989381976cfd91532d4cbea33ea907c65bf9 | |
parent | 90e5650f96dabadaaf141beae20a646855073ae1 (diff) | |
download | frameworks_base-a36cce06a63ff0eb1c3a765ceb3863195732b4bf.zip frameworks_base-a36cce06a63ff0eb1c3a765ceb3863195732b4bf.tar.gz frameworks_base-a36cce06a63ff0eb1c3a765ceb3863195732b4bf.tar.bz2 |
Fix a threading issue in AudioPlaybackHandler
Never allow the AudioTrack to be observed in a state where
it is release()d but non null.
Change-Id: I1e5b61355f30c2aafcd55ecdf83077d7a9d99c66
-rw-r--r-- | core/java/android/speech/tts/AudioPlaybackHandler.java | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index 96864c4..255b333 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -418,22 +418,30 @@ class AudioPlaybackHandler { if (DBG) Log.d(TAG, "handleSynthesisDone()"); final AudioTrack audioTrack = params.getAudioTrack(); - try { - if (audioTrack != null) { - if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + - audioTrack.hashCode()); - blockUntilDone(params); - if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); - // The last call to AudioTrack.write( ) will return only after - // all data from the audioTrack has been sent to the mixer, so - // it's safe to release at this point. - audioTrack.release(); - } - } finally { + if (audioTrack == null) { + return; + } + + if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + + audioTrack.hashCode()); + blockUntilDone(params); + if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); + + // The last call to AudioTrack.write( ) will return only after + // all data from the audioTrack has been sent to the mixer, so + // it's safe to release at this point. Make sure release() and the call + // that set the audio track to null are performed atomically. + synchronized (this) { + // Never allow the audioTrack to be observed in a state where + // it is released but non null. The only case this might happen + // is in the various stopFoo methods that call AudioTrack#stop from + // different threads, but they are synchronized on AudioPlayBackHandler#this + // too. + audioTrack.release(); params.setAudioTrack(null); - params.getDispatcher().dispatchUtteranceCompleted(); - mLastSynthesisRequest = null; } + params.getDispatcher().dispatchUtteranceCompleted(); + mLastSynthesisRequest = null; } private static void blockUntilDone(SynthesisMessageParams params) { |