Add TtsSpan class.

The TtsSpan can be used to provide addtional data for  TTS engines.

For now it only includes the types text and cardinals, but more will follow.

Change-Id: I31392dd413c0902ba4ce702fa3307253c90c618f
diff --git a/api/current.txt b/api/current.txt
index 88c66b6..2915e36 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16287,20 +16287,20 @@
     method public void unregisterDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public void unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
     field public static final deprecated java.lang.String ACTION_BACKGROUND_DATA_SETTING_CHANGED = "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
+    field public static final java.lang.String ACTION_CAPTIVE_PORTAL_DETECTED = "android.net.conn.CAPTIVE_PORTAL_DETECTED";
+    field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL_SIGN_IN";
+    field public static final int CAPTIVE_PORTAL_DISCONNECT = 2; // 0x2
+    field public static final int CAPTIVE_PORTAL_SIGNED_IN = 1; // 0x1
     field public static final java.lang.String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
     field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
     field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
     field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
+    field public static final java.lang.String EXTRA_NETWORK = "network";
     field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
     field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
     field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
     field public static final java.lang.String EXTRA_REASON = "reason";
-    field public static final java.lang.String ACTION_CAPTIVE_PORTAL_DETECTED = "android.net.conn.CAPTIVE_PORTAL_DETECTED";
-    field public static final java.lang.String ACTION_CAPTIVE_PORTAL_SIGN_IN = "android.net.conn.CAPTIVE_PORTAL_SIGN_IN";
-    field public static final java.lang.String EXTRA_NETWORK = "network";
-    field public static final int CAPTIVE_PORTAL_SIGNED_IN = 1;
-    field public static final int CAPTIVE_PORTAL_DISCONNECT = 2;
     field public static final int TYPE_BLUETOOTH = 7; // 0x7
     field public static final int TYPE_DUMMY = 8; // 0x8
     field public static final int TYPE_ETHERNET = 9; // 0x9
@@ -30386,6 +30386,40 @@
     method public void writeToParcel(android.os.Parcel, int);
   }
 
