182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler/*
282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * Copyright (C) 2015 The Android Open Source Project
382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler *
482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * Licensed under the Apache License, Version 2.0 (the "License");
582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * you may not use this file except in compliance with the License.
682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * You may obtain a copy of the License at
782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler *
882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler *      http://www.apache.org/licenses/LICENSE-2.0
982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler *
1082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * Unless required by applicable law or agreed to in writing, software
1182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * distributed under the License is distributed on an "AS IS" BASIS,
1282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * See the License for the specific language governing permissions and
1482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler * limitations under the License
1582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler */
1682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
1782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerpackage com.android.tv.settings.system;
1882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
1982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.app.AlertDialog;
2082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.content.ActivityNotFoundException;
2182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.content.ContentResolver;
2282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.content.Intent;
2382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.os.Bundle;
2482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.provider.Settings;
2582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.speech.tts.TextToSpeech;
2682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.speech.tts.TtsEngines;
2782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.speech.tts.UtteranceProgressListener;
2882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.support.v17.preference.LeanbackPreferenceFragment;
2982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.support.v7.preference.ListPreference;
3082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.support.v7.preference.Preference;
3182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.support.v7.preference.PreferenceCategory;
3282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.text.TextUtils;
3382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.util.Log;
3482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport android.widget.Checkable;
3582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
3682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport com.android.tv.settings.R;
3782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
3882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.ArrayList;
3982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.HashMap;
4082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.List;
4182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.Locale;
4282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.MissingResourceException;
4382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.Objects;
4482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerimport java.util.Set;
4582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
4682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantlerpublic class TextToSpeechFragment extends LeanbackPreferenceFragment  implements
4782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
4882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        TtsEnginePreference.RadioButtonGroupState {
4982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final String TAG = "TextToSpeechSettings";
5082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final boolean DBG = false;
5182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
5282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /** Preference key for the engine settings preference */
5382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final String KEY_ENGINE_SETTINGS = "tts_engine_settings";
5482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
5582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /** Preference key for the "play TTS example" preference. */
5682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final String KEY_PLAY_EXAMPLE = "tts_play_example";
5782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
5882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /** Preference key for the TTS rate selection dialog. */
5982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final String KEY_DEFAULT_RATE = "tts_default_rate";
6082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
6182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /** Preference key for the TTS status field. */
6282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final String KEY_STATUS = "tts_status";
6382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
6482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
6582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Preference key for the engine selection preference.
6682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
6782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final String KEY_ENGINE_PREFERENCE_SECTION =
6882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            "tts_engine_preference_section";
6982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
7082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
7182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * These look like birth years, but they aren't mine. I'm much younger than this.
7282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
7382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final int GET_SAMPLE_TEXT = 1983;
7482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private static final int VOICE_DATA_INTEGRITY_CHECK = 1977;
7582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
7682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private PreferenceCategory mEnginePreferenceCategory;
7782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private Preference mEngineSettingsPref;
7882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private ListPreference mDefaultRatePref;
7982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private Preference mPlayExample;
8082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private Preference mEngineStatus;
8182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
8282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
8382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
8482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
8582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * The currently selected engine.
8682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
8782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private String mCurrentEngine;
8882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
8982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
9082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * The engine checkbox that is currently checked. Saves us a bit of effort
9182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * in deducing the right one from the currently selected engine.
9282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
9382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private Checkable mCurrentChecked;
9482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
9582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
9682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * The previously selected TTS engine. Useful for rollbacks if the users
9782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * choice is not loaded or fails a voice integrity check.
9882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
9982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private String mPreviousEngine;
10082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
10182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private TextToSpeech mTts = null;
10282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private TtsEngines mEnginesHelper = null;
10382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
10482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private String mSampleText = null;
10582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
10682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
10782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Default locale used by selected TTS engine, null if not connected to any engine.
10882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
10982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private Locale mCurrentDefaultLocale;
11082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
11182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
11282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * List of available locals of selected TTS engine, as returned by
11382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * {@link TextToSpeech.Engine#ACTION_CHECK_TTS_DATA} activity. If empty, then activity
11482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * was not yet called.
11582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
11682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private List<String> mAvailableStrLocals;
11782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
11882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
11982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * The initialization listener used when we are initalizing the settings
12082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * screen for the first time (as opposed to when a user changes his choice
12182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * of engine).
12282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
12382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private final TextToSpeech.OnInitListener mInitListener = new TextToSpeech.OnInitListener() {
12482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        @Override
12582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        public void onInit(int status) {
12682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            onInitEngine(status);
12782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
12882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    };
12982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
13082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
13182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * The initialization listener used when the user changes his choice of
13282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * engine (as opposed to when then screen is being initialized for the first
13382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * time).
13482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
13582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private final TextToSpeech.OnInitListener mUpdateListener = new TextToSpeech.OnInitListener() {
13682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        @Override
13782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        public void onInit(int status) {
13882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            onUpdateEngine(status);
13982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
14082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    };
14182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
14282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
14382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
14482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        addPreferencesFromResource(R.xml.tts_settings);
14582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
14682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEngineSettingsPref = findPreference(KEY_ENGINE_SETTINGS);
14782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
14882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mPlayExample = findPreference(KEY_PLAY_EXAMPLE);
14982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mPlayExample.setOnPreferenceClickListener(this);
15082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mPlayExample.setEnabled(false);
15182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
15282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEnginePreferenceCategory = (PreferenceCategory) findPreference(
15382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                KEY_ENGINE_PREFERENCE_SECTION);
15482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mDefaultRatePref = (ListPreference) findPreference(KEY_DEFAULT_RATE);
15582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
15682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEngineStatus = findPreference(KEY_STATUS);
15782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        updateEngineStatus(R.string.tts_status_checking);
15882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
15982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
16082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
16182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onCreate(Bundle savedInstanceState) {
16282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        super.onCreate(savedInstanceState);
16382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
16482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        getActivity().setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
16582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
16682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener);
16782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEnginesHelper = new TtsEngines(getActivity().getApplicationContext());
16882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
16982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        setTtsUtteranceProgressListener();
17082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        initSettings();
17182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
17282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
17382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
17482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onResume() {
17582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        super.onResume();
17682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
17782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mTts == null || mCurrentDefaultLocale == null) {
17882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return;
17982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
18082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Locale ttsDefaultLocale = mTts.getDefaultLanguage();
18182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (!mCurrentDefaultLocale.equals(ttsDefaultLocale)) {
18282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(false);
18382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            checkDefaultLocale();
18482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
18582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
18682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
18782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void setTtsUtteranceProgressListener() {
18882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mTts == null) {
18982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return;
19082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
19182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
19282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            @Override
19382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            public void onStart(String utteranceId) {}
19482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
19582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            @Override
19682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            public void onDone(String utteranceId) {}
19782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
19882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            @Override
19982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            public void onError(String utteranceId) {
20082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                Log.e(TAG, "Error while trying to synthesize sample text");
20182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
20282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        });
20382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
20482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
20582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
20682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onDestroy() {
20782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        super.onDestroy();
20882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mTts != null) {
20982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mTts.shutdown();
21082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mTts = null;
21182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
21282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
21382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
21482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void initSettings() {
21582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        final ContentResolver resolver = getActivity().getContentResolver();
21682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
21782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Set up the default rate.
21882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        try {
21982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mDefaultRate = android.provider.Settings.Secure.getInt(resolver,
22082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    Settings.Secure.TTS_DEFAULT_RATE);
22182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } catch (Settings.SettingNotFoundException e) {
22282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            // Default rate setting not found, initialize it
22382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
22482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
22582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mDefaultRatePref.setValue(String.valueOf(mDefaultRate));
22682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mDefaultRatePref.setOnPreferenceChangeListener(this);
22782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
22882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mCurrentEngine = mTts.getCurrentEngine();
22982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
23082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEnginePreferenceCategory.removeAll();
23182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
23282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        List<TextToSpeech.EngineInfo> engines = mEnginesHelper.getEngines();
23382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        for (TextToSpeech.EngineInfo engine : engines) {
23482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            TtsEnginePreference enginePref =
23582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    new TtsEnginePreference(getPreferenceManager().getContext(), engine,
23682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    this);
23782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mEnginePreferenceCategory.addPreference(enginePref);
23882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
23982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
24082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        checkVoiceData(mCurrentEngine);
24182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
24282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
24382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
24482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Called when the TTS engine is initialized.
24582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
24682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onInitEngine(int status) {
24782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (status == TextToSpeech.SUCCESS) {
24882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "TTS engine for settings screen initialized.");
24982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            checkDefaultLocale();
25082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else {
25182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "TTS engine for settings screen failed to initialize successfully.");
25282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(false);
25382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
25482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
25582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
25682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void checkDefaultLocale() {
25782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Locale defaultLocale = mTts.getDefaultLanguage();
25882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (defaultLocale == null) {
25982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Failed to get default language from engine " + mCurrentEngine);
26082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(false);
26182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateEngineStatus(R.string.tts_status_not_supported);
26282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return;
26382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
26482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
26582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // ISO-3166 alpha 3 country codes are out of spec. If we won't normalize,
26682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // we may end up with English (USA)and German (DEU).
26782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        final Locale oldDefaultLocale = mCurrentDefaultLocale;
26882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mCurrentDefaultLocale = mEnginesHelper.parseLocaleString(defaultLocale.toString());
26982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (!Objects.equals(oldDefaultLocale, mCurrentDefaultLocale)) {
27082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mSampleText = null;
27182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
27282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
27382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mTts.setLanguage(defaultLocale);
27482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (evaluateDefaultLocale() && mSampleText == null) {
27582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            getSampleText();
27682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
27782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
27882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
27982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private boolean evaluateDefaultLocale() {
28082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Check if we are connected to the engine, and CHECK_VOICE_DATA returned list
28182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // of available languages.
28282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mCurrentDefaultLocale == null || mAvailableStrLocals == null) {
28382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return false;
28482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
28582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
28682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        boolean notInAvailableLangauges = true;
28782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        try {
28882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            // Check if language is listed in CheckVoices Action result as available voice.
28982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            String defaultLocaleStr = mCurrentDefaultLocale.getISO3Language();
29082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (!TextUtils.isEmpty(mCurrentDefaultLocale.getISO3Country())) {
29182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                defaultLocaleStr += "-" + mCurrentDefaultLocale.getISO3Country();
29282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
29382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (!TextUtils.isEmpty(mCurrentDefaultLocale.getVariant())) {
29482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                defaultLocaleStr += "-" + mCurrentDefaultLocale.getVariant();
29582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
29682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
29782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            for (String loc : mAvailableStrLocals) {
29882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                if (loc.equalsIgnoreCase(defaultLocaleStr)) {
29982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    notInAvailableLangauges = false;
30082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    break;
30182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                }
30282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
30382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } catch (MissingResourceException e) {
30482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.wtf(TAG, "MissingResourceException", e);
30582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateEngineStatus(R.string.tts_status_not_supported);
30682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(false);
30782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return false;
30882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
30982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
31082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        int defaultAvailable = mTts.setLanguage(mCurrentDefaultLocale);
31182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (defaultAvailable == TextToSpeech.LANG_NOT_SUPPORTED ||
31282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                defaultAvailable == TextToSpeech.LANG_MISSING_DATA ||
31382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                notInAvailableLangauges) {
31482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "Default locale for this TTS engine is not supported.");
31582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateEngineStatus(R.string.tts_status_not_supported);
31682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(false);
31782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return false;
31882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else {
31982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (isNetworkRequiredForSynthesis()) {
32082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                updateEngineStatus(R.string.tts_status_requires_network);
32182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            } else {
32282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                updateEngineStatus(R.string.tts_status_ok);
32382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
32482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(true);
32582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return true;
32682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
32782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
32882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
32982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
33082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Ask the current default engine to return a string of sample text to be
33182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * spoken to the user.
33282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
33382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void getSampleText() {
33482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        String currentEngine = mTts.getCurrentEngine();
33582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
33682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (TextUtils.isEmpty(currentEngine)) currentEngine = mTts.getDefaultEngine();
33782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
33882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // TODO: This is currently a hidden private API. The intent extras
33982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // and the intent action should be made public if we intend to make this
34082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // a public API. We fall back to using a canned set of strings if this
34182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // doesn't work.
34282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Intent intent = new Intent(TextToSpeech.Engine.ACTION_GET_SAMPLE_TEXT);
34382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
34482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        intent.putExtra("language", mCurrentDefaultLocale.getLanguage());
34582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        intent.putExtra("country", mCurrentDefaultLocale.getCountry());
34682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        intent.putExtra("variant", mCurrentDefaultLocale.getVariant());
34782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        intent.setPackage(currentEngine);
34882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
34982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        try {
35082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "Getting sample text: " + intent.toUri(0));
35182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            startActivityForResult(intent, GET_SAMPLE_TEXT);
35282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } catch (ActivityNotFoundException ex) {
35382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Failed to get sample text, no activity found for " + intent + ")");
35482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
35582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
35682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
35782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
35882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Called when voice data integrity check returns
35982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
36082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
36182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onActivityResult(int requestCode, int resultCode, Intent data) {
36282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (requestCode == GET_SAMPLE_TEXT) {
36382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            onSampleTextReceived(resultCode, data);
36482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else if (requestCode == VOICE_DATA_INTEGRITY_CHECK) {
36582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            onVoiceDataIntegrityCheckDone(data);
36682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
36782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
36882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
36982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private String getDefaultSampleString() {
37082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mTts != null && mTts.getLanguage() != null) {
37182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            try {
37282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                final String currentLang = mTts.getLanguage().getISO3Language();
37382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                String[] strings = getActivity().getResources().getStringArray(
37482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                        R.array.tts_demo_strings);
37582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                String[] langs = getActivity().getResources().getStringArray(
37682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                        R.array.tts_demo_string_langs);
37782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
37882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                for (int i = 0; i < strings.length; ++i) {
37982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    if (langs[i].equals(currentLang)) {
38082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                        return strings[i];
38182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    }
38282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                }
38382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            } catch (MissingResourceException e) {
38482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                if (DBG) Log.wtf(TAG, "MissingResourceException", e);
38582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                // Ignore and fall back to default sample string
38682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
38782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
38882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        return getString(R.string.tts_default_sample_string);
38982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
39082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
39182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private boolean isNetworkRequiredForSynthesis() {
39282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Set<String> features = mTts.getFeatures(mCurrentDefaultLocale);
39382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        return features != null &&
39482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                features.contains(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS) &&
39582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                !features.contains(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS);
39682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
39782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
39882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void onSampleTextReceived(int resultCode, Intent data) {
39982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        String sample = getDefaultSampleString();
40082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
40182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (resultCode == TextToSpeech.LANG_AVAILABLE && data != null) {
40282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (data.getStringExtra("sampleText") != null) {
40382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                sample = data.getStringExtra("sampleText");
40482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
40582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "Got sample text: " + sample);
40682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else {
40782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "Using default sample text :" + sample);
40882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
40982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
41082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mSampleText = sample;
41182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mSampleText != null) {
41282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            updateWidgetState(true);
41382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else {
41482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Did not have a sample string for the requested language. Using default");
41582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
41682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
41782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
41882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void speakSampleText() {
41982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        final boolean networkRequired = isNetworkRequiredForSynthesis();
42082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (!networkRequired ||
42182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                mTts.isLanguageAvailable(mCurrentDefaultLocale) >= TextToSpeech.LANG_AVAILABLE) {
42282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            HashMap<String, String> params = new HashMap<>();
42382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "Sample");
42482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
42582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mTts.speak(mSampleText, TextToSpeech.QUEUE_FLUSH, params);
42682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else {
42782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.w(TAG, "Network required for sample synthesis for requested language");
42882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            displayNetworkAlert();
42982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
43082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
43182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
43282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
43382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public boolean onPreferenceChange(Preference preference, Object objValue) {
43482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (KEY_DEFAULT_RATE.equals(preference.getKey())) {
43582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            // Default rate
43682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mDefaultRate = Integer.parseInt((String) objValue);
43782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            try {
43882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                android.provider.Settings.Secure.putInt(getActivity().getContentResolver(),
43982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                        Settings.Secure.TTS_DEFAULT_RATE, mDefaultRate);
44082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                if (mTts != null) {
44182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    mTts.setSpeechRate(mDefaultRate / 100.0f);
44282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                }
44382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                if (DBG) Log.d(TAG, "TTS default rate changed, now " + mDefaultRate);
44482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            } catch (NumberFormatException e) {
44582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                Log.e(TAG, "could not persist default TTS rate setting", e);
44682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
44782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
44882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
44982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        return true;
45082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
45182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
45282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /**
45382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Called when mPlayExample is clicked
45482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
45582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
45682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public boolean onPreferenceClick(Preference preference) {
45782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (preference == mPlayExample) {
45882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            // Get the sample text from the TTS engine; onActivityResult will do
45982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            // the actual speaking
46082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            speakSampleText();
46182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return true;
46282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
46382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
46482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        return false;
46582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
46682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
46782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void updateWidgetState(boolean enable) {
46882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEngineSettingsPref.setEnabled(enable);
46982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mPlayExample.setEnabled(enable);
47082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mDefaultRatePref.setEnabled(enable);
47182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEngineStatus.setEnabled(enable);
47282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
47382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
47482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void updateEngineStatus(int resourceId) {
47582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Locale locale = mCurrentDefaultLocale;
47682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (locale == null) {
47782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            locale = Locale.getDefault();
47882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
47982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mEngineStatus.setSummary(getString(resourceId, locale.getDisplayName()));
48082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
48182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
48282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void displayNetworkAlert() {
48382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
48482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        builder.setTitle(android.R.string.dialog_alert_title)
48582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                .setMessage(getActivity().getString(R.string.tts_engine_network_required))
48682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                .setCancelable(false)
48782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                .setPositiveButton(android.R.string.ok, null);
48882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
48982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        AlertDialog dialog = builder.create();
49082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        dialog.show();
49182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
49282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
49382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void updateDefaultEngine(String engine) {
49482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (DBG) Log.d(TAG, "Updating default synth to : " + engine);
49582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
49682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Disable the "play sample text" preference and the speech
49782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // rate preference while the engine is being swapped.
49882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        updateWidgetState(false);
49982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        updateEngineStatus(R.string.tts_status_checking);
50082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
50182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Keep track of the previous engine that was being used. So that
50282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // we can reuse the previous engine.
50382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        //
50482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Note that if TextToSpeech#getCurrentEngine is not null, it means at
50582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // the very least that we successfully bound to the engine service.
50682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mPreviousEngine = mTts.getCurrentEngine();
50782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
50882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Step 1: Shut down the existing TTS engine.
50982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        try {
51082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mTts.shutdown();
51182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mTts = null;
51282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } catch (Exception e) {
51382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Error shutting down TTS engine" + e);
51482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
51582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
51682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Step 2: Connect to the new TTS engine.
51782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // Step 3 is continued on #onUpdateEngine (below) which is called when
51882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        // the app binds successfully to the engine.
51982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (DBG) Log.d(TAG, "Updating engine : Attempting to connect to engine: " + engine);
52082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mTts = new TextToSpeech(getActivity().getApplicationContext(), mUpdateListener, engine);
52182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        setTtsUtteranceProgressListener();
52282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
52382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
52482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /*
52582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Step 3: We have now bound to the TTS engine the user requested. We will
52682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * attempt to check voice data for the engine if we successfully bound to it,
52782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * or revert to the previous engine if we didn't.
52882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
52982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void onUpdateEngine(int status) {
53082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (status == TextToSpeech.SUCCESS) {
53182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) {
53282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                Log.d(TAG, "Updating engine: Successfully bound to the engine: " +
53382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                        mTts.getCurrentEngine());
53482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
53582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            checkVoiceData(mTts.getCurrentEngine());
53682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } else {
53782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "Updating engine: Failed to bind to engine, reverting.");
53882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (mPreviousEngine != null) {
53982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                // This is guaranteed to at least bind, since mPreviousEngine would be
54082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                // null if the previous bind to this engine failed.
54182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener,
54282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                        mPreviousEngine);
54382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                setTtsUtteranceProgressListener();
54482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            }
54582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mPreviousEngine = null;
54682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
54782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
54882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
54982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /*
55082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Step 4: Check whether the voice data for the engine is ok.
55182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
55282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void checkVoiceData(String engine) {
55382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        Intent intent = new Intent(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
55482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        intent.setPackage(engine);
55582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        try {
55682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            if (DBG) Log.d(TAG, "Updating engine: Checking voice data: " + intent.toUri(0));
55782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            startActivityForResult(intent, VOICE_DATA_INTEGRITY_CHECK);
55882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        } catch (ActivityNotFoundException ex) {
55982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Failed to check TTS data, no activity found for " + intent + ")");
56082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
56182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
56282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
56382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    /*
56482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     * Step 5: The voice data check is complete.
56582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler     */
56682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    private void onVoiceDataIntegrityCheckDone(Intent data) {
56782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        final String engine = mTts.getCurrentEngine();
56882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
56982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (engine == null) {
57082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Voice data check complete, but no engine bound");
57182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return;
57282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
57382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
57482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (data == null){
57582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Engine failed voice data integrity check (null return)" +
57682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                    mTts.getCurrentEngine());
57782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            return;
57882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
57982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
58082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        android.provider.Settings.Secure.putString(getActivity().getContentResolver(),
58182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                Settings.Secure.TTS_DEFAULT_SYNTH, engine);
58282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
58382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mAvailableStrLocals = data.getStringArrayListExtra(
58482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES);
58582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (mAvailableStrLocals == null) {
58682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            Log.e(TAG, "Voice data check complete, but no available voices found");
58782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            // Set mAvailableStrLocals to empty list
58882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            mAvailableStrLocals = new ArrayList<String>();
58982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
59082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        if (evaluateDefaultLocale()) {
59182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler            getSampleText();
59282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        }
59382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
59482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        final TextToSpeech.EngineInfo engineInfo = mEnginesHelper.getEngineInfo(engine);
59582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        TtsEngineSettingsFragment.prepareArgs(mEngineSettingsPref.getExtras(),
59682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler                engineInfo.name, engineInfo.label, data);
59782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
59882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
59982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
60082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public Checkable getCurrentChecked() {
60182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        return mCurrentChecked;
60282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
60382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
60482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
60582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public String getCurrentKey() {
60682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        return mCurrentEngine;
60782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
60882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
60982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
61082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void setCurrentChecked(Checkable current) {
61182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mCurrentChecked = current;
61282a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
61382a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
61482a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    @Override
61582a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    public void setCurrentKey(String key) {
61682a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        mCurrentEngine = key;
61782a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler        updateDefaultEngine(mCurrentEngine);
61882a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler    }
61982a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
62082a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler
62182a7d036da6c8372a42c1d6bde48ea174d0d3e49Tony Mantler}
622