diff options
author | Przemyslaw Szczepaniak <pszczepaniak@google.com> | 2014-09-05 15:36:49 +0100 |
---|---|---|
committer | Przemyslaw Szczepaniak <pszczepaniak@google.com> | 2014-09-08 11:04:19 +0100 |
commit | 35c7698a1b17c3e4ca0eae753e68bf069a463d70 (patch) | |
tree | 267dc354d02b8210552a469dd6b1ed19acaa18a1 | |
parent | 9a245b5de347cb723ed327098a0375707b2139b0 (diff) | |
download | frameworks_base-35c7698a1b17c3e4ca0eae753e68bf069a463d70.zip frameworks_base-35c7698a1b17c3e4ca0eae753e68bf069a463d70.tar.gz frameworks_base-35c7698a1b17c3e4ca0eae753e68bf069a463d70.tar.bz2 |
API review requests for the TTS package.
- New TextToSpeechService methods are no longer protected.
- s/getRequiresNetworkConnection/isNetworkConnectionRequired
- New TextToSpeec#play.. methods use a Bundle instead of a HashMap
- New synthesizeToFile(), addSpeech(), addEarcon() methods
take a File instead of a String with filepath.
- TextToSpeechService#s/isValidVoiceName/onIsValidVoiceName
Bug:17389935,17253934
Change-Id: Iec76f59015c34104683c050fe1ff1ceccd604134
-rw-r--r-- | api/current.txt | 19 | ||||
-rw-r--r-- | core/java/android/speech/tts/TextToSpeech.java | 149 | ||||
-rw-r--r-- | core/java/android/speech/tts/TextToSpeechService.java | 12 | ||||
-rw-r--r-- | core/java/android/speech/tts/Voice.java | 2 |
4 files changed, 140 insertions, 42 deletions
diff --git a/api/current.txt b/api/current.txt index dca7481..7bae1fc 100644 --- a/api/current.txt +++ b/api/current.txt @@ -27412,11 +27412,12 @@ package android.speech.tts { ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener); ctor public TextToSpeech(android.content.Context, android.speech.tts.TextToSpeech.OnInitListener, java.lang.String); method public int addEarcon(java.lang.String, java.lang.String, int); - method public int addEarcon(java.lang.String, java.lang.String); + method public deprecated int addEarcon(java.lang.String, java.lang.String); + method public int addEarcon(java.lang.String, java.io.File); method public int addSpeech(java.lang.String, java.lang.String, int); method public int addSpeech(java.lang.CharSequence, java.lang.String, int); method public int addSpeech(java.lang.String, java.lang.String); - method public int addSpeech(java.lang.CharSequence, java.lang.String); + method public int addSpeech(java.lang.CharSequence, java.io.File); method public deprecated boolean areDefaultsEnforced(); method public java.util.Set<java.util.Locale> getAvailableLanguages(); method public java.lang.String getDefaultEngine(); @@ -27430,7 +27431,7 @@ package android.speech.tts { method public java.util.Set<android.speech.tts.Voice> getVoices(); method public int isLanguageAvailable(java.util.Locale); method public boolean isSpeaking(); - method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String); + method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String); method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String); method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>); @@ -27443,10 +27444,10 @@ package android.speech.tts { method public int setSpeechRate(float); method public int setVoice(android.speech.tts.Voice); method public void shutdown(); - method public int speak(java.lang.CharSequence, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String); + method public int speak(java.lang.CharSequence, int, android.os.Bundle, java.lang.String); method public deprecated int speak(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>); method public int stop(); - method public int synthesizeToFile(java.lang.CharSequence, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String, java.lang.String); + method public int synthesizeToFile(java.lang.CharSequence, android.os.Bundle, java.io.File, java.lang.String); method public deprecated int synthesizeToFile(java.lang.String, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String); field public static final java.lang.String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED"; field public static final int ERROR = -1; // 0xffffffff @@ -27519,15 +27520,15 @@ package android.speech.tts { public abstract class TextToSpeechService extends android.app.Service { ctor public TextToSpeechService(); - method protected int isValidVoiceName(java.lang.String); method public android.os.IBinder onBind(android.content.Intent); method protected java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String); method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String); method protected abstract java.lang.String[] onGetLanguage(); - method protected java.util.List<android.speech.tts.Voice> onGetVoices(); + method public java.util.List<android.speech.tts.Voice> onGetVoices(); method protected abstract int onIsLanguageAvailable(java.lang.String, java.lang.String, java.lang.String); + method public int onIsValidVoiceName(java.lang.String); method protected abstract int onLoadLanguage(java.lang.String, java.lang.String, java.lang.String); - method protected int onLoadVoice(java.lang.String); + method public int onLoadVoice(java.lang.String); method protected abstract void onStop(); method protected abstract void onSynthesizeText(android.speech.tts.SynthesisRequest, android.speech.tts.SynthesisCallback); } @@ -27548,7 +27549,7 @@ package android.speech.tts { method public java.util.Locale getLocale(); method public java.lang.String getName(); method public int getQuality(); - method public boolean getRequiresNetworkConnection(); + method public boolean isNetworkConnectionRequired(); method public void writeToParcel(android.os.Parcel, int); field public static final int LATENCY_HIGH = 400; // 0x190 field public static final int LATENCY_LOW = 200; // 0xc8 diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 7245975..a4b6e92 100644 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -578,7 +578,7 @@ public class TextToSpeech { * * @deprecated Starting from API level 20, to select network synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable network voice - * ({@link Voice#getRequiresNetworkConnection()}) and pass it + * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). */ @Deprecated @@ -596,7 +596,7 @@ public class TextToSpeech { * @deprecated Starting from API level 20, to select embedded synthesis, call * ({@link TextToSpeech#getVoices()}, find a suitable embedded voice - * ({@link Voice#getRequiresNetworkConnection()}) and pass it + * ({@link Voice#isNetworkConnectionRequired()}) and pass it * to {@link TextToSpeech#setVoice(Voice)}). */ @Deprecated @@ -957,20 +957,18 @@ public class TextToSpeech { * * @param text * The string of text. Example: <code>"south_south_east"</code> - * @param filename - * The full path to the sound file (for example: - * "/sdcard/mysounds/hello.wav") + * @param file + * File object pointing to the sound file. * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. */ - public int addSpeech(CharSequence text, String filename) { + public int addSpeech(CharSequence text, File file) { synchronized (mStartLock) { - mUtterances.put(text, Uri.parse(filename)); + mUtterances.put(text, Uri.fromFile(file)); return SUCCESS; } } - /** * Adds a mapping between a string of text and a sound resource in a * package. Use this to add custom earcons. @@ -1017,7 +1015,11 @@ public class TextToSpeech { * "/sdcard/mysounds/tick.wav") * * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. + * + * @deprecated As of API level 20, replaced by + * {@link #addEarcon(String, File)}. */ + @Deprecated public int addEarcon(String earcon, String filename) { synchronized(mStartLock) { mEarcons.put(earcon, Uri.parse(filename)); @@ -1025,6 +1027,27 @@ public class TextToSpeech { } } + /** + * Adds a mapping between a string of text and a sound file. + * Use this to add custom earcons. + * + * @see #playEarcon(String, int, HashMap) + * + * @param earcon + * The name of the earcon. + * Example: <code>"[tick]"</code> + * @param file + * File object pointing to the sound file. + * + * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. + */ + public int addEarcon(String earcon, File file) { + synchronized(mStartLock) { + mEarcons.put(earcon, Uri.fromFile(file)); + return SUCCESS; + } + } + private Uri makeResourceUri(String packageName, int resourceId) { return new Uri.Builder() .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) @@ -1061,7 +1084,7 @@ public class TextToSpeech { */ public int speak(final CharSequence text, final int queueMode, - final HashMap<String, String> params, + final Bundle params, final String utteranceId) { return runAction(new Action<Integer>() { @Override @@ -1103,11 +1126,11 @@ public class TextToSpeech { * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation. * @deprecated As of API level 20, replaced by - * {@link #speak(CharSequence, int, HashMap, String)}. + * {@link #speak(CharSequence, int, Bundle, String)}. */ @Deprecated public int speak(final String text, final int queueMode, final HashMap<String, String> params) { - return speak(text, queueMode, params, + return speak(text, queueMode, convertParamsHashMaptoBundle(params), params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } @@ -1135,7 +1158,7 @@ public class TextToSpeech { * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation. */ public int playEarcon(final String earcon, final int queueMode, - final HashMap<String, String> params, final String utteranceId) { + final Bundle params, final String utteranceId) { return runAction(new Action<Integer>() { @Override public Integer run(ITextToSpeechService service) throws RemoteException { @@ -1173,12 +1196,12 @@ public class TextToSpeech { * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation. * @deprecated As of API level 20, replaced by - * {@link #playEarcon(String, int, HashMap, String)}. + * {@link #playEarcon(String, int, Bundle, String)}. */ @Deprecated public int playEarcon(final String earcon, final int queueMode, final HashMap<String, String> params) { - return playEarcon(earcon, queueMode, params, + return playEarcon(earcon, queueMode, convertParamsHashMaptoBundle(params), params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } @@ -1757,22 +1780,20 @@ public class TextToSpeech { * must be prefixed by the name of the engine they are intended for. For example * the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the * engine named "com.svox.pico" if it is being used. - * @param filename Absolute file filename to write the generated audio data to.It should be - * something like "/sdcard/myappsounds/mysound.wav". + * @param file File to write the generated audio data to. * @param utteranceId An unique identifier for this request. * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation. */ - public int synthesizeToFile(final CharSequence text, final HashMap<String, String> params, - final String filename, final String utteranceId) { + public int synthesizeToFile(final CharSequence text, final Bundle params, + final File file, final String utteranceId) { return runAction(new Action<Integer>() { @Override public Integer run(ITextToSpeechService service) throws RemoteException { ParcelFileDescriptor fileDescriptor; int returnValue; try { - File file = new File(filename); if(file.exists() && !file.canWrite()) { - Log.e(TAG, "Can't write to " + filename); + Log.e(TAG, "Can't write to " + file); return ERROR; } fileDescriptor = ParcelFileDescriptor.open(file, @@ -1784,10 +1805,10 @@ public class TextToSpeech { fileDescriptor.close(); return returnValue; } catch (FileNotFoundException e) { - Log.e(TAG, "Opening file " + filename + " failed", e); + Log.e(TAG, "Opening file " + file + " failed", e); return ERROR; } catch (IOException e) { - Log.e(TAG, "Closing file " + filename + " failed", e); + Log.e(TAG, "Closing file " + file + " failed", e); return ERROR; } } @@ -1817,16 +1838,18 @@ public class TextToSpeech { * * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation. * @deprecated As of API level 20, replaced by - * {@link #synthesizeToFile(CharSequence, HashMap, String, String)}. + * {@link #synthesizeToFile(CharSequence, Bundle, File, String)}. */ + @Deprecated public int synthesizeToFile(final String text, final HashMap<String, String> params, final String filename) { - return synthesizeToFile(text, params, filename, params.get(Engine.KEY_PARAM_UTTERANCE_ID)); + return synthesizeToFile(text, convertParamsHashMaptoBundle(params), + new File(filename), params.get(Engine.KEY_PARAM_UTTERANCE_ID)); } - private Bundle getParams(HashMap<String, String> params) { + private Bundle convertParamsHashMaptoBundle(HashMap<String, String> params) { if (params != null && !params.isEmpty()) { - Bundle bundle = new Bundle(mParams); + Bundle bundle = new Bundle(); copyIntParam(bundle, params, Engine.KEY_PARAM_STREAM); copyIntParam(bundle, params, Engine.KEY_PARAM_SESSION_ID); copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID); @@ -1852,11 +1875,85 @@ public class TextToSpeech { } return bundle; + } + return null; + } + + private Bundle getParams(Bundle params) { + if (params != null && !params.isEmpty()) { + Bundle bundle = new Bundle(mParams); + bundle.putAll(params); + + verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_STREAM); + verifyIntegerBundleParam(bundle, Engine.KEY_PARAM_SESSION_ID); + verifyStringBundleParam(bundle, Engine.KEY_PARAM_UTTERANCE_ID); + verifyFloatBundleParam(bundle, Engine.KEY_PARAM_VOLUME); + verifyFloatBundleParam(bundle, Engine.KEY_PARAM_PAN); + + // Copy feature strings defined by the framework. + verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_SYNTHESIS); + verifyBooleanBundleParam(bundle, Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS); + verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_TIMEOUT_MS); + verifyIntegerBundleParam(bundle, Engine.KEY_FEATURE_NETWORK_RETRIES_COUNT); + + return bundle; } else { return mParams; } } + private static boolean verifyIntegerBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof Integer || + bundle.get(key) instanceof Long)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be an Integer or a Long"); + return false; + } + } + return true; + } + + private static boolean verifyStringBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof String)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be a String"); + return false; + } + } + return true; + } + + private static boolean verifyBooleanBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof Boolean || + bundle.get(key) instanceof String)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be a Boolean or String"); + return false; + } + } + return true; + } + + + private static boolean verifyFloatBundleParam(Bundle bundle, String key) { + if (bundle.containsKey(key)) { + if (!(bundle.get(key) instanceof Float || + bundle.get(key) instanceof Double)) { + bundle.remove(key); + Log.w(TAG, "Synthesis request paramter " + key + " containst value " + + " with invalid type. Should be a Float or a Double"); + return false; + } + } + return true; + } + private void copyStringParam(Bundle bundle, HashMap<String, String> params, String key) { String value = params.get(key); if (value != null) { diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java index 4fea109..d00a433 100644 --- a/core/java/android/speech/tts/TextToSpeechService.java +++ b/core/java/android/speech/tts/TextToSpeechService.java @@ -84,7 +84,7 @@ import java.util.Set; * the following methods: * <ul> * <li>{@link #onGetVoices()}</li> - * <li>{@link #isValidVoiceName(String)}</li> + * <li>{@link #onIsValidVoiceName(String)}</li> * <li>{@link #onLoadVoice(String)}</li> * <li>{@link #onGetDefaultVoiceNameFor(String, String, String)}</li> * </ul> @@ -278,7 +278,7 @@ public abstract class TextToSpeechService extends Service { * * @return A list of voices supported. */ - protected List<Voice> onGetVoices() { + public List<Voice> onGetVoices() { // Enumerate all locales and check if they are available ArrayList<Voice> voices = new ArrayList<Voice>(); for (Locale locale : Locale.getAvailableLocales()) { @@ -335,7 +335,7 @@ public abstract class TextToSpeechService extends Service { } Locale properLocale = TtsEngines.normalizeTTSLocale(iso3Locale); String voiceName = properLocale.toLanguageTag(); - if (isValidVoiceName(voiceName) == TextToSpeech.SUCCESS) { + if (onIsValidVoiceName(voiceName) == TextToSpeech.SUCCESS) { return voiceName; } else { return null; @@ -357,7 +357,7 @@ public abstract class TextToSpeechService extends Service { * @param voiceName Name of the voice. * @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}. */ - protected int onLoadVoice(String voiceName) { + public int onLoadVoice(String voiceName) { Locale locale = Locale.forLanguageTag(voiceName); if (locale == null) { return TextToSpeech.ERROR; @@ -388,7 +388,7 @@ public abstract class TextToSpeechService extends Service { * @param voiceName Name of the voice. * @return {@link TextToSpeech#ERROR} or {@link TextToSpeech#SUCCESS}. */ - protected int isValidVoiceName(String voiceName) { + public int onIsValidVoiceName(String voiceName) { Locale locale = Locale.forLanguageTag(voiceName); if (locale == null) { return TextToSpeech.ERROR; @@ -1275,7 +1275,7 @@ public abstract class TextToSpeechService extends Service { if (!checkNonNull(voiceName)) { return TextToSpeech.ERROR; } - int retVal = isValidVoiceName(voiceName); + int retVal = onIsValidVoiceName(voiceName); if (retVal == TextToSpeech.SUCCESS) { SpeechItem item = new LoadVoiceItem(caller, Binder.getCallingUid(), diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java index a97141c..a1fa51d 100644 --- a/core/java/android/speech/tts/Voice.java +++ b/core/java/android/speech/tts/Voice.java @@ -162,7 +162,7 @@ public class Voice implements Parcelable { /** * @return Does the Voice require a network connection to work. */ - public boolean getRequiresNetworkConnection() { + public boolean isNetworkConnectionRequired() { return mRequiresNetworkConnection; } |