Loading core/java/android/speech/tts/AudioPlaybackHandler.java +4 −11 Original line number Diff line number Diff line Loading @@ -46,10 +46,7 @@ class AudioPlaybackHandler { new PriorityBlockingQueue<ListEntry>(); private final Thread mHandlerThread; private final Object mStateLock = new Object(); // Accessed by multiple threads, synchronized by "mStateLock". private MessageParams mCurrentParams = null; private volatile MessageParams mCurrentParams = null; // Used only for book keeping and error detection. private volatile SynthesisMessageParams mLastSynthesisRequest = null; // Used to order incoming messages in our priority queue. Loading Loading @@ -79,7 +76,7 @@ class AudioPlaybackHandler { if (token.getType() == MessageParams.TYPE_SYNTHESIS) { mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY)); } else { MessageParams current = getCurrentParams(); final MessageParams current = getCurrentParams(); if (current != null) { if (token.getType() == MessageParams.TYPE_AUDIO) { Loading Loading @@ -257,16 +254,12 @@ class AudioPlaybackHandler { } private void setCurrentParams(MessageParams p) { synchronized (mStateLock) { mCurrentParams = p; } } private MessageParams getCurrentParams() { synchronized (mStateLock) { return mCurrentParams; } } // ----------------------------------------- // Methods for dealing with individual messages, the methods Loading core/java/android/speech/tts/TextToSpeech.java +10 −0 Original line number Diff line number Diff line Loading @@ -67,12 +67,22 @@ public class TextToSpeech { /** * Queue mode where all entries in the playback queue (media to be played * and text to be synthesized) are dropped and replaced by the new entry. * Queues are flushed with respect to a given calling app. Entries in the queue * from other callees are not discarded. */ public static final int QUEUE_FLUSH = 0; /** * Queue mode where the new entry is added at the end of the playback queue. */ public static final int QUEUE_ADD = 1; /** * Queue mode where the entire playback queue is purged. This is different * from {@link #QUEUE_FLUSH} in that all entries are purged, not just entries * from a given caller. * * @hide */ static final int QUEUE_DESTROY = 2; /** * Denotes the language is available exactly as specified by the locale. Loading core/java/android/speech/tts/TextToSpeechService.java +56 −6 Original line number Diff line number Diff line Loading @@ -301,7 +301,7 @@ public abstract class TextToSpeechService extends Service { if (queueMode == TextToSpeech.QUEUE_FLUSH) { stop(speechItem.getCallingApp()); } else if (queueMode == 2) { } else if (queueMode == TextToSpeech.QUEUE_DESTROY) { // Stop the current speech item. stop(speechItem.getCallingApp()); // Remove all other items from the queue. Loading @@ -319,6 +319,8 @@ public abstract class TextToSpeechService extends Service { }; Message msg = Message.obtain(this, runnable); // The obj is used to remove all callbacks from the given app in stop(String). // // Note that this string is interned, so the == comparison works. msg.obj = speechItem.getCallingApp(); if (sendMessage(msg)) { return TextToSpeech.SUCCESS; Loading Loading @@ -679,27 +681,46 @@ public abstract class TextToSpeechService extends Service { * Binder returned from {@code #onBind(Intent)}. The methods in this class can be * called called from several different threads. */ // NOTE: All calls that are passed in a calling app are interned so that // they can be used as message objects (which are tested for equality using ==). private final ITextToSpeechService.Stub mBinder = new ITextToSpeechService.Stub() { public int speak(String callingApp, String text, int queueMode, Bundle params) { SpeechItem item = new SynthesisSpeechItem(callingApp, params, text); if (!checkNonNull(callingApp, text, params)) { return TextToSpeech.ERROR; } SpeechItem item = new SynthesisSpeechItem(intern(callingApp), params, text); return mSynthHandler.enqueueSpeechItem(queueMode, item); } public int synthesizeToFile(String callingApp, String text, String filename, Bundle params) { if (!checkNonNull(callingApp, text, filename, params)) { return TextToSpeech.ERROR; } File file = new File(filename); SpeechItem item = new SynthesisToFileSpeechItem(callingApp, params, text, file); SpeechItem item = new SynthesisToFileSpeechItem(intern(callingApp), params, text, file); return mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item); } public int playAudio(String callingApp, Uri audioUri, int queueMode, Bundle params) { SpeechItem item = new AudioSpeechItem(callingApp, params, audioUri); if (!checkNonNull(callingApp, audioUri, params)) { return TextToSpeech.ERROR; } SpeechItem item = new AudioSpeechItem(intern(callingApp), params, audioUri); return mSynthHandler.enqueueSpeechItem(queueMode, item); } public int playSilence(String callingApp, long duration, int queueMode, Bundle params) { SpeechItem item = new SilenceSpeechItem(callingApp, params, duration); if (!checkNonNull(callingApp, params)) { return TextToSpeech.ERROR; } SpeechItem item = new SilenceSpeechItem(intern(callingApp), params, duration); return mSynthHandler.enqueueSpeechItem(queueMode, item); } Loading @@ -708,7 +729,11 @@ public abstract class TextToSpeechService extends Service { } public int stop(String callingApp) { return mSynthHandler.stop(callingApp); if (!checkNonNull(callingApp)) { return TextToSpeech.ERROR; } return mSynthHandler.stop(intern(callingApp)); } public String[] getLanguage() { Loading @@ -720,6 +745,10 @@ public abstract class TextToSpeechService extends Service { * perhaps the default language selected by the user. */ public int isLanguageAvailable(String lang, String country, String variant) { if (!checkNonNull(lang)) { return TextToSpeech.ERROR; } if (areDefaultsEnforced()) { if (isDefault(lang, country, variant)) { return mDefaultAvailability; Loading @@ -735,6 +764,10 @@ public abstract class TextToSpeechService extends Service { * are enforced. */ public int loadLanguage(String lang, String country, String variant) { if (!checkNonNull(lang)) { return TextToSpeech.ERROR; } if (areDefaultsEnforced()) { if (isDefault(lang, country, variant)) { return mDefaultAvailability; Loading @@ -746,12 +779,29 @@ public abstract class TextToSpeechService extends Service { } public void setCallback(String packageName, ITextToSpeechCallback cb) { // Note that passing in a null callback is a valid use case. if (!checkNonNull(packageName)) { return; } mCallbacks.setCallback(packageName, cb); } private boolean isDefault(String lang, String country, String variant) { return Locale.getDefault().equals(new Locale(lang, country, variant)); } private String intern(String in) { // The input parameter will be non null. return in.intern(); } private boolean checkNonNull(Object... args) { for (Object o : args) { if (o == null) return false; } return true; } }; private class CallbackMap extends RemoteCallbackList<ITextToSpeechCallback> { Loading Loading
core/java/android/speech/tts/AudioPlaybackHandler.java +4 −11 Original line number Diff line number Diff line Loading @@ -46,10 +46,7 @@ class AudioPlaybackHandler { new PriorityBlockingQueue<ListEntry>(); private final Thread mHandlerThread; private final Object mStateLock = new Object(); // Accessed by multiple threads, synchronized by "mStateLock". private MessageParams mCurrentParams = null; private volatile MessageParams mCurrentParams = null; // Used only for book keeping and error detection. private volatile SynthesisMessageParams mLastSynthesisRequest = null; // Used to order incoming messages in our priority queue. Loading Loading @@ -79,7 +76,7 @@ class AudioPlaybackHandler { if (token.getType() == MessageParams.TYPE_SYNTHESIS) { mQueue.add(new ListEntry(SYNTHESIS_DONE, token, HIGH_PRIORITY)); } else { MessageParams current = getCurrentParams(); final MessageParams current = getCurrentParams(); if (current != null) { if (token.getType() == MessageParams.TYPE_AUDIO) { Loading Loading @@ -257,16 +254,12 @@ class AudioPlaybackHandler { } private void setCurrentParams(MessageParams p) { synchronized (mStateLock) { mCurrentParams = p; } } private MessageParams getCurrentParams() { synchronized (mStateLock) { return mCurrentParams; } } // ----------------------------------------- // Methods for dealing with individual messages, the methods Loading
core/java/android/speech/tts/TextToSpeech.java +10 −0 Original line number Diff line number Diff line Loading @@ -67,12 +67,22 @@ public class TextToSpeech { /** * Queue mode where all entries in the playback queue (media to be played * and text to be synthesized) are dropped and replaced by the new entry. * Queues are flushed with respect to a given calling app. Entries in the queue * from other callees are not discarded. */ public static final int QUEUE_FLUSH = 0; /** * Queue mode where the new entry is added at the end of the playback queue. */ public static final int QUEUE_ADD = 1; /** * Queue mode where the entire playback queue is purged. This is different * from {@link #QUEUE_FLUSH} in that all entries are purged, not just entries * from a given caller. * * @hide */ static final int QUEUE_DESTROY = 2; /** * Denotes the language is available exactly as specified by the locale. Loading
core/java/android/speech/tts/TextToSpeechService.java +56 −6 Original line number Diff line number Diff line Loading @@ -301,7 +301,7 @@ public abstract class TextToSpeechService extends Service { if (queueMode == TextToSpeech.QUEUE_FLUSH) { stop(speechItem.getCallingApp()); } else if (queueMode == 2) { } else if (queueMode == TextToSpeech.QUEUE_DESTROY) { // Stop the current speech item. stop(speechItem.getCallingApp()); // Remove all other items from the queue. Loading @@ -319,6 +319,8 @@ public abstract class TextToSpeechService extends Service { }; Message msg = Message.obtain(this, runnable); // The obj is used to remove all callbacks from the given app in stop(String). // // Note that this string is interned, so the == comparison works. msg.obj = speechItem.getCallingApp(); if (sendMessage(msg)) { return TextToSpeech.SUCCESS; Loading Loading @@ -679,27 +681,46 @@ public abstract class TextToSpeechService extends Service { * Binder returned from {@code #onBind(Intent)}. The methods in this class can be * called called from several different threads. */ // NOTE: All calls that are passed in a calling app are interned so that // they can be used as message objects (which are tested for equality using ==). private final ITextToSpeechService.Stub mBinder = new ITextToSpeechService.Stub() { public int speak(String callingApp, String text, int queueMode, Bundle params) { SpeechItem item = new SynthesisSpeechItem(callingApp, params, text); if (!checkNonNull(callingApp, text, params)) { return TextToSpeech.ERROR; } SpeechItem item = new SynthesisSpeechItem(intern(callingApp), params, text); return mSynthHandler.enqueueSpeechItem(queueMode, item); } public int synthesizeToFile(String callingApp, String text, String filename, Bundle params) { if (!checkNonNull(callingApp, text, filename, params)) { return TextToSpeech.ERROR; } File file = new File(filename); SpeechItem item = new SynthesisToFileSpeechItem(callingApp, params, text, file); SpeechItem item = new SynthesisToFileSpeechItem(intern(callingApp), params, text, file); return mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item); } public int playAudio(String callingApp, Uri audioUri, int queueMode, Bundle params) { SpeechItem item = new AudioSpeechItem(callingApp, params, audioUri); if (!checkNonNull(callingApp, audioUri, params)) { return TextToSpeech.ERROR; } SpeechItem item = new AudioSpeechItem(intern(callingApp), params, audioUri); return mSynthHandler.enqueueSpeechItem(queueMode, item); } public int playSilence(String callingApp, long duration, int queueMode, Bundle params) { SpeechItem item = new SilenceSpeechItem(callingApp, params, duration); if (!checkNonNull(callingApp, params)) { return TextToSpeech.ERROR; } SpeechItem item = new SilenceSpeechItem(intern(callingApp), params, duration); return mSynthHandler.enqueueSpeechItem(queueMode, item); } Loading @@ -708,7 +729,11 @@ public abstract class TextToSpeechService extends Service { } public int stop(String callingApp) { return mSynthHandler.stop(callingApp); if (!checkNonNull(callingApp)) { return TextToSpeech.ERROR; } return mSynthHandler.stop(intern(callingApp)); } public String[] getLanguage() { Loading @@ -720,6 +745,10 @@ public abstract class TextToSpeechService extends Service { * perhaps the default language selected by the user. */ public int isLanguageAvailable(String lang, String country, String variant) { if (!checkNonNull(lang)) { return TextToSpeech.ERROR; } if (areDefaultsEnforced()) { if (isDefault(lang, country, variant)) { return mDefaultAvailability; Loading @@ -735,6 +764,10 @@ public abstract class TextToSpeechService extends Service { * are enforced. */ public int loadLanguage(String lang, String country, String variant) { if (!checkNonNull(lang)) { return TextToSpeech.ERROR; } if (areDefaultsEnforced()) { if (isDefault(lang, country, variant)) { return mDefaultAvailability; Loading @@ -746,12 +779,29 @@ public abstract class TextToSpeechService extends Service { } public void setCallback(String packageName, ITextToSpeechCallback cb) { // Note that passing in a null callback is a valid use case. if (!checkNonNull(packageName)) { return; } mCallbacks.setCallback(packageName, cb); } private boolean isDefault(String lang, String country, String variant) { return Locale.getDefault().equals(new Locale(lang, country, variant)); } private String intern(String in) { // The input parameter will be non null. return in.intern(); } private boolean checkNonNull(Object... args) { for (Object o : args) { if (o == null) return false; } return true; } }; private class CallbackMap extends RemoteCallbackList<ITextToSpeechCallback> { Loading