summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/speech/tts/ITextToSpeechCallback.aidl2
-rw-r--r--core/java/android/speech/tts/TextToSpeech.java4
-rw-r--r--core/java/android/speech/tts/TextToSpeechService.java79
-rw-r--r--core/java/android/speech/tts/UtteranceProgressListener.java19
4 files changed, 90 insertions, 14 deletions
diff --git a/core/java/android/speech/tts/ITextToSpeechCallback.aidl b/core/java/android/speech/tts/ITextToSpeechCallback.aidl
index 899515f..d785c3f 100644
--- a/core/java/android/speech/tts/ITextToSpeechCallback.aidl
+++ b/core/java/android/speech/tts/ITextToSpeechCallback.aidl
@@ -40,7 +40,7 @@ oneway interface ITextToSpeechCallback {
*
* @param utteranceId Unique id identifying synthesis request.
*/
- void onStop(String utteranceId);
+ void onStop(String utteranceId, boolean isStarted);
/**
* Tells the client that the synthesis has failed.
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index c59ca8a..06e9ce0 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -2066,10 +2066,10 @@ public class TextToSpeech {
private boolean mEstablished;
private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() {
- public void onStop(String utteranceId) throws RemoteException {
+ public void onStop(String utteranceId, boolean isStarted) throws RemoteException {
UtteranceProgressListener listener = mUtteranceProgressListener;
if (listener != null) {
- listener.onDone(utteranceId);
+ listener.onStop(utteranceId, isStarted);
}
};
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 9bb7f02..02c9a36 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -455,10 +455,37 @@ public abstract class TextToSpeechService extends Service {
private class SynthHandler extends Handler {
private SpeechItem mCurrentSpeechItem = null;
+ private ArrayList<Object> mFlushedObjects = new ArrayList<Object>();
+ private boolean mFlushAll;
+
public SynthHandler(Looper looper) {
super(looper);
}
+ private void startFlushingSpeechItems(Object callerIdentity) {
+ synchronized (mFlushedObjects) {
+ if (callerIdentity == null) {
+ mFlushAll = true;
+ } else {
+ mFlushedObjects.add(callerIdentity);
+ }
+ }
+ }
+ private void endFlushingSpeechItems(Object callerIdentity) {
+ synchronized (mFlushedObjects) {
+ if (callerIdentity == null) {
+ mFlushAll = false;
+ } else {
+ mFlushedObjects.remove(callerIdentity);
+ }
+ }
+ }
+ private boolean isFlushed(SpeechItem speechItem) {
+ synchronized (mFlushedObjects) {
+ return mFlushAll || mFlushedObjects.contains(speechItem.getCallerIdentity());
+ }
+ }
+
private synchronized SpeechItem getCurrentSpeechItem() {
return mCurrentSpeechItem;
}
@@ -522,9 +549,13 @@ public abstract class TextToSpeechService extends Service {
Runnable runnable = new Runnable() {
@Override
public void run() {
- setCurrentSpeechItem(speechItem);
- speechItem.play();
- setCurrentSpeechItem(null);
+ if (isFlushed(speechItem)) {
+ speechItem.stop();
+ } else {
+ setCurrentSpeechItem(speechItem);
+ speechItem.play();
+ setCurrentSpeechItem(null);
+ }
}
};
Message msg = Message.obtain(this, runnable);
@@ -552,12 +583,14 @@ public abstract class TextToSpeechService extends Service {
*
* Called on a service binder thread.
*/
- public int stopForApp(Object callerIdentity) {
+ public int stopForApp(final Object callerIdentity) {
if (callerIdentity == null) {
return TextToSpeech.ERROR;
}
- removeCallbacksAndMessages(callerIdentity);
+ // Flush pending messages from callerIdentity
+ startFlushingSpeechItems(callerIdentity);
+
// This stops writing data to the file / or publishing
// items to the audio playback handler.
//
@@ -573,20 +606,39 @@ public abstract class TextToSpeechService extends Service {
// Remove any enqueued audio too.
mAudioPlaybackHandler.stopForApp(callerIdentity);
+ // Stop flushing pending messages
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ endFlushingSpeechItems(callerIdentity);
+ }
+ };
+ sendMessage(Message.obtain(this, runnable));
return TextToSpeech.SUCCESS;
}
public int stopAll() {
+ // Order to flush pending messages
+ startFlushingSpeechItems(null);
+
// 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.stop();
+ // Message to stop flushing pending messages
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ endFlushingSpeechItems(null);
+ }
+ };
+ sendMessage(Message.obtain(this, runnable));
+
+
return TextToSpeech.SUCCESS;
}
}
@@ -698,7 +750,6 @@ public abstract class TextToSpeechService extends Service {
return mCallerIdentity;
}
-
public int getCallerUid() {
return mCallerUid;
}
@@ -752,6 +803,10 @@ public abstract class TextToSpeechService extends Service {
protected synchronized boolean isStopped() {
return mStopped;
}
+
+ protected synchronized boolean isStarted() {
+ return mStarted;
+ }
}
/**
@@ -777,7 +832,7 @@ public abstract class TextToSpeechService extends Service {
public void dispatchOnStop() {
final String utteranceId = getUtteranceId();
if (utteranceId != null) {
- mCallbacks.dispatchOnStop(getCallerIdentity(), utteranceId);
+ mCallbacks.dispatchOnStop(getCallerIdentity(), utteranceId, isStarted());
}
}
@@ -940,6 +995,8 @@ public abstract class TextToSpeechService extends Service {
// turn implies that synthesis would not have started.
synthesisCallback.stop();
TextToSpeechService.this.onStop();
+ } else {
+ dispatchOnStop();
}
}
@@ -1345,11 +1402,11 @@ public abstract class TextToSpeechService extends Service {
}
}
- public void dispatchOnStop(Object callerIdentity, String utteranceId) {
+ public void dispatchOnStop(Object callerIdentity, String utteranceId, boolean started) {
ITextToSpeechCallback cb = getCallbackFor(callerIdentity);
if (cb == null) return;
try {
- cb.onStop(utteranceId);
+ cb.onStop(utteranceId, started);
} catch (RemoteException e) {
Log.e(TAG, "Callback onStop failed: " + e);
}
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index 6769794..9eb22ef 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -60,6 +60,20 @@ public abstract class UtteranceProgressListener {
}
/**
+ * Called when an utterance has been stopped while in progress or flushed from the
+ * synthesis queue. This can happen if client calls {@link TextToSpeech#stop()}
+ * or use {@link TextToSpeech#QUEUE_FLUSH} as an argument in
+ * {@link TextToSpeech#speak} or {@link TextToSpeech#synthesizeToFile} methods.
+ *
+ * @param utteranceId the utterance ID of the utterance.
+ * @param isStarted If true, then utterance was interrupted while being synthesized
+ * and it's output is incomplete. If it's false, then utterance was flushed
+ * before the synthesis started.
+ */
+ public void onStop(String utteranceId, boolean isStarted) {
+ }
+
+ /**
* Wraps an old deprecated OnUtteranceCompletedListener with a shiny new
* progress listener.
*
@@ -83,6 +97,11 @@ public abstract class UtteranceProgressListener {
// Left unimplemented, has no equivalent in the old
// API.
}
+
+ @Override
+ public void onStop(String utteranceId, boolean isStarted) {
+ listener.onUtteranceCompleted(utteranceId);
+ }
};
}
}