am e35581ad: Merge "Fix regressions in TTS completion callbacks." into ics-mr1

* commit 'e35581ad5ad635f9dcfe4ab6a432c48b46b782cd':
  Fix regressions in TTS completion callbacks.
This commit is contained in:
Narayan Kamath
2011-11-24 09:40:04 -08:00
committed by Android Git Automerger
5 changed files with 65 additions and 19 deletions

View File

@@ -118,12 +118,26 @@ class AudioPlaybackHandler {
if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
stop(current);
}
final MessageParams lastSynthesis = mLastSynthesisRequest;
if (lastSynthesis != null && lastSynthesis != current &&
TextUtils.equals(callingApp, lastSynthesis.getCallingApp())) {
stop(lastSynthesis);
}
}
synchronized public void removeAllItems() {
if (DBG_THREADING) Log.d(TAG, "Removing all items");
removeAllMessages();
stop(getCurrentParams());
final MessageParams current = getCurrentParams();
final MessageParams lastSynthesis = mLastSynthesisRequest;
stop(current);
if (lastSynthesis != null && lastSynthesis != current) {
stop(lastSynthesis);
}
}
/**
@@ -350,7 +364,7 @@ class AudioPlaybackHandler {
// extra trouble to clean the data to prevent the AudioTrack resources
// from being leaked.
if (mLastSynthesisRequest != null) {
Log.w(TAG, "Error : Missing call to done() for request : " +
Log.e(TAG, "Error : Missing call to done() for request : " +
mLastSynthesisRequest);
handleSynthesisDone(mLastSynthesisRequest);
}
@@ -443,7 +457,11 @@ class AudioPlaybackHandler {
audioTrack.release();
params.setAudioTrack(null);
}
params.getDispatcher().dispatchOnDone();
if (params.isError()) {
params.getDispatcher().dispatchOnError();
} else {
params.getDispatcher().dispatchOnDone();
}
mLastSynthesisRequest = null;
params.mLogger.onWriteData();
}

View File

@@ -80,27 +80,23 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
@Override
void stop() {
stopImpl(false);
}
void stopImpl(boolean wasError) {
if (DBG) Log.d(TAG, "stop()");
// Note that mLogger.mError might be true too at this point.
mLogger.onStopped();
SynthesisMessageParams token = null;
SynthesisMessageParams token;
synchronized (mStateLock) {
if (mStopped) {
Log.w(TAG, "stop() called twice");
return;
}
// mToken will be null if the engine encounters
// an error before it called start().
if (mToken == null) {
// In all other cases, mAudioTrackHandler.stop() will
// result in onComplete being called.
mLogger.onWriteData();
} else {
token = mToken;
}
token = mToken;
mStopped = true;
}
@@ -109,7 +105,24 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
// point it will write an additional buffer to the token - but we
// won't worry about that because the audio playback queue will be cleared
// soon after (see SynthHandler#stop(String).
token.setIsError(wasError);
token.clearBuffers();
if (wasError) {
// Also clean up the audio track if an error occurs.
mAudioTrackHandler.enqueueSynthesisDone(token);
}
} else {
// This happens when stop() or error() were called before start() was.
// In all other cases, mAudioTrackHandler.stop() will
// result in onSynthesisDone being called, and we will
// write data there.
mLogger.onWriteData();
if (wasError) {
// We have to dispatch the error ourselves.
mDispatcher.dispatchOnError();
}
}
}
@@ -219,7 +232,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
// Currently, this call will not be logged if error( ) is called
// before start.
mLogger.onError();
stop();
stopImpl(true);
}
}

View File

@@ -51,6 +51,7 @@ final class SynthesisMessageParams extends MessageParams {
int mAudioBufferSize;
// Always synchronized on "this".
int mUnconsumedBytes;
volatile boolean mIsError;
private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
@@ -74,6 +75,7 @@ final class SynthesisMessageParams extends MessageParams {
mAudioTrack = null;
mBytesWritten = 0;
mAudioBufferSize = 0;
mIsError = false;
}
@Override
@@ -120,6 +122,14 @@ final class SynthesisMessageParams extends MessageParams {
return mAudioTrack;
}
void setIsError(boolean isError) {
mIsError = isError;
}
boolean isError() {
return mIsError;
}
// Must be called synchronized on this.
private long getUnconsumedAudioLengthMs() {
final int unconsumedFrames = mUnconsumedBytes / mBytesPerFrame;

View File

@@ -509,6 +509,7 @@ public abstract class TextToSpeechService extends Service {
}
class SynthesisSpeechItem extends SpeechItem {
// Never null.
private final String mText;
private final SynthesisRequest mSynthesisRequest;
private final String[] mDefaultLocale;
@@ -532,8 +533,8 @@ public abstract class TextToSpeechService extends Service {
@Override
public boolean isValid() {
if (TextUtils.isEmpty(mText)) {
Log.w(TAG, "Got empty text");
if (mText == null) {
Log.wtf(TAG, "Got null text");
return false;
}
if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {

View File

@@ -57,12 +57,16 @@ public abstract class UtteranceProgressListener {
listener.onUtteranceCompleted(utteranceId);
}
// The following methods are left unimplemented.
@Override
public void onStart(String utteranceId) { }
public void onError(String utteranceId) {
listener.onUtteranceCompleted(utteranceId);
}
@Override
public void onError(String utteranceId) { }
public void onStart(String utteranceId) {
// Left unimplemented, has no equivalent in the old
// API.
}
};
}
}