summaryrefslogtreecommitdiffstats
path: root/core/java/android/speech
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2011-06-09 11:35:13 +0100
committerNarayan Kamath <narayan@google.com>2011-06-09 16:42:16 +0100
commit4924fe38675f0bf69bb0c16fc059ffa1606807ce (patch)
treebaeb74c7276d9ff6ae6f599841b4780ee41233b0 /core/java/android/speech
parent6276814a67e633c342acc7bf3d982b091bfe9f08 (diff)
downloadframeworks_base-4924fe38675f0bf69bb0c16fc059ffa1606807ce.zip
frameworks_base-4924fe38675f0bf69bb0c16fc059ffa1606807ce.tar.gz
frameworks_base-4924fe38675f0bf69bb0c16fc059ffa1606807ce.tar.bz2
Implement QUEUE_FLUSH and QUEUE_DESTROY addition modes.
Note that this change is slightly more flexible, it defines a priority for each playback request. We needn't really throw away synthesis requests from other apps. We could just play them after higher priority ones (for e.g from talkback). Change-Id: I6c7dd9abe4871e87da08d9aaa4c55225a69078e5
Diffstat (limited to 'core/java/android/speech')
-rw-r--r--core/java/android/speech/tts/AudioMessageParams.java5
-rw-r--r--core/java/android/speech/tts/AudioPlaybackHandler.java288
-rw-r--r--core/java/android/speech/tts/MessageParams.java12
-rw-r--r--core/java/android/speech/tts/PlaybackSynthesisCallback.java10
-rw-r--r--core/java/android/speech/tts/SilenceMessageParams.java5
-rw-r--r--core/java/android/speech/tts/SynthesisMessageParams.java5
-rw-r--r--core/java/android/speech/tts/TextToSpeechService.java26
7 files changed, 270 insertions, 81 deletions
diff --git a/core/java/android/speech/tts/AudioMessageParams.java b/core/java/android/speech/tts/AudioMessageParams.java
index db4d622..68d8738 100644
--- a/core/java/android/speech/tts/AudioMessageParams.java
+++ b/core/java/android/speech/tts/AudioMessageParams.java
@@ -20,8 +20,9 @@ import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher;
class AudioMessageParams extends MessageParams {
private final BlockingMediaPlayer mPlayer;
- AudioMessageParams(UtteranceCompletedDispatcher dispatcher, BlockingMediaPlayer player) {
- super(dispatcher);
+ AudioMessageParams(UtteranceCompletedDispatcher dispatcher,
+ String callingApp, BlockingMediaPlayer player) {
+ super(dispatcher, callingApp);
mPlayer = player;
}
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index 924bbbc..c068b75 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -17,13 +17,13 @@ package android.speech.tts;
import android.media.AudioFormat;
import android.media.AudioTrack;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.speech.tts.SynthesisMessageParams.ListEntry;
import android.util.Log;
-class AudioPlaybackHandler extends Handler {
+import java.util.Iterator;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.atomic.AtomicLong;
+
+class AudioPlaybackHandler {
private static final String TAG = "TTS.AudioPlaybackHandler";
private static final boolean DBG = false;
@@ -37,33 +37,31 @@ class AudioPlaybackHandler extends Handler {
private static final int PLAY_AUDIO = 5;
private static final int PLAY_SILENCE = 6;
- // Accessed by multiple threads, synchronized by "this".
- private MessageParams mCurrentParams;
+ private static final int SHUTDOWN = -1;
+
+ private static final int DEFAULT_PRIORITY = 1;
+ private static final int HIGH_PRIORITY = 0;
+
+ private final PriorityBlockingQueue<ListEntry> mQueue =
+ new PriorityBlockingQueue<ListEntry>();
+ private final Thread mHandlerThread;
+
+ private final Object mStateLock = new Object();
+
+ // Accessed by multiple threads, synchronized by "mStateLock".
+ private MessageParams mCurrentParams = null;
// Used only for book keeping and error detection.
- private SynthesisMessageParams mLastSynthesisRequest;
+ private volatile SynthesisMessageParams mLastSynthesisRequest = null;
+ // Used to order incoming messages in our priority queue.
+ private final AtomicLong mSequenceIdCtr = new AtomicLong(0);
- AudioPlaybackHandler(Looper looper) {
- super(looper);
- }
- @Override
- public synchronized void handleMessage(Message msg) {
- if (msg.what == SYNTHESIS_START) {
- mCurrentParams = (SynthesisMessageParams) msg.obj;
- handleSynthesisStart(msg);
- } else if (msg.what == SYNTHESIS_DATA_AVAILABLE) {
- handleSynthesisDataAvailable(msg);
- } else if (msg.what == SYNTHESIS_DONE) {
- handleSynthesisDone(msg);
- } else if (msg.what == SYNTHESIS_COMPLETE_DATA_AVAILABLE) {
- handleSynthesisCompleteDataAvailable(msg);
- } else if (msg.what == PLAY_AUDIO) {
- handleAudio(msg);
- } else if (msg.what == PLAY_SILENCE) {
- handleSilence(msg);
- }
+ AudioPlaybackHandler() {
+ mHandlerThread = new Thread(new MessageLoop(), "TTS.AudioPlaybackThread");
+ }
- mCurrentParams = null;
+ public void start() {
+ mHandlerThread.start();
}
/**
@@ -72,63 +70,232 @@ class AudioPlaybackHandler extends Handler {
* that is not guaranteed.
*/
synchronized public void stop(MessageParams token) {
- removeCallbacksAndMessages(token);
+ if (token == null) {
+ return;
+ }
+
+ removeMessages(token);
if (token.getType() == MessageParams.TYPE_SYNTHESIS) {
- sendMessageAtFrontOfQueue(obtainMessage(SYNTHESIS_DONE, token));
- } else if (token == mCurrentParams) {
- if (token.getType() == MessageParams.TYPE_AUDIO) {
- ((AudioMessageParams) mCurrentParams).getPlayer().stop();
- } else if (token.getType() == MessageParams.TYPE_SILENCE) {
- ((SilenceMessageParams) mCurrentParams).getConditionVariable().open();
+ mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY));
+ } else {
+ MessageParams current = getCurrentParams();
+
+ if (current != null) {
+ if (token.getType() == MessageParams.TYPE_AUDIO) {
+ ((AudioMessageParams) current).getPlayer().stop();
+ } else if (token.getType() == MessageParams.TYPE_SILENCE) {
+ ((SilenceMessageParams) current).getConditionVariable().open();
+ }
}
}
}
+ synchronized public void removePlaybackItems(String callingApp) {
+ removeMessages(callingApp);
+ stop(getCurrentParams());
+ }
+
+ synchronized public void removeAllItems() {
+ removeAllMessages();
+ stop(getCurrentParams());
+ }
+
/**
* Shut down the audio playback thread.
*/
synchronized public void quit() {
- if (mCurrentParams != null) {
- stop(mCurrentParams);
- }
- getLooper().quit();
+ stop(getCurrentParams());
+ mQueue.add(new ListEntry(SHUTDOWN, null, HIGH_PRIORITY));
}
void enqueueSynthesisStart(SynthesisMessageParams token) {
- sendMessage(obtainMessage(SYNTHESIS_START, token));
+ mQueue.add(new ListEntry(SYNTHESIS_START, token));
}
void enqueueSynthesisDataAvailable(SynthesisMessageParams token) {
- sendMessage(obtainMessage(SYNTHESIS_DATA_AVAILABLE, token));
+ mQueue.add(new ListEntry(SYNTHESIS_DATA_AVAILABLE, token));
}
void enqueueSynthesisCompleteDataAvailable(SynthesisMessageParams token) {
- sendMessage(obtainMessage(SYNTHESIS_COMPLETE_DATA_AVAILABLE, token));
+ mQueue.add(new ListEntry(SYNTHESIS_COMPLETE_DATA_AVAILABLE, token));
}
void enqueueSynthesisDone(SynthesisMessageParams token) {
- sendMessage(obtainMessage(SYNTHESIS_DONE, token));
+ mQueue.add(new ListEntry(SYNTHESIS_DONE, token));
}
void enqueueAudio(AudioMessageParams token) {
- sendMessage(obtainMessage(PLAY_AUDIO, token));
+ mQueue.add(new ListEntry(PLAY_AUDIO, token));
}
void enqueueSilence(SilenceMessageParams token) {
- sendMessage(obtainMessage(PLAY_SILENCE, token));
+ mQueue.add(new ListEntry(PLAY_SILENCE, token));
}
// -----------------------------------------
// End of public API methods.
// -----------------------------------------
+ // -----------------------------------------
+ // Methods for managing the message queue.
+ // -----------------------------------------
+
+ /*
+ * The MessageLoop is a handler like implementation that
+ * processes messages from a priority queue.
+ */
+ private final class MessageLoop implements Runnable {
+ @Override
+ public void run() {
+ while (true) {
+ ListEntry entry = null;
+ try {
+ entry = mQueue.take();
+ } catch (InterruptedException ie) {
+ return;
+ }
+
+ if (entry.mWhat == SHUTDOWN) {
+ if (DBG) Log.d(TAG, "MessageLoop : Shutting down");
+ return;
+ }
+
+ if (DBG) {
+ Log.d(TAG, "MessageLoop : Handling message :" + entry.mWhat
+ + " ,seqId : " + entry.mSequenceId);
+ }
+
+ setCurrentParams(entry.mMessage);
+ handleMessage(entry);
+ setCurrentParams(null);
+ }
+ }
+ }
+
+ /*
+ * Remove all messages from the queue that contain the supplied token.
+ * Note that the Iterator is thread safe, and other methods can safely
+ * continue adding to the queue at this point.
+ */
+ synchronized private void removeMessages(MessageParams token) {
+ if (token == null) {
+ return;
+ }
+
+ Iterator<ListEntry> it = mQueue.iterator();
+
+ while (it.hasNext()) {
+ final ListEntry current = it.next();
+ if (current.mMessage == token) {
+ it.remove();
+ }
+ }
+ }
+
+ /*
+ * Atomically clear the queue of all messages.
+ */
+ synchronized private void removeAllMessages() {
+ mQueue.clear();
+ }
+
+ /*
+ * Remove all messages that originate from a given calling app.
+ */
+ synchronized private void removeMessages(String callingApp) {
+ Iterator<ListEntry> it = mQueue.iterator();
+
+ while (it.hasNext()) {
+ final ListEntry current = it.next();
+ // The null check is to prevent us from removing control messages,
+ // such as a shutdown message.
+ if (current.mMessage != null &&
+ callingApp.equals(current.mMessage.getCallingApp())) {
+ it.remove();
+ }
+ }
+ }
+
+ /*
+ * An element of our priority queue of messages. Each message has a priority,
+ * and a sequence id (defined by the order of enqueue calls). Among messages
+ * with the same priority, messages that were received earlier win out.
+ */
+ private final class ListEntry implements Comparable<ListEntry> {
+ final int mWhat;
+ final MessageParams mMessage;
+ final int mPriority;
+ final long mSequenceId;
+
+ private ListEntry(int what, MessageParams message) {
+ this(what, message, DEFAULT_PRIORITY);
+ }
+
+ private ListEntry(int what, MessageParams message, int priority) {
+ mWhat = what;
+ mMessage = message;
+ mPriority = priority;
+ mSequenceId = mSequenceIdCtr.incrementAndGet();
+ }
+
+ @Override
+ public int compareTo(ListEntry that) {
+ if (that == this) {
+ return 0;
+ }
+
+ // Note that this is always 0, 1 or -1.
+ int priorityDiff = mPriority - that.mPriority;
+ if (priorityDiff == 0) {
+ // The == case cannot occur.
+ return (mSequenceId < that.mSequenceId) ? -1 : 1;
+ }
+
+ return priorityDiff;
+ }
+ }
+
+ private void setCurrentParams(MessageParams p) {
+ synchronized (mStateLock) {
+ mCurrentParams = p;
+ }
+ }
+
+ private MessageParams getCurrentParams() {
+ synchronized (mStateLock) {
+ return mCurrentParams;
+ }
+ }
+
+ // -----------------------------------------
+ // Methods for dealing with individual messages, the methods
+ // below do the actual work.
+ // -----------------------------------------
+
+ private void handleMessage(ListEntry entry) {
+ final MessageParams msg = entry.mMessage;
+ if (entry.mWhat == SYNTHESIS_START) {
+ handleSynthesisStart(msg);
+ } else if (entry.mWhat == SYNTHESIS_DATA_AVAILABLE) {
+ handleSynthesisDataAvailable(msg);
+ } else if (entry.mWhat == SYNTHESIS_DONE) {
+ handleSynthesisDone(msg);
+ } else if (entry.mWhat == SYNTHESIS_COMPLETE_DATA_AVAILABLE) {
+ handleSynthesisCompleteDataAvailable(msg);
+ } else if (entry.mWhat == PLAY_AUDIO) {
+ handleAudio(msg);
+ } else if (entry.mWhat == PLAY_SILENCE) {
+ handleSilence(msg);
+ }
+ }
+
// Currently implemented as blocking the audio playback thread for the
// specified duration. If a call to stop() is made, the thread
// unblocks.
- private void handleSilence(Message msg) {
+ private void handleSilence(MessageParams msg) {
if (DBG) Log.d(TAG, "handleSilence()");
- SilenceMessageParams params = (SilenceMessageParams) msg.obj;
+ SilenceMessageParams params = (SilenceMessageParams) msg;
if (params.getSilenceDurationMs() > 0) {
params.getConditionVariable().block(params.getSilenceDurationMs());
}
@@ -137,9 +304,9 @@ class AudioPlaybackHandler extends Handler {
}
// Plays back audio from a given URI. No TTS engine involvement here.
- private void handleAudio(Message msg) {
+ private void handleAudio(MessageParams msg) {
if (DBG) Log.d(TAG, "handleAudio()");
- AudioMessageParams params = (AudioMessageParams) msg.obj;
+ AudioMessageParams params = (AudioMessageParams) msg;
// Note that the BlockingMediaPlayer spawns a separate thread.
//
// TODO: This can be avoided.
@@ -157,9 +324,9 @@ class AudioPlaybackHandler extends Handler {
// handleSynthesisStart -> handleSynthesisDataAvailable(*) -> handleSynthesisDone
// OR
// handleSynthesisCompleteDataAvailable.
- private void handleSynthesisStart(Message msg) {
+ private void handleSynthesisStart(MessageParams msg) {
if (DBG) Log.d(TAG, "handleSynthesisStart()");
- final SynthesisMessageParams param = (SynthesisMessageParams) msg.obj;
+ final SynthesisMessageParams param = (SynthesisMessageParams) msg;
// Oops, looks like the engine forgot to call done(). We go through
// extra trouble to clean the data to prevent the AudioTrack resources
@@ -177,12 +344,14 @@ class AudioPlaybackHandler extends Handler {
param.mStreamType, param.mSampleRateInHz, param.mAudioFormat,
param.mChannelCount, param.mVolume, param.mPan);
+ if (DBG) Log.d(TAG, "Created audio track [" + audioTrack.hashCode() + "]");
+
param.setAudioTrack(audioTrack);
}
// More data available to be flushed to the audio track.
- private void handleSynthesisDataAvailable(Message msg) {
- final SynthesisMessageParams param = (SynthesisMessageParams) msg.obj;
+ private void handleSynthesisDataAvailable(MessageParams msg) {
+ final SynthesisMessageParams param = (SynthesisMessageParams) msg;
if (param.getAudioTrack() == null) {
Log.w(TAG, "Error : null audio track in handleDataAvailable.");
return;
@@ -194,7 +363,7 @@ class AudioPlaybackHandler extends Handler {
}
final AudioTrack audioTrack = param.getAudioTrack();
- final ListEntry bufferCopy = param.getNextBuffer();
+ final SynthesisMessageParams.ListEntry bufferCopy = param.getNextBuffer();
if (bufferCopy == null) {
Log.e(TAG, "No buffers available to play.");
@@ -218,8 +387,8 @@ class AudioPlaybackHandler extends Handler {
}
}
- private void handleSynthesisDone(Message msg) {
- final SynthesisMessageParams params = (SynthesisMessageParams) msg.obj;
+ private void handleSynthesisDone(MessageParams msg) {
+ final SynthesisMessageParams params = (SynthesisMessageParams) msg;
handleSynthesisDone(params);
}
@@ -233,6 +402,7 @@ class AudioPlaybackHandler extends Handler {
if (audioTrack != null) {
audioTrack.flush();
audioTrack.stop();
+ if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]");
audioTrack.release();
}
} finally {
@@ -242,8 +412,8 @@ class AudioPlaybackHandler extends Handler {
}
}
- private void handleSynthesisCompleteDataAvailable(Message msg) {
- final SynthesisMessageParams params = (SynthesisMessageParams) msg.obj;
+ private void handleSynthesisCompleteDataAvailable(MessageParams msg) {
+ final SynthesisMessageParams params = (SynthesisMessageParams) msg;
if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
// Channel config and bytes per frame are checked before
@@ -251,7 +421,7 @@ class AudioPlaybackHandler extends Handler {
int channelConfig = AudioPlaybackHandler.getChannelConfig(params.mChannelCount);
int bytesPerFrame = AudioPlaybackHandler.getBytesPerFrame(params.mAudioFormat);
- ListEntry entry = params.getNextBuffer();
+ SynthesisMessageParams.ListEntry entry = params.getNextBuffer();
if (entry == null) {
Log.w(TAG, "completeDataAvailable : No buffers available to play.");
diff --git a/core/java/android/speech/tts/MessageParams.java b/core/java/android/speech/tts/MessageParams.java
index 2d96df4..4c1b6d2 100644
--- a/core/java/android/speech/tts/MessageParams.java
+++ b/core/java/android/speech/tts/MessageParams.java
@@ -18,19 +18,25 @@ package android.speech.tts;
import android.speech.tts.TextToSpeechService.UtteranceCompletedDispatcher;
abstract class MessageParams {
- private final UtteranceCompletedDispatcher mDispatcher;
-
static final int TYPE_SYNTHESIS = 1;
static final int TYPE_AUDIO = 2;
static final int TYPE_SILENCE = 3;
- MessageParams(UtteranceCompletedDispatcher dispatcher) {
+ private final UtteranceCompletedDispatcher mDispatcher;
+ private final String mCallingApp;
+
+ MessageParams(UtteranceCompletedDispatcher dispatcher, String callingApp) {
mDispatcher = dispatcher;
+ mCallingApp = callingApp;
}
UtteranceCompletedDispatcher getDispatcher() {
return mDispatcher;
}
+ String getCallingApp() {
+ return mCallingApp;
+ }
+
abstract int getType();
}
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index 1888dda..bdaa1b8 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -64,15 +64,17 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
private volatile boolean mDone = false;
private final UtteranceCompletedDispatcher mDispatcher;
+ private final String mCallingApp;
PlaybackSynthesisCallback(int streamType, float volume, float pan,
- AudioPlaybackHandler audioTrackHandler,
- UtteranceCompletedDispatcher dispatcher) {
+ AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher,
+ String callingApp) {
mStreamType = streamType;
mVolume = volume;
mPan = pan;
mAudioTrackHandler = audioTrackHandler;
mDispatcher = dispatcher;
+ mCallingApp = callingApp;
}
@Override
@@ -122,7 +124,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
}
SynthesisMessageParams params = new SynthesisMessageParams(
mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
- mDispatcher);
+ mDispatcher, mCallingApp);
mAudioTrackHandler.enqueueSynthesisStart(params);
mToken = params;
@@ -206,7 +208,7 @@ class PlaybackSynthesisCallback extends AbstractSynthesisCallback {
}
SynthesisMessageParams params = new SynthesisMessageParams(
mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
- mDispatcher);
+ mDispatcher, mCallingApp);
params.addBuffer(buffer, offset, length);
mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params);
diff --git a/core/java/android/speech/tts/SilenceMessageParams.java b/core/java/android/speech/tts/SilenceMessageParams.java
index eee8b68..7a4ff1c 100644
--- a/core/java/android/speech/tts/SilenceMessageParams.java
+++ b/core/java/android/speech/tts/SilenceMessageParams.java
@@ -22,8 +22,9 @@ class SilenceMessageParams extends MessageParams {
private final ConditionVariable mCondVar = new ConditionVariable();
private final long mSilenceDurationMs;
- SilenceMessageParams(UtteranceCompletedDispatcher dispatcher, long silenceDurationMs) {
- super(dispatcher);
+ SilenceMessageParams(UtteranceCompletedDispatcher dispatcher,
+ String callingApp, long silenceDurationMs) {
+ super(dispatcher, callingApp);
mSilenceDurationMs = silenceDurationMs;
}
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index aabaa5a..51f3d2e 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -37,8 +37,9 @@ final class SynthesisMessageParams extends MessageParams {
SynthesisMessageParams(int streamType, int sampleRate,
int audioFormat, int channelCount,
- float volume, float pan, UtteranceCompletedDispatcher dispatcher) {
- super(dispatcher);
+ float volume, float pan, UtteranceCompletedDispatcher dispatcher,
+ String callingApp) {
+ super(dispatcher, callingApp);
mStreamType = streamType;
mSampleRateInHz = sampleRate;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 55cfea3..4898f0e 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -94,9 +94,8 @@ public abstract class TextToSpeechService extends Service {
synthThread.start();
mSynthHandler = new SynthHandler(synthThread.getLooper());
- HandlerThread audioTrackThread = new HandlerThread("TTS.audioTrackThread");
- audioTrackThread.start();
- mAudioPlaybackHandler = new AudioPlaybackHandler(audioTrackThread.getLooper());
+ mAudioPlaybackHandler = new AudioPlaybackHandler();
+ mAudioPlaybackHandler.start();
mCallbacks = new CallbackMap();
@@ -299,11 +298,16 @@ public abstract class TextToSpeechService extends Service {
if (!speechItem.isValid()) {
return TextToSpeech.ERROR;
}
- // TODO: The old code also supported the undocumented queueMode == 2,
- // which clears out all pending items from the calling app, as well as all
- // non-file items from other apps.
+
if (queueMode == TextToSpeech.QUEUE_FLUSH) {
stop(speechItem.getCallingApp());
+ } else if (queueMode == 2) {
+ // Stop the current speech item.
+ stop(speechItem.getCallingApp());
+ // Remove all other items from the queue.
+ removeCallbacksAndMessages(null);
+ // Remove all pending playback as well.
+ mAudioPlaybackHandler.removeAllItems();
}
Runnable runnable = new Runnable() {
@Override
@@ -334,12 +338,16 @@ public abstract class TextToSpeechService extends Service {
if (TextUtils.isEmpty(callingApp)) {
return TextToSpeech.ERROR;
}
+
removeCallbacksAndMessages(callingApp);
SpeechItem current = setCurrentSpeechItem(null);
if (current != null && TextUtils.equals(callingApp, current.getCallingApp())) {
current.stop();
}
+ // Remove any enqueued audio too.
+ mAudioPlaybackHandler.removePlaybackItems(callingApp);
+
return TextToSpeech.SUCCESS;
}
}
@@ -490,7 +498,7 @@ public abstract class TextToSpeechService extends Service {
protected AbstractSynthesisCallback createSynthesisCallback() {
return new PlaybackSynthesisCallback(getStreamType(), getVolume(), getPan(),
- mAudioPlaybackHandler, this);
+ mAudioPlaybackHandler, this, getCallingApp());
}
private void setRequestParams(SynthesisRequest request) {
@@ -617,7 +625,7 @@ public abstract class TextToSpeechService extends Service {
@Override
protected int playImpl() {
- mToken = new AudioMessageParams(this, mPlayer);
+ mToken = new AudioMessageParams(this, getCallingApp(), mPlayer);
mAudioPlaybackHandler.enqueueAudio(mToken);
return TextToSpeech.SUCCESS;
}
@@ -646,7 +654,7 @@ public abstract class TextToSpeechService extends Service {
@Override
protected int playImpl() {
- mToken = new SilenceMessageParams(this, mDuration);
+ mToken = new SilenceMessageParams(this, getCallingApp(), mDuration);
mAudioPlaybackHandler.enqueueSilence(mToken);
return TextToSpeech.SUCCESS;
}