Merge change 5434 into donut

* changes:
  Adding splitting to the TTS to guard against extremely long strings.
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index bc016a7..1502d98 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -88,8 +88,6 @@
     public static final int TTS_LANG_NOT_SUPPORTED = -2;
 
 
-
-
     /**
      * Called when the TTS has initialized.
      *
@@ -101,15 +99,6 @@
     }
 
     /**
-     * Called when the TTS has finished speaking by itself (speaking
-     * finished without being canceled).
-     *
-     */
-    public interface OnSpeechCompletedListener {
-        public void onSpeechCompleted();
-    }
-
-    /**
      * Internal constants for the TTS functionality
      *
      * {@hide}
@@ -129,6 +118,16 @@
         public static final int CHECK_VOICE_DATA_BAD_DATA = -1;
         public static final int CHECK_VOICE_DATA_MISSING_DATA = -2;
         public static final int CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD = -3;
+        
+        // keys for the parameters passed with speak commands
+        public static final String TTS_KEY_PARAM_RATE = "rate";
+        public static final String TTS_KEY_PARAM_LANGUAGE = "language";
+        public static final String TTS_KEY_PARAM_COUNTRY = "country";
+        public static final String TTS_KEY_PARAM_VARIANT = "variant";
+        public static final int TTS_PARAM_POSITION_RATE = 0;
+        public static final int TTS_PARAM_POSITION_LANGUAGE = 2;
+        public static final int TTS_PARAM_POSITION_COUNTRY = 4;
+        public static final int TTS_PARAM_POSITION_VARIANT = 6;
     }
 
     /**
@@ -141,11 +140,11 @@
     private OnInitListener mInitListener = null;
     private boolean mStarted = false;
     private final Object mStartLock = new Object();
-    private ITtsCallback mITtsCallback;
-    private OnSpeechCompletedListener mSpeechCompListener = null;
-    private final Object mSpeechCompListenerLock = new Object();
-
-
+    private int mCachedRate = Engine.FALLBACK_TTS_DEFAULT_RATE;
+    private String mCachedLang = Engine.FALLBACK_TTS_DEFAULT_LANG;
+    private String mCachedCountry = Engine.FALLBACK_TTS_DEFAULT_COUNTRY;
+    private String mCachedVariant = Engine.FALLBACK_TTS_DEFAULT_VARIANT;
+    private String[] mCachedParams;
 
     /**
      * The constructor for the TTS.
@@ -159,14 +158,23 @@
     public TextToSpeech(Context context, OnInitListener listener) {
         mContext = context;
         mInitListener = listener;
+
+        mCachedParams = new String[2*4]; //4 parameters, store key and value
+        mCachedParams[Engine.TTS_PARAM_POSITION_RATE] = Engine.TTS_KEY_PARAM_RATE;
+        mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE] = Engine.TTS_KEY_PARAM_LANGUAGE;
+        mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY;
+        mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT;
+        updateCachedParamArray();
+
         initTts();
     }
 
 
-    public void setOnSpeechCompletedListener(final OnSpeechCompletedListener listener) {
-        synchronized(mSpeechCompListenerLock) {
-            mSpeechCompListener = listener;
-        }
+    private void updateCachedParamArray() {
+        mCachedParams[Engine.TTS_PARAM_POSITION_RATE+1] = String.valueOf(mCachedRate);
+        mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE+1] = mCachedLang;
+        mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY+1] = mCachedCountry;
+        mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT+1] = mCachedVariant;
     }
 
 
@@ -178,34 +186,7 @@
             public void onServiceConnected(ComponentName name, IBinder service) {
                 synchronized(mStartLock) {
                     mITts = ITts.Stub.asInterface(service);
-                    try {
-                        mITtsCallback = new ITtsCallback.Stub() {
-                            public void markReached(String mark)
-                            throws RemoteException {
-                                // call the listener of that event, but not
-                                // while locked.
-                                OnSpeechCompletedListener listener = null;
-                                synchronized(mSpeechCompListenerLock) {
-                                    listener = mSpeechCompListener;
-                                }
-                                if (listener != null) {
-                                    listener.onSpeechCompleted();
-                                }
-                            }
-                        };
-                        mITts.registerCallback(mITtsCallback);
-
-                    } catch (RemoteException e) {
-                        initTts();
-                        return;
-                    }
-
                     mStarted = true;
-                    // The callback can become null if the Android OS decides to
-                    // restart the TTS process as well as whatever is using it.
-                    // In such cases, do nothing - the error handling from the
-                    // speaking calls will kick in and force a proper restart of
-                    // the TTS.
                     if (mInitListener != null) {
                         // TODO manage failures and missing resources
                         mInitListener.onInit(TTS_SUCCESS);
@@ -352,8 +333,8 @@
                 return;
             }
             try {
-                // TODO support extra parameters, passing null for the moment
-                mITts.speak(text, queueMode, null);
+                // TODO support extra parameters, passing cache of current parameters for the moment
+                mITts.speak(text, queueMode, mCachedParams);
             } catch (RemoteException e) {
                 // TTS died; restart it.
                 mStarted = false;
@@ -510,7 +491,9 @@
             }
             try {
                 if (speechRate > 0) {
-                    mITts.setSpeechRate((int)(speechRate*100));
+                    mCachedRate = (int)(speechRate*100);
+                    updateCachedParamArray();
+                    mITts.setSpeechRate(mCachedRate);
                 }
             } catch (RemoteException e) {
                 // TTS died; restart it.
@@ -568,7 +551,11 @@
                 return;
             }
             try {
-                mITts.setLanguage(loc.getISO3Language(), loc.getISO3Country(), loc.getVariant());
+                mCachedLang = loc.getISO3Language();
+                mCachedCountry = loc.getISO3Country();
+                mCachedVariant = loc.getVariant();
+                updateCachedParamArray();
+                mITts.setLanguage(mCachedLang, mCachedCountry, mCachedVariant);
             } catch (RemoteException e) {
                 // TTS died; restart it.
                 mStarted = false;
@@ -582,10 +569,12 @@
      *
      * @param loc
      *            The locale describing the language to be used.
+     * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE,
+               TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE.
      */
     public int isLanguageAvailable(Locale loc) {
         //TODO: Implement isLanguageAvailable
-        return 0;
+        return TTS_LANG_NOT_SUPPORTED;
     }
 
 
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index e9b2fc0..a5fa41e 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1562,7 +1562,7 @@
 
         // adjust the default scale to match the density
         if (WebView.DEFAULT_SCALE_PERCENT != 100) {
-            float adjust = WebView.DEFAULT_SCALE_PERCENT / 100;
+            float adjust = (float) WebView.DEFAULT_SCALE_PERCENT / 100.0f;
             if (mViewportInitialScale > 0) {
                 mViewportInitialScale *= adjust;
             }
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 00bc21e..12bb01c 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -41,6 +41,7 @@
 import java.util.TreeSet;
 import java.util.LinkedList;
 import java.util.HashSet;
+import java.util.ArrayList;
 
 /**
  * A Layout where the positions of the children can be described in relation to each other or to the
@@ -339,10 +340,16 @@
         int right = Integer.MIN_VALUE;
         int bottom = Integer.MIN_VALUE;
 
+        boolean offsetHorizontalAxis = false;
+        boolean offsetVerticalAxis = false;
+
         if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) {
             ignore = findViewById(mIgnoreGravity);
         }
 
+        final boolean isWrapContentWidth = widthMode != MeasureSpec.EXACTLY;
+        final boolean isWrapContentHeight = heightMode != MeasureSpec.EXACTLY;
+
         View[] views = mSortedHorizontalChildren;
         int count = views.length;
         for (int i = 0; i < count; i++) {
@@ -351,13 +358,16 @@
                 LayoutParams params = (LayoutParams) child.getLayoutParams();
 
                 applyHorizontalSizeRules(params, myWidth);
-                measureChildHorizontal(child, params, myWidth);
-                positionChildHorizontal(child, params, myWidth);
+                measureChildHorizontal(child, params, myWidth, myHeight);
+                if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {
+                    offsetHorizontalAxis = true;
+                }
             }
         }
 
         views = mSortedVerticalChildren;
         count = views.length;
+
         for (int i = 0; i < count; i++) {
             View child = views[i];
             if (child.getVisibility() != GONE) {
@@ -365,12 +375,15 @@
                 
                 applyVerticalSizeRules(params, myHeight);
                 measureChild(child, params, myWidth, myHeight);
-                positionChildVertical(child, params, myHeight);
+                if (positionChildVertical(child, params, myHeight, isWrapContentHeight)) {
+                    offsetVerticalAxis = true;
+                }
 
-                if (widthMode != MeasureSpec.EXACTLY) {
+                if (isWrapContentWidth) {
                     width = Math.max(width, params.mRight);
                 }
-                if (heightMode != MeasureSpec.EXACTLY) {
+
+                if (isWrapContentHeight) {
                     height = Math.max(height, params.mBottom);
                 }
 
@@ -406,7 +419,7 @@
             }
         }
 
-        if (widthMode != MeasureSpec.EXACTLY) {
+        if (isWrapContentWidth) {
             // Width already has left padding in it since it was calculated by looking at
             // the right of each child view
             width += mPaddingRight;
@@ -417,8 +430,22 @@
 
             width = Math.max(width, getSuggestedMinimumWidth());
             width = resolveSize(width, widthMeasureSpec);
+
+            if (offsetHorizontalAxis) {
+                    for (int i = 0; i < count; i++) {
+                    View child = getChildAt(i);
+                    if (child.getVisibility() != GONE) {
+                        LayoutParams params = (LayoutParams) child.getLayoutParams();
+                        final int[] rules = params.getRules();
+                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
+                            centerHorizontal(child, params, width);
+                        }
+                    }
+                }
+            }
         }
-        if (heightMode != MeasureSpec.EXACTLY) {
+
+        if (isWrapContentHeight) {
             // Height already has top padding in it since it was calculated by looking at
             // the bottom of each child view
             height += mPaddingBottom;
@@ -429,6 +456,19 @@
 
             height = Math.max(height, getSuggestedMinimumHeight());
             height = resolveSize(height, heightMeasureSpec);
+
+            if (offsetVerticalAxis) {
+                for (int i = 0; i < count; i++) {
+                    View child = getChildAt(i);
+                    if (child.getVisibility() != GONE) {
+                        LayoutParams params = (LayoutParams) child.getLayoutParams();
+                        final int[] rules = params.getRules();
+                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
+                            centerVertical(child, params, height);
+                        }
+                    }
+                }
+            }
         }
 
         if (horizontalGravity || verticalGravity) {
@@ -510,13 +550,18 @@
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
 
-    private void measureChildHorizontal(View child, LayoutParams params, int myWidth) {
+    private void measureChildHorizontal(View child, LayoutParams params, int myWidth, int myHeight) {
         int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
                 params.mRight, params.width,
                 params.leftMargin, params.rightMargin,
                 mPaddingLeft, mPaddingRight,
                 myWidth);
-        int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        int childHeightMeasureSpec;
+        if (params.width == LayoutParams.FILL_PARENT) {
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, myHeight);
+        } else {
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        }
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
 
@@ -599,7 +644,9 @@
         return MeasureSpec.makeMeasureSpec(childSpecSize, childSpecMode);
     }
 
-    private void positionChildHorizontal(View child, LayoutParams params, int myWidth) {
+    private boolean positionChildHorizontal(View child, LayoutParams params, int myWidth,
+            boolean wrapContent) {
+
         int[] rules = params.getRules();
 
         if (params.mLeft < 0 && params.mRight >= 0) {
@@ -610,16 +657,25 @@
             params.mRight = params.mLeft + child.getMeasuredWidth();
         } else if (params.mLeft < 0 && params.mRight < 0) {
             // Both left and right vary
-            if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_HORIZONTAL]) {
-                centerHorizontal(child, params, myWidth);
+            if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {
+                if (!wrapContent) {
+                    centerHorizontal(child, params, myWidth);
+                } else {
+                    params.mLeft = mPaddingLeft + params.leftMargin;
+                    params.mRight = params.mLeft + child.getMeasuredWidth();
+                }
+                return true;
             } else {
                 params.mLeft = mPaddingLeft + params.leftMargin;
                 params.mRight = params.mLeft + child.getMeasuredWidth();
             }
         }
+        return false;
     }
 
-    private void positionChildVertical(View child, LayoutParams params, int myHeight) {
+    private boolean positionChildVertical(View child, LayoutParams params, int myHeight,
+            boolean wrapContent) {
+
         int[] rules = params.getRules();
 
         if (params.mTop < 0 && params.mBottom >= 0) {
@@ -630,13 +686,20 @@
             params.mBottom = params.mTop + child.getMeasuredHeight();
         } else if (params.mTop < 0 && params.mBottom < 0) {
             // Both top and bottom vary
-            if (0 != rules[CENTER_IN_PARENT] || 0 != rules[CENTER_VERTICAL]) {
-                centerVertical(child, params, myHeight);
+            if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
+                if (!wrapContent) {
+                    centerVertical(child, params, myHeight);
+                } else {
+                    params.mTop = mPaddingTop + params.topMargin;
+                    params.mBottom = params.mTop + child.getMeasuredHeight();
+                }
+                return true;
             } else {
                 params.mTop = mPaddingTop + params.topMargin;
                 params.mBottom = params.mTop + child.getMeasuredHeight();
             }
         }
+        return false;
     }
 
     private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
@@ -766,14 +829,14 @@
     private View getRelatedView(int[] rules, int relation) {
         int id = rules[relation];
         if (id != 0) {
-            DependencyGraph.Node node = mGraph.mNodes.get(id);
+            DependencyGraph.Node node = mGraph.mKeyNodes.get(id);
             if (node == null) return null;
             View v = node.view;
 
             // Find the first non-GONE view up the chain
             while (v.getVisibility() == View.GONE) {
                 rules = ((LayoutParams) v.getLayoutParams()).getRules();
-                node = mGraph.mNodes.get((rules[relation]));
+                node = mGraph.mKeyNodes.get((rules[relation]));
                 if (node == null) return null;
                 v = node.view;
             }
@@ -1109,10 +1172,15 @@
 
     private static class DependencyGraph {
         /**
+         * List of all views in the graph.
+         */
+        private ArrayList<Node> mNodes = new ArrayList<Node>();
+
+        /**
          * List of nodes in the graph. Each node is identified by its
          * view id (see View#getId()).
          */
-        private SparseArray<Node> mNodes = new SparseArray<Node>();
+        private SparseArray<Node> mKeyNodes = new SparseArray<Node>();
 
         /**
          * Temporary data structure used to build the list of roots
@@ -1124,14 +1192,15 @@
          * Clears the graph.
          */
         void clear() {
-            final SparseArray<Node> nodes = mNodes;
+            final ArrayList<Node> nodes = mNodes;
             final int count = nodes.size();
 
             for (int i = 0; i < count; i++) {
-                nodes.valueAt(i).release();
+                nodes.get(i).release();
             }
             nodes.clear();
 
+            mKeyNodes.clear();
             mRoots.clear();
         }
 
@@ -1141,7 +1210,14 @@
          * @param view The view to be added as a node to the graph.
          */
         void add(View view) {
-            mNodes.put(view.getId(), Node.acquire(view));
+            final int id = view.getId();
+            final Node node = Node.acquire(view);
+
+            if (id != View.NO_ID) {
+                mKeyNodes.put(id, node);
+            }
+
+            mNodes.add(node);
         }
 
         /**
@@ -1192,20 +1268,21 @@
          * @return A list of node, each being a root of the graph
          */
         private LinkedList<Node> findRoots(int[] rulesFilter) {
-            final SparseArray<Node> nodes = mNodes;
+            final SparseArray<Node> keyNodes = mKeyNodes;
+            final ArrayList<Node> nodes = mNodes;
             final int count = nodes.size();
 
             // Find roots can be invoked several times, so make sure to clear
             // all dependents and dependencies before running the algorithm
             for (int i = 0; i < count; i++) {
-                final Node node = nodes.valueAt(i);
+                final Node node = nodes.get(i);
                 node.dependents.clear();
                 node.dependencies.clear();
             }
 
             // Builds up the dependents and dependencies for each node of the graph
             for (int i = 0; i < count; i++) {
-                final Node node = nodes.valueAt(i);
+                final Node node = nodes.get(i);
 
                 final LayoutParams layoutParams = (LayoutParams) node.view.getLayoutParams();
                 final int[] rules = layoutParams.mRules;
@@ -1217,7 +1294,7 @@
                     final int rule = rules[rulesFilter[j]];
                     if (rule > 0) {
                         // The node this node depends on
-                        final Node dependency = nodes.get(rule);
+                        final Node dependency = keyNodes.get(rule);
                         if (dependency == node) {
                             throw new IllegalStateException("A view cannot have a dependency" +
                                     " on itself");
@@ -1238,7 +1315,7 @@
 
             // Finds all the roots in the graph: all nodes with no dependencies
             for (int i = 0; i < count; i++) {
-                final Node node = nodes.valueAt(i);
+                final Node node = nodes.get(i);
                 if (node.dependencies.size() == 0) roots.add(node);
             }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 80c2489..b328869 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -19,6 +19,7 @@
 	ActivityManager.cpp \
 	AndroidRuntime.cpp \
 	CursorWindow.cpp \
+	Time.cpp \
 	com_google_android_gles_jni_EGLImpl.cpp \
 	com_google_android_gles_jni_GLImpl.cpp.arm \
 	android_opengl_GLES10.cpp \
diff --git a/libs/ui/Time.cpp b/core/jni/Time.cpp
similarity index 98%
rename from libs/ui/Time.cpp
rename to core/jni/Time.cpp
index b553913..f3037f3 100644
--- a/libs/ui/Time.cpp
+++ b/core/jni/Time.cpp
@@ -1,4 +1,4 @@
-#include <utils/TimeUtils.h>
+#include "TimeUtils.h"
 #include <stdio.h>
 #include <cutils/tztime.h>
 
diff --git a/include/utils/TimeUtils.h b/core/jni/TimeUtils.h
similarity index 100%
rename from include/utils/TimeUtils.h
rename to core/jni/TimeUtils.h
diff --git a/core/jni/android_text_format_Time.cpp b/core/jni/android_text_format_Time.cpp
index 7c208e9..98f4e03 100644
--- a/core/jni/android_text_format_Time.cpp
+++ b/core/jni/android_text_format_Time.cpp
@@ -23,7 +23,7 @@
 #include "jni.h"
 #include "utils/misc.h"
 #include "android_runtime/AndroidRuntime.h"
-#include <utils/TimeUtils.h>
+#include "TimeUtils.h"
 #include <nativehelper/JNIHelp.h>
 #include <cutils/tztime.h>
 
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index b3b2104..7bbe38b 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -24,8 +24,7 @@
 	Region.cpp \
 	Surface.cpp \
 	SurfaceComposerClient.cpp \
-	SurfaceFlingerSynchro.cpp \
-	Time.cpp
+	SurfaceFlingerSynchro.cpp 
 
 LOCAL_SHARED_LIBRARIES := \
 	libcorecg \