Skip to content

Commit 40f71f0

Browse files
committed
Fix regressions in TTS completion callbacks.
(a) onUtteranceCompleted should be called on errors too. Also, fix up the error handling so that onUtteranceCompleted is always called. (b) Don't treat empty utterances as errors, and let the engine synthesize them, as before. bug:5662598 Change-Id: I9223592bc6fe5f47d71103f4f02f046b54a655a8
1 parent 8bb5618 commit 40f71f0

File tree

5 files changed

+65
-19
lines changed

5 files changed

+65
-19
lines changed

core/java/android/speech/tts/AudioPlaybackHandler.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,26 @@ synchronized public void removePlaybackItems(String callingApp) {
118118
if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
119119
stop(current);
120120
}
121+
122+
final MessageParams lastSynthesis = mLastSynthesisRequest;
123+
124+
if (lastSynthesis != null && lastSynthesis != current &&
125+
TextUtils.equals(callingApp, lastSynthesis.getCallingApp())) {
126+
stop(lastSynthesis);
127+
}
121128
}
122129

123130
synchronized public void removeAllItems() {
124131
if (DBG_THREADING) Log.d(TAG, "Removing all items");
125132
removeAllMessages();
126-
stop(getCurrentParams());
133+
134+
final MessageParams current = getCurrentParams();
135+
final MessageParams lastSynthesis = mLastSynthesisRequest;
136+
stop(current);
137+
138+
if (lastSynthesis != null && lastSynthesis != current) {
139+
stop(lastSynthesis);
140+
}
127141
}
128142

129143
/**
@@ -350,7 +364,7 @@ private void handleSynthesisStart(MessageParams msg) {
350364
// extra trouble to clean the data to prevent the AudioTrack resources
351365
// from being leaked.
352366
if (mLastSynthesisRequest != null) {
353-
Log.w(TAG, "Error : Missing call to done() for request : " +
367+
Log.e(TAG, "Error : Missing call to done() for request : " +
354368
mLastSynthesisRequest);
355369
handleSynthesisDone(mLastSynthesisRequest);
356370
}
@@ -443,7 +457,11 @@ private void handleSynthesisDone(MessageParams msg) {
443457
audioTrack.release();
444458
params.setAudioTrack(null);
445459
}
446-
params.getDispatcher().dispatchOnDone();
460+
if (params.isError()) {
461+
params.getDispatcher().dispatchOnError();
462+
} else {
463+
params.getDispatcher().dispatchOnDone();
464+
}
447465
mLastSynthesisRequest = null;
448466
params.mLogger.onWriteData();
449467
}

core/java/android/speech/tts/PlaybackSynthesisCallback.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -80,27 +80,23 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
8080

8181
@Override
8282
void stop() {
83+
stopImpl(false);
84+
}
85+
86+
void stopImpl(boolean wasError) {
8387
if (DBG) Log.d(TAG, "stop()");
8488

8589
// Note that mLogger.mError might be true too at this point.
8690
mLogger.onStopped();
8791

88-
SynthesisMessageParams token = null;
92+
SynthesisMessageParams token;
8993
synchronized (mStateLock) {
9094
if (mStopped) {
9195
Log.w(TAG, "stop() called twice");
9296
return;
9397
}
9498

95-
// mToken will be null if the engine encounters
96-
// an error before it called start().
97-
if (mToken == null) {
98-
// In all other cases, mAudioTrackHandler.stop() will
99-
// result in onComplete being called.
100-
mLogger.onWriteData();
101-
} else {
102-
token = mToken;
103-
}
99+
token = mToken;
104100
mStopped = true;
105101
}
106102

@@ -109,7 +105,24 @@ void stop() {
109105
// point it will write an additional buffer to the token - but we
110106
// won't worry about that because the audio playback queue will be cleared
111107
// soon after (see SynthHandler#stop(String).
108+
token.setIsError(wasError);
112109
token.clearBuffers();
110+
if (wasError) {
111+
// Also clean up the audio track if an error occurs.
112+
mAudioTrackHandler.enqueueSynthesisDone(token);
113+
}
114+
} else {
115+
// This happens when stop() or error() were called before start() was.
116+
117+
// In all other cases, mAudioTrackHandler.stop() will
118+
// result in onSynthesisDone being called, and we will
119+
// write data there.
120+
mLogger.onWriteData();
121+
122+
if (wasError) {
123+
// We have to dispatch the error ourselves.
124+
mDispatcher.dispatchOnError();
125+
}
113126
}
114127
}
115128

@@ -219,7 +232,7 @@ public void error() {
219232
// Currently, this call will not be logged if error( ) is called
220233
// before start.
221234
mLogger.onError();
222-
stop();
235+
stopImpl(true);
223236
}
224237

225238
}

core/java/android/speech/tts/SynthesisMessageParams.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ final class SynthesisMessageParams extends MessageParams {
5151
int mAudioBufferSize;
5252
// Always synchronized on "this".
5353
int mUnconsumedBytes;
54+
volatile boolean mIsError;
5455

5556
private final LinkedList<ListEntry> mDataBufferList = new LinkedList<ListEntry>();
5657

@@ -74,6 +75,7 @@ final class SynthesisMessageParams extends MessageParams {
7475
mAudioTrack = null;
7576
mBytesWritten = 0;
7677
mAudioBufferSize = 0;
78+
mIsError = false;
7779
}
7880

7981
@Override
@@ -120,6 +122,14 @@ AudioTrack getAudioTrack() {
120122
return mAudioTrack;
121123
}
122124

125+
void setIsError(boolean isError) {
126+
mIsError = isError;
127+
}
128+
129+
boolean isError() {
130+
return mIsError;
131+
}
132+
123133
// Must be called synchronized on this.
124134
private long getUnconsumedAudioLengthMs() {
125135
final int unconsumedFrames = mUnconsumedBytes / mBytesPerFrame;

core/java/android/speech/tts/TextToSpeechService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@ protected float getFloatParam(String key, float defaultValue) {
509509
}
510510

511511
class SynthesisSpeechItem extends SpeechItem {
512+
// Never null.
512513
private final String mText;
513514
private final SynthesisRequest mSynthesisRequest;
514515
private final String[] mDefaultLocale;
@@ -532,8 +533,8 @@ public String getText() {
532533

533534
@Override
534535
public boolean isValid() {
535-
if (TextUtils.isEmpty(mText)) {
536-
Log.w(TAG, "Got empty text");
536+
if (mText == null) {
537+
Log.wtf(TAG, "Got null text");
537538
return false;
538539
}
539540
if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {

core/java/android/speech/tts/UtteranceProgressListener.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,16 @@ public synchronized void onDone(String utteranceId) {
5757
listener.onUtteranceCompleted(utteranceId);
5858
}
5959

60-
// The following methods are left unimplemented.
6160
@Override
62-
public void onStart(String utteranceId) { }
61+
public void onError(String utteranceId) {
62+
listener.onUtteranceCompleted(utteranceId);
63+
}
6364

6465
@Override
65-
public void onError(String utteranceId) { }
66+
public void onStart(String utteranceId) {
67+
// Left unimplemented, has no equivalent in the old
68+
// API.
69+
}
6670
};
6771
}
6872
}

0 commit comments

Comments
 (0)