TextToSpeech.java revision a981013aa7315e13c6c5f6aad489813c419031ea
1/*
2 * Copyright (C) 2009 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16package android.speech.tts;
17
18import android.speech.tts.ITts;
19import android.speech.tts.ITtsCallback;
20
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.ServiceConnection;
25import android.media.AudioManager;
26import android.os.IBinder;
27import android.os.RemoteException;
28import android.util.Log;
29
30import java.util.HashMap;
31import java.util.Locale;
32
33/**
34 *
35 * Synthesizes speech from text for immediate playback or to create a sound file.
36 *
37 */
38//TODO complete javadoc + add links to constants
39public class TextToSpeech {
40
41    /**
42     * Denotes a successful operation.
43     */
44    public static final int TTS_SUCCESS                = 0;
45    /**
46     * Denotes a generic operation failure.
47     */
48    public static final int TTS_ERROR                  = -1;
49
50    /**
51     * Queue mode where all entries in the playback queue (media to be played
52     * and text to be synthesized) are dropped and replaced by the new entry.
53     */
54    public static final int TTS_QUEUE_FLUSH = 0;
55    /**
56     * Queue mode where the new entry is added at the end of the playback queue.
57     */
58    public static final int TTS_QUEUE_ADD = 1;
59
60
61    /**
62     * Denotes the language is available exactly as specified by the locale
63     */
64    public static final int TTS_LANG_COUNTRY_VAR_AVAILABLE = 2;
65
66
67    /**
68     * Denotes the language is available for the language and country specified
69     * by the locale, but not the variant.
70     */
71    public static final int TTS_LANG_COUNTRY_AVAILABLE = 1;
72
73
74    /**
75     * Denotes the language is available for the language by the locale,
76     * but not the country and variant.
77     */
78    public static final int TTS_LANG_AVAILABLE = 0;
79
80    /**
81     * Denotes the language data is missing.
82     */
83    public static final int TTS_LANG_MISSING_DATA = -1;
84
85    /**
86     * Denotes the language is not supported by the current TTS engine.
87     */
88    public static final int TTS_LANG_NOT_SUPPORTED = -2;
89
90
91    /**
92     * Called when the TTS has initialized.
93     *
94     * The InitListener must implement the onInit function. onInit is passed a
95     * status code indicating the result of the TTS initialization.
96     */
97    public interface OnInitListener {
98        public void onInit(int status);
99    }
100
101    /**
102     * Internal constants for the TTS functionality
103     *
104     * {@hide}
105     */
106    public class Engine {
107        // default values for a TTS engine when settings are not found in the provider
108        public static final int FALLBACK_TTS_DEFAULT_RATE = 100; // 1x
109        public static final int FALLBACK_TTS_DEFAULT_PITCH = 100;// 1x
110        public static final int FALLBACK_TTS_USE_DEFAULTS = 0; // false
111        public static final String FALLBACK_TTS_DEFAULT_SYNTH = "com.svox.pico";
112
113        // default values for rendering
114        public static final int TTS_DEFAULT_STREAM = AudioManager.STREAM_MUSIC;
115
116        // return codes for a TTS engine's check data activity
117        public static final int CHECK_VOICE_DATA_PASS = 1;
118        public static final int CHECK_VOICE_DATA_FAIL = 0;
119        public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
120        public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
121        public static final int CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD = -3;
122
123        // return codes for a TTS engine's check data activity
124        public static final String VOICE_DATA_ROOT_DIRECTORY = "dataRoot";
125        public static final String VOICE_DATA_FILES = "dataFiles";
126        public static final String VOICE_DATA_FILES_INFO = "dataFilesInfo";
127
128        // keys for the parameters passed with speak commands
129        public static final String TTS_KEY_PARAM_RATE = "rate";
130        public static final String TTS_KEY_PARAM_LANGUAGE = "language";
131        public static final String TTS_KEY_PARAM_COUNTRY = "country";
132        public static final String TTS_KEY_PARAM_VARIANT = "variant";
133        public static final String TTS_KEY_PARAM_STREAM = "streamType";
134        public static final String TTS_KEY_PARAM_UTTERANCE_ID = "utteranceId";
135        protected static final int TTS_PARAM_POSITION_RATE = 0;
136        protected static final int TTS_PARAM_POSITION_LANGUAGE = 2;
137        protected static final int TTS_PARAM_POSITION_COUNTRY = 4;
138        protected static final int TTS_PARAM_POSITION_VARIANT = 6;
139        protected static final int TTS_PARAM_POSITION_STREAM = 8;
140        protected static final int TTS_PARAM_POSITION_UTTERANCE_ID = 10;
141        protected static final int TTS_NB_CACHED_PARAMS = 6;
142    }
143
144    /**
145     * Connection needed for the TTS.
146     */
147    private ServiceConnection mServiceConnection;
148
149    private ITts mITts = null;
150    private Context mContext = null;
151    private String mPackageName = "";
152    private OnInitListener mInitListener = null;
153    private boolean mStarted = false;
154    private final Object mStartLock = new Object();
155    /**
156     * Used to store the cached parameters sent along with each synthesis request to the
157     * TTS service.
158     */
159    private String[] mCachedParams;
160
161    /**
162     * The constructor for the TTS.
163     *
164     * @param context
165     *            The context
166     * @param listener
167     *            The InitListener that will be called when the TTS has
168     *            initialized successfully.
169     */
170    public TextToSpeech(Context context, OnInitListener listener) {
171        mContext = context;
172        mPackageName = mContext.getPackageName();
173        mInitListener = listener;
174
175        mCachedParams = new String[2*Engine.TTS_NB_CACHED_PARAMS]; // store key and value
176        mCachedParams[Engine.TTS_PARAM_POSITION_RATE] = Engine.TTS_KEY_PARAM_RATE;
177        mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE] = Engine.TTS_KEY_PARAM_LANGUAGE;
178        mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY;
179        mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT;
180        mCachedParams[Engine.TTS_PARAM_POSITION_STREAM] = Engine.TTS_KEY_PARAM_STREAM;
181
182        mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] =
183                String.valueOf(Engine.FALLBACK_TTS_DEFAULT_RATE);
184        // initialize the language cached parameters with the current Locale
185        Locale defaultLoc = Locale.getDefault();
186        mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language();
187        mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country();
188        mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant();
189
190        mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] =
191                String.valueOf(Engine.TTS_DEFAULT_STREAM);
192        mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = "";
193
194        initTts();
195    }
196
197
198    private void initTts() {
199        mStarted = false;
200
201        // Initialize the TTS, run the callback after the binding is successful
202        mServiceConnection = new ServiceConnection() {
203            public void onServiceConnected(ComponentName name, IBinder service) {
204                synchronized(mStartLock) {
205                    mITts = ITts.Stub.asInterface(service);
206                    mStarted = true;
207                    if (mInitListener != null) {
208                        // TODO manage failures and missing resources
209                        mInitListener.onInit(TTS_SUCCESS);
210                    }
211                }
212            }
213
214            public void onServiceDisconnected(ComponentName name) {
215                synchronized(mStartLock) {
216                    mITts = null;
217                    mInitListener = null;
218                    mStarted = false;
219                }
220            }
221        };
222
223        Intent intent = new Intent("android.intent.action.START_TTS_SERVICE");
224        intent.addCategory("android.intent.category.TTS");
225        mContext.bindService(intent, mServiceConnection,
226                Context.BIND_AUTO_CREATE);
227        // TODO handle case where the binding works (should always work) but
228        //      the plugin fails
229    }
230
231
232    /**
233     * Shuts down the TTS. It is good practice to call this in the onDestroy
234     * method of the Activity that is using the TTS so that the TTS is stopped
235     * cleanly.
236     */
237    public void shutdown() {
238        try {
239            mContext.unbindService(mServiceConnection);
240        } catch (IllegalArgumentException e) {
241            // Do nothing and fail silently since an error here indicates that
242            // binding never succeeded in the first place.
243        }
244    }
245
246
247    /**
248     * Adds a mapping between a string of text and a sound resource in a
249     * package.
250     *
251     * @see #TTS.speak(String text, int queueMode, String[] params)
252     *
253     * @param text
254     *            Example: <b><code>"south_south_east"</code></b><br/>
255     *
256     * @param packagename
257     *            Pass the packagename of the application that contains the
258     *            resource. If the resource is in your own application (this is
259     *            the most common case), then put the packagename of your
260     *            application here.<br/>
261     *            Example: <b>"com.google.marvin.compass"</b><br/>
262     *            The packagename can be found in the AndroidManifest.xml of
263     *            your application.
264     *            <p>
265     *            <code>&lt;manifest xmlns:android=&quot;...&quot;
266     *      package=&quot;<b>com.google.marvin.compass</b>&quot;&gt;</code>
267     *            </p>
268     *
269     * @param resourceId
270     *            Example: <b><code>R.raw.south_south_east</code></b>
271     *
272     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
273     */
274    public int addSpeech(String text, String packagename, int resourceId) {
275        synchronized(mStartLock) {
276            if (!mStarted) {
277                return TTS_ERROR;
278            }
279            try {
280                mITts.addSpeech(mPackageName, text, packagename, resourceId);
281                return TTS_SUCCESS;
282            } catch (RemoteException e) {
283                // TTS died; restart it.
284                mStarted = false;
285                initTts();
286            } catch (NullPointerException e) {
287                // TTS died; restart it.
288                mStarted = false;
289                initTts();
290            } catch (IllegalStateException e) {
291                // TTS died; restart it.
292                mStarted = false;
293                initTts();
294            }
295            return TTS_ERROR;
296        }
297    }
298
299
300    /**
301     * Adds a mapping between a string of text and a sound file. Using this, it
302     * is possible to add custom pronounciations for text.
303     *
304     * @param text
305     *            The string of text
306     * @param filename
307     *            The full path to the sound file (for example:
308     *            "/sdcard/mysounds/hello.wav")
309     *
310     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
311     */
312    public int addSpeech(String text, String filename) {
313        synchronized (mStartLock) {
314            if (!mStarted) {
315                return TTS_ERROR;
316            }
317            try {
318                mITts.addSpeechFile(mPackageName, text, filename);
319                return TTS_SUCCESS;
320            } catch (RemoteException e) {
321                // TTS died; restart it.
322                mStarted = false;
323                initTts();
324            } catch (NullPointerException e) {
325                // TTS died; restart it.
326                mStarted = false;
327                initTts();
328            } catch (IllegalStateException e) {
329                // TTS died; restart it.
330                mStarted = false;
331                initTts();
332            }
333            return TTS_ERROR;
334        }
335    }
336
337
338    /**
339     * Speaks the string using the specified queuing strategy and speech
340     * parameters. Note that the speech parameters are not universally supported
341     * by all engines and will be treated as a hint. The TTS library will try to
342     * fulfill these parameters as much as possible, but there is no guarantee
343     * that the voice used will have the properties specified.
344     *
345     * @param text
346     *            The string of text to be spoken.
347     * @param queueMode
348     *            The queuing strategy to use.
349     *            See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
350     * @param params
351     *            The hashmap of speech parameters to be used.
352     *
353     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
354     */
355    public int speak(String text, int queueMode, HashMap<String,String> params)
356    {
357        synchronized (mStartLock) {
358            int result = TTS_ERROR;
359            Log.i("TTS received: ", text);
360            if (!mStarted) {
361                return result;
362            }
363            try {
364                String extra = params.get(Engine.TTS_KEY_PARAM_STREAM);
365                if (extra != null) {
366                    mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra;
367                }
368                extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
369                if (extra != null) {
370                    mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra;
371                }
372                result = mITts.speak(mPackageName, text, queueMode, mCachedParams);
373            } catch (RemoteException e) {
374                // TTS died; restart it.
375                mStarted = false;
376                initTts();
377            } catch (NullPointerException e) {
378                // TTS died; restart it.
379                mStarted = false;
380                initTts();
381            } catch (IllegalStateException e) {
382                // TTS died; restart it.
383                mStarted = false;
384                initTts();
385            } finally {
386                resetCachedParams();
387                return result;
388            }
389        }
390    }
391
392
393    /**
394     * Plays the earcon using the specified queueing mode and parameters.
395     *
396     * @param earcon
397     *            The earcon that should be played
398     * @param queueMode
399     *            See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
400     * @param params
401     *            The hashmap of parameters to be used.
402     *
403     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
404     */
405    public int playEarcon(String earcon, int queueMode,
406            HashMap<String,String> params) {
407        synchronized (mStartLock) {
408            int result = TTS_ERROR;
409            if (!mStarted) {
410                return result;
411            }
412            try {
413                if ((params != null) && (!params.isEmpty())) {
414                    String extra = params.get(Engine.TTS_KEY_PARAM_STREAM);
415                    if (extra != null) {
416                        mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra;
417                    }
418                    extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
419                    if (extra != null) {
420                        mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra;
421                    }
422                }
423                result = mITts.playEarcon(mPackageName, earcon, queueMode, null);
424            } catch (RemoteException e) {
425                // TTS died; restart it.
426                mStarted = false;
427                initTts();
428            } catch (NullPointerException e) {
429                // TTS died; restart it.
430                mStarted = false;
431                initTts();
432            } catch (IllegalStateException e) {
433                // TTS died; restart it.
434                mStarted = false;
435                initTts();
436            } finally {
437                resetCachedParams();
438                return result;
439            }
440        }
441    }
442
443    /**
444     * Plays silence for the specified amount of time using the specified
445     * queue mode.
446     *
447     * @param durationInMs
448     *            A long that indicates how long the silence should last.
449     * @param queueMode
450     *            See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
451     *
452     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
453     */
454    public int playSilence(long durationInMs, int queueMode) {
455        synchronized (mStartLock) {
456            int result = TTS_ERROR;
457            if (!mStarted) {
458                return result;
459            }
460            try {
461                result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams);
462            } catch (RemoteException e) {
463                // TTS died; restart it.
464                mStarted = false;
465                initTts();
466            } catch (NullPointerException e) {
467                // TTS died; restart it.
468                mStarted = false;
469                initTts();
470            } catch (IllegalStateException e) {
471                // TTS died; restart it.
472                mStarted = false;
473                initTts();
474            } finally {
475              return result;
476            }
477        }
478    }
479
480
481    /**
482     * Returns whether or not the TTS is busy speaking.
483     *
484     * @return Whether or not the TTS is busy speaking.
485     */
486    public boolean isSpeaking() {
487        synchronized (mStartLock) {
488            if (!mStarted) {
489                return false;
490            }
491            try {
492                return mITts.isSpeaking();
493            } catch (RemoteException e) {
494                // TTS died; restart it.
495                mStarted = false;
496                initTts();
497            } catch (NullPointerException e) {
498                // TTS died; restart it.
499                mStarted = false;
500                initTts();
501            } catch (IllegalStateException e) {
502                // TTS died; restart it.
503                mStarted = false;
504                initTts();
505            }
506            return false;
507        }
508    }
509
510
511    /**
512     * Stops speech from the TTS.
513     *
514     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
515     */
516    public int stop() {
517        synchronized (mStartLock) {
518            int result = TTS_ERROR;
519            if (!mStarted) {
520                return result;
521            }
522            try {
523                result = mITts.stop(mPackageName);
524            } catch (RemoteException e) {
525                // TTS died; restart it.
526                mStarted = false;
527                initTts();
528            } catch (NullPointerException e) {
529                // TTS died; restart it.
530                mStarted = false;
531                initTts();
532            } catch (IllegalStateException e) {
533                // TTS died; restart it.
534                mStarted = false;
535                initTts();
536            } finally {
537              return result;
538            }
539        }
540    }
541
542
543    /**
544     * Sets the speech rate for the TTS engine.
545     *
546     * Note that the speech rate is not universally supported by all engines and
547     * will be treated as a hint. The TTS library will try to use the specified
548     * speech rate, but there is no guarantee.
549     * This has no effect on any pre-recorded speech.
550     *
551     * @param speechRate
552     *            The speech rate for the TTS engine. 1 is the normal speed,
553     *            lower values slow down the speech (0.5 is half the normal speech rate),
554     *            greater values accelerate it (2 is twice the normal speech rate).
555     *
556     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
557     */
558    public int setSpeechRate(float speechRate) {
559        synchronized (mStartLock) {
560            int result = TTS_ERROR;
561            if (!mStarted) {
562                return result;
563            }
564            try {
565                if (speechRate > 0) {
566                    int rate = (int)(speechRate*100);
567                    mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(rate);
568                    result = mITts.setSpeechRate(mPackageName, rate);
569                }
570            } catch (RemoteException e) {
571                // TTS died; restart it.
572                mStarted = false;
573                initTts();
574            } finally {
575              return result;
576            }
577        }
578    }
579
580
581    /**
582     * Sets the speech pitch for the TTS engine.
583     *
584     * Note that the pitch is not universally supported by all engines and
585     * will be treated as a hint. The TTS library will try to use the specified
586     * pitch, but there is no guarantee.
587     * This has no effect on any pre-recorded speech.
588     *
589     * @param pitch
590     *            The pitch for the TTS engine. 1 is the normal pitch,
591     *            lower values lower the tone of the synthesized voice,
592     *            greater values increase it.
593     *
594     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
595     */
596    public int setPitch(float pitch) {
597        synchronized (mStartLock) {
598            int result = TTS_ERROR;
599            if (!mStarted) {
600                return result;
601            }
602            try {
603                if (pitch > 0) {
604                    result = mITts.setPitch(mPackageName, (int)(pitch*100));
605                }
606            } catch (RemoteException e) {
607                // TTS died; restart it.
608                mStarted = false;
609                initTts();
610            } finally {
611              return result;
612            }
613        }
614    }
615
616
617    /**
618     * Sets the language for the TTS engine.
619     *
620     * Note that the language is not universally supported by all engines and
621     * will be treated as a hint. The TTS library will try to use the specified
622     * language as represented by the Locale, but there is no guarantee.
623     *
624     * @param loc
625     *            The locale describing the language to be used.
626     *
627     * @return Code indicating the support status for the locale. See the TTS_LANG_ codes.
628     */
629    public int setLanguage(Locale loc) {
630        synchronized (mStartLock) {
631            int result = TTS_LANG_NOT_SUPPORTED;
632            if (!mStarted) {
633                return result;
634            }
635            try {
636                mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language();
637                mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country();
638                mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant();
639                result = mITts.setLanguage(mPackageName,
640                        mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1],
641                        mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1],
642                        mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] );
643            } catch (RemoteException e) {
644                // TTS died; restart it.
645                mStarted = false;
646                initTts();
647            } finally {
648              return result;
649            }
650        }
651    }
652
653
654    /**
655     * Returns a Locale instance describing the language currently being used by the TTS engine.
656     * @return language, country (if any) and variant (if any) used by the engine stored in a Locale
657     *     instance, or null is the TTS engine has failed.
658     */
659    public Locale getLanguage() {
660        synchronized (mStartLock) {
661            if (!mStarted) {
662                return null;
663            }
664            try {
665                String[] locStrings =  mITts.getLanguage();
666                if (locStrings.length == 3) {
667                    return new Locale(locStrings[0], locStrings[1], locStrings[2]);
668                } else {
669                    return null;
670                }
671            } catch (RemoteException e) {
672                // TTS died; restart it.
673                mStarted = false;
674                initTts();
675            }
676            return null;
677        }
678    }
679
680    /**
681     * Checks if the specified language as represented by the Locale is available.
682     *
683     * @param loc
684     *            The Locale describing the language to be used.
685     *
686     * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE,
687     *         TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE.
688     */
689    public int isLanguageAvailable(Locale loc) {
690        synchronized (mStartLock) {
691            int result = TTS_LANG_NOT_SUPPORTED;
692            if (!mStarted) {
693                return result;
694            }
695            try {
696                result = mITts.isLanguageAvailable(loc.getISO3Language(),
697                        loc.getISO3Country(), loc.getVariant());
698            } catch (RemoteException e) {
699                // TTS died; restart it.
700                mStarted = false;
701                initTts();
702            } finally {
703              return result;
704            }
705        }
706    }
707
708
709    /**
710     * Synthesizes the given text to a file using the specified parameters.
711     *
712     * @param text
713     *            The String of text that should be synthesized
714     * @param params
715     *            A hashmap of parameters.
716     * @param filename
717     *            The string that gives the full output filename; it should be
718     *            something like "/sdcard/myappsounds/mysound.wav".
719     *
720     * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS.
721     */
722    public int synthesizeToFile(String text, HashMap<String,String> params,
723            String filename) {
724        synchronized (mStartLock) {
725            int result = TTS_ERROR;
726            if (!mStarted) {
727                return result;
728            }
729            try {
730                // no need to read the stream type here
731                String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID);
732                if (extra != null) {
733                    mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra;
734                }
735                if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){
736                    result = TTS_SUCCESS;
737                }
738            } catch (RemoteException e) {
739                // TTS died; restart it.
740                mStarted = false;
741                initTts();
742            } catch (NullPointerException e) {
743                // TTS died; restart it.
744                mStarted = false;
745                initTts();
746            } catch (IllegalStateException e) {
747                // TTS died; restart it.
748                mStarted = false;
749                initTts();
750            } finally {
751                resetCachedParams();
752                return result;
753            }
754        }
755    }
756
757
758    /**
759     * Convenience method to reset the cached parameters to the current default values
760     * if they are not persistent between calls to the service.
761     */
762    private void resetCachedParams() {
763        mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] =
764                String.valueOf(Engine.TTS_DEFAULT_STREAM);
765        mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = "";
766    }
767
768}
769