Fix threading issue in BlockingAudioTrack.

This fixes the issue where one thread calls .stop() on
mAudioTrack that was released (or being released) by other thread.

Bug: 7029291
Change-Id: Ia6db803e8ee40379b63327acf578466127cfabcb
This commit is contained in:
Przemyslaw Szczepaniak
2012-08-23 17:45:46 +01:00
committed by Android (Google) Code Review
parent c5fd6e59db
commit 70574efd8f

View File

@@ -69,7 +69,8 @@ class BlockingAudioTrack {
// Need to be seen by stop() which can be called from another thread. mAudioTrack will be
// set to null only after waitAndRelease().
private volatile AudioTrack mAudioTrack;
private Object mAudioTrackLock = new Object();
private AudioTrack mAudioTrack;
private volatile boolean mStopped;
BlockingAudioTrack(int streamType, int sampleRate,
@@ -93,7 +94,9 @@ class BlockingAudioTrack {
public boolean init() {
AudioTrack track = createStreamingAudioTrack();
mAudioTrack = track;
synchronized (mAudioTrackLock) {
mAudioTrack = track;
}
if (track == null) {
return false;
@@ -103,24 +106,34 @@ class BlockingAudioTrack {
}
public void stop() {
AudioTrack track = mAudioTrack;
if (track != null) {
track.stop();
synchronized (mAudioTrackLock) {
if (mAudioTrack != null) {
mAudioTrack.stop();
}
mStopped = true;
}
mStopped = true;
}
public int write(byte[] data) {
if (mAudioTrack == null || mStopped) {
AudioTrack track = null;
synchronized (mAudioTrackLock) {
track = mAudioTrack;
}
if (track == null || mStopped) {
return -1;
}
final int bytesWritten = writeToAudioTrack(mAudioTrack, data);
final int bytesWritten = writeToAudioTrack(track, data);
mBytesWritten += bytesWritten;
return bytesWritten;
}
public void waitAndRelease() {
AudioTrack track = mAudioTrack;
AudioTrack track = null;
synchronized (mAudioTrackLock) {
track = mAudioTrack;
}
if (track == null) {
if (DBG) Log.d(TAG, "Audio track null [duplicate call to waitAndRelease ?]");
return;
@@ -152,8 +165,10 @@ class BlockingAudioTrack {
// all data from the audioTrack has been sent to the mixer, so
// it's safe to release at this point.
if (DBG) Log.d(TAG, "Releasing audio track [" + track.hashCode() + "]");
synchronized(mAudioTrackLock) {
mAudioTrack = null;
}
track.release();
mAudioTrack = null;
}