+  public class TtsSpan implements android.text.ParcelableSpan {
+    ctor public TtsSpan(java.lang.String, android.os.PersistableBundle);
+    ctor public TtsSpan(android.os.Parcel);
+    method public int describeContents();
+    method public android.os.PersistableBundle getArgs();
+    method public int getSpanTypeId();
+    method public java.lang.String getType();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final java.lang.String ANIMACY_ANIMATE = "android.animate";
+    field public static final java.lang.String ANIMACY_INANIMATE = "android.inanimate";
+    field public static final java.lang.String ARG_ANIMACY = "android.arg.animacy";
+    field public static final java.lang.String ARG_CASE = "android.arg.case";
+    field public static final java.lang.String ARG_GENDER = "android.arg.gender";
+    field public static final java.lang.String ARG_MULTIPLICITY = "android.arg.multiplicity";
+    field public static final java.lang.String ARG_NUMBER = "android.arg.number";
+    field public static final java.lang.String ARG_TEXT = "android.arg.text";
+    field public static final java.lang.String CASE_ABLATIVE = "android.ablative";
+    field public static final java.lang.String CASE_ACCUSATIVE = "android.accusative";
+    field public static final java.lang.String CASE_DATIVE = "android.dative";
+    field public static final java.lang.String CASE_GENITIVE = "android.genitive";
+    field public static final java.lang.String CASE_INSTRUMENTAL = "android.instrumental";
+    field public static final java.lang.String CASE_LOCATIVE = "android.locative";
+    field public static final java.lang.String CASE_NOMINATIVE = "android.nomative";
+    field public static final java.lang.String CASE_VOCATIVE = "android.vocative";
+    field public static final java.lang.String GENDER_FEMALE = "android.female";
+    field public static final java.lang.String GENDER_MALE = "android.male";
+    field public static final java.lang.String GENDER_NEUTRAL = "android.neutral";
+    field public static final java.lang.String MULTIPLICITY_DUAL = "android.dual";
+    field public static final java.lang.String MULTIPLICITY_PLURAL = "android.plural";
+    field public static final java.lang.String MULTIPLICITY_SINGLE = "android.single";
+    field public static final java.lang.String TYPE_CARDINAL = "android.type.cardinal";
+    field public static final java.lang.String TYPE_TEXT = "android.type.text";
+  }
+
   public class TypefaceSpan extends android.text.style.MetricAffectingSpan implements android.text.ParcelableSpan {
     ctor public TypefaceSpan(java.lang.String);
     ctor public TypefaceSpan(android.os.Parcel);
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 48122d6..1d1aafb 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -43,6 +43,7 @@
 import android.text.style.SuggestionSpan;
 import android.text.style.SuperscriptSpan;
 import android.text.style.TextAppearanceSpan;
+import android.text.style.TtsSpan;
 import android.text.style.TypefaceSpan;
 import android.text.style.URLSpan;
 import android.text.style.UnderlineSpan;
@@ -607,7 +608,9 @@
     /** @hide */
     public static final int LOCALE_SPAN = 23;
     /** @hide */
-    public static final int LAST_SPAN = LOCALE_SPAN;
+    public static final int TTS_SPAN = 24;
+    /** @hide */
+    public static final int LAST_SPAN = TTS_SPAN;
 
     /**
      * Flatten a CharSequence and whatever styles can be copied across processes
@@ -786,6 +789,10 @@
                     readSpan(p, sp, new LocaleSpan(p));
                     break;
 
+                case TTS_SPAN:
+                    readSpan(p, sp, new TtsSpan(p));
+                    break;
+
                 default:
                     throw new RuntimeException("bogus span encoding " + kind);
                 }
diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java
new file mode 100644
index 0000000..ab736c5
--- /dev/null
+++ b/core/java/android/text/style/TtsSpan.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2014 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 android.text.style;
+
+import android.os.Parcel;
+import android.os.PersistableBundle;
+import android.text.ParcelableSpan;
+import android.text.TextUtils;
+
+/**
+ * A span that supplies addition meta-data intended for text-to-speech rendering
+ * of the associated text.  If the text is being processed by a text-to-speech
+ * engine, the engine may use the data in this span in addition to or instead of
+ * its associated text.
+ */
+public class TtsSpan implements ParcelableSpan {
+    private final String mType;
+    private final PersistableBundle mArgs;
+
+    /**
+     * This span type can be used to add morphosyntactic features to the text it
+     * spans over, or synthesize a something else than the spanned text.  Use
+     * the argument {@link #ARG_TEXT} to set a different text.
+     * Accepts the arguments {@link TtsSpan#ARG_GENDER},
+     * {@link TtsSpan#ARG_ANIMACY}, {@link TtsSpan#ARG_MULTIPLICITY} and
+     * {@link TtsSpan#ARG_CASE}.
+     */
+    public static final String TYPE_TEXT = "android.type.text";
+
+    /**
+     * The text associated with this span is a cardinal.  Must include the
+     * number to be synthesized with {@link #ARG_NUMBER}.
+     * Also accepts the arguments {@link TtsSpan#ARG_GENDER},
+     * {@link TtsSpan#ARG_ANIMACY}, {@link TtsSpan#ARG_MULTIPLICITY} and
+     * {@link TtsSpan#ARG_CASE}.
+     */
+    public static final String TYPE_CARDINAL = "android.type.cardinal";
+
+    /**
+     * String supplying the text to be synthesized.  The synthesizer is free
+     * to decide how to interpret the text.
+     */
+    public static final String ARG_TEXT = "android.arg.text";
+
+    /**
+     * Argument used to specify a whole number.  The value can be a string of
+     * digits of any size optionally prefixed with a - or +.
+     */
+    public static final String ARG_NUMBER = "android.arg.number";
+
+    /**
+     * String argument supplying gender information.  Can be any of
+     * {@link TtsSpan#GENDER_NEUTRAL}, {@link TtsSpan#GENDER_MALE} and
+     * {@link TtsSpan#GENDER_FEMALE}.
+     */
+    public static final String ARG_GENDER = "android.arg.gender";
+
+    public static final String GENDER_NEUTRAL = "android.neutral";
+    public static final String GENDER_MALE = "android.male";
+    public static final String GENDER_FEMALE = "android.female";
+
+    /**
+     * String argument supplying animacy information.  Can be
+     * {@link TtsSpan#ANIMACY_ANIMATE} or
+     * {@link TtsSpan#ANIMACY_INANIMATE}
+     */
+    public static final String ARG_ANIMACY = "android.arg.animacy";
+
+    public static final String ANIMACY_ANIMATE = "android.animate";
+    public static final String ANIMACY_INANIMATE = "android.inanimate";
+
+    /**
+     * String argument supplying multiplicity information.  Can be any of
+     * {@link TtsSpan#MULTIPLICITY_SINGLE},
+     * {@link TtsSpan#MULTIPLICITY_DUAL} and
+     * {@link TtsSpan#MULTIPLICITY_PLURAL}
+     */
+    public static final String ARG_MULTIPLICITY = "android.arg.multiplicity";
+
+    public static final String MULTIPLICITY_SINGLE = "android.single";
+    public static final String MULTIPLICITY_DUAL = "android.dual";
+    public static final String MULTIPLICITY_PLURAL = "android.plural";
+
+    /**
+     * String argument supplying case information.  Can be any of
+     * {@link TtsSpan#CASE_NOMINATIVE}, {@link TtsSpan#CASE_ACCUSATIVE},
+     * {@link TtsSpan#CASE_DATIVE}, {@link TtsSpan#CASE_ABLATIVE},
+     * {@link TtsSpan#CASE_GENITIVE}, {@link TtsSpan#CASE_VOCATIVE},
+     * {@link TtsSpan#CASE_LOCATIVE} and
+     * {@link TtsSpan#CASE_INSTRUMENTAL}
+     */
+    public static final String ARG_CASE = "android.arg.case";
+
+    public static final String CASE_NOMINATIVE = "android.nomative";
+    public static final String CASE_ACCUSATIVE = "android.accusative";
+    public static final String CASE_DATIVE = "android.dative";
+    public static final String CASE_ABLATIVE = "android.ablative";
+    public static final String CASE_GENITIVE = "android.genitive";
+    public static final String CASE_VOCATIVE = "android.vocative";
+    public static final String CASE_LOCATIVE = "android.locative";
+    public static final String CASE_INSTRUMENTAL = "android.instrumental";
+
+    public TtsSpan(String type, PersistableBundle args) {
+        mType = type;
+        mArgs = args;
+    }
+
+    public TtsSpan(Parcel src) {
+        mType = src.readString();
+        mArgs = src.readPersistableBundle();
+    }
+
+    public String getType() {
+        return mType;
+    }
+
+    public PersistableBundle getArgs() {
+        return mArgs;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mType);
+        dest.writePersistableBundle(mArgs);
+    }
+
+    @Override
+    public int getSpanTypeId() {
+        return TextUtils.TTS_SPAN;
+    }
+}