Merge "Slightly more legible background for notification panel."
diff --git a/api/current.xml b/api/current.xml
index 87394ce..2427376 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19042,6 +19042,19 @@
 <parameter name="items" type="android.animation.Animator...">
 </parameter>
 </method>
+<method name="playSequentially"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="java.util.List&lt;android.animation.Animator&gt;">
+</parameter>
+</method>
 <method name="playTogether"
  return="void"
  abstract="false"
@@ -19055,6 +19068,19 @@
 <parameter name="items" type="android.animation.Animator...">
 </parameter>
 </method>
+<method name="playTogether"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="items" type="java.util.Collection&lt;android.animation.Animator&gt;">
+</parameter>
+</method>
 <method name="setDuration"
  return="android.animation.AnimatorSet"
  abstract="false"
@@ -249335,7 +249361,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
@@ -249367,6 +249393,25 @@
 </package>
 <package name="dalvik.bytecode"
 >
+<class name="OpcodeInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="MAXIMUM_VALUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <interface name="Opcodes"
  abstract="true"
  static="false"
@@ -249722,7 +249767,7 @@
  value="236"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250063,7 +250108,7 @@
  value="238"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250074,7 +250119,7 @@
  value="239"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250371,7 +250416,7 @@
  value="244"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250382,7 +250427,7 @@
  value="242"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250415,7 +250460,7 @@
  value="243"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250426,7 +250471,7 @@
  value="232"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250525,7 +250570,7 @@
  value="240"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250602,7 +250647,7 @@
  value="250"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250613,7 +250658,7 @@
  value="251"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250646,7 +250691,7 @@
  value="248"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250657,7 +250702,7 @@
  value="249"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250734,7 +250779,7 @@
  value="247"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250745,7 +250790,7 @@
  value="245"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250778,7 +250823,7 @@
  value="246"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -250789,7 +250834,7 @@
  value="233"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -251537,7 +251582,7 @@
  value="234"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -251746,7 +251791,7 @@
  value="235"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -251856,7 +251901,7 @@
  value="237"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -334583,7 +334628,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="minSize" type="int">
+<parameter name="numElements" type="int">
 </parameter>
 </constructor>
 <constructor name="ArrayDeque"
@@ -334849,7 +334894,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="obj" type="java.lang.Object">
+<parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
 <method name="removeLast"
@@ -334873,7 +334918,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="obj" type="java.lang.Object">
+<parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
 <method name="size"
@@ -339631,6 +339676,19 @@
 >
 <implements name="java.util.Queue">
 </implements>
+<method name="add"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="E">
+</parameter>
+</method>
 <method name="addFirst"
  return="void"
  abstract="true"
@@ -339657,6 +339715,19 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="contains"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
 <method name="descendingIterator"
  return="java.util.Iterator&lt;E&gt;"
  abstract="true"
@@ -339668,6 +339739,17 @@
  visibility="public"
 >
 </method>
+<method name="element"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getFirst"
  return="E"
  abstract="true"
@@ -339690,6 +339772,30 @@
  visibility="public"
 >
 </method>
+<method name="iterator"
+ return="java.util.Iterator&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="offer"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="E">
+</parameter>
+</method>
 <method name="offerFirst"
  return="boolean"
  abstract="true"
@@ -339716,6 +339822,17 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="peek"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="peekFirst"
  return="E"
  abstract="true"
@@ -339738,6 +339855,17 @@
  visibility="public"
 >
 </method>
+<method name="poll"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="pollFirst"
  return="E"
  abstract="true"
@@ -339784,6 +339912,30 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="remove"
+ return="E"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="remove"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="java.lang.Object">
+</parameter>
+</method>
 <method name="removeFirst"
  return="E"
  abstract="true"
@@ -339832,6 +339984,17 @@
 <parameter name="o" type="java.lang.Object">
 </parameter>
 </method>
+<method name="size"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </interface>
 <class name="Dictionary"
  extends="java.lang.Object"
@@ -343756,11 +343919,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="endKey" type="K">
+<parameter name="toKey" type="K">
 </parameter>
 <parameter name="inclusive" type="boolean">
 </parameter>
 </method>
+<method name="headMap"
+ return="java.util.SortedMap&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="toKey" type="K">
+</parameter>
+</method>
 <method name="higherEntry"
  return="java.util.Map.Entry&lt;K, V&gt;"
  abstract="true"
@@ -343867,13 +344043,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="startKey" type="K">
+<parameter name="fromKey" type="K">
 </parameter>
-<parameter name="startInclusive" type="boolean">
+<parameter name="fromInclusive" type="boolean">
 </parameter>
-<parameter name="endKey" type="K">
+<parameter name="toKey" type="K">
 </parameter>
-<parameter name="endInclusive" type="boolean">
+<parameter name="toInclusive" type="boolean">
+</parameter>
+</method>
+<method name="subMap"
+ return="java.util.SortedMap&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromKey" type="K">
+</parameter>
+<parameter name="toKey" type="K">
 </parameter>
 </method>
 <method name="tailMap"
@@ -343886,11 +344077,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="startKey" type="K">
+<parameter name="fromKey" type="K">
 </parameter>
 <parameter name="inclusive" type="boolean">
 </parameter>
 </method>
+<method name="tailMap"
+ return="java.util.SortedMap&lt;K, V&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromKey" type="K">
+</parameter>
+</method>
 </interface>
 <interface name="NavigableSet"
  abstract="true"
@@ -343959,9 +344163,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="end" type="E">
+<parameter name="toElement" type="E">
 </parameter>
-<parameter name="endInclusive" type="boolean">
+<parameter name="inclusive" type="boolean">
+</parameter>
+</method>
+<method name="headSet"
+ return="java.util.SortedSet&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="toElement" type="E">
 </parameter>
 </method>
 <method name="higher"
@@ -343977,6 +344194,17 @@
 <parameter name="e" type="E">
 </parameter>
 </method>
+<method name="iterator"
+ return="java.util.Iterator&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="lower"
  return="E"
  abstract="true"
@@ -344022,13 +344250,28 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="start" type="E">
+<parameter name="fromElement" type="E">
 </parameter>
-<parameter name="startInclusive" type="boolean">
+<parameter name="fromInclusive" type="boolean">
 </parameter>
-<parameter name="end" type="E">
+<parameter name="toElement" type="E">
 </parameter>
-<parameter name="endInclusive" type="boolean">
+<parameter name="toInclusive" type="boolean">
+</parameter>
+</method>
+<method name="subSet"
+ return="java.util.SortedSet&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromElement" type="E">
+</parameter>
+<parameter name="toElement" type="E">
 </parameter>
 </method>
 <method name="tailSet"
@@ -344041,9 +344284,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="start" type="E">
+<parameter name="fromElement" type="E">
 </parameter>
-<parameter name="startInclusive" type="boolean">
+<parameter name="inclusive" type="boolean">
+</parameter>
+</method>
+<method name="tailSet"
+ return="java.util.SortedSet&lt;E&gt;"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fromElement" type="E">
 </parameter>
 </method>
 </interface>
@@ -344705,6 +344961,19 @@
 >
 <implements name="java.util.Collection">
 </implements>
+<method name="add"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="e" type="E">
+</parameter>
+</method>
 <method name="element"
  return="E"
  abstract="true"
@@ -344726,7 +344995,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="o" type="E">
+<parameter name="e" type="E">
 </parameter>
 </method>
 <method name="peek"
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index b96391a..6e589e4 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -21,6 +21,7 @@
 import android.content.res.XmlResourceParser;
 import android.content.res.Resources.NotFoundException;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.util.Xml;
 import android.view.animation.AnimationUtils;
 import org.xmlpull.v1.XmlPullParser;
@@ -195,72 +196,95 @@
             anim = new ValueAnimator();
         }
         TypeEvaluator evaluator = null;
-        boolean hasFrom = a.hasValue(com.android.internal.R.styleable.Animator_valueFrom);
-        boolean hasTo = a.hasValue(com.android.internal.R.styleable.Animator_valueTo);
 
