Add a synchronous stop method to TTS synth engine so that upon its destruction,
if it was synthesing to a file, the latter can be deleted without
still being written to.
Clear the hashmap of SpeechItem to be stopped (mKillList) when the speech
queue is empty.
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 1793587..071a90d 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -721,6 +721,27 @@
 }
 
 
+static int
+android_tts_SynthProxy_stopSync(JNIEnv *env, jobject thiz, jint jniData)
+{
+    int result = TTS_FAILURE;
+
+    if (jniData == 0) {
+        LOGE("android_tts_SynthProxy_stop(): invalid JNI data");
+        return result;
+    }
+
+    // perform a regular stop
+    result = android_tts_SynthProxy_stop(env, thiz, jniData);
+    // but wait on the engine having released the engine mutex which protects
+    // the synthesizer resources.
+    engineMutex.lock();
+    engineMutex.unlock();
+
+    return result;
+}
+
+
 static jobjectArray
 android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
 {
@@ -778,6 +799,10 @@
         "(I)I",
         (void*)android_tts_SynthProxy_stop
     },
+    {   "native_stopSync",
+        "(I)I",
+        (void*)android_tts_SynthProxy_stopSync
+    },
     {   "native_speak",
         "(ILjava/lang/String;I)I",
         (void*)android_tts_SynthProxy_speak
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index a0814aa..b59a626 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -52,6 +52,18 @@
     }
 
     /**
+     * Synchronous stop of the synthesizer. This method returns when the synth
+     * has completed the stop procedure and doesn't use any of the resources it
+     * was using while synthesizing.
+     *
+     * @return {@link android.speech.tts.TextToSpeech.SUCCESS} or
+     *         {@link android.speech.tts.TextToSpeech.ERROR}
+     */
+    public int stopSync() {
+        return native_stopSync(mJniData);
+    }
+
+    /**
      * Synthesize speech and speak it directly using AudioTrack.
      */
     public int speak(String text, int streamType) {
@@ -156,6 +168,8 @@
 
     private native final int native_stop(int jniData);
 
+    private native final int native_stopSync(int jniData);
+
     private native final int native_speak(int jniData, String text, int streamType);
 
     private native final int native_synthesizeToFile(int jniData, String text, String filename);
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 2e11698..6094494 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -188,6 +188,8 @@
 
         // Unregister all callbacks.
         mCallbacks.kill();
+
+        Log.v("TtsService", "onDestroy() completed");
     }
 
 
@@ -497,14 +499,13 @@
 
                 // clear the current speech item
                 if (mCurrentSpeechItem != null) {
-                    result = sNativeSynth.stop();
+                    result = sNativeSynth.stopSync();
                     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);
@@ -884,6 +885,7 @@
             }
             if (mSpeechQueue.size() < 1) {
                 mIsSpeaking = false;
+                mKillList.clear();
                 broadcastTtsQueueProcessingCompleted();
                 return;
             }