OSDN Git Service

am d9d8ef26: Merge "b/2335780 Fixed race conditions which causes BT to not be in...
[android-x86/packages-apps-Settings.git] / src / com / android / settings / TextToSpeechSettings.java
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.settings;
18
19 import static android.provider.Settings.Secure.TTS_USE_DEFAULTS;
20 import static android.provider.Settings.Secure.TTS_DEFAULT_RATE;
21 import static android.provider.Settings.Secure.TTS_DEFAULT_LANG;
22 import static android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY;
23 import static android.provider.Settings.Secure.TTS_DEFAULT_VARIANT;
24 import static android.provider.Settings.Secure.TTS_DEFAULT_SYNTH;
25
26 import android.content.ContentResolver;
27 import android.content.Intent;
28 import android.content.pm.ActivityInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ResolveInfo;
31 import android.os.Bundle;
32 import android.preference.ListPreference;
33 import android.preference.Preference;
34 import android.preference.PreferenceActivity;
35 import android.preference.CheckBoxPreference;
36 import android.provider.Settings;
37 import android.provider.Settings.SettingNotFoundException;
38 import android.speech.tts.TextToSpeech;
39 import android.util.Log;
40
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.StringTokenizer;
44
45 public class TextToSpeechSettings extends PreferenceActivity implements
46         Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
47         TextToSpeech.OnInitListener {
48
49     private static final String TAG = "TextToSpeechSettings";
50
51     private static final String KEY_TTS_PLAY_EXAMPLE = "tts_play_example";
52     private static final String KEY_TTS_INSTALL_DATA = "tts_install_data";
53     private static final String KEY_TTS_USE_DEFAULT = "toggle_use_default_tts_settings";
54     private static final String KEY_TTS_DEFAULT_RATE = "tts_default_rate";
55     private static final String KEY_TTS_DEFAULT_LANG = "tts_default_lang";
56     private static final String KEY_TTS_DEFAULT_COUNTRY = "tts_default_country";
57     private static final String KEY_TTS_DEFAULT_VARIANT = "tts_default_variant";
58     // TODO move default Locale values to TextToSpeech.Engine
59     private static final String DEFAULT_LANG_VAL = "eng";
60     private static final String DEFAULT_COUNTRY_VAL = "USA";
61     private static final String DEFAULT_VARIANT_VAL = "";
62
63     private static final String LOCALE_DELIMITER = "-";
64
65     private static final String FALLBACK_TTS_DEFAULT_SYNTH =
66             TextToSpeech.Engine.DEFAULT_SYNTH;
67
68     private Preference         mPlayExample = null;
69     private Preference         mInstallData = null;
70     private CheckBoxPreference mUseDefaultPref = null;
71     private ListPreference     mDefaultRatePref = null;
72     private ListPreference     mDefaultLocPref = null;
73     private String             mDefaultLanguage = null;
74     private String             mDefaultCountry = null;
75     private String             mDefaultLocVariant = null;
76     private String             mDefaultEng = "";
77     private int                mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
78
79     // Array of strings used to demonstrate TTS in the different languages.
80     private String[] mDemoStrings;
81     // Index of the current string to use for the demo.
82     private int      mDemoStringIndex = 0;
83
84     private boolean mEnableDemo = false;
85
86     private TextToSpeech mTts = null;
87
88     /**
89      * Request code (arbitrary value) for voice data check through
90      * startActivityForResult.
91      */
92     private static final int VOICE_DATA_INTEGRITY_CHECK = 1977;
93
94     @Override
95     protected void onCreate(Bundle savedInstanceState) {
96         super.onCreate(savedInstanceState);
97
98         addPreferencesFromResource(R.xml.tts_settings);
99
100         mDemoStrings = getResources().getStringArray(R.array.tts_demo_strings);
101
102         setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
103
104         mEnableDemo = false;
105         initClickers();
106         initDefaultSettings();
107     }
108
109
110     @Override
111     protected void onStart() {
112         super.onStart();
113         // whenever we return to this screen, we don't know the state of the
114         // system, so we have to recheck that we can play the demo, or it must be disabled.
115         // TODO make the TTS service listen to "changes in the system", i.e. sd card un/mount
116         initClickers();
117         updateWidgetState();
118         checkVoiceData();
119     }
120
121
122     @Override
123     protected void onDestroy() {
124         super.onDestroy();
125         if (mTts != null) {
126             mTts.shutdown();
127         }
128     }
129
130
131     private void initClickers() {
132         mPlayExample = findPreference(KEY_TTS_PLAY_EXAMPLE);
133         mPlayExample.setOnPreferenceClickListener(this);
134
135         mInstallData = findPreference(KEY_TTS_INSTALL_DATA);
136         mInstallData.setOnPreferenceClickListener(this);
137     }
138
139
140     private void initDefaultSettings() {
141         ContentResolver resolver = getContentResolver();
142
143         // Find the default TTS values in the settings, initialize and store the
144         // settings if they are not found.
145
146         // "Use Defaults"
147         int useDefault = 0;
148         mUseDefaultPref = (CheckBoxPreference) findPreference(KEY_TTS_USE_DEFAULT);
149         try {
150             useDefault = Settings.Secure.getInt(resolver, TTS_USE_DEFAULTS);
151         } catch (SettingNotFoundException e) {
152             // "use default" setting not found, initialize it
153             useDefault = TextToSpeech.Engine.USE_DEFAULTS;
154             Settings.Secure.putInt(resolver, TTS_USE_DEFAULTS, useDefault);
155         }
156         mUseDefaultPref.setChecked(useDefault == 1);
157         mUseDefaultPref.setOnPreferenceChangeListener(this);
158
159         // Default engine
160         String engine = Settings.Secure.getString(resolver, TTS_DEFAULT_SYNTH);
161         if (engine == null) {
162             // TODO move FALLBACK_TTS_DEFAULT_SYNTH to TextToSpeech
163             engine = FALLBACK_TTS_DEFAULT_SYNTH;
164             Settings.Secure.putString(resolver, TTS_DEFAULT_SYNTH, engine);
165         }
166         mDefaultEng = engine;
167
168         // Default rate
169         mDefaultRatePref = (ListPreference) findPreference(KEY_TTS_DEFAULT_RATE);
170         try {
171             mDefaultRate = Settings.Secure.getInt(resolver, TTS_DEFAULT_RATE);
172         } catch (SettingNotFoundException e) {
173             // default rate setting not found, initialize it
174             mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
175             Settings.Secure.putInt(resolver, TTS_DEFAULT_RATE, mDefaultRate);
176         }
177         mDefaultRatePref.setValue(String.valueOf(mDefaultRate));
178         mDefaultRatePref.setOnPreferenceChangeListener(this);
179
180         // Default language / country / variant : these three values map to a single ListPref
181         // representing the matching Locale
182         mDefaultLocPref = (ListPreference) findPreference(KEY_TTS_DEFAULT_LANG);
183         initDefaultLang();
184         mDefaultLocPref.setOnPreferenceChangeListener(this);
185     }
186
187
188     /**
189      * Ask the current default engine to launch the matching CHECK_TTS_DATA activity
190      * to check the required TTS files are properly installed.
191      */
192     private void checkVoiceData() {
193         PackageManager pm = getPackageManager();
194         Intent intent = new Intent();
195         intent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
196         List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
197         // query only the package that matches that of the default engine
198         for (int i = 0; i < resolveInfos.size(); i++) {
199             ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
200             if (mDefaultEng.equals(currentActivityInfo.packageName)) {
201                 intent.setClassName(mDefaultEng, currentActivityInfo.name);
202                 this.startActivityForResult(intent, VOICE_DATA_INTEGRITY_CHECK);
203             }
204         }
205     }
206
207
208     /**
209      * Ask the current default engine to launch the matching INSTALL_TTS_DATA activity
210      * so the required TTS files are properly installed.
211      */
212     private void installVoiceData() {
213         PackageManager pm = getPackageManager();
214         Intent intent = new Intent();
215         intent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
216         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
217         List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
218         // query only the package that matches that of the default engine
219         for (int i = 0; i < resolveInfos.size(); i++) {
220             ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
221             if (mDefaultEng.equals(currentActivityInfo.packageName)) {
222                 intent.setClassName(mDefaultEng, currentActivityInfo.name);
223                 this.startActivity(intent);
224             }
225         }
226     }
227
228
229     /**
230      * Called when the TTS engine is initialized.
231      */
232     public void onInit(int status) {
233         if (status == TextToSpeech.SUCCESS) {
234             Log.v(TAG, "TTS engine for settings screen initialized.");
235             mEnableDemo = true;
236             mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry));
237             mTts.setSpeechRate((float)(mDefaultRate/100.0f));
238         } else {
239             Log.v(TAG, "TTS engine for settings screen failed to initialize successfully.");
240             mEnableDemo = false;
241         }
242         updateWidgetState();
243     }
244
245
246     /**
247      * Called when voice data integrity check returns
248      */
249     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
250         if (requestCode == VOICE_DATA_INTEGRITY_CHECK) {
251             if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
252                 Log.v(TAG, "Voice data check passed");
253                 if (mTts == null) {
254                     mTts = new TextToSpeech(this, this);
255                 }
256             } else {
257                 Log.v(TAG, "Voice data check failed");
258                 mEnableDemo = false;
259                 updateWidgetState();
260             }
261         }
262     }
263
264
265     public boolean onPreferenceChange(Preference preference, Object objValue) {
266         if (KEY_TTS_USE_DEFAULT.equals(preference.getKey())) {
267             // "Use Defaults"
268             int value = (Boolean)objValue ? 1 : 0;
269             Settings.Secure.putInt(getContentResolver(), TTS_USE_DEFAULTS,
270                     value);
271             Log.i(TAG, "TTS use default settings is "+objValue.toString());
272         } else if (KEY_TTS_DEFAULT_RATE.equals(preference.getKey())) {
273             // Default rate
274             mDefaultRate = Integer.parseInt((String) objValue);
275             try {
276                 Settings.Secure.putInt(getContentResolver(),
277                         TTS_DEFAULT_RATE, mDefaultRate);
278                 if (mTts != null) {
279                     mTts.setSpeechRate((float)(mDefaultRate/100.0f));
280                 }
281                 Log.i(TAG, "TTS default rate is " + mDefaultRate);
282             } catch (NumberFormatException e) {
283                 Log.e(TAG, "could not persist default TTS rate setting", e);
284             }
285         } else if (KEY_TTS_DEFAULT_LANG.equals(preference.getKey())) {
286             // Default locale
287             ContentResolver resolver = getContentResolver();
288             parseLocaleInfo((String) objValue);
289             Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, mDefaultLanguage);
290             Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, mDefaultCountry);
291             Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, mDefaultLocVariant);
292             Log.v(TAG, "TTS default lang/country/variant set to "
293                     + mDefaultLanguage + "/" + mDefaultCountry + "/" + mDefaultLocVariant);
294             if (mTts != null) {
295                 mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry));
296             }
297             int newIndex = mDefaultLocPref.findIndexOfValue((String)objValue);
298             Log.v("Settings", " selected is " + newIndex);
299             mDemoStringIndex = newIndex > -1 ? newIndex : 0;
300         }
301
302         return true;
303     }
304
305
306     /**
307      * Called when mPlayExample or mInstallData is clicked
308      */
309     public boolean onPreferenceClick(Preference preference) {
310         if (preference == mPlayExample) {
311             // Play example
312             if (mTts != null) {
313                 mTts.speak(mDemoStrings[mDemoStringIndex], TextToSpeech.QUEUE_FLUSH, null);
314             }
315             return true;
316         }
317         if (preference == mInstallData) {
318             installVoiceData();
319             // quit this activity so it needs to be restarted after installation of the voice data
320             finish();
321             return true;
322         }
323         return false;
324     }
325
326
327     private void updateWidgetState() {
328         mPlayExample.setEnabled(mEnableDemo);
329         mUseDefaultPref.setEnabled(mEnableDemo);
330         mDefaultRatePref.setEnabled(mEnableDemo);
331         mDefaultLocPref.setEnabled(mEnableDemo);
332
333         mInstallData.setEnabled(!mEnableDemo);
334     }
335
336
337     private void parseLocaleInfo(String locale) {
338         StringTokenizer tokenizer = new StringTokenizer(locale, LOCALE_DELIMITER);
339         mDefaultLanguage = "";
340         mDefaultCountry = "";
341         mDefaultLocVariant = "";
342         if (tokenizer.hasMoreTokens()) {
343             mDefaultLanguage = tokenizer.nextToken().trim();
344         }
345         if (tokenizer.hasMoreTokens()) {
346             mDefaultCountry = tokenizer.nextToken().trim();
347         }
348         if (tokenizer.hasMoreTokens()) {
349             mDefaultLocVariant = tokenizer.nextToken().trim();
350         }
351     }
352
353
354     /**
355      *  Initialize the default language in the UI and in the preferences.
356      *  After this method has been invoked, the default language is a supported Locale.
357      */
358     private void initDefaultLang() {
359         // if there isn't already a default language preference
360         if (!hasLangPref()) {
361             // if the current Locale is supported
362             if (isCurrentLocSupported()) {
363                 // then use the current Locale as the default language
364                 useCurrentLocAsDefault();
365             } else {
366                 // otherwise use a default supported Locale as the default language
367                 useSupportedLocAsDefault();
368             }
369         }
370
371         // Update the language preference list with the default language and the matching
372         // demo string (at this stage there is a default language pref)
373         ContentResolver resolver = getContentResolver();
374         mDefaultLanguage = Settings.Secure.getString(resolver, TTS_DEFAULT_LANG);
375         mDefaultCountry = Settings.Secure.getString(resolver, KEY_TTS_DEFAULT_COUNTRY);
376         mDefaultLocVariant = Settings.Secure.getString(resolver, KEY_TTS_DEFAULT_VARIANT);
377
378         // update the demo string
379         mDemoStringIndex = mDefaultLocPref.findIndexOfValue(mDefaultLanguage + LOCALE_DELIMITER
380                 + mDefaultCountry);
381         mDefaultLocPref.setValueIndex(mDemoStringIndex);
382     }
383
384     /**
385      * (helper function for initDefaultLang() )
386      * Returns whether there is a default language in the TTS settings.
387      */
388     private boolean hasLangPref() {
389         String language = Settings.Secure.getString(getContentResolver(), TTS_DEFAULT_LANG);
390         return (language != null);
391     }
392
393     /**
394      * (helper function for initDefaultLang() )
395      * Returns whether the current Locale is supported by this Settings screen
396      */
397     private boolean isCurrentLocSupported() {
398         String currentLocID = Locale.getDefault().getISO3Language() + LOCALE_DELIMITER
399                 + Locale.getDefault().getISO3Country();
400         return (mDefaultLocPref.findIndexOfValue(currentLocID) > -1);
401     }
402
403     /**
404      * (helper function for initDefaultLang() )
405      * Sets the default language in TTS settings to be the current Locale.
406      * This should only be used after checking that the current Locale is supported.
407      */
408     private void useCurrentLocAsDefault() {
409         Locale currentLocale = Locale.getDefault();
410         ContentResolver resolver = getContentResolver();
411         Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, currentLocale.getISO3Language());
412         Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, currentLocale.getISO3Country());
413         Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, currentLocale.getVariant());
414     }
415
416     /**
417      * (helper function for initDefaultLang() )
418      * Sets the default language in TTS settings to be one known to be supported
419      */
420     private void useSupportedLocAsDefault() {
421         ContentResolver resolver = getContentResolver();
422         Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, DEFAULT_LANG_VAL);
423         Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, DEFAULT_COUNTRY_VAL);
424         Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, DEFAULT_VARIANT_VAL);
425     }
426
427 }