Merge "Fix two TTS bugs."

This commit is contained in:
Narayan Kamath
2011-09-07 05:53:14 -07:00
committed by Android (Google) Code Review

View File

@@ -260,6 +260,17 @@ public abstract class TextToSpeechService extends Service {
return old; return old;
} }
private synchronized SpeechItem maybeRemoveCurrentSpeechItem(String callingApp) {
if (mCurrentSpeechItem != null &&
TextUtils.equals(mCurrentSpeechItem.getCallingApp(), callingApp)) {
SpeechItem current = mCurrentSpeechItem;
mCurrentSpeechItem = null;
return current;
}
return null;
}
public boolean isSpeaking() { public boolean isSpeaking() {
return getCurrentSpeechItem() != null; return getCurrentSpeechItem() != null;
} }
@@ -287,14 +298,9 @@ public abstract class TextToSpeechService extends Service {
} }
if (queueMode == TextToSpeech.QUEUE_FLUSH) { if (queueMode == TextToSpeech.QUEUE_FLUSH) {
stop(speechItem.getCallingApp()); stopForApp(speechItem.getCallingApp());
} else if (queueMode == TextToSpeech.QUEUE_DESTROY) { } else if (queueMode == TextToSpeech.QUEUE_DESTROY) {
// Stop the current speech item. stopAll();
stop(speechItem.getCallingApp());
// Remove all other items from the queue.
removeCallbacksAndMessages(null);
// Remove all pending playback as well.
mAudioPlaybackHandler.removeAllItems();
} }
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
@@ -305,7 +311,8 @@ public abstract class TextToSpeechService extends Service {
} }
}; };
Message msg = Message.obtain(this, runnable); Message msg = Message.obtain(this, runnable);
// The obj is used to remove all callbacks from the given app in stop(String). // The obj is used to remove all callbacks from the given app in
// stopForApp(String).
// //
// Note that this string is interned, so the == comparison works. // Note that this string is interned, so the == comparison works.
msg.obj = speechItem.getCallingApp(); msg.obj = speechItem.getCallingApp();
@@ -323,7 +330,7 @@ public abstract class TextToSpeechService extends Service {
* *
* Called on a service binder thread. * Called on a service binder thread.
*/ */
public int stop(String callingApp) { public int stopForApp(String callingApp) {
if (TextUtils.isEmpty(callingApp)) { if (TextUtils.isEmpty(callingApp)) {
return TextToSpeech.ERROR; return TextToSpeech.ERROR;
} }
@@ -331,8 +338,13 @@ public abstract class TextToSpeechService extends Service {
removeCallbacksAndMessages(callingApp); removeCallbacksAndMessages(callingApp);
// This stops writing data to the file / or publishing // This stops writing data to the file / or publishing
// items to the audio playback handler. // items to the audio playback handler.
SpeechItem current = setCurrentSpeechItem(null); //
if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) { // Note that the current speech item must be removed only if it
// belongs to the callingApp, else the item will be "orphaned" and
// not stopped correctly if a stop request comes along for the item
// from the app it belongs to.
SpeechItem current = maybeRemoveCurrentSpeechItem(callingApp);
if (current != null) {
current.stop(); current.stop();
} }
@@ -341,6 +353,20 @@ public abstract class TextToSpeechService extends Service {
return TextToSpeech.SUCCESS; return TextToSpeech.SUCCESS;
} }
public int stopAll() {
// Stop the current speech item unconditionally.
SpeechItem current = setCurrentSpeechItem(null);
if (current != null) {
current.stop();
}
// Remove all other items from the queue.
removeCallbacksAndMessages(null);
// Remove all pending playback as well.
mAudioPlaybackHandler.removeAllItems();
return TextToSpeech.SUCCESS;
}
} }
interface UtteranceCompletedDispatcher { interface UtteranceCompletedDispatcher {
@@ -412,6 +438,10 @@ public abstract class TextToSpeechService extends Service {
} }
} }
protected synchronized boolean isStopped() {
return mStopped;
}
protected abstract int playImpl(); protected abstract int playImpl();
protected abstract void stopImpl(); protected abstract void stopImpl();
@@ -473,7 +503,7 @@ public abstract class TextToSpeechService extends Service {
Log.w(TAG, "Got empty text"); Log.w(TAG, "Got empty text");
return false; return false;
} }
if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH){ if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {
Log.w(TAG, "Text too long: " + mText.length() + " chars"); Log.w(TAG, "Text too long: " + mText.length() + " chars");
return false; return false;
} }
@@ -485,6 +515,11 @@ public abstract class TextToSpeechService extends Service {
AbstractSynthesisCallback synthesisCallback; AbstractSynthesisCallback synthesisCallback;
mEventLogger.onRequestProcessingStart(); mEventLogger.onRequestProcessingStart();
synchronized (this) { synchronized (this) {
// stop() might have been called before we enter this
// synchronized block.
if (isStopped()) {
return TextToSpeech.ERROR;
}
mSynthesisCallback = createSynthesisCallback(); mSynthesisCallback = createSynthesisCallback();
synthesisCallback = mSynthesisCallback; synthesisCallback = mSynthesisCallback;
} }
@@ -510,8 +545,13 @@ public abstract class TextToSpeechService extends Service {
synchronized (this) { synchronized (this) {
synthesisCallback = mSynthesisCallback; synthesisCallback = mSynthesisCallback;
} }
synthesisCallback.stop(); if (synthesisCallback != null) {
TextToSpeechService.this.onStop(); // If the synthesis callback is null, it implies that we haven't
// entered the synchronized(this) block in playImpl which in
// turn implies that synthesis would not have started.
synthesisCallback.stop();
TextToSpeechService.this.onStop();
}
} }
public String getLanguage() { public String getLanguage() {
@@ -719,7 +759,7 @@ public abstract class TextToSpeechService extends Service {
return TextToSpeech.ERROR; return TextToSpeech.ERROR;
} }
return mSynthHandler.stop(intern(callingApp)); return mSynthHandler.stopForApp(intern(callingApp));
} }
public String[] getLanguage() { public String[] getLanguage() {
@@ -811,7 +851,7 @@ public abstract class TextToSpeechService extends Service {
synchronized (mAppToCallback) { synchronized (mAppToCallback) {
mAppToCallback.remove(packageName); mAppToCallback.remove(packageName);
} }
mSynthHandler.stop(packageName); mSynthHandler.stopForApp(packageName);
} }
@Override @Override