Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35c7698a authored by Przemyslaw Szczepaniak's avatar Przemyslaw Szczepaniak
Browse files

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
parent 9a245b5d
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -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
+123 −26
Original line number Diff line number Diff line
@@ -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);
@@ -1851,12 +1874,86 @@ 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) {
+6 −6
Original line number Diff line number Diff line
@@ -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(),
+1 −1
Original line number Diff line number Diff line
@@ -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;
    }