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

Commit e77e22e2 authored by Josh Imbriani's avatar Josh Imbriani
Browse files

Fixing TTS Settings crash on rotation caused by using deprecated API.

Test: manual - rotated phone while playing TTS
Fix: 145579714

Change-Id: I7232704c92ba8ec34769cf68afe2278e22532d86
parent 8b15d86c
Loading
Loading
Loading
Loading
+28 −18
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.util.Log;
import android.util.Pair;

import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProviders;
import androidx.preference.ListPreference;
import androidx.preference.Preference;

@@ -205,13 +206,18 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
            mLocalePreference.setEnabled(entries.length > 0);
        }

        mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener);
        final TextToSpeechViewModel ttsViewModel =
                ViewModelProviders.of(this).get(TextToSpeechViewModel.class);
        Pair<TextToSpeech, Boolean> ttsAndNew = ttsViewModel.getTtsAndWhetherNew(mInitListener);
        mTts = ttsAndNew.first;
        // If the TTS object is not newly created, we need to run the setup on the settings side to
        // ensure that we can use the TTS object.
        if (!ttsAndNew.second) {
            successSetup();
        }

        setTtsUtteranceProgressListener();
        initSettings();

        // Prevent restarting the TTS connection on rotation
        setRetainInstance(true);
    }

    @Override
@@ -227,13 +233,21 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
            return;
        }
        if (!mTts.getDefaultEngine().equals(mTts.getCurrentEngine())) {
            final TextToSpeechViewModel ttsViewModel =
                    ViewModelProviders.of(this).get(TextToSpeechViewModel.class);
            try {
                mTts.shutdown();
                mTts = null;
                // If the current engine isn't the default engine shut down the current engine in
                // preparation for creating the new engine.
                ttsViewModel.shutdownTts();
            } catch (Exception e) {
                Log.e(TAG, "Error shutting down TTS engine" + e);
            }
            mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener);
            final Pair<TextToSpeech, Boolean> ttsAndNew =
                    ttsViewModel.getTtsAndWhetherNew(mInitListener);
            mTts = ttsAndNew.first;
            if (!ttsAndNew.second) {
                successSetup();
            }
            setTtsUtteranceProgressListener();
            initSettings();
        } else {
@@ -276,15 +290,6 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mTts != null) {
            mTts.shutdown();
            mTts = null;
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
@@ -375,8 +380,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
    public void onInitEngine(int status) {
        if (status == TextToSpeech.SUCCESS) {
            if (DBG) Log.d(TAG, "TTS engine for settings screen initialized.");
            checkDefaultLocale();
            getActivity().runOnUiThread(() -> mLocalePreference.setEnabled(true));
            successSetup();
        } else {
            if (DBG) {
                Log.d(TAG,
@@ -386,6 +390,12 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment
        }
    }

    /** Initialize TTS Settings on successful engine init. */
    private void successSetup() {
        checkDefaultLocale();
        getActivity().runOnUiThread(() -> mLocalePreference.setEnabled(true));
    }

    private void checkDefaultLocale() {
        Locale defaultLocale = mTts.getDefaultLanguage();
        if (defaultLocale == null) {
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settings.tts;

import android.app.Application;
import android.speech.tts.TextToSpeech;
import android.util.Pair;

import androidx.lifecycle.AndroidViewModel;

/**
 * A helper view model to protect the TTS object from being destroyed and
 * recreated on orientation change.
*/
public class TextToSpeechViewModel extends AndroidViewModel {
    private TextToSpeech mTts;

    // Save the application so we can use it as the TTS context
    private final Application mApplication;

    public TextToSpeechViewModel(Application application) {
        super(application);

        mApplication = application;
    }

    /*
     * Since the view model now controls the TTS object, we need to handle shutting it down
     * ourselves.
     */
    @Override
    protected void onCleared() {
        shutdownTts();
    }

    protected void shutdownTts() {
        mTts.shutdown();
        mTts = null;
    }

    /*
     * An accessor method to get the TTS object. Returns a pair of the TTS object and a boolean
     * indicating whether the TTS object was newly created or not.
     */
    protected Pair<TextToSpeech, Boolean> getTtsAndWhetherNew(
            TextToSpeech.OnInitListener listener) {
        boolean ttsCreated = false;
        if (mTts == null) {
            mTts = new TextToSpeech(this.mApplication, listener);
            ttsCreated = true;
        }

        return Pair.create(mTts, ttsCreated);
    }

}