Pass synthesis request params through to the TTS service.

Change-Id: I1ffd617d8dfa0814382643e3cf6b3ab7417c742a
diff --git a/api/current.txt b/api/current.txt
index 1309575..5482cb8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -17137,7 +17137,7 @@
 package android.speech.tts {
 
   public abstract class SynthesisRequest {
-    ctor public SynthesisRequest(java.lang.String);
+    ctor public SynthesisRequest(java.lang.String, android.os.Bundle);
     method public abstract int audioAvailable(byte[], int, int);
     method public abstract int completeAudioAvailable(int, int, int, byte[], int, int);
     method public abstract int done();
@@ -17145,6 +17145,7 @@
     method public java.lang.String getCountry();
     method public java.lang.String getLanguage();
     method public abstract int getMaxBufferSize();
+    method public android.os.Bundle getParams();
     method public int getPitch();
     method public int getSpeechRate();
     method public java.lang.String getText();
diff --git a/core/java/android/speech/tts/FileSynthesisRequest.java b/core/java/android/speech/tts/FileSynthesisRequest.java
index 7efc264..62be2bf 100644
--- a/core/java/android/speech/tts/FileSynthesisRequest.java
+++ b/core/java/android/speech/tts/FileSynthesisRequest.java
@@ -16,6 +16,7 @@
 package android.speech.tts;
 
 import android.media.AudioFormat;
+import android.os.Bundle;
 import android.util.Log;
 
 import java.io.File;
@@ -47,8 +48,8 @@
     private boolean mStopped = false;
     private boolean mDone = false;
 
-    FileSynthesisRequest(String text, File fileName) {
-        super(text);
+    FileSynthesisRequest(String text, Bundle params, File fileName) {
+        super(text, params);
         mFileName = fileName;
     }
 
diff --git a/core/java/android/speech/tts/PlaybackSynthesisRequest.java b/core/java/android/speech/tts/PlaybackSynthesisRequest.java
index dc5ff70..6f4c15b 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisRequest.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisRequest.java
@@ -17,6 +17,7 @@
 
 import android.media.AudioFormat;
 import android.media.AudioTrack;
+import android.os.Bundle;
 import android.util.Log;
 
 /**
@@ -52,8 +53,9 @@
     private boolean mStopped = false;
     private boolean mDone = false;
 
-    PlaybackSynthesisRequest(String text, int streamType, float volume, float pan) {
-        super(text);
+    PlaybackSynthesisRequest(String text, Bundle params,
+            int streamType, float volume, float pan) {
+        super(text, params);
         mStreamType = streamType;
         mVolume = volume;
         mPan = pan;
diff --git a/core/java/android/speech/tts/SynthesisRequest.java b/core/java/android/speech/tts/SynthesisRequest.java
index 6df9af2..57ae10d 100644
--- a/core/java/android/speech/tts/SynthesisRequest.java
+++ b/core/java/android/speech/tts/SynthesisRequest.java
@@ -15,6 +15,8 @@
  */
 package android.speech.tts;
 
+import android.os.Bundle;
+
 /**
  * A request for speech synthesis given to a TTS engine for processing.
  *
@@ -28,14 +30,16 @@
 public abstract class SynthesisRequest {
 
     private final String mText;
+    private final Bundle mParams;
     private String mLanguage;
     private String mCountry;
     private String mVariant;
     private int mSpeechRate;
     private int mPitch;
 
-    public SynthesisRequest(String text) {
+    public SynthesisRequest(String text, Bundle params) {
         mText = text;
+        mParams = new Bundle(params);
     }
 
     /**
@@ -104,6 +108,13 @@
     }
 
     /**
+     * Gets the additional params, if any.
+     */
+    public Bundle getParams() {
+        return mParams;
+    }
+
+    /**
      * Gets the maximum number of bytes that the TTS engine can pass in a single call of
      * {@link #audioAvailable}. This does not apply to {@link #completeAudioAvailable}.
      */
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 1d26c22..4b19469 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -80,13 +80,13 @@
     public static final int LANG_COUNTRY_VAR_AVAILABLE = 2;
 
     /**
-     * Denotes the language is available for the language and country specified 
+     * Denotes the language is available for the language and country specified
      * by the locale, but not the variant.
      */
     public static final int LANG_COUNTRY_AVAILABLE = 1;
 
     /**
-     * Denotes the language is available for the language by the locale, 
+     * Denotes the language is available for the language by the locale,
      * but not the country and variant.
      */
     public static final int LANG_AVAILABLE = 0;
@@ -424,6 +424,7 @@
     private final Map<String, Uri> mEarcons;
     private final Map<String, Uri> mUtterances;
     private final Bundle mParams = new Bundle();
+    private String mCurrentEngine = null;
 
     /**
      * The constructor for the TextToSpeech class, using the default TTS engine.
@@ -524,6 +525,7 @@
             dispatchOnInit(ERROR);
             return false;
         } else {
+            mCurrentEngine = engine;
             return true;
         }
     }
@@ -685,6 +687,10 @@
      *            {@link Engine#KEY_PARAM_UTTERANCE_ID},
      *            {@link Engine#KEY_PARAM_VOLUME},
      *            {@link Engine#KEY_PARAM_PAN}.
+     *            Engine specific parameters may be passed in but the parameter keys
+     *            must be prefixed by the name of the engine they are intended for. For example
+     *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
+     *            engine named "com.svox.pico" if it is being used.
      *
      * @return {@link #ERROR} or {@link #SUCCESS}.
      */
@@ -714,6 +720,10 @@
      *            Supported parameter names:
      *            {@link Engine#KEY_PARAM_STREAM},
      *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
+     *            Engine specific parameters may be passed in but the parameter keys
+     *            must be prefixed by the name of the engine they are intended for. For example
+     *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
+     *            engine named "com.svox.pico" if it is being used.
      *
      * @return {@link #ERROR} or {@link #SUCCESS}.
      */
@@ -741,6 +751,10 @@
      * @param params Parameters for the request. Can be null.
      *            Supported parameter names:
      *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
+     *            Engine specific parameters may be passed in but the parameter keys
+     *            must be prefixed by the name of the engine they are intended for. For example
+     *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
+     *            engine named "com.svox.pico" if it is being used.
      *
      * @return {@link #ERROR} or {@link #SUCCESS}.
      */
@@ -922,6 +936,10 @@
      * @param params Parameters for the request. Can be null.
      *            Supported parameter names:
      *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
+     *            Engine specific parameters may be passed in but the parameter keys
+     *            must be prefixed by the name of the engine they are intended for. For example
+     *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
+     *            engine named "com.svox.pico" if it is being used.
      * @param filename Absolute file filename to write the generated audio data to.It should be
      *            something like "/sdcard/myappsounds/mysound.wav".
      *
@@ -945,6 +963,19 @@
             copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID);
             copyFloatParam(bundle, params, Engine.KEY_PARAM_VOLUME);
             copyFloatParam(bundle, params, Engine.KEY_PARAM_PAN);
+
+            // Copy over all parameters that start with the name of the
+            // engine that we are currently connected to. The engine is
+            // free to interpret them as it chooses.
+            if (!TextUtils.isEmpty(mCurrentEngine)) {
+                for (Map.Entry<String, String> entry : params.entrySet()) {
+                    final String key = entry.getKey();
+                    if (key != null && key.startsWith(mCurrentEngine)) {
+                        bundle.putString(key, entry.getValue());
+                    }
+                }
+            }
+
             return bundle;
         } else {
             return mParams;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 590e2ef..f32474f 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -318,7 +318,7 @@
      */
     private static abstract class SpeechItem {
         private final String mCallingApp;
-        private final Bundle mParams;
+        protected final Bundle mParams;
         private boolean mStarted = false;
         private boolean mStopped = false;
 
@@ -443,7 +443,8 @@
         }
 
         protected SynthesisRequest createSynthesisRequest() {
-            return new PlaybackSynthesisRequest(mText, getStreamType(), getVolume(), getPan());
+            return new PlaybackSynthesisRequest(mText, mParams,
+                    getStreamType(), getVolume(), getPan());
         }
 
         private void setRequestParams(SynthesisRequest request) {
@@ -513,7 +514,7 @@
 
         @Override
         protected SynthesisRequest createSynthesisRequest() {
-            return new FileSynthesisRequest(getText(), mFile);
+            return new FileSynthesisRequest(getText(), mParams, mFile);
         }
 
         /**