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