-        switch (valueType) {
+        int valueFromIndex = com.android.internal.R.styleable.Animator_valueFrom;
+        int valueToIndex = com.android.internal.R.styleable.Animator_valueTo;
 
-            case VALUE_TYPE_FLOAT: {
-                float valueFrom;
-                float valueTo;
-                if (hasFrom) {
-                    valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
-                    if (hasTo) {
-                        valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
-                        anim.setFloatValues(valueFrom, valueTo);
-                    } else {
-                        anim.setFloatValues(valueFrom);
-                    }
+        boolean getFloats = (valueType == VALUE_TYPE_FLOAT);
+
+        TypedValue tvFrom = a.peekValue(valueFromIndex);
+        boolean hasFrom = (tvFrom != null);
+        int fromType = hasFrom ? tvFrom.type : 0;
+        TypedValue tvTo = a.peekValue(valueToIndex);
+        boolean hasTo = (tvTo != null);
+        int toType = hasTo ? tvTo.type : 0;
+
+        if ((hasFrom && (fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
+                (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) ||
+            (hasTo && (toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
+                (toType <= TypedValue.TYPE_LAST_COLOR_INT))) {
+            // special case for colors: ignore valueType and get ints
+            getFloats = false;
+            anim.setEvaluator(new RGBEvaluator());
+        }
+
+        if (getFloats) {
+            float valueFrom;
+            float valueTo;
+            if (hasFrom) {
+                if (fromType == TypedValue.TYPE_DIMENSION) {
+                    valueFrom = a.getDimension(valueFromIndex, 0f);
                 } else {
-                    valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
-                    anim.setFloatValues(valueTo);
+                    valueFrom = a.getFloat(valueFromIndex, 0f);
                 }
-            }
-            break;
-
-            case VALUE_TYPE_COLOR:
-                evaluator = new RGBEvaluator();
-                anim.setEvaluator(evaluator);
-                // fall through to pick up values
-            case VALUE_TYPE_INT: {
-                int valueFrom;
-                int valueTo;
-                if (hasFrom) {
-                    valueFrom = a.getInteger(com.android.internal.R.styleable.Animator_valueFrom, 0);
-                    if (hasTo) {
-                        valueTo = a.getInteger(com.android.internal.R.styleable.Animator_valueTo, 0);
-                        anim.setIntValues(valueFrom, valueTo);
+                if (hasTo) {
+                    if (toType == TypedValue.TYPE_DIMENSION) {
+                        valueTo = a.getDimension(valueToIndex, 0f);
                     } else {
-                        anim.setIntValues(valueFrom);
+                        valueTo = a.getFloat(valueToIndex, 0f);
                     }
+                    anim.setFloatValues(valueFrom, valueTo);
                 } else {
-                    valueTo = a.getInteger(com.android.internal.R.styleable.Animator_valueTo, 0);
+                    anim.setFloatValues(valueFrom);
+                }
+            } else {
+                if (toType == TypedValue.TYPE_DIMENSION) {
+                    valueTo = a.getDimension(valueToIndex, 0f);
+                } else {
+                    valueTo = a.getFloat(valueToIndex, 0f);
+                }
+                anim.setFloatValues(valueTo);
+            }
+        } else {
+            int valueFrom;
+            int valueTo;
+            if (hasFrom) {
+                if (fromType == TypedValue.TYPE_DIMENSION) {
+                    valueFrom = (int) a.getDimension(valueFromIndex, 0f);
+                } else if ((fromType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
+                        (fromType <= TypedValue.TYPE_LAST_COLOR_INT)) {
+                    valueFrom = a.getColor(valueFromIndex, 0);
+                } else {
+                    valueFrom = a.getInt(valueFromIndex, 0);
+                }
+                if (hasTo) {
+                    if (toType == TypedValue.TYPE_DIMENSION) {
+                        valueTo = (int) a.getDimension(valueToIndex, 0f);
+                    } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
+                            (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
+                        valueTo = a.getColor(valueToIndex, 0);
+                    } else {
+                        valueTo = a.getInt(valueToIndex, 0);
+                    }
+                    anim.setIntValues(valueFrom, valueTo);
+                } else {
+                    anim.setIntValues(valueFrom);
+                }
+            } else {
+                if (hasTo) {
+                    if (toType == TypedValue.TYPE_DIMENSION) {
+                        valueTo = (int) a.getDimension(valueToIndex, 0f);
+                    } else if ((toType >= TypedValue.TYPE_FIRST_COLOR_INT) &&
+                        (toType <= TypedValue.TYPE_LAST_COLOR_INT)) {
+                        valueTo = a.getColor(valueToIndex, 0);
+                    } else {
+                        valueTo = a.getInt(valueToIndex, 0);
+                    }
                     anim.setIntValues(valueTo);
                 }
             }
-            break;
-
-            case VALUE_TYPE_CUSTOM: {
-                // TODO: How to get an 'Object' value?
-                float valueFrom;
-                float valueTo;
-                if (hasFrom) {
-                    valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
-                    if (hasTo) {
-                        valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
-                        anim.setFloatValues(valueFrom, valueTo);
-                    } else {
-                        anim.setFloatValues(valueFrom);
-                    }
-                } else {
-                    valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
-                    anim.setFloatValues(valueTo);
-                }
-            }
-            break;
         }
 
-
         anim.setDuration(duration);
         anim.setStartDelay(startDelay);
 
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index f5420d1..154e084 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -17,7 +17,9 @@
 package android.animation;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 
 /**
  * This class plays a set of {@link Animator} objects in the specified order. Animations
@@ -117,10 +119,29 @@
     }
 
     /**
+     * Sets up this AnimatorSet to play all of the supplied animations at the same time.
+     *
+     * @param items The animations that will be started simultaneously.
+     */
+    public void playTogether(Collection<Animator> items) {
+        if (items != null && items.size() > 0) {
+            mNeedsSort = true;
+            Builder builder = null;
+            for (Animator anim : items) {
+                if (builder == null) {
+                    builder = play(anim);
+                } else {
+                    builder.with(anim);
+                }
+            }
+        }
+    }
+
+    /**
      * Sets up this AnimatorSet to play each of the supplied animations when the
      * previous animation ends.
      *
-     * @param items The aniamtions that will be started one after another.
+     * @param items The animations that will be started one after another.
      */
     public void playSequentially(Animator... items) {
         if (items != null) {
@@ -136,6 +157,25 @@
     }
 
     /**
+     * Sets up this AnimatorSet to play each of the supplied animations when the
+     * previous animation ends.
+     *
+     * @param items The animations that will be started one after another.
+     */
+    public void playSequentially(List<Animator> items) {
+        if (items != null && items.size() > 0) {
+            mNeedsSort = true;
+            if (items.size() == 1) {
+                play(items.get(0));
+            } else {
+                for (int i = 0; i < items.size() - 1; ++i) {
+                    play(items.get(i)).before(items.get(i+1));
+                }
+            }
+        }
+    }
+
+    /**
      * Returns the current list of child Animator objects controlled by this
      * AnimatorSet. This is a copy of the internal list; modifications to the returned list
      * will not affect the AnimatorSet, although changes to the underlying Animator objects
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 32ff3b3..8c55bf3 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -220,25 +220,47 @@
      * </p>
      * 
      *  <h4>{@link android.hardware.Sensor#TYPE_GRAVITY Sensor.TYPE_GRAVITY}:</h4>
-     *  A three dimensional vector indicating the direction and magnitude of gravity.  Units
-     *  are m/s^2.  The coordinate system is the same as is used by the acceleration sensor.
+     *  <p>A three dimensional vector indicating the direction and magnitude of gravity.  Units
+     *  are m/s^2. The coordinate system is the same as is used by the acceleration sensor.</p>
+     *  <p><b>Note:</b> When the device is at rest, the output of the gravity sensor should be identical
+     *  to that of the accelerometer.</p>
      *
      *  <h4>{@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION Sensor.TYPE_LINEAR_ACCELERATION}:</h4>
      *  A three dimensional vector indicating acceleration along each device axis, not including
      *  gravity.  All values have units of m/s^2.  The coordinate system is the same as is used by the
-     * acceleration sensor.
+     *  acceleration sensor.
+     *  <p>The output of the accelerometer, gravity and  linear-acceleration sensors must obey the
+     *  following relation:</p>
+     *   <p><ul>acceleration = gravity + linear-acceleration</ul></p>
      *
      *  <h4>{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR Sensor.TYPE_ROTATION_VECTOR}:</h4>
-     *  The rotation vector represents the orientation of the device as a combination of an angle
-     *  and an axis, in which the device has rotated through an angle theta around an axis
-     *  &lt;x, y, z>. The three elements of the rotation vector are
-     *  &lt;x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>, such that the magnitude of the rotation
-     *  vector is equal to sin(theta/2), and the direction of the rotation vector is equal to the
-     *  direction of the axis of rotation. The three elements of the rotation vector are equal to
-     *  the last three components of a unit quaternion
-     *  &lt;cos(theta/2), x*sin(theta/2), y*sin(theta/2), z*sin(theta/2)>.  Elements of the rotation
-     *  vector are unitless.  The x,y, and z axis are defined in the same way as the acceleration
-     *  sensor.
+     *  <p>The rotation vector represents the orientation of the device as a combination of an <i>angle</i>
+     *  and an <i>axis</i>, in which the device has rotated through an angle &#952 around an axis
+     *  &lt;x, y, z>.</p>
+     *  <p>The three elements of the rotation vector are
+     *  &lt;x*sin(&#952/2), y*sin(&#952/2), z*sin(&#952/2)>, such that the magnitude of the rotation
+     *  vector is equal to sin(&#952/2), and the direction of the rotation vector is equal to the
+     *  direction of the axis of rotation.</p>
+     *  </p>The three elements of the rotation vector are equal to
+     *  the last three components of a <b>unit</b> quaternion
+     *  &lt;cos(&#952/2), x*sin(&#952/2), y*sin(&#952/2), z*sin(&#952/2)>.</p>
+     *  <p>Elements of the rotation vector are unitless.
+     *  The x,y, and z axis are defined in the same way as the acceleration
+     *  sensor.</p>
+     * <ul>
+     * <p>
+     * values[0]: x*sin(&#952/2)
+     * </p>
+     * <p>
+     * values[1]: y*sin(&#952/2)
+     * </p>
+     * <p>
+     * values[2]: z*sin(&#952/2)
+     * </p>
+     * <p>
+     * values[3]: cos(&#952/2) <i>(optional: only if value.length = 4)</i>
+     * </p>
+     * </ul>
      *
      * <h4>{@link android.hardware.Sensor#TYPE_ORIENTATION
      * Sensor.TYPE_ORIENTATION}:</h4> All values are angles in degrees.
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index c178aee..1b799ae 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1938,13 +1938,18 @@
      *  @param R an array of floats in which to store the rotation matrix
      */
     public static void getRotationMatrixFromVector(float[] R, float[] rotationVector) {
-        float q0 = (float)Math.sqrt(1 - rotationVector[0]*rotationVector[0] -
-                                    rotationVector[1]*rotationVector[1] -
-                                    rotationVector[2]*rotationVector[2]);
+
+        float q0;
         float q1 = rotationVector[0];
         float q2 = rotationVector[1];
         float q3 = rotationVector[2];
 
+        if (rotationVector.length == 4) {
+            q0 = rotationVector[3];
+        } else {
+            q0 = (float)Math.sqrt(1 - q1*q1 - q2*q2 - q3*q3);
+        }
+
         float sq_q1 = 2 * q1 * q1;
         float sq_q2 = 2 * q2 * q2;
         float sq_q3 = 2 * q3 * q3;
@@ -1995,10 +2000,12 @@
      *  @param Q an array of floats in which to store the computed quaternion
      */
     public static void getQuaternionFromVector(float[] Q, float[] rv) {
-        float w = (float)Math.sqrt(1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]);
-        //In this case, the w component of the quaternion is known to be a positive number
-
-        Q[0] = w;
+        if (rv.length == 4) {
+            Q[0] = rv[3];
+        } else {
+            //In this case, the w component of the quaternion is known to be a positive number
+            Q[0] = (float)Math.sqrt(1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]);
+        }
         Q[1] = rv[0];
         Q[2] = rv[1];
         Q[3] = rv[2];
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 1c295a7..9c3bc9d 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -40,6 +40,7 @@
 import org.apache.harmony.dalvik.ddmc.ChunkHandler;
 import org.apache.harmony.dalvik.ddmc.DdmServer;
 
+import dalvik.bytecode.OpcodeInfo;
 import dalvik.bytecode.Opcodes;
 import dalvik.system.VMDebug;
 
@@ -786,7 +787,7 @@
      * @hide
      */
     public static long countInstancesOfClass(Class cls) {
-        return VMDebug.countInstancesOfClass(cls);
+        return VMDebug.countInstancesOfClass(cls, true);
     }
 
     /**
@@ -865,7 +866,7 @@
      * </pre>
      */
     public static class InstructionCount {
-        private static final int NUM_INSTR = 256;
+        private static final int NUM_INSTR = OpcodeInfo.MAXIMUM_VALUE + 1;
 
         private int[] mCounts;
 
@@ -909,8 +910,11 @@
          */
         public int globalTotal() {
             int count = 0;
-            for (int i = 0; i < NUM_INSTR; i++)
+
+            for (int i = 0; i < NUM_INSTR; i++) {
                 count += mCounts[i];
+            }
+
             return count;
         }
 
@@ -921,27 +925,16 @@
         public int globalMethodInvocations() {
             int count = 0;
 
-            //count += mCounts[Opcodes.OP_EXECUTE_INLINE];
-            count += mCounts[Opcodes.OP_INVOKE_VIRTUAL];
-            count += mCounts[Opcodes.OP_INVOKE_SUPER];
-            count += mCounts[Opcodes.OP_INVOKE_DIRECT];
-            count += mCounts[Opcodes.OP_INVOKE_STATIC];
-            count += mCounts[Opcodes.OP_INVOKE_INTERFACE];
-            count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_RANGE];
-            count += mCounts[Opcodes.OP_INVOKE_SUPER_RANGE];
-            count += mCounts[Opcodes.OP_INVOKE_DIRECT_RANGE];
-            count += mCounts[Opcodes.OP_INVOKE_STATIC_RANGE];
-            count += mCounts[Opcodes.OP_INVOKE_INTERFACE_RANGE];
-            //count += mCounts[Opcodes.OP_INVOKE_DIRECT_EMPTY];
-            count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_QUICK];
-            count += mCounts[Opcodes.OP_INVOKE_VIRTUAL_QUICK_RANGE];
-            count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK];
-            count += mCounts[Opcodes.OP_INVOKE_SUPER_QUICK_RANGE];
+            for (int i = 0; i < NUM_INSTR; i++) {
+                if (OpcodeInfo.isInvoke(i)) {
+                    count += mCounts[i];
+                }
+            }
+
             return count;
         }
     }
 
-
     /**
      * A Map of typed debug properties.
      */
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 754d073..6414936 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -847,6 +847,13 @@
         }
     };
 
+    // Note: only access this once verifying the thread has a Looper.
+    private static final ThreadLocal<Handler> threadHandler = new ThreadLocal<Handler>() {
+        @Override protected Handler initialValue() {
+            return new Handler();
+        }
+    };
+
     private static boolean tooManyViolationsThisLoop() {
         return violationsBeingTimed.get().size() >= MAX_OFFENSES_PER_LOOP;
     }
@@ -954,7 +961,6 @@
                 return;
             }
 
-            MessageQueue queue = Looper.myQueue();
             final ArrayList<ViolationInfo> records = violationsBeingTimed.get();
             if (records.size() >= MAX_OFFENSES_PER_LOOP) {
                 // Not worth measuring.  Too many offenses in one loop.
@@ -977,9 +983,30 @@
                 }
             }
 
-            queue.addIdleHandler(new MessageQueue.IdleHandler() {
-                    public boolean queueIdle() {
+            // We post a runnable to a Handler (== delay 0 ms) for
+            // measuring the end time of a violation instead of using
+            // an IdleHandler (as was previously used) because an
+            // IdleHandler may not run for quite a long period of time
+            // if an ongoing animation is happening and continually
+            // posting ASAP (0 ms) animation steps.  Animations are
+            // throttled back to 60fps via SurfaceFlinger/View
+            // invalidates, _not_ by posting frame updates every 16
+            // milliseconds.
+            threadHandler.get().post(new Runnable() {
+                    public void run() {
                         long loopFinishTime = SystemClock.uptimeMillis();
+
+                        // Note: we do this early, before handling the
+                        // violation below, as handling the violation
+                        // may include PENALTY_DEATH and we don't want
+                        // to keep the red border on.
+                        if (windowManager != null) {
+                            try {
+                                windowManager.showStrictModeViolation(false);
+                            } catch (RemoteException unused) {
+                            }
+                        }
+
                         for (int n = 0; n < records.size(); ++n) {
                             ViolationInfo v = records.get(n);
                             v.violationNumThisLoop = n + 1;
@@ -988,13 +1015,6 @@
                             handleViolation(v);
                         }
                         records.clear();
-                        if (windowManager != null) {
-                            try {
-                                windowManager.showStrictModeViolation(false);
-                            } catch (RemoteException unused) {
-                            }
-                        }
-                        return false;  // remove this idle handler from the array
                     }
                 });
         }
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 0d012d6..d724320 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -190,7 +190,9 @@
 
     public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
         int initialScrollX = -1, initialScrollY = -1;
-        if (event.getAction() == MotionEvent.ACTION_UP) {
+        final int action = event.getAction();
+
+        if (action == MotionEvent.ACTION_UP) {
             initialScrollX = Touch.getInitialScrollX(widget, buffer);
             initialScrollY = Touch.getInitialScrollY(widget, buffer);
         }
@@ -198,7 +200,7 @@
         boolean handled = Touch.onTouchEvent(widget, buffer, event);
 
         if (widget.isFocused() && !widget.didTouchFocusSelect()) {
-            if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            if (action == MotionEvent.ACTION_DOWN) {
               boolean cap = isCap(buffer);
               if (cap) {
                   int offset = widget.getOffset((int) event.getX(), (int) event.getY());
@@ -211,7 +213,7 @@
                   // mode once the view detected it needed to scroll.
                   widget.getParent().requestDisallowInterceptTouchEvent(true);
               }
-            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+            } else if (action == MotionEvent.ACTION_MOVE) {
                 boolean cap = isCap(buffer);
 
                 if (cap && handled) {
@@ -231,7 +233,7 @@
                     Selection.extendSelection(buffer, offset);
                     return true;
                 }
-            } else if (event.getAction() == MotionEvent.ACTION_UP) {
+            } else if (action == MotionEvent.ACTION_UP) {
                 // If we have scrolled, then the up shouldn't move the cursor,
                 // but we do need to make sure the cursor is still visible at
                 // the current scroll offset to avoid the scroll jumping later
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 6f4abef..24a9f87 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -94,13 +94,18 @@
      */
     abstract void setup(int width, int height);
 
+    interface HardwareDrawCallbacks {
+        void onHardwarePreDraw(Canvas canvas);
+        void onHardwarePostDraw(Canvas canvas);
+    }
+
     /**
      * Draws the specified view.
      * 
      * @param view The view to draw.
      * @param attachInfo AttachInfo tied to the specified view.
      */
-    abstract void draw(View view, View.AttachInfo attachInfo, int yOffset);
+    abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
 
     /**
      * Creates a new display list that can be used to record batches of
@@ -456,7 +461,7 @@
         }
 
         @Override
-        void draw(View view, View.AttachInfo attachInfo, int yOffset) {
+        void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
             if (canDraw()) {
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
                 attachInfo.mIgnoreDirtyState = true;
@@ -473,11 +478,12 @@
 
                 Canvas canvas = mCanvas;
                 int saveCount = canvas.save();
-                canvas.translate(0, -yOffset);
+                callbacks.onHardwarePreDraw(canvas);
 
                 try {
                     view.draw(canvas);
                 } finally {
+                    callbacks.onHardwarePostDraw(canvas);
                     canvas.restoreToCount(saveCount);
                 }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index cb7d0e2..77083a9 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -25,7 +25,9 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -57,6 +59,8 @@
 import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.Interpolator;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Scroller;
@@ -79,7 +83,8 @@
  * {@hide}
  */
 @SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
-public final class ViewRoot extends Handler implements ViewParent, View.AttachInfo.Callbacks {
+public final class ViewRoot extends Handler implements ViewParent,
+        View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
     private static final String TAG = "ViewRoot";
     private static final boolean DBG = false;
     private static final boolean SHOW_FPS = false;
@@ -213,6 +218,10 @@
     int mScrollY;
     int mCurScrollY;
     Scroller mScroller;
+    Bitmap mResizeBitmap;
+    long mResizeBitmapStartTime;
+    int mResizeBitmapDuration;
+    static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator();
 
     final ViewConfiguration mViewConfiguration;
 
@@ -626,6 +635,13 @@
         return mAppVisible ? mView.getVisibility() : View.GONE;
     }
 
+    void disposeResizeBitmap() {
+        if (mResizeBitmap != null) {
+            mResizeBitmap.recycle();
+            mResizeBitmap = null;
+        }
+    }
+
     private void performTraversals() {
         // cache mView since it is used so much below...
         final View host = mView;
@@ -734,6 +750,48 @@
                 ensureTouchModeLocally(mAddedTouchMode);
             } else {
                 if (!mAttachInfo.mContentInsets.equals(mPendingContentInsets)) {
+                    if (mWidth > 0 && mHeight > 0 &&
+                            mSurface != null && mSurface.isValid() &&
+                            mAttachInfo.mHardwareRenderer != null &&
+                            mAttachInfo.mHardwareRenderer.isEnabled() &&
+                            lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
+
+                        disposeResizeBitmap();
+
+                        boolean completed = false;
+                        try {
+                            mResizeBitmap = Bitmap.createBitmap(mWidth, mHeight,
+                                    Bitmap.Config.ARGB_8888);
+                            mResizeBitmap.setHasAlpha(false);
+                            Canvas canvas = new Canvas(mResizeBitmap);
+                            int yoff;
+                            final boolean scrolling = mScroller != null
+                                    && mScroller.computeScrollOffset();
+                            if (scrolling) {
+                                yoff = mScroller.getCurrY();
+                                mScroller.abortAnimation();
+                            } else {
+                                yoff = mScrollY;
+                            }
+                            canvas.translate(0, -yoff);
+                            if (mTranslator != null) {
+                                mTranslator.translateCanvas(canvas);
+                            }
+                            canvas.setScreenDensity(mAttachInfo.mScalingRequired
+                                    ? DisplayMetrics.DENSITY_DEVICE : 0);
+                            mView.draw(canvas);
+                            mResizeBitmapStartTime = SystemClock.uptimeMillis();
+                            mResizeBitmapDuration = mView.getResources().getInteger(
+                                    com.android.internal.R.integer.config_mediumAnimTime);
+                            completed = true;
+                        } catch (OutOfMemoryError e) {
+                            Log.w(TAG, "Not enough memory for content change anim buffer", e);
+                        } finally {
+                            if (!completed) {
+                                mResizeBitmap = null;
+                            }
+                        }
+                    }
                     mAttachInfo.mContentInsets.set(mPendingContentInsets);
                     host.fitSystemWindows(mAttachInfo.mContentInsets);
                     insetsChanged = true;
@@ -787,7 +845,6 @@
                     // Maybe we can just try the next size up, and see if that reduces
                     // the height?
                     if (host.getWidth() <= baseSize /*&& host.getHeight() <= maxHeight*/) {
-                        Log.v(TAG, "Good!");
                         goodMeasure = true;
                     } else {
                         // Didn't fit in that size... try expanding a bit.
@@ -972,6 +1029,7 @@
                     if (mScroller != null) {
                         mScroller.abortAnimation();
                     }
+                    disposeResizeBitmap();
                 }
             } catch (RemoteException e) {
             }
@@ -1310,6 +1368,22 @@
         return measureSpec;
     }
 
+    int mHardwareYOffset;
+    int mResizeAlpha;
+    final Paint mResizePaint = new Paint();
+
+    public void onHardwarePreDraw(Canvas canvas) {
+        canvas.translate(0, -mHardwareYOffset);
+    }
+
+    public void onHardwarePostDraw(Canvas canvas) {
+        if (mResizeBitmap != null) {
+            canvas.translate(0, mHardwareYOffset);
+            mResizePaint.setAlpha(mResizeAlpha);
+            canvas.drawBitmap(mResizeBitmap, 0, 0, mResizePaint);
+        }
+    }
+
     private void draw(boolean fullRedrawNeeded) {
         Surface surface = mSurface;
         if (surface == null || !surface.isValid()) {
@@ -1334,8 +1408,8 @@
         }
 
         int yoff;
-        final boolean scrolling = mScroller != null && mScroller.computeScrollOffset();
-        if (scrolling) {
+        boolean animating = mScroller != null && mScroller.computeScrollOffset();
+        if (animating) {
             yoff = mScroller.getCurrY();
         } else {
             yoff = mScrollY;
@@ -1347,10 +1421,29 @@
         float appScale = mAttachInfo.mApplicationScale;
         boolean scalingRequired = mAttachInfo.mScalingRequired;
 
+        int resizeAlpha = 0;
+        if (mResizeBitmap != null) {
+            long deltaTime = SystemClock.uptimeMillis() - mResizeBitmapStartTime;
+            if (deltaTime < mResizeBitmapDuration) {
+                float amt = deltaTime/(float)mResizeBitmapDuration;
+                amt = mResizeInterpolator.getInterpolation(amt);
+                animating = true;
+                resizeAlpha = 255 - (int)(amt*255);
+            } else {
+                disposeResizeBitmap();
+            }
+        }
+
         Rect dirty = mDirty;
         if (mSurfaceHolder != null) {
             // The app owns the surface, we won't draw.
             dirty.setEmpty();
+            if (animating) {
+                if (mScroller != null) {
+                    mScroller.abortAnimation();
+                }
+                disposeResizeBitmap();
+            }
             return;
         }
 
@@ -1363,10 +1456,12 @@
             if (!dirty.isEmpty() || mIsAnimating) {
                 mIsAnimating = false;
                 dirty.setEmpty();
-                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, yoff);
+                mHardwareYOffset = yoff;
+                mResizeAlpha = resizeAlpha;
+                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
             }
 
-            if (scrolling) {
+            if (animating) {
                 mFullRedrawNeeded = true;
                 scheduleTraversals();
             }
@@ -1486,7 +1581,7 @@
             Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost");
         }
 
-        if (scrolling) {
+        if (animating) {
             mFullRedrawNeeded = true;
             scheduleTraversals();
         }
@@ -1600,7 +1695,7 @@
         if (scrollY != mScrollY) {
             if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old="
                     + mScrollY + " , new=" + scrollY);
-            if (!immediate) {
+            if (!immediate && mResizeBitmap == null) {
                 if (mScroller == null) {
                     mScroller = new Scroller(mView.getContext());
                 }
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 0e9d9b7..1647540 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -621,6 +621,20 @@
     }
 
     /**
+     * Tell the cookie store that this is a good time to flush cookies to flash.
+     *
+     * This should be called when the app is paused. Note that this method only
+     * acts as a hint, and may not have any effect. Flushing is asynchronous.
+     *
+     * @hide pending API council approval.
+     */
+    public void flushCookieStore() {
+        if (useChromiumHttpStack()) {
+            nativeFlushCookieStore();
+        }
+    }
+
+    /**
      * Package level api, called from CookieSyncManager
      *
      * Get a list of cookies which are updated since a given time.
@@ -1078,4 +1092,5 @@
     private static native void nativeRemoveSessionCookie();
     private static native void nativeSetAcceptCookie(boolean accept);
     private static native void nativeSetCookie(String url, String value);
+    private static native void nativeFlushCookieStore();
 }
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 6769563..85bff4f 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -138,6 +138,10 @@
                         mCurrentProxy.dispatchOnEnded();
                     else
                         mCurrentProxy.dispatchOnPaused();
+
+                    // Re enable plugin views.
+                    mCurrentProxy.getWebView().getViewManager().showAll();
+
                     isVideoSelfEnded = false;
                     mCurrentProxy = null;
                     mLayout.removeView(mVideoView);
@@ -199,6 +203,9 @@
             mTimer = new Timer();
             mVideoView.start();
             client.onShowCustomView(mLayout, mCallback);
+            // Plugins like Flash will draw over the video so hide
+            // them while we're playing.
+            mCurrentProxy.getWebView().getViewManager().hideAll();
         }
 
         public static boolean isPlaying(HTML5VideoViewProxy proxy) {
@@ -599,6 +606,10 @@
         return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr);
     }
 
+    /* package */ WebView getWebView() {
+        return mWebView;
+    }
+
     private native void nativeOnPrepared(int duration, int width, int height, int nativePointer);
     private native void nativeOnEnded(int nativePointer);
     private native void nativeOnPaused(int nativePointer);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6e27b7a..b8ccf45 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2183,14 +2183,13 @@
     // look at the cursor node, and not the focus node.  Also, what is
     // getFocusNodePath?
     public void requestFocusNodeHref(Message hrefMsg) {
-        if (hrefMsg == null || mNativeClass == 0) {
+        if (hrefMsg == null) {
             return;
         }
-        if (nativeCursorIsAnchor()) {
-            mWebViewCore.sendMessage(EventHub.REQUEST_CURSOR_HREF,
-                    nativeCursorFramePointer(), nativeCursorNodePointer(),
-                    hrefMsg);
-        }
+        int contentX = viewToContentX((int) mLastTouchX + mScrollX);
+        int contentY = viewToContentY((int) mLastTouchY + mScrollY);
+        mWebViewCore.sendMessage(EventHub.REQUEST_CURSOR_HREF,
+                contentX, contentY, hrefMsg);
     }
 
     /**
@@ -3739,6 +3738,8 @@
         if (mNativeClass != 0 && nativeWordSelection(x, y)) {
             nativeSetExtendSelection();
             mDrawSelectionPointer = false;
+            mSelectionStarted = true;
+            mTouchMode = TOUCH_DRAG_MODE;
             return true;
         }
         selectionDone();
@@ -4989,10 +4990,10 @@
         startTouch(detector.getFocusX(), detector.getFocusY(), mLastTouchTime);
     }
 
-    private void startScrollingLayer(float gestureX, float gestureY) {
+    private void startScrollingLayer(float x, float y) {
         if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
-            int contentX = viewToContentX((int) gestureX + mScrollX);
-            int contentY = viewToContentY((int) gestureY + mScrollY);
+            int contentX = viewToContentX((int) x + mScrollX);
+            int contentY = viewToContentY((int) y + mScrollY);
             mScrollingLayer = nativeScrollableLayer(contentX, contentY);
             if (mScrollingLayer != 0) {
                 mTouchMode = TOUCH_DRAG_LAYER_MODE;
@@ -5025,52 +5026,12 @@
         float y = ev.getY();
         long eventTime = ev.getEventTime();
 
-        final ScaleGestureDetector detector =
-                mZoomManager.getMultiTouchGestureDetector();
-        boolean isScrollGesture = false;
-        // Set to the mid-point of a two-finger gesture used to detect if the
-        // user has touched a layer.
-        float gestureX = x;
-        float gestureY = y;
-        if (detector == null || !detector.isInProgress()) {
-            // The gesture for scrolling a layer is two fingers close together.
-            // FIXME: we may consider giving WebKit an option to handle
-            // multi-touch events later.
-            if (ev.getPointerCount() > 1) {
-                float dx = ev.getX(1) - ev.getX(0);
-                float dy = ev.getY(1) - ev.getY(0);
-                float dist = (dx * dx + dy * dy) *
-                        DRAG_LAYER_INVERSE_DENSITY_SQUARED;
-                // Use the approximate center to determine if the gesture is in
-                // a layer.
-                gestureX = ev.getX(0) + (dx * .5f);
-                gestureY = ev.getY(0) + (dy * .5f);
-                // Now use a consistent point for tracking movement.
-                if (ev.getX(0) < ev.getX(1)) {
-                    x = ev.getX(0);
-                    y = ev.getY(0);
-                } else {
-                    x = ev.getX(1);
-                    y = ev.getY(1);
-                }
-                action = ev.getActionMasked();
-                if (dist < DRAG_LAYER_FINGER_DISTANCE) {
-                    isScrollGesture = true;
-                } else if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
-                    // Fingers moved too far apart while dragging, the user
-                    // might be trying to zoom.
-                    mTouchMode = TOUCH_INIT_MODE;
-                }
-            }
-        }
-
-        // If the page disallows zoom, pass multi-touch events to webkit.
         // mDeferMultitouch is a hack for layout tests, where it is used to
         // force passing multi-touch events to webkit.
         // FIXME: always pass multi-touch events to webkit and remove everything
         // related to mDeferMultitouch.
         if (ev.getPointerCount() > 1 &&
-                (mDeferMultitouch || (!isScrollGesture && mZoomManager.isZoomScaleFixed()))) {
+                (mDeferMultitouch || mZoomManager.isZoomScaleFixed())) {
             if (DebugFlags.WEB_VIEW) {
                 Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit");
             }
@@ -5078,8 +5039,11 @@
             return true;
         }
 
+        final ScaleGestureDetector detector =
+                mZoomManager.getMultiTouchGestureDetector();
+
         if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1 &&
-                mTouchMode != TOUCH_DRAG_LAYER_MODE && !isScrollGesture) {
+                mTouchMode != TOUCH_DRAG_LAYER_MODE) {
             if (!detector.isInProgress() &&
                     ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) {
                 // Insert a fake pointer down event in order to start
@@ -5369,9 +5333,7 @@
                     deltaX = 0;
                     deltaY = 0;
 
-                    if (isScrollGesture) {
-                        startScrollingLayer(gestureX, gestureY);
-                    }
+                    startScrollingLayer(x, y);
                     startDrag();
                 }
 
@@ -5667,8 +5629,10 @@
                 deltaY = viewToContentDimension(deltaY);
                 if (nativeScrollLayer(mScrollingLayer, deltaX, deltaY)) {
                     invalidate();
+                    return;
                 }
-                return;
+                // Switch to drag mode and fall through.
+                mTouchMode = TOUCH_DRAG_MODE;
             }
 
             final int oldX = mScrollX;
@@ -7706,6 +7670,10 @@
         mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM, autoFillQueryId, /* unused */0);
     }
 
+    /* package */ ViewManager getViewManager() {
+        return mViewManager;
+    }
+
     private native int nativeCacheHitFramePointer();
     private native Rect nativeCacheHitNodeBounds();
     private native int nativeCacheHitNodePointer();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index b7d20b4..99a0386 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -553,8 +553,8 @@
     private native void nativeMoveMouseIfLatest(int moveGeneration,
             int framePtr, int x, int y);
 
-    private native String nativeRetrieveHref(int framePtr, int nodePtr);
-    private native String nativeRetrieveAnchorText(int framePtr, int nodePtr);
+    private native String nativeRetrieveHref(int x, int y);
+    private native String nativeRetrieveAnchorText(int x, int y);
 
     private native void nativeTouchUp(int touchGeneration,
             int framePtr, int nodePtr, int x, int y);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 57af643..cfdcd32 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -220,8 +220,8 @@
     private boolean mTemporaryDetach;
     private boolean mDispatchTemporaryDetach;
 
-    private boolean mEatTouchRelease = false;
-    private boolean mScrolled = false;
+    private boolean mDiscardNextActionUp = false;
+    private boolean mIgnoreActionUpEvent = false;
 
     private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
     private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
@@ -7002,26 +7002,6 @@
         }
     }
 
-    private void onTapUpEvent(int prevStart, int prevEnd) {
-        final int start = getSelectionStart();
-        final int end = getSelectionEnd();
-
-        if (start == end) {
-            if (start >= prevStart && start < prevEnd) {
-                // Restore previous selection
-                Selection.setSelection((Spannable)mText, prevStart, prevEnd);
-                return;
-            } else {
-                // Tapping outside stops selection mode, if any
-                stopSelectionActionMode();
-
-                if (hasInsertionController()) {
-                    getInsertionController().show();
-                }
-            }
-        }
-    }
-
     class CommitSelectionReceiver extends ResultReceiver {
         private final int mPrevStart, mPrevEnd;
 
@@ -7066,7 +7046,7 @@
             // Reset this state; it will be re-set if super.onTouchEvent
             // causes focus to move to the view.
             mTouchFocusSelected = false;
-            mScrolled = false;
+            mIgnoreActionUpEvent = false;
         }
 
         final boolean superResult = super.onTouchEvent(event);
@@ -7076,8 +7056,8 @@
          * move the selection away from whatever the menu action was
          * trying to affect.
          */
-        if (mEatTouchRelease && action == MotionEvent.ACTION_UP) {
-            mEatTouchRelease = false;
+        if (mDiscardNextActionUp && action == MotionEvent.ACTION_UP) {
+            mDiscardNextActionUp = false;
             return superResult;
         }
 
@@ -7106,7 +7086,7 @@
                         mSelectionModifierCursorController.updatePosition();
                     }
                 }
-                if (action == MotionEvent.ACTION_UP && !mScrolled && isFocused()) {
+                if (action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) {
                     InputMethodManager imm = (InputMethodManager)
                     getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
@@ -7117,13 +7097,14 @@
                     }
 
                     if (!mTextIsSelectable) {
-                        // Selection in read-only text should not bring up the IME.
+                        // Show the IME, except when selecting in read-only text.
                         handled |= imm.showSoftInput(this, 0, csr) && (csr != null);
                     }
 
-                    // Cannot be done by CommitSelectionReceiver, which might not always be called,
-                    // for instance when dealing with an ExtractEditText.
-                    onTapUpEvent(oldSelStart, oldSelEnd);
+                    stopSelectionActionMode();
+                    if (hasInsertionController()) {
+                        getInsertionController().show();
+                    }
                 }
             }
 
@@ -7181,7 +7162,7 @@
     @Override
     public void cancelLongPress() {
         super.cancelLongPress();
-        mScrolled = true;
+        mIgnoreActionUpEvent = true;
     }
     
     @Override
@@ -7815,7 +7796,7 @@
     @Override
     public boolean performLongClick() {
         if (super.performLongClick()) {
-            mEatTouchRelease = true;
+            mDiscardNextActionUp = true;
             return true;
         }
 
@@ -7826,7 +7807,7 @@
             stopSelectionActionMode();
             Selection.setSelection((Spannable)mText, offset);
             getInsertionController().show(0);
-            mEatTouchRelease = true;
+            mDiscardNextActionUp = true;
             return true;
         }
 
@@ -7845,13 +7826,13 @@
                 getSelectionController().show();
             }
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-            mEatTouchRelease = true;
+            mDiscardNextActionUp = true;
             return true;
         }
 
         if (startSelectionActionMode()) {
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-            mEatTouchRelease = true;
+            mDiscardNextActionUp = true;
             return true;
         }
 
@@ -8772,6 +8753,7 @@
                             final int slopSquared = doubleTapSlop * doubleTapSlop;
                             if (distanceSquared < slopSquared) {
                                 startSelectionActionMode();
+                                mDiscardNextActionUp = true;
                             }
                         }
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index cc6dc2a..a911e8d 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3418,21 +3418,18 @@
              greater than 0 or infinite. The default value is restart. -->
         <attr name="repeatMode"/>
         <!-- Value the animation starts from. -->
-        <attr name="valueFrom" format="float|integer"/>
+        <attr name="valueFrom" format="float|integer|color|dimension"/>
         <!-- Value the animation animates to. -->
-        <attr name="valueTo" format="float|integer"/>
+        <attr name="valueTo" format="float|integer|color|dimension"/>
         <!-- The type of valueFrom and valueTo. -->
         <attr name="valueType">
-            <!-- valueFrom and valueTo are floats. -->
+            <!-- valueFrom and valueTo are floats. This is the default value is valueType is
+                 unspecified. Note that if either valueFrom or valueTo represent colors
+                 (beginning with "#"), then this attribute is ignored and the color values are
+                 interpreted as integers. -->
             <enum name="floatType" value="0" />
             <!-- valueFrom and valueTo are integers. -->
             <enum name="intType"   value="1" />
-            <!-- valueFrom and valueTo are doubles. -->
-            <enum name="doubleType" value="2" />
-            <!-- valueFrom and valueTo are colors. -->
-            <enum name="colorType" value="3" />
-            <!-- valueFrom and valueTo are a custom type. -->
-            <enum name="customType" value="4" />
         </attr>
     </declare-styleable>
 
diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd
index 6c02031..623ee22 100644
--- a/docs/html/guide/topics/data/backup.jd
+++ b/docs/html/guide/topics/data/backup.jd
@@ -7,7 +7,9 @@
 
   <h2>Quickview</h2>
   <ul>
-    <li>Back up your data to the cloud in case the user looses it</li>
+    <li>Back up the user's data to the cloud in case the user loses it</li>
+    <li>If the user upgrades to a new Android-powered device, your app can restore the user's
+data onto the new device</li>
     <li>Easily back up SharedPreferences and private files with BackupAgentHelper</li>
     <li>Requires API Level 8</li>
   </ul>
@@ -389,7 +391,7 @@
     <p>To add an entity to your backup data set, you must:</p>
     <ol>
       <li>Call {@link android.app.backup.BackupDataOutput#writeEntityHeader(String,int)
-writeEntityheader()}, passing a unique string key for the data you're about to write and the data
+writeEntityHeader()}, passing a unique string key for the data you're about to write and the data
 size.</li>
       <li>Call {@link android.app.backup.BackupDataOutput#writeEntityData(byte[],int)
 writeEntityData()}, passing a byte buffer that contains your data and the number of bytes to write
@@ -403,8 +405,8 @@
 ByteArrayOutputStream bufStream = new ByteArrayOutputStream();
 DataOutputStream outWriter = new DataOutputStream(bufStream);
 // Write structured data
-outWriter.writeString(playerName);
-outWriter.writeInt(playerScore);
+outWriter.writeUTF(mPlayerName);
+outWriter.writeInt(mPlayerScore);
 // Send the data to the Backup Manager via the BackupDataOutput
 byte[] buffer = bufStream.toByteArray();
 int len = buffer.length;
@@ -422,10 +424,10 @@
 onBackup()} so you can determine whether another backup is necessary (as handled in step 1). If you
 do not write the current data state to this file, then
 {@code oldState} will be empty during the next callback.
-    <p>Again, the following example saves a representation of the data using the file's
-last-modified timestamp:</p>
+    <p>The following example saves a representation of the current data into {@code newState} using
+the file's last-modified timestamp:</p>
     <pre>
-FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
+FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
 DataOutputStream out = new DataOutputStream(outstream);
 
 long modified = mDataFile.lastModified();
@@ -493,7 +495,8 @@
 
 <p>In your implementation of {@link
 android.app.backup.BackupAgent#onRestore(BackupDataInput,int,ParcelFileDescriptor)
-onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} to iterate
+onRestore()}, you should call {@link android.app.backup.BackupDataInput#readNextHeader()} on the
+{@code data} to iterate
 through all entities in the data set. For each entity found, do the following:</p>
 
 <ol>
@@ -517,6 +520,54 @@
 onBackup()}.
 </ol>
 
+<p>For example, here's how you can restore the data backed up by the example in the previous
+section:</p>
+
+<pre>
+&#64;Override
+public void onRestore(BackupDataInput data, int appVersionCode,
+                      ParcelFileDescriptor newState) throws IOException {
+    // There should be only one entity, but the safest
+    // way to consume it is using a while loop
+    while (data.readNextHeader()) {
+        String key = data.getKey();
+        int dataSize = data.getDataSize();
+
+        // If the key is ours (for saving top score). Note this key was used when
+        // we wrote the backup entity header
+        if (TOPSCORE_BACKUP_KEY.equals(key)) {
+            // Create an input stream for the BackupDataInput
+            byte[] dataBuf = new byte[dataSize];
+            data.readEntityData(dataBuf, 0, dataSize);
+            ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
+            DataInputStream in = new DataInputStream(baStream);
+
+            // Read the player name and score from the backup data
+            mPlayerName = in.readUTF();
+            mPlayerScore = in.readInt();
+
+            // Record the score on the device (to a file or something)
+            recordScore(mPlayerName, mPlayerScore);
+        } else {
+            // We don't know this entity key. Skip it. (Shouldn't happen.)
+            data.skipEntityData();
+        }
+    }
+
+    // Finally, write to the state blob (newState) that describes the restored data
+    FileOutputStream outstream = new FileOutputStream(newState.getFileDescriptor());
+    DataOutputStream out = new DataOutputStream(outstream);
+    out.writeUTF(mPlayerName);
+    out.writeInt(mPlayerScore);
+}
+</pre>
+
+<p>In this example, the {@code appVersionCode} parameter passed to {@link
+android.app.backup.BackupAgent#onRestore onRestore()} is not used. However, you might want to use
+it if you've chosen to perform backup when the user's version of the application has actually moved
+backward (for example, the user went from version 1.5 of your app to 1.0). For more information, see
+the section about <a href="#RestoreVersion">Checking the Restore Data Version</a>.</p>
+
 <div class="special">
 <p>For an example implementation of {@link android.app.backup.BackupAgent}, see the <a
 href="{@docRoot}resources/samples/BackupRestore/src/com/example/android/backuprestore/ExampleAgent.html">{@code
@@ -592,7 +643,8 @@
     static final String PREFS_BACKUP_KEY = "prefs";
 
     // Allocate a helper and add it to the backup agent
-    void onCreate() {
+    &#64;Override
+    public void onCreate() {
         SharedPreferencesBackupHelper helper = new SharedPreferencesBackupHelper(this, PREFS);
         addHelper(PREFS_BACKUP_KEY, helper);
     }
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 0f36345..2c8e4c2 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -67,73 +67,71 @@
          width="9px" /> Android NDK, Revision 5</a> <em>(November 2010)</em>
 
     <div class="toggleme">
-      <dl>
-        <dt>NDK r5 notes:</dt>
-
-        <dd>
-          <p>The r5 release of the NDK includes many new APIs, many of which are introduced to
-          support native game development and applications that require similar requirements. Most
-          notably, native activities are now supported, which allow you to write an application
-          entirely with native code. For detailed information describing the changes in this
-          release, read the CHANGES.HTML document included in the downloaded NDK package.</p>
-        </dd>
-      </dl>
-
+      <p>This release of the NDK includes many new APIs, most of which are introduced to
+         support the development of games and similar applications that make extensive use
+         of native code. Using the APIs, developers have direct native access to events, audio,
+         graphics and window management, assets, and storage. Developers can also implement the
+         Android application lifecycle in native code with help from the new
+         {@link android.app.NativeActivity} class. For detailed information describing the changes in this
+         release, read the CHANGES.HTML document included in the downloaded NDK package.
+      </p>
       <dl>
         <dt>General notes:</dt>
-
         <dd>
           <ul>
-          
-            <li>A new toolchain (based on GCC 4.4.3), which generates better code, and can also now
-be used as a standalone cross-compiler, for people who want to build their stuff with
-<code>./configure &amp;&amp; make</code>. See
-docs/STANDALONE-TOOLCHAIN.html for the details. The binaries for GCC 4.4.0 are still provided,
-but the 4.2.1 binaries were removed.</li>
-
-            <li>Support for prebuilt static and shared libraries (docs/PREBUILTS.html), module
-exports and imports to make sharing and reuse of third-party modules much easier
-(docs/IMPORT-MODULE.html explains why).</li>
-
-            <li>A C++ STL implementation (based on STLport) is now provided as a helper module. It
-can be used either as a static or shared library (details and usage exemple under
-sources/android/stlport/README). <strong>Note:</strong> For now, C++ Exceptions and RTTI are still
-not supported.</li>
-
-            <li>Improvements to the <code>cpufeatures</code> helper library to deal with buggy
-kernel that incorrectly report they run on an ARMv7 CPU (while the device really is an ARMv6). We
-recommend developers that use it to simply rebuild their applications to benefit from it, then
-upload to Market.</li>
-
-            <li>Adds support for native activities, which allows you to write completely native
-            applications.</li>
-
-            <li>Adds an EGL library that lets you create and manage OpenGL ES textures and
-            services.</li>
+            <li>Adds support for native activities, which allows you to implement the
+            Android application lifecycle in native code.</li>
 
             <li>Adds native support for the following:
 
               <ul>
+
                 <li>Input subsystem (such as the keyboard and touch screen)</li>
 
+                <li>Access to sensor data (accelerometer, compass, gyroscope, etc).</li>
+
+                <li>Event loop APIs to wait for things such as input and sensor events.</li>
+
                 <li>Window and surface subsystem</li>
 
                 <li>Audio APIs based on the OpenSL ES standard that support playback and recording
                 as well as control over platform audio effects</li>
 
-                <li>Event loop APIs to wait for things such as input and sensor events</li>
-
-                <li>Access to assets packaged in the <code>.apk</code></li>
-
-                <li>Access to sensor data (accelerometer, compass, gyroscope, etc.)</li>
+                <li>Access to assets packaged in an <code>.apk</code> file.</li>
+                
               </ul>
             </li>
 
-            <li>New sample applications, <code>native-plasma</code> and
-              <code>native-activity</code>, to demonstrate how to write a native activity.</li>
-            
-            <li>Plus many bugfixes and other small improvements; see docs/CHANGES.html for a more
-detailed list of changes.</li>
+            <li>Includes a new toolchain (based on GCC 4.4.3), which generates better code, and can also now
+            be used as a standalone cross-compiler, for people who want to build their stuff with
+            <code>./configure &amp;&amp; make</code>. See
+            docs/STANDALONE-TOOLCHAIN.html for the details. The binaries for GCC 4.4.0 are still provided,
+            but the 4.2.1 binaries were removed.</li>
+
+            <li>Adds support for prebuilt static and shared libraries (docs/PREBUILTS.html) and module
+            exports and imports to make sharing and reuse of third-party modules much easier
+            (docs/IMPORT-MODULE.html explains why).</li>
+
+            <li>Provides a default C++ STL implementation (based on STLport) as a helper module. It can be used either
+            as a static or shared library (details and usage examples are in sources/android/stlport/README). Prebuilt
+            binaries for STLport (static or shared) and GNU libstdc++ (static only) are also provided if you choose to
+            compile against those libraries instead of the default C++ STL implementation. 
+            C++ Exceptions and RTTI are not supported in the default STL implementation. For more information, see
+            docs/CPLUSPLUS-SUPPORT.HTML.</li>
+
+            <li>Includes improvements to the <code>cpufeatures</code> helper library that improves reporting
+            of the CPU type (some devices previously reported ARMv7 CPU when the device really was an ARMv6). We
+            recommend developers that use this library to rebuild their applications then
+            upload to Market to benefit from the improvements.</li>
+
+            <li>Adds an EGL library that lets you create and manage OpenGL ES textures and
+              services.</li>
+                
+            <li>Adds new sample applications, <code>native-plasma</code> and <code>native-activity</code>, 
+            to demonstrate how to write a native activity.</li>
+
+            <li>Includes many bugfixes and other small improvements; see docs/CHANGES.html for a more
+              detailed list of changes.</li>
           </ul>
         </dd>
       </dl>
@@ -296,14 +294,13 @@
   
   <h2 id="installing">Installing the NDK</h2>
   <p>Installing the NDK on your development computer is straightforward and involves extracting the
-  NDK from its download package. Unlike previous releases, there is no need to run a host-setup
-  script.</p>
+  NDK from its download package.</p>
 
   <p>Before you get started make sure that you have downloaded the latest <a href=
   "{@docRoot}sdk/index.html">Android SDK</a> and upgraded your applications and environment as
-  needed. The NDK will not work with older versions of the Android SDK. Also, take a moment to
-  review the <a href="{@docRoot}sdk/ndk/reqs.html">System and Software Requirements</a> for the
-  NDK, if you haven't already.</p>
+  needed. The NDK is compatible with older platform versions but not older versions of the SDK tools.
+  Also, take a moment to review the <a href="{@docRoot}sdk/ndk/reqs.html">System and Software Requirements</a>
+  for the NDK, if you haven't already.</p>
 
   <p>To install the NDK, follow these steps:</p>
 
@@ -318,7 +315,7 @@
     <code>&lt;ndk&gt;</code>.</li>
   </ol>
 
-  <p>You are now ready start working with the NDK.</p>
+  <p>You are now ready to start working with the NDK.</p>
 
   <h2 id="gettingstarted">Getting Started with the NDK</h2>
 
@@ -342,8 +339,7 @@
 
     <li>Build your native code by running the 'ndk-build' script from your project's directory. It
     is located in the top-level NDK directory:
-      <pre class="no-pretty-print">
-cd &lt;project&gt;
+      <pre class="no-pretty-print">cd &lt;project&gt;
 &lt;ndk&gt;/ndk-build
 </pre>
 
@@ -360,220 +356,10 @@
 
   <h2 id="samples">Sample Applications</h2>
 
-  <p>The NDK includes sample applications that illustrate how to use native code in your Android
-  applications:</p>
+  <p>The NDK includes sample Android applications that illustrate how to use native code in your
+  Android applications. For more information, see <a href=
+  "{@docRoot}sdk/ndk/overview.html#samples">Sample Applications</a>.</p>
 
-  <ul>
-    <li><code>hello-jni</code> &mdash; a simple application that loads a string from a native
-    method implemented in a shared library and then displays it in the application UI.</li>
-
-    <li><code>two-libs</code> &mdash; a simple application that loads a shared library dynamically
-    and calls a native method provided by the library. In this case, the method is implemented in a
-    static library imported by the shared library.</li>
-
-    <li><code>san-angeles</code> &mdash; a simple application that renders 3D graphics through the
-    native OpenGL ES APIs, while managing activity lifecycle with a {@link
-    android.opengl.GLSurfaceView} object.</li>
-
-    <li><code>hello-gl2</code> &mdash; a simple application that renders a triangle using OpenGL ES
-    2.0 vertex and fragment shaders.</li>
-
-    <li><code>hello-neon</code> &mdash; a simple application that shows how to use the
-    <code>cpufeatures</code> library to check CPU capabilities at runtime, then use NEON intrinsics
-    if supported by the CPU. Specifically, the application implements two versions of a tiny
-    benchmark for a FIR filter loop, a C version and a NEON-optimized version for devices that
-    support it.</li>
-
-    <li><code>bitmap-plasma</code> &mdash; a simple application that demonstrates how to access the
-    pixel buffers of Android {@link android.graphics.Bitmap} objects from native code, and uses
-    this to generate an old-school "plasma" effect.</li>
-
-    <li><code>native-activity</code> &mdash; a simple application that demonstrates how to use the
-    native-app-glue static library to create a native activity</li>
-
-    <li><code>native-plasma</code> &mdash; a version of bitmap-plasma implemented with a native
-    activity.</li>
-  </ul>
-
-  <p>For each sample, the NDK includes the corresponding C source code and the necessary Android.mk
-  and Application.mk files. There are located under <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code>
-  and their source code can be found under <code>&lt;ndk&gt;/samples/&lt;name&gt;/jni/</code>.</p>
-
-  <p>You can build the shared libraries for the sample apps by going into
-  <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code> then calling the <code>ndk-build</code> command.
-  The generated shared libraries will be located under
-  <code>&lt;ndk&gt;/samples/&lt;name&gt;/libs/armeabi/</code> for (ARMv5TE machine code) and/or
-  <code>&lt;ndk&gt;/samples/&lt;name&gt;/libs/armeabi-v7a/</code> for (ARMv7 machine code).</p>
-
-  <p>Next, build the sample Android applications that use the shared libraries:</p>
-
-  <ul>
-    <li>If you are developing in Eclipse with ADT, use the New Project Wizard to create a new
-    Android project for each sample, using the "Import from Existing Source" option and importing
-    the source from <code>&lt;ndk&gt;/apps/&lt;app_name&gt;/project/</code>. Then, set up an AVD,
-    if necessary, and build/run the application in the emulator. For more information about
-    creating a new Android project in Eclipse, see <a href=
-    "{@docRoot}guide/developing/eclipse-adt.html">Developing in Eclipse</a>.</li>
-
-    <li>If you are developing with Ant, use the <code>android</code> tool to create the build file
-    for each of the sample projects at <code>&lt;ndk&gt;/apps/&lt;app_name&gt;/project/</code>.
-    Then set up an AVD, if necessary, build your project in the usual way, and run it in the
-    emulator. For more information, see <a href=
-    "{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</li>
-  </ul>
-
-  <h3 id="hello-jni">Exploring the hello-jni Sample</h3>
-
-  <p>The hello-jni sample is a simple demonstration on how to use JNI from an Android application.
-  The HelloJni activity receives a string from a simple C function and displays it in a
-  TextView.</p>
-
-  <p>The main components of the sample include:</p>
-
-  <ul>
-    <li>The familiar basic structure of an Android application (an <code>AndroidManifest.xml</code>
-    file, a <code>src/</code> and <code>res</code> directories, and a main activity)</li>
-
-    <li>A <code>jni/</code> directory that includes the implemented source file for the native code
-    as well as the Android.mk file</li>
-
-    <li>A <code>tests/</code> directory that contains unit test code.</li>
-  </ul>
-
-  <ol>
-    <li>Create a new project in Eclipse from the existing sample source or use the
-    <code>android</code> tool to update the project so it generates a build.xml file that you can
-    use to build the sample.
-
-      <ul>
-        <li>In Eclipse:
-
-          <ol type="a">
-            <li>Click <strong>File &gt; New Android Project...</strong></li>
-
-            <li>Select the <strong>Create project from existing source</strong> radio button.</li>
-
-            <li>Select any API level above Android 1.5.</li>
-
-            <li>In the <strong>Location</strong> field, click <strong>Browse...</strong> and select
-            the <code>&lt;ndk-root&gt;/samples/hello-jni</code> directory.</li>
-
-            <li>Click <strong>Finish</strong>.</li>
-          </ol>
-        </li>
-
-        <li>On the command line:
-
-          <ol type="a">
-            <li>Change to the <code>&lt;ndk-root&gt;/samples/hello-jni</code> directory.</li>
-
-            <li>Run the following command to generate a build.xml file:
-              <pre class="no-pretty-print">
-android update project -p . -s
-</pre>
-            </li>
-          </ol>
-        </li>
-      </ul>
-    </li>
-
-    <li>Compile the native code using the <code>ndk-build</code> command.
-      <pre class="no-pretty-print">
-cd &lt;ndk-root&gt;/samples/hello-jni
-&lt;ndk_root&gt;/ndk-build
-</pre>
-    </li>
-
-    <li>Build and install the application as you would a normal Android application. If you are
-    using Eclipse, run the application to build and install it on a device. If you are using Ant,
-    run the following commands from the project directory:
-      <pre class="no-pretty-print">
-ant debug
-adb install bin/HelloJni-debug.apk
-</pre>
-    </li>
-  </ol>
-
-  <p>When you run the application on the device, the string <code>Hello JNI</code> should appear on
-  your device. You can explore the rest of the samples that are located in the
-  <code>&lt;ndk-root&gt;/samples</code> directory for more examples on how to use the JNI.</p>
-
-  <h3 id="native-activity">Exploring the native-activity Sample Application</h3>
-
-  <p>The native-activity sample provided with the Android NDK demonstrates how to use the
-  android_native_app_glue static library. This static library makes creating a native activity
-  easier by providing you with an implementation that handles your callbacks in another thread, so
-  you do not have to worry about them blocking your main UI thread. The main parts of the sample
-  are described below:</p>
-
-  <ul>
-    <li>The familiar basic structure of an Android application (an <code>AndroidManifest.xml</code>
-    file, a <code>src/</code> and <code>res</code> directories). The AndroidManifest.xml declares
-    that the application is native and specifies the .so file of the native activity. See {@link
-    android.app.NativeActivity} for the source or see the
-    <code>&lt;ndk_root&gt;/platforms/samples/native-activity/AndroidManifest.xml</code> file.</li>
-
-    <li>A <code>jni/</code> directory contains the native activity, main.c, which uses the
-    <code>android_native_app_glue.h</code> interface to implement the activity. The Android.mk that
-    describes the native module to the build system also exists here.</li>
-  </ul>
-
-  <p>To build this sample application:</p>
-
-  <ol>
-    <li>Create a new project in Eclipse from the existing sample source or use the
-    <code>android</code> tool to update the project so it generates a build.xml file that you can
-    use to build the sample.
-
-      <ul>
-        <li>In Eclipse:
-
-          <ol type="a">
-            <li>Click <strong>File &gt; New Android Project...</strong></li>
-
-            <li>Select the <strong>Create project from existing source</strong> radio button.</li>
-
-            <li>Select any API level above Android 2.3.</li>
-
-            <li>In the <strong>Location</strong> field, click <strong>Browse...</strong> and select
-            the <code>&lt;ndk-root&gt;/samples/native-activity</code> directory.</li>
-
-            <li>Click <strong>Finish</strong>.</li>
-          </ol>
-        </li>
-
-        <li>On the command line:
-
-          <ol type="a">
-            <li>Change to the <code>&lt;ndk-root&gt;/samples/native-activity</code> directory.</li>
-
-            <li>Run the following command to generate a build.xml file:
-              <pre class="no-pretty-print">
-android update project -p . -s
-</pre>
-            </li>
-          </ol>
-        </li>
-      </ul>
-    </li>
-
-    <li>Compile the native code using the <code>ndk-build</code> command.
-      <pre class="no-pretty-print">
-cd &lt;ndk-root&gt;/platforms/samples/android-9/samples/native-activity
-&lt;ndk_root&gt;/ndk-build
-</pre>
-    </li>
-
-    <li>Build and install the application as you would a normal Android application. If you are
-    using Eclipse, run the application to build and install it on a device. If you are using Ant,
-    run the following commands in the project directory, then run the application on the device:
-      <pre class="no-pretty-print">
-ant debug
-adb install bin/NativeActivity-debug.apk
-</pre>
-    </li>
-  </ol>
-  
   <h2 id="forum">Discussion Forum and Mailing List</h2>
 
   <p>If you have questions about the NDK or would like to read or contribute to discussions about
diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd
index a7ec5d4..f6d148a 100644
--- a/docs/html/sdk/ndk/overview.jd
+++ b/docs/html/sdk/ndk/overview.jd
@@ -7,10 +7,8 @@
 
       <ol>
         <li><a href="#choosing">When to Develop in Native Code</a></li>
-
         <li>
           <a href="#contents">Contents of the NDK</a>
-
           <ol>
             <li><a href="#tools">Development tools</a></li>
 
@@ -19,9 +17,7 @@
             <li><a href="#samples">Sample applications</a></li>
           </ol>
         </li>
-
         <li><a href="#reqs">System and Software Requirements</a></li>
-        
       </ol>
     </div>
   </div>
@@ -102,9 +98,8 @@
     later.</li>
 
     <li>
-      <p>Write a native activity, which allows you to potentially create an application completely in native
-      code, because you can implement the lifecycle callbacks natively. The Android SDK provides
-      the {@link android.app.NativeActivity} class, which is a convenience class that notifies your
+      <p>Write a native activity, which allows you to implement the lifecycle callbacks in native
+      code. The Android SDK provides the {@link android.app.NativeActivity} class, which is a convenience class that notifies your
       native code of any activity lifecycle callbacks (<code>onCreate()</code>, <code>onPause()</code>,
       <code>onResume()</code>, etc). You can implement the callbacks in your native code to handle
       these events when they occur. Applications that use native activities must be run on Android
@@ -142,6 +137,10 @@
     <li>libjnigraphics (Pixel buffer access) header (for Android 2.2 and above).</li>
 
     <li>A Minimal set of headers for C++ support</li>
+    
+    <li>OpenSL ES native audio libraries</li>
+    
+    <li>Android native application APIS</li>
   </ul>
 
   <p>The NDK also provides a build system that lets you work efficiently with your sources, without
@@ -163,25 +162,18 @@
   the <code>&lt;ndk&gt;/docs/</code> directory. Included are these files:</p>
 
   <ul>
-    <li>INSTALL.HTML &mdash; describes how to install the NDK and configure it for your host
+    <li>
+    INSTALL.HTML &mdash; describes how to install the NDK and configure it for your host
     system</li>
 
     <li>OVERVIEW.HTML &mdash; provides an overview of the NDK capabilities and usage</li>
-
+    
     <li>ANDROID-MK.HTML &mdash; describes the use of the Android.mk file, which defines the native
     sources you want to compile</li>
-
+    
     <li>APPLICATION-MK.HTML &mdash; describes the use of the Application.mk file, which describes
-    the native sources required by your Android application</li>
-
-    <li>HOWTO.HTML &mdash; information about common tasks associated with NDK development.</li>
-
-    <li>SYSTEM-ISSUES.HTML &mdash; known issues in the Android system images that you should be
-    aware of, if you are developing using the NDK.</li>
-
-    <li>STABLE-APIS.HTML &mdash; a complete list of the stable APIs exposed by headers in the
-    NDK.</li>
-
+    the native sources required by your Android application</li>    
+    <li>CPLUSPLUS-SUPPORT.HTML &mdash; describes the C++ support provided in the Android NDK</li>    
     <li>CPU-ARCH-ABIS.HTML &mdash; a description of supported CPU architectures and how to target
     them.</li>
 
@@ -193,6 +185,32 @@
     instructions.</li>
 
     <li>CHANGES.HTML &mdash; a complete list of changes to the NDK across all releases.</li>
+
+    <li>DEVELOPMENT.HTML &mdash; describes how to modify the NDK and generate release packages for it</li>
+    
+    <li>HOWTO.HTML &mdash; information about common tasks associated with NDK development</li>
+    
+    <li>IMPORT-MODULE.HTML &mdash; describes how to share and reuse modules</li>
+    
+    <li>LICENSES.HTML  &mdash; information about the various open source licenses that govern the Android NDK</li>
+ 
+    <li>NATIVE-ACTIVITY.HTML &mdash; describes how to implement native activities</li>
+    
+    <li>NDK-BUILD.HTML &mdash; describes the usage of the ndk-build script</li>
+
+    <li>NDK-GDB.HTML &mdash; describes how to use the native code debugger</li>
+
+    <li>PREBUILTS.HTML &mdash; information about how shared and static prebuilt libraries work </li>
+
+    <li>STANDALONE-TOOLCHAIN.HTML &mdash; describes how to use Android NDK toolchain as a standalone
+    compiler (still in beta).</li>
+    
+    <li>SYSTEM-ISSUES.HTML &mdash; known issues in the Android system images that you should be
+    aware of, if you are developing using the NDK.</li>
+
+    <li>STABLE-APIS.HTML &mdash; a complete list of the stable APIs exposed by headers in the
+    NDK.</li>
+    
   </ul>
 
   <p>Additionally, the package includes detailed information about the "bionic" C library provided
@@ -206,9 +224,218 @@
 
   <h3 id="samples">Sample applications</h3>
 
-  <p>The NDK includes sample Android applications that illustrate how to use native code in your
-  Android applications. For more information, see <a href=
-  "{@docRoot}sdk/ndk/installing.html#samples">Sample Applications</a>.</p>
+<p>The NDK includes sample applications that illustrate how to use native code in your Android
+  applications:</p>
+
+  <ul>
+    <li><code>hello-jni</code> &mdash; a simple application that loads a string from a native
+    method implemented in a shared library and then displays it in the application UI.</li>
+
+    <li><code>two-libs</code> &mdash; a simple application that loads a shared library dynamically
+    and calls a native method provided by the library. In this case, the method is implemented in a
+    static library imported by the shared library.</li>
+
+    <li><code>san-angeles</code> &mdash; a simple application that renders 3D graphics through the
+    native OpenGL ES APIs, while managing activity lifecycle with a {@link
+    android.opengl.GLSurfaceView} object.</li>
+
+    <li><code>hello-gl2</code> &mdash; a simple application that renders a triangle using OpenGL ES
+    2.0 vertex and fragment shaders.</li>
+
+    <li><code>hello-neon</code> &mdash; a simple application that shows how to use the
+    <code>cpufeatures</code> library to check CPU capabilities at runtime, then use NEON intrinsics
+    if supported by the CPU. Specifically, the application implements two versions of a tiny
+    benchmark for a FIR filter loop, a C version and a NEON-optimized version for devices that
+    support it.</li>
+
+    <li><code>bitmap-plasma</code> &mdash; a simple application that demonstrates how to access the
+    pixel buffers of Android {@link android.graphics.Bitmap} objects from native code, and uses
+    this to generate an old-school "plasma" effect.</li>
+
+    <li><code>native-activity</code> &mdash; a simple application that demonstrates how to use the
+    native-app-glue static library to create a native activity</li>
+
+    <li><code>native-plasma</code> &mdash; a version of bitmap-plasma implemented with a native
+    activity.</li>
+  </ul>
+
+  <p>For each sample, the NDK includes the corresponding C source code and the necessary Android.mk
+  and Application.mk files. There are located under <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code>
+  and their source code can be found under <code>&lt;ndk&gt;/samples/&lt;name&gt;/jni/</code>.</p>
+
+  <p>You can build the shared libraries for the sample apps by going into
+  <code>&lt;ndk&gt;/samples/&lt;name&gt;/</code> then calling the <code>ndk-build</code> command.
+  The generated shared libraries will be located under
+  <code>&lt;ndk&gt;/samples/&lt;name&gt;/libs/armeabi/</code> for (ARMv5TE machine code) and/or
+  <code>&lt;ndk&gt;/samples/&lt;name&gt;/libs/armeabi-v7a/</code> for (ARMv7 machine code).</p>
+
+  <p>Next, build the sample Android applications that use the shared libraries:</p>
+
+  <ul>
+    <li>If you are developing in Eclipse with ADT, use the New Project Wizard to create a new
+    Android project for each sample, using the "Import from Existing Source" option and importing
+    the source from <code>&lt;ndk&gt;/apps/&lt;app_name&gt;/project/</code>. Then, set up an AVD,
+    if necessary, and build/run the application in the emulator. For more information about
+    creating a new Android project in Eclipse, see <a href=
+    "{@docRoot}guide/developing/eclipse-adt.html">Developing in Eclipse</a>.</li>
+
+    <li>If you are developing with Ant, use the <code>android</code> tool to create the build file
+    for each of the sample projects at <code>&lt;ndk&gt;/apps/&lt;app_name&gt;/project/</code>.
+    Then set up an AVD, if necessary, build your project in the usual way, and run it in the
+    emulator. For more information, see <a href=
+    "{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>.</li>
+  </ul>
+
+  <h4 id="hello-jni">Exploring the hello-jni Sample</h4>
+
+  <p>The hello-jni sample is a simple demonstration on how to use JNI from an Android application.
+  The HelloJni activity receives a string from a simple C function and displays it in a
+  TextView.</p>
+
+  <p>The main components of the sample include:</p>
+
+  <ul>
+    <li>The familiar basic structure of an Android application (an <code>AndroidManifest.xml</code>
+    file, a <code>src/</code> and <code>res</code> directories, and a main activity)</li>
+
+    <li>A <code>jni/</code> directory that includes the implemented source file for the native code
+    as well as the Android.mk file</li>
+
+    <li>A <code>tests/</code> directory that contains unit test code.</li>
+  </ul>
+
+  <ol>
+    <li>Create a new project in Eclipse from the existing sample source or use the
+    <code>android</code> tool to update the project so it generates a build.xml file that you can
+    use to build the sample.
+
+      <ul>
+        <li>In Eclipse:
+
+          <ol type="a">
+            <li>Click <strong>File &gt; New Android Project...</strong></li>
+
+            <li>Select the <strong>Create project from existing source</strong> radio button.</li>
+
+            <li>Select any API level above Android 1.5.</li>
+
+            <li>In the <strong>Location</strong> field, click <strong>Browse...</strong> and select
+            the <code>&lt;ndk-root&gt;/samples/hello-jni</code> directory.</li>
+
+            <li>Click <strong>Finish</strong>.</li>
+          </ol>
+        </li>
+
+        <li>On the command line:
+
+          <ol type="a">
+            <li>Change to the <code>&lt;ndk-root&gt;/samples/hello-jni</code> directory.</li>
+
+            <li>Run the following command to generate a build.xml file:
+              <pre class="no-pretty-print">android update project -p . -s</pre>
+            </li>
+          </ol>
+        </li>
+      </ul>
+    </li>
+
+    <li>Compile the native code using the <code>ndk-build</code> command.
+      <pre class="no-pretty-print">
+cd &lt;ndk-root&gt;/samples/hello-jni
+&lt;ndk_root&gt;/ndk-build
+</pre>
+    </li>
+
+    <li>Build and install the application as you would a normal Android application. If you are
+    using Eclipse, run the application to build and install it on a device. If you are using Ant,
+    run the following commands from the project directory:
+      <pre class="no-pretty-print">
+ant debug
+adb install bin/HelloJni-debug.apk
+</pre>
+    </li>
+  </ol>
+
+  <p>When you run the application on the device, the string <code>Hello JNI</code> should appear on
+  your device. You can explore the rest of the samples that are located in the
+  <code>&lt;ndk-root&gt;/samples</code> directory for more examples on how to use the JNI.</p>
+
+  <h4 id="native-activity">Exploring the native-activity Sample Application</h4>
+
+  <p>The native-activity sample provided with the Android NDK demonstrates how to use the
+  android_native_app_glue static library. This static library makes creating a native activity
+  easier by providing you with an implementation that handles your callbacks in another thread, so
+  you do not have to worry about them blocking your main UI thread. The main parts of the sample
+  are described below:</p>
+
+  <ul>
+    <li>The familiar basic structure of an Android application (an <code>AndroidManifest.xml</code>
+    file, a <code>src/</code> and <code>res</code> directories). The AndroidManifest.xml declares
+    that the application is native and specifies the .so file of the native activity. See {@link
+    android.app.NativeActivity} for the source or see the
+    <code>&lt;ndk_root&gt;/platforms/samples/native-activity/AndroidManifest.xml</code> file.</li>
+
+    <li>A <code>jni/</code> directory contains the native activity, main.c, which uses the
+    <code>android_native_app_glue.h</code> interface to implement the activity. The Android.mk that
+    describes the native module to the build system also exists here.</li>
+  </ul>
+
+  <p>To build this sample application:</p>
+
+  <ol>
+    <li>Create a new project in Eclipse from the existing sample source or use the
+    <code>android</code> tool to update the project so it generates a build.xml file that you can
+    use to build the sample.
+
+      <ul>
+        <li>In Eclipse:
+
+          <ol type="a">
+            <li>Click <strong>File &gt; New Android Project...</strong></li>
+
+            <li>Select the <strong>Create project from existing source</strong> radio button.</li>
+
+            <li>Select any API level above Android 2.3.</li>
+
+            <li>In the <strong>Location</strong> field, click <strong>Browse...</strong> and select
+            the <code>&lt;ndk-root&gt;/samples/native-activity</code> directory.</li>
+
+            <li>Click <strong>Finish</strong>.</li>
+          </ol>
+        </li>
+
+        <li>On the command line:
+
+          <ol type="a">
+            <li>Change to the <code>&lt;ndk-root&gt;/samples/native-activity</code> directory.</li>
+
+            <li>Run the following command to generate a build.xml file:
+              <pre class="no-pretty-print">
+android update project -p . -s
+</pre>
+            </li>
+          </ol>
+        </li>
+      </ul>
+    </li>
+
+    <li>Compile the native code using the <code>ndk-build</code> command.
+      <pre class="no-pretty-print">
+cd &lt;ndk-root&gt;/platforms/samples/android-9/samples/native-activity
+&lt;ndk_root&gt;/ndk-build
+</pre>
+    </li>
+
+    <li>Build and install the application as you would a normal Android application. If you are
+    using Eclipse, run the application to build and install it on a device. If you are using Ant,
+    run the following commands in the project directory, then run the application on the device:
+      <pre class="no-pretty-print">
+ant debug
+adb install bin/NativeActivity-debug.apk
+</pre>
+    </li>
+  </ol>
+
 
   <h2 id="reqs">System and Software Requirements</h2>
 
@@ -313,7 +540,7 @@
     to users whose devices are capable of supporting your application. For example:
       <pre style="margin:1em;">
 &lt;manifest&gt;
-  ...
+  ... 
 <!-- Declare that the application uses the OpenGL ES 2.0 API and is designed
      to run only on devices that support OpenGL ES 2.0 or higher. -->
   &lt;uses-feature android:glEsVersion="0x00020000" /&gt;
@@ -331,4 +558,4 @@
     containing the library can be deployed only to devices running Android 2.2 (API level 8) or
     higher. To ensure compatibility, make sure that your application declares <code>&lt;uses-sdk
     android:minSdkVersion="8" /&gt;</code> attribute value in its manifest.</li>
-  </ul>
\ No newline at end of file
+  </ul>
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 6364d58..431aaa47 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -79,6 +79,14 @@
     // the camera only has a single output, and does not have
     // separate output for video frames and preview frame.
     void getSupportedVideoSizes(Vector<Size> &sizes) const;
+    // Retrieve the preferred preview size (width and height) in pixels
+    // for video recording. The given width and height must be one of
+    // supported preview sizes returned from getSupportedPreviewSizes().
+    // Must not be called if getSupportedVideoSizes() returns an empty
+    // Vector of Size. If getSupportedVideoSizes() returns an empty
+    // Vector of Size, the width and height returned from this method
+    // is invalid, and is "-1x-1".
+    void getPreferredPreviewSizeForVideo(int *width, int *height) const;
 
     void setPreviewFrameRate(int fps);
     int getPreviewFrameRate() const;
@@ -319,6 +327,21 @@
     // frameworks/base/include/camera/Camera.h.
     // Example: "176x144,1280x720". Read only.
     static const char KEY_SUPPORTED_VIDEO_SIZES[];
+
+    // Preferred preview frame size in pixels for video recording.
+    // The width and height must be one of the supported sizes retrieved
+    // via KEY_SUPPORTED_PREVIEW_SIZES. This key can be used only when
+    // getSupportedVideoSizes() does not return an empty Vector of Size.
+    // Camcorder applications are recommended to set the preview size
+    // to a value that is not larger than the preferred preview size.
+    // In other words, the product of the width and height of the
+    // preview size should not be larger than that of the preferred
+    // preview size. In addition, we recommend to choos a preview size
+    // that has the same aspect ratio as the resolution of video to be
+    // recorded.
+    // Example value: "800x600". Read only.
+    static const char KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[];
+
     // The image format for video frames. See CAMERA_MSG_VIDEO_FRAME in
     // frameworks/base/include/camera/Camera.h.
     // Example value: "yuv420sp" or PIXEL_FORMAT_XXX constants. Read only.
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 45b1b9a..e9a5f8c 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -75,6 +75,7 @@
 const char CameraParameters::KEY_VIDEO_FRAME_FORMAT[] = "video-frame-format";
 const char CameraParameters::KEY_VIDEO_SIZE[] = "video-size";
 const char CameraParameters::KEY_SUPPORTED_VIDEO_SIZES[] = "video-size-values";
+const char CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO[] = "preferred-preview-size-for-video";
 
 const char CameraParameters::TRUE[] = "true";
 const char CameraParameters::FOCUS_DISTANCE_INFINITY[] = "Infinity";
@@ -333,6 +334,14 @@
     parse_pair(p, width, height, 'x');
 }
 
+void CameraParameters::getPreferredPreviewSizeForVideo(int *width, int *height) const
+{
+    *width = *height = -1;
+    const char *p = get(KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO);
+    if (p == 0)  return;
+    parse_pair(p, width, height, 'x');
+}
+
 void CameraParameters::getSupportedPreviewSizes(Vector<Size> &sizes) const
 {
     const char *previewSizesStr = get(KEY_SUPPORTED_PREVIEW_SIZES);
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 0c48556..41309dc 100755
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -43,10 +43,8 @@
  *   <li>Frequency data: 8-bit magnitude FFT by using the {@link #getFft(byte[])} method</li>
  * </ul>
  * <p>The length of the capture can be retrieved or specified by calling respectively
- * {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. Note that the size of the FFT
- * is half of the specified capture size but both sides of the spectrum are returned yielding in a
- * number of bytes equal to the capture size. The capture size must be a power of 2 in the range
- * returned by {@link #getCaptureSizeRange()}.
+ * {@link #getCaptureSize()} and {@link #setCaptureSize(int)} methods. The capture size must be a
+ * power of 2 in the range returned by {@link #getCaptureSizeRange()}.
  * <p>In addition to the polling capture mode described above with {@link #getWaveForm(byte[])} and
  *  {@link #getFft(byte[])} methods, a callback mode is also available by installing a listener by
  *  use of the {@link #setDataCaptureListener(OnDataCaptureListener, int, boolean, boolean)} method.
@@ -333,11 +331,43 @@
         }
     }
     /**
-     * Returns a frequency capture of currently playing audio content. The capture is a 8-bit
-     * magnitude FFT. Note that the size of the FFT is half of the specified capture size but both
-     * sides of the spectrum are returned yielding in a number of bytes equal to the capture size.
-     * {@see #getCaptureSize()}.
+     * Returns a frequency capture of currently playing audio content.
      * <p>This method must be called when the Visualizer is enabled.
+     * <p>The capture is an 8-bit magnitude FFT, the frequency range covered being 0 (DC) to half of
+     * the sampling rate returned by {@link #getSamplingRate()}. The capture returns the real and
+     * imaginary parts of a number of frequency points equal to half of the capture size plus one.
+     * <p>Note: only the real part is returned for the first point (DC) and the last point
+     * (sampling frequency / 2).
+     * <p>The layout in the returned byte array is as follows:
+     * <ul>
+     *   <li> n is the capture size returned by getCaptureSize()</li>
+     *   <li> Rfk, Ifk are respectively  the real and imaginary parts of the kth frequency
+     *   component</li>
+     *   <li> If Fs is the sampling frequency retuned by getSamplingRate() the kth frequency is:
+     *   (k*Fs)/(n/2) </li>
+     * </ul>
+     * <table border="0" cellspacing="0" cellpadding="0">
+     * <tr><td>Index </p></td>
+     *     <td>0 </p></td>
+     *     <td>1 </p></td>
+     *     <td>2 </p></td>
+     *     <td>3 </p></td>
+     *     <td>4 </p></td>
+     *     <td>5 </p></td>
+     *     <td>... </p></td>
+     *     <td>n - 2 </p></td>
+     *     <td>n - 1 </p></td></tr>
+     * <tr><td>Data </p></td>
+     *     <td>Rf0 </p></td>
+     *     <td>Rf(n/2) </p></td>
+     *     <td>Rf1 </p></td>
+     *     <td>If1 </p></td>
+     *     <td>Rf2 </p></td>
+     *     <td>If2 </p></td>
+     *     <td>... </p></td>
+     *     <td>Rf(n-1)/2 </p></td>
+     *     <td>If(n-1)/2 </p></td></tr>
+     * </table>
      * @param fft array of bytes where the FFT should be returned
      * @return {@link #SUCCESS} in case of success,
      * {@link #ERROR_NO_MEMORY}, {@link #ERROR_INVALID_OPERATION} or {@link #ERROR_DEAD_OBJECT}
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index 1cc6a2a..a95a6c7 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -122,7 +122,9 @@
         mSurface.unlockCanvasAndPost(c);
         Surface.closeTransaction();
 
-        screenshot.recycle();
+        if (screenshot != null) {
+            screenshot.recycle();
+        }
     }
 
     static int deltaRotation(int oldRotation, int newRotation) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 5e49404..27ec1af 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -6848,6 +6848,8 @@
             }
 
             if (!mParentFrame.equals(pf)) {
+                //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
+                //        + " to " + pf);
                 mParentFrame.set(pf);
                 mContentChanged = true;
             }
@@ -7734,12 +7736,10 @@
          * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
          */
         boolean shouldAnimateMove() {
-            return mContentChanged && !mAnimating && !mLastHidden && !mDisplayFrozen
+            return mContentChanged && !mExiting && !mLastHidden && !mDisplayFrozen
                     && (mFrame.top != mLastFrame.top
                             || mFrame.left != mLastFrame.left)
-                    && (mAttachedWindow == null
-                            || (mAttachedWindow.mAnimation == null
-                                    && !mAttachedWindow.shouldAnimateMove()))
+                    && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
                     && mPolicy.isScreenOn();
         }
 
@@ -9223,6 +9223,7 @@
             if (!gone || !win.mHaveFrame) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
+                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
                         win.mContentChanged = false;
                     }
                     mPolicy.layoutWindowLw(win, win.mAttrs, null);
@@ -9257,6 +9258,7 @@
                 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
                         || !win.mHaveFrame) {
                     if (initial) {
+                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
                         win.mContentChanged = false;
                     }
                     mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
@@ -9455,7 +9457,6 @@
                             w.setAnimation(a);
                             animDw = w.mLastFrame.left - w.mFrame.left;
                             animDh = w.mLastFrame.top - w.mFrame.top;
-                            w.mContentChanged = false;
                         }
 
                         // Execute animation.
@@ -10242,6 +10243,11 @@
                     w.mOrientationChanging = false;
                 }
 
+                if (w.mContentChanged) {
+                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+                    w.mContentChanged = false;
+                }
+
                 final boolean canBeSeen = w.isDisplayedLw();
 
                 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index 18bd359..5c6aa99 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -29,8 +29,8 @@
 
 GravitySensor::GravitySensor(sensor_t const* list, size_t count)
     : mSensorDevice(SensorDevice::getInstance()),
-      mEnabled(false), mAccTime(0),
-      mLowPass(M_SQRT1_2, 1),
+      mAccTime(0),
+      mLowPass(M_SQRT1_2, 1.5f),
       mX(mLowPass), mY(mLowPass), mZ(mLowPass)
 
 {
@@ -71,15 +71,9 @@
     }
     return false;
 }
-
-bool GravitySensor::isEnabled() const {
-    return mEnabled;
-}
-
 status_t GravitySensor::activate(void* ident, bool enabled) {
     status_t err = mSensorDevice.activate(this, mAccelerometer.getHandle(), enabled);
     if (err == NO_ERROR) {
-        mEnabled = enabled;
         if (enabled) {
             mAccTime = 0;
         }
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index f9850b7..decfbb8 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -33,17 +33,15 @@
 class GravitySensor : public SensorInterface {
     SensorDevice& mSensorDevice;
     Sensor mAccelerometer;
-    bool mEnabled;
     double mAccTime;
 
     SecondOrderLowPassFilter mLowPass;
-    BiquadFilter mX, mY, mZ;
+    CascadedBiquadFilter mX, mY, mZ;
 
 public:
     GravitySensor(sensor_t const* list, size_t count);
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
-    virtual bool isEnabled() const;
     virtual status_t activate(void* ident, bool enabled);
     virtual status_t setDelay(void* ident, int handle, int64_t ns);
     virtual Sensor getSensor() const;
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index 2dc12dc..9425a92 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -53,10 +53,6 @@
     return result;
 }
 
-bool LinearAccelerationSensor::isEnabled() const {
-    return mGravitySensor.isEnabled();
-}
-
 status_t LinearAccelerationSensor::activate(void* ident, bool enabled) {
     return mGravitySensor.activate(ident, enabled);
 }
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
index ee918ce..c577086a 100644
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -40,7 +40,6 @@
             const sensors_event_t& event);
 public:
     LinearAccelerationSensor(sensor_t const* list, size_t count);
-    virtual bool isEnabled() const;
     virtual status_t activate(void* ident, bool enabled);
     virtual status_t setDelay(void* ident, int handle, int64_t ns);
     virtual Sensor getSensor() const;
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index 6f4b8be..418e7f8 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -34,7 +34,6 @@
 
 RotationVectorSensor::RotationVectorSensor(sensor_t const* list, size_t count)
     : mSensorDevice(SensorDevice::getInstance()),
-      mEnabled(false),
       mALowPass(M_SQRT1_2, 5.0f),
       mAX(mALowPass), mAY(mALowPass), mAZ(mALowPass),
       mMLowPass(M_SQRT1_2, 2.5f),
@@ -114,15 +113,18 @@
         float qx = sqrtf( clamp( Hx - My - Az + 1) * 0.25f );
         float qy = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f );
         float qz = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f );
-        const float n = 1.0f / (qw*qw + qx*qx + qy*qy + qz*qz);
-        qx = copysignf(qx, Ay - Mz) * n;
-        qy = copysignf(qy, Hz - Ax) * n;
-        qz = copysignf(qz, Mx - Hy) * n;
+        qx = copysignf(qx, Ay - Mz);
+        qy = copysignf(qy, Hz - Ax);
+        qz = copysignf(qz, Mx - Hy);
+
+        // this quaternion is guaranteed to be normalized, by construction
+        // of the rotation matrix.
 
         *outEvent = event;
         outEvent->data[0] = qx;
         outEvent->data[1] = qy;
         outEvent->data[2] = qz;
+        outEvent->data[3] = qw;
         outEvent->sensor = '_rov';
         outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
         return true;
@@ -130,19 +132,12 @@
     return false;
 }
 
-bool RotationVectorSensor::isEnabled() const {
-    return mEnabled;
-}
-
 status_t RotationVectorSensor::activate(void* ident, bool enabled) {
-    if (mEnabled != enabled) {
-        mSensorDevice.activate(this, mAcc.getHandle(), enabled);
-        mSensorDevice.activate(this, mMag.getHandle(), enabled);
-        mEnabled = enabled;
-        if (enabled) {
-            mMagTime = 0;
-            mAccTime = 0;
-        }
+    mSensorDevice.activate(this, mAcc.getHandle(), enabled);
+    mSensorDevice.activate(this, mMag.getHandle(), enabled);
+    if (enabled) {
+        mMagTime = 0;
+        mAccTime = 0;
     }
     return NO_ERROR;
 }
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index e7f28c9..b7c9512 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -34,7 +34,6 @@
     SensorDevice& mSensorDevice;
     Sensor mAcc;
     Sensor mMag;
-    bool mEnabled;
     float mMagData[3];
     double mAccTime;
     double mMagTime;
@@ -47,7 +46,6 @@
     RotationVectorSensor(sensor_t const* list, size_t count);
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
-    virtual bool isEnabled() const;
     virtual status_t activate(void* ident, bool enabled);
     virtual status_t setDelay(void* ident, int handle, int64_t ns);
     virtual Sensor getSensor() const;
diff --git a/services/sensorservice/SecondOrderLowPassFilter.cpp b/services/sensorservice/SecondOrderLowPassFilter.cpp
index e13e1362..eeb6d1e 100644
--- a/services/sensorservice/SecondOrderLowPassFilter.cpp
+++ b/services/sensorservice/SecondOrderLowPassFilter.cpp
@@ -67,4 +67,23 @@
 }
 
 // ---------------------------------------------------------------------------
+
+CascadedBiquadFilter::CascadedBiquadFilter(const SecondOrderLowPassFilter& s)
+    : mA(s), mB(s)
+{
+}
+
+float CascadedBiquadFilter::init(float x)
+{
+    mA.init(x);
+    mB.init(x);
+    return x;
+}
+
+float CascadedBiquadFilter::operator()(float x)
+{
+    return mB(mA(x));
+}
+
+// ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SecondOrderLowPassFilter.h b/services/sensorservice/SecondOrderLowPassFilter.h
index 998ca35b9..85698ca 100644
--- a/services/sensorservice/SecondOrderLowPassFilter.h
+++ b/services/sensorservice/SecondOrderLowPassFilter.h
@@ -54,6 +54,18 @@
     float operator()(float in);
 };
 
+/*
+ * Two cascaded biquad IIR filters
+ * (4-poles IIR)
+ */
+class CascadedBiquadFilter {
+    BiquadFilter mA;
+    BiquadFilter mB;
+public:
+    CascadedBiquadFilter(const SecondOrderLowPassFilter& s);
+    float init(float in);
+    float operator()(float in);
+};
 
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 73f85ba..f192913 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -137,9 +137,8 @@
 
     Mutex::Autolock _l(mLock);
     for (size_t i=0 ; i<size_t(count) ; i++) {
-        snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d / %d\n",
+        snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d\n",
                 list[i].handle,
-                mActivationCount.valueFor(list[i].handle).count,
                 mActivationCount.valueFor(list[i].handle).rates.size());
         result.append(buffer);
     }
@@ -167,22 +166,25 @@
     bool actuateHardware = false;
 
     Info& info( mActivationCount.editValueFor(handle) );
-    int32_t& count(info.count);
     if (enabled) {
-        if (android_atomic_inc(&count) == 0) {
-            actuateHardware = true;
-        }
         Mutex::Autolock _l(mLock);
         if (info.rates.indexOfKey(ident) < 0) {
             info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
+            actuateHardware = true;
+        } else {
+            // sensor was already activated for this ident
         }
     } else {
-        if (android_atomic_dec(&count) == 1) {
-            actuateHardware = true;
-        }
         Mutex::Autolock _l(mLock);
-        info.rates.removeItem(ident);
+        if (info.rates.removeItem(ident) >= 0) {
+            if (info.rates.size() == 0) {
+                actuateHardware = true;
+            }
+        } else {
+            // sensor wasn't enabled for this ident
+        }
     }
+
     if (actuateHardware) {
         err = mSensorDevice->activate(mSensorDevice, handle, enabled);
         if (enabled) {
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 63ecbcd..c19b2ce 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -40,8 +40,7 @@
     Mutex mLock; // protect mActivationCount[].rates
     // fixed-size array after construction
     struct Info {
-        Info() : count(0) { }
-        int32_t count;
+        Info() { }
         KeyedVector<void*, nsecs_t> rates;
     };
     DefaultKeyedVector<int, Info> mActivationCount;
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 93d23d9..be8eaff 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -32,7 +32,7 @@
 
 HardwareSensor::HardwareSensor(const sensor_t& sensor)
     : mSensorDevice(SensorDevice::getInstance()),
-      mSensor(&sensor), mEnabled(false)
+      mSensor(&sensor)
 {
     LOGI("%s", sensor.name);
 }
@@ -46,15 +46,8 @@
     return true;
 }
 
-bool HardwareSensor::isEnabled() const {
-    return mEnabled;
-}
-
-status_t HardwareSensor::activate(void* ident,bool enabled) {
-    status_t err = mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
-    if (err == NO_ERROR)
-        mEnabled = enabled;
-    return err;
+status_t HardwareSensor::activate(void* ident, bool enabled) {
+    return mSensorDevice.activate(ident, mSensor.getHandle(), enabled);
 }
 
 status_t HardwareSensor::setDelay(void* ident, int handle, int64_t ns) {
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index eebd563..084f2f5 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -38,7 +38,6 @@
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event) = 0;
 
-    virtual bool isEnabled() const = 0;
     virtual status_t activate(void* ident, bool enabled) = 0;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
     virtual Sensor getSensor() const = 0;
@@ -51,7 +50,6 @@
 {
     SensorDevice& mSensorDevice;
     Sensor mSensor;
-    bool mEnabled;
 
 public:
     HardwareSensor(const sensor_t& sensor);
@@ -61,7 +59,6 @@
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
 
-    virtual bool isEnabled() const;
     virtual status_t activate(void* ident, bool enabled);
     virtual status_t setDelay(void* ident, int handle, int64_t ns);
     virtual Sensor getSensor() const;
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 5b49305..719e5b4 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -700,6 +700,10 @@
             Log.d(LOG_TAG, this.toString());
         }
 
+        if (!canDial(phone)) {
+            throw new CallStateException("cannot dial in current state");
+        }
+
         if ( hasActiveFgCall() ) {
             Phone activePhone = getActiveFgCall().getPhone();
             boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
@@ -753,6 +757,32 @@
     }
 
     /**
+     * Phone can make a call only if ALL of the following are true:
+     *        - Phone is not powered off
+     *        - There's no incoming or waiting call
+     *        - There's available call slot in either foreground or background
+     *        - The foreground call is ACTIVE or IDLE or DISCONNECTED.
+     *          (We mainly need to make sure it *isn't* DIALING or ALERTING.)
+     * @param phone
+     * @return true if the phone can make a new call
+     */
+    private boolean canDial(Phone phone) {
+        int serviceState = phone.getServiceState().getState();
+        boolean hasRingingCall = hasActiveRingingCall();
+        boolean hasActiveCall = hasActiveFgCall();
+        boolean hasHoldingCall = hasActiveBgCall();
+        boolean allLinesTaken = hasActiveCall && hasHoldingCall;
+        Call.State fgCallState = getActiveFgCallState();
+
+        return (serviceState != ServiceState.STATE_POWER_OFF
+                && !hasRingingCall
+                && !allLinesTaken
+                && ((fgCallState == Call.State.ACTIVE)
+                    || (fgCallState == Call.State.IDLE)
+                    || (fgCallState == Call.State.DISCONNECTED)));
+            }
+
+    /**
      * Whether or not the phone can do explicit call transfer in the current
      * phone state--that is, one call holding and one call active.
      * @return true if the phone can do explicit call transfer; false otherwise.
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 82fcb6a..014901d 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -20,12 +20,13 @@
 import android.database.Cursor;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.provider.ContactsContract.PhoneLookup;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
-import static android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-import android.telephony.TelephonyManager;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.RawContacts;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.Log;
 
 
@@ -171,33 +172,17 @@
                     }
                 }
 
-                // Look for the person ID.
-
-                // TODO: This is pretty ugly now, see bug 2269240 for
-                // more details. The column to use depends upon the type of URL,
-                // for content://com.android.contacts/data/phones the "contact_id"
-                // column is used. For content/com.andriod.contacts/phone_lookup"
-                // the "_ID" column is used. If it is neither we leave columnIndex
-                // at -1 and no person ID will be available.
-
-                columnIndex = -1;
-                String url = contactRef.toString();
-                if (url.startsWith("content://com.android.contacts/data/phones")) {
-                    if (VDBG) Log.v(TAG,
-                        "URL path starts with 'data/phones' using RawContacts.CONTACT_ID");
-                    columnIndex = cursor.getColumnIndex(RawContacts.CONTACT_ID);
-                } else if (url.startsWith("content://com.android.contacts/phone_lookup")) {
-                    if (VDBG) Log.v(TAG,
-                        "URL path starts with 'phone_lookup' using PhoneLookup._ID");
-                    columnIndex = cursor.getColumnIndex(PhoneLookup._ID);
-                } else {
-                    Log.e(TAG, "Bad contact URL '" + url + "'");
-                }
-
+                // Look for the person_id.
+                columnIndex = getColumnIndexForPersonId(contactRef, cursor);
                 if (columnIndex != -1) {
                     info.person_id = cursor.getLong(columnIndex);
+                    if (VDBG) Log.v(TAG, "==> got info.person_id: " + info.person_id);
                 } else {
-                    Log.e(TAG, "person_id column missing for " + contactRef);
+                    // No valid columnIndex, so we can't look up person_id.
+                    Log.w(TAG, "Couldn't find person_id column for " + contactRef);
+                    // Watch out: this means that anything that depends on
+                    // person_id will be broken (like contact photo lookups in
+                    // the in-call UI, for example.)
                 }
 
                 // look for the custom ringtone, create from the string stored
@@ -411,30 +396,120 @@
     }
 
     /**
+     * Returns the column index to use to find the "person_id" field in
+     * the specified cursor, based on the contact URI that was originally
+     * queried.
+     *
+     * This is a helper function for the getCallerInfo() method that takes
+     * a Cursor.  Looking up the person_id is nontrivial (compared to all
+     * the other CallerInfo fields) since the column we need to use
+     * depends on what query we originally ran.
+     *
+     * Watch out: be sure to not do any database access in this method, since
+     * it's run from the UI thread (see comments below for more info.)
+     *
+     * @return the columnIndex to use (with cursor.getLong()) to get the
+     * person_id, or -1 if we couldn't figure out what colum to use.
+     *
+     * TODO: Add a unittest for this method.  (This is a little tricky to
+     * test, since we'll need a live contacts database to test against,
+     * preloaded with at least some phone numbers and SIP addresses.  And
+     * we'll probably have to hardcode the column indexes we expect, so
+     * the test might break whenever the contacts schema changes.  But we
+     * can at least make sure we handle all the URI patterns we claim to,
+     * and that the mime types match what we expect...)
+     */
+    private static int getColumnIndexForPersonId(Uri contactRef, Cursor cursor) {
+        // TODO: This is pretty ugly now, see bug 2269240 for
+        // more details. The column to use depends upon the type of URL:
+        // - content://com.android.contacts/data/phones ==> use the "contact_id" column
+        // - content://com.android.contacts/phone_lookup ==> use the "_ID" column
+        // - content://com.android.contacts/data ==> use the "contact_id" column
+        // If it's none of the above, we leave columnIndex=-1 which means
+        // that the person_id field will be left unset.
+        //
+        // The logic here *used* to be based on the mime type of contactRef
+        // (for example Phone.CONTENT_ITEM_TYPE would tell us to use the
+        // RawContacts.CONTACT_ID column).  But looking up the mime type requires
+        // a call to context.getContentResolver().getType(contactRef), which
+        // isn't safe to do from the UI thread since it can cause an ANR if
+        // the contacts provider is slow or blocked (like during a sync.)
+        //
+        // So instead, figure out the column to use for person_id by just
+        // looking at the URI itself.
+
+        if (VDBG) Log.v(TAG, "- getColumnIndexForPersonId: contactRef URI = '"
+                        + contactRef + "'...");
+        // Warning: Do not enable the following logging (due to ANR risk.)
+        // if (VDBG) Log.v(TAG, "- MIME type: "
+        //                 + context.getContentResolver().getType(contactRef));
+
+        String url = contactRef.toString();
+        String columnName = null;
+        if (url.startsWith("content://com.android.contacts/data/phones")) {
+            // Direct lookup in the Phone table.
+            // MIME type: Phone.CONTENT_ITEM_TYPE (= "vnd.android.cursor.item/phone_v2")
+            if (VDBG) Log.v(TAG, "'data/phones' URI; using RawContacts.CONTACT_ID");
+            columnName = RawContacts.CONTACT_ID;
+        } else if (url.startsWith("content://com.android.contacts/data")) {
+            // Direct lookup in the Data table.
+            // MIME type: Data.CONTENT_TYPE (= "vnd.android.cursor.dir/data")
+            if (VDBG) Log.v(TAG, "'data' URI; using Data.CONTACT_ID");
+            // (Note Data.CONTACT_ID and RawContacts.CONTACT_ID are equivalent.)
+            columnName = Data.CONTACT_ID;
+        } else if (url.startsWith("content://com.android.contacts/phone_lookup")) {
+            // Lookup in the PhoneLookup table, which provides "fuzzy matching"
+            // for phone numbers.
+            // MIME type: PhoneLookup.CONTENT_TYPE (= "vnd.android.cursor.dir/phone_lookup")
+            if (VDBG) Log.v(TAG, "'phone_lookup' URI; using PhoneLookup._ID");
+            columnName = PhoneLookup._ID;
+        } else {
+            Log.w(TAG, "Unexpected prefix for contactRef '" + url + "'");
+        }
+        int columnIndex = (columnName != null) ? cursor.getColumnIndex(columnName) : -1;
+        if (VDBG) Log.v(TAG, "==> Using column '" + columnName
+                        + "' (columnIndex = " + columnIndex + ") for person_id lookup...");
+        return columnIndex;
+    }
+
+    /**
      * @return a string debug representation of this instance.
      */
     public String toString() {
-        return new StringBuilder(384)
-                .append("\nname: " + /*name*/ "nnnnnn")
-                .append("\nphoneNumber: " + /*phoneNumber*/ "xxxxxxx")
-                .append("\ncnapName: " + cnapName)
-                .append("\nnumberPresentation: " + numberPresentation)
-                .append("\nnamePresentation: " + namePresentation)
-                .append("\ncontactExits: " + contactExists)
-                .append("\nphoneLabel: " + phoneLabel)
-                .append("\nnumberType: " + numberType)
-                .append("\nnumberLabel: " + numberLabel)
-                .append("\nphotoResource: " + photoResource)
-                .append("\nperson_id: " + person_id)
-                .append("\nneedUpdate: " + needUpdate)
-                .append("\ncontactRefUri: " + /*contactRefUri*/ "xxxxxxx")
-                .append("\ncontactRingtoneUri: " + /*contactRefUri*/ "xxxxxxx")
-                .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail)
-                .append("\ncachedPhoto: " + cachedPhoto)
-                .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent)
-                .append("\nemergency: " + mIsEmergency)
-                .append("\nvoicemail " + mIsVoiceMail)
-                .append("\ncontactExists " + contactExists)
-                .toString();
+        // Warning: never check in this file with VERBOSE_DEBUG = true
+        // because that will result in PII in the system log.
+        final boolean VERBOSE_DEBUG = false;
+
+        if (VERBOSE_DEBUG) {
+            return new StringBuilder(384)
+                    .append("\nname: " + name)
+                    .append("\nphoneNumber: " + phoneNumber)
+                    .append("\ncnapName: " + cnapName)
+                    .append("\nnumberPresentation: " + numberPresentation)
+                    .append("\nnamePresentation: " + namePresentation)
+                    .append("\ncontactExits: " + contactExists)
+                    .append("\nphoneLabel: " + phoneLabel)
+                    .append("\nnumberType: " + numberType)
+                    .append("\nnumberLabel: " + numberLabel)
+                    .append("\nphotoResource: " + photoResource)
+                    .append("\nperson_id: " + person_id)
+                    .append("\nneedUpdate: " + needUpdate)
+                    .append("\ncontactRefUri: " + contactRefUri)
+                    .append("\ncontactRingtoneUri: " + contactRefUri)
+                    .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail)
+                    .append("\ncachedPhoto: " + cachedPhoto)
+                    .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent)
+                    .append("\nemergency: " + mIsEmergency)
+                    .append("\nvoicemail " + mIsVoiceMail)
+                    .append("\ncontactExists " + contactExists)
+                    .toString();
+        } else {
+            return new StringBuilder(128)
+                    .append("CallerInfo { ")
+                    .append("name " + ((name == null) ? "null" : "non-null"))
+                    .append(", phoneNumber " + ((phoneNumber == null) ? "null" : "non-null"))
+                    .append(" }")
+                    .toString();
+        }
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 1f1338c..58a4cba 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -659,12 +659,6 @@
             @Override
             protected void onError(DisconnectCause cause) {
                 if (DEBUG) Log.d(LOG_TAG, "SIP error: " + cause);
-                if (mSipAudioCall.isInCall()
-                        && (cause != DisconnectCause.LOST_SIGNAL)) {
-                    // Don't end the call when in a call.
-                    return;
-                }
-
                 onCallEnded(cause);
             }
         };
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index c151251..dc44b25 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -25,7 +25,9 @@
                 <category android:name="android.intent.category.TEST" />
             </intent-filter>
         </activity>
-        <activity android:name="TestShellActivity" android:launchMode="singleTop"
+        <activity android:name="TestShellActivity"
+          android:launchMode="singleTop"
+          android:hardwareAccelerated="true"
           android:screenOrientation="portrait"
           android:theme="@android:style/Theme.Light"/>
         <activity android:name="ReliabilityTestActivity" android:screenOrientation="portrait"
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index 0859976..8a07767 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -440,8 +440,13 @@
 
             // draw the views
             // create the BufferedImage into which the layout will be rendered.
-            mImage = new BufferedImage(renderScreenWidth, renderScreenHeight - mScreenOffset,
-                    BufferedImage.TYPE_INT_ARGB);
+            if (mParams.getImageFactory() != null) {
+                mImage = mParams.getImageFactory().getImage(renderScreenWidth,
+                        renderScreenHeight - mScreenOffset);
+            } else {
+                mImage = new BufferedImage(renderScreenWidth, renderScreenHeight - mScreenOffset,
+                        BufferedImage.TYPE_INT_ARGB);
+            }
 
             if (mParams.isCustomBackgroundEnabled()) {
                 Graphics2D gc = mImage.createGraphics();
@@ -482,7 +487,7 @@
             // log it
             mParams.getLogger().error(t);
 
-            return new SceneResult("Unknown error during inflation.", t);
+            return new SceneResult("Unknown error during rendering.", t);
         }
     }
 
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 2fbaee2..30ddfb5 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -527,11 +527,14 @@
         }
 
         public void answerCall(String sessionDescription, int timeout) {
-            try {
-                processCommand(new MakeCallCommand(mPeerProfile,
-                        sessionDescription, timeout));
-            } catch (SipException e) {
-                onError(e);
+            synchronized (SipSessionGroup.this) {
+                if (mPeerProfile == null) return;
+                try {
+                    processCommand(new MakeCallCommand(mPeerProfile,
+                            sessionDescription, timeout));
+                } catch (SipException e) {
+                    onError(e);
+                }
             }
         }
 
@@ -540,14 +543,11 @@
         }
 
         public void changeCall(String sessionDescription, int timeout) {
-            doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription,
-                    timeout));
-        }
-
-        public void changeCallWithTimeout(
-                String sessionDescription, int timeout) {
-            doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription,
-                    timeout));
+            synchronized (SipSessionGroup.this) {
+                if (mPeerProfile == null) return;
+                doCommandAsync(new MakeCallCommand(mPeerProfile,
+                        sessionDescription, timeout));
+            }
         }
 
         public void register(int duration) {
@@ -1163,11 +1163,6 @@
             mProxy.onCallEstablished(this, mPeerSessionDescription);
         }
 
-        private void fallbackToPreviousInCall(int errorCode, String message) {
-            mState = SipSession.State.IN_CALL;
-            mProxy.onCallChangeFailed(this, errorCode, message);
-        }
-
         private void endCallNormally() {
             reset();
             mProxy.onCallEnded(this);
@@ -1191,12 +1186,7 @@
                     onRegistrationFailed(errorCode, message);
                     break;
                 default:
-                    if ((errorCode != SipErrorCode.DATA_CONNECTION_LOST)
-                            && mInCall) {
-                        fallbackToPreviousInCall(errorCode, message);
-                    } else {
-                        endCallOnError(errorCode, message);
-                    }
+                    endCallOnError(errorCode, message);
             }
         }