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

Commit 4813b51e authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 22838 into eclair

* changes:
  Implement clean killing of the TTS service. If files were being synthesized to while the service was being killed, it would have left partially written files (with no header). This CL checks if the service is rendering to a file at the time the service is destroyed: if it is, it will stop the rendering and deletes the file.
parents 1339614e a3046b6f
Loading
Loading
Loading
Loading
+62 −4
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import android.speech.tts.ITts.Stub;
import android.speech.tts.ITtsCallback;
import android.speech.tts.TextToSpeech;
import android.util.Log;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -138,6 +140,7 @@ public class TtsService extends Service implements OnCompletionListener {

    private ContentResolver mResolver;

    // lock for the speech queue (mSpeechQueue) and the current speech item (mCurrentSpeechItem)
    private final ReentrantLock speechQueueLock = new ReentrantLock();
    private final ReentrantLock synthesizerLock = new ReentrantLock();

@@ -173,10 +176,7 @@ public class TtsService extends Service implements OnCompletionListener {
    public void onDestroy() {
        super.onDestroy();

        // TODO replace the call to stopAll() with a method to clear absolutely all upcoming
        // uses of the native synth, including synthesis to a file, and delete files for which
        // synthesis was not complete.
        stopAll("");
        killAllUtterances();

        // Don't hog the media player
        cleanUpPlayer();
@@ -477,6 +477,64 @@ public class TtsService extends Service implements OnCompletionListener {
    }


    /**
     * Stops all speech output, both rendered to a file and directly spoken, and removes any
     * utterances still in the queue globally. Files that were being written are deleted.
     */
    @SuppressWarnings("finally")
    private int killAllUtterances() {
        int result = TextToSpeech.ERROR;
        boolean speechQueueAvailable = false;

        try {
            speechQueueAvailable = speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT,
                    TimeUnit.MILLISECONDS);
            if (speechQueueAvailable) {
                // remove every single entry in the speech queue
                mSpeechQueue.clear();

                // clear the current speech item
                if (mCurrentSpeechItem != null) {
                    result = sNativeSynth.stop();
                    mKillList.put(mCurrentSpeechItem, true);
                    mIsSpeaking = false;

                    // was the engine writing to a file?
                    if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) {
                        // delete the file that was being written
                        // TODO make sure the synth is not writing to the file anymore
                        if (mCurrentSpeechItem.mFilename != null) {
                            File tempFile = new File(mCurrentSpeechItem.mFilename);
                            Log.v("TtsService", "Leaving behind " + mCurrentSpeechItem.mFilename);
                            if (tempFile.exists()) {
                                Log.v("TtsService", "About to delete "
                                        + mCurrentSpeechItem.mFilename);
                                if (tempFile.delete()) {
                                    Log.v("TtsService", "file successfully deleted");
                                }
                            }
                        }
                    }

                    mCurrentSpeechItem = null;
                }
            } else {
                Log.e("TtsService", "TTS killAllUtterances(): queue locked longer than expected");
                result = TextToSpeech.ERROR;
            }
        } catch (InterruptedException e) {
            Log.e("TtsService", "TTS killAllUtterances(): tryLock interrupted");
            result = TextToSpeech.ERROR;
        } finally {
            // This check is needed because finally will always run, even if the
            // method returns somewhere in the try block.
            if (speechQueueAvailable) {
                speechQueueLock.unlock();
            }
            return result;
        }
    }


    /**
     * Stops all speech output and removes any utterances still in the queue globally, except