Merge "Implement SurfaceTexture frame-available callback." into honeycomb
diff --git a/api/11.xml b/api/11.xml
index 34a7a5c..1733652 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -20082,42 +20082,6 @@
 </parameter>
 </method>
 </class>
-<class name="DoubleEvaluator"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.animation.TypeEvaluator">
-</implements>
-<constructor name="DoubleEvaluator"
- type="android.animation.DoubleEvaluator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="evaluate"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fraction" type="float">
-</parameter>
-<parameter name="startValue" type="java.lang.Object">
-</parameter>
-<parameter name="endValue" type="java.lang.Object">
-</parameter>
-</method>
-</class>
 <class name="FloatEvaluator"
  extends="java.lang.Object"
  abstract="false"
diff --git a/api/current.xml b/api/current.xml
index 86c47f5..f7172f4 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -4250,6 +4250,17 @@
  visibility="public"
 >
 </field>
+<field name="fastScrollTextColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843611"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fastScrollThumbDrawable"
  type="int"
  transient="false"
@@ -5812,6 +5823,17 @@
  visibility="public"
 >
 </field>
+<field name="largeHeap"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843612"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="largeScreens"
  type="int"
  transient="false"
@@ -11462,6 +11484,28 @@
  visibility="public"
 >
 </field>
+<field name="notification_large_icon_height"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104902"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="notification_large_icon_width"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104901"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="thumbnail_height"
  type="int"
  transient="false"
@@ -20082,42 +20126,6 @@
 </parameter>
 </method>
 </class>
-<class name="DoubleEvaluator"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.animation.TypeEvaluator">
-</implements>
-<constructor name="DoubleEvaluator"
- type="android.animation.DoubleEvaluator"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="evaluate"
- return="java.lang.Object"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="fraction" type="float">
-</parameter>
-<parameter name="startValue" type="java.lang.Object">
-</parameter>
-<parameter name="endValue" type="java.lang.Object">
-</parameter>
-</method>
-</class>
 <class name="FloatEvaluator"
  extends="java.lang.Object"
  abstract="false"
@@ -58257,6 +58265,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_LARGE_HEAP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1048576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_PERSISTENT"
  type="int"
  transient="false"
@@ -61542,6 +61561,36 @@
  visibility="public"
 >
 </field>
+<field name="externalCacheSize"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="externalDataSize"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="externalMediaSize"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="packageName"
  type="java.lang.String"
  transient="false"
@@ -137521,6 +137570,34 @@
 <parameter name="params" type="Params...">
 </parameter>
 </method>
+<method name="execute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="runnable" type="java.lang.Runnable">
+</parameter>
+</method>
+<method name="executeOnExecutor"
+ return="android.os.AsyncTask&lt;Params, Progress, Result&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="exec" type="java.util.concurrent.Executor">
+</parameter>
+<parameter name="params" type="Params...">
+</parameter>
+</method>
 <method name="get"
  return="Result"
  abstract="false"
@@ -137653,6 +137730,16 @@
 <parameter name="values" type="Progress...">
 </parameter>
 </method>
+<field name="THREAD_POOL_EXECUTOR"
+ type="java.util.concurrent.ThreadPoolExecutor"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="AsyncTask.Status"
  extends="java.lang.Enum"
@@ -167298,6 +167385,38 @@
 <parameter name="dimX" type="int">
 </parameter>
 </method>
+<method name="setFromFieldPacker"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="fp" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
+<method name="setFromFieldPacker"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="xoff" type="int">
+</parameter>
+<parameter name="component_number" type="int">
+</parameter>
+<parameter name="fp" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
 <method name="syncAll"
  return="void"
  abstract="false"
@@ -173058,6 +173177,49 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="bindAllocation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="va" type="android.renderscript.Allocation">
+</parameter>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="invoke"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="slot" type="int">
+</parameter>
+</method>
+<method name="invoke"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="slot" type="int">
+</parameter>
+<parameter name="v" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
 <method name="setTimeZone"
  return="void"
  abstract="false"
@@ -173071,6 +173233,111 @@
 <parameter name="timeZone" type="java.lang.String">
 </parameter>
 </method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="v" type="float">
+</parameter>
+</method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="v" type="double">
+</parameter>
+</method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="v" type="int">
+</parameter>
+</method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="v" type="long">
+</parameter>
+</method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="v" type="boolean">
+</parameter>
+</method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="o" type="android.renderscript.BaseObj">
+</parameter>
+</method>
+<method name="setVar"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="v" type="android.renderscript.FieldPacker">
+</parameter>
+</method>
 </class>
 <class name="Script.Builder"
  extends="java.lang.Object"
@@ -173202,6 +173469,32 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<constructor name="ScriptC"
+ type="android.renderscript.ScriptC"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="id" type="int">
+</parameter>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+</constructor>
+<constructor name="ScriptC"
+ type="android.renderscript.ScriptC"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="rs" type="android.renderscript.RenderScript">
+</parameter>
+<parameter name="resources" type="android.content.res.Resources">
+</parameter>
+<parameter name="resourceID" type="int">
+</parameter>
+</constructor>
 </class>
 <class name="Short2"
  extends="java.lang.Object"
@@ -260231,7 +260524,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/animation/DoubleEvaluator.java b/core/java/android/animation/DoubleEvaluator.java
deleted file mode 100644
index e46eb37..0000000
--- a/core/java/android/animation/DoubleEvaluator.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.animation;
-
-/**
- * This evaluator can be used to perform type interpolation between <code>double</code> values.
- */
-public class DoubleEvaluator implements TypeEvaluator {
-    /**
-     * This function returns the result of linearly interpolating the start and end values, with
-     * <code>fraction</code> representing the proportion between the start and end values. The
-     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
-     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
-     * and <code>t</code> is <code>fraction</code>.
-     *
-     * @param fraction   The fraction from the starting to the ending values
-     * @param startValue The start value; should be of type <code>double</code> or
-     *                   <code>Double</code>
-     * @param endValue   The end value; should be of type <code>double</code> or
-     *                   <code>Double</code>
-     * @return A linear interpolation between the start and end values, given the
-     *         <code>fraction</code> parameter.
-     */
-    public Object evaluate(float fraction, Object startValue, Object endValue) {
-        double startDouble = ((Number) startValue).doubleValue();
-        return startDouble + fraction * (((Number) endValue).doubleValue() - startDouble);
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java
index 6fad4a68..4009f13 100644
--- a/core/java/android/animation/FloatKeyframeSet.java
+++ b/core/java/android/animation/FloatKeyframeSet.java
@@ -25,8 +25,8 @@
  * values between those keyframes for a given animation. The class internal to the animation
  * package because it is an implementation detail of how Keyframes are stored and used.
  *
- * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclasses for
- * int, long, and double, exists to speed up the getValue() method when there is no custom
+ * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for
+ * int, exists to speed up the getValue() method when there is no custom
  * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the
  * Object equivalents of these primitive types.</p>
  */
diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java
index 14a4e3a..5629c5e 100644
--- a/core/java/android/animation/IntKeyframeSet.java
+++ b/core/java/android/animation/IntKeyframeSet.java
@@ -25,8 +25,8 @@
  * values between those keyframes for a given animation. The class internal to the animation
  * package because it is an implementation detail of how Keyframes are stored and used.
  *
- * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclasses for
- * float, long, and double, exists to speed up the getValue() method when there is no custom
+ * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for
+ * float, exists to speed up the getValue() method when there is no custom
  * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the
  * Object equivalents of these primitive types.</p>
  */
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 3212cba..d038cd6 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -18,7 +18,6 @@
 
 import android.util.Log;
 
-import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 
@@ -29,8 +28,6 @@
  * are then determined internally and the animation will call these functions as necessary to
  * animate the property.
  *
- * <p class="note"><b>Note:</b> Instances of this class hold only a {@link WeakReference}
- * to the target object.</p>
  * @see #setPropertyName(String)
  *
  */
@@ -38,7 +35,7 @@
     private static final boolean DBG = false;
 
     // The target object on which the property exists, set in the constructor
-    private WeakReference<Object> mTargetRef;
+    private Object mTarget;
 
     private String mPropertyName;
 
@@ -105,9 +102,6 @@
      * @return Method the method associated with mPropertyName.
      */
     private Method getPropertyFunction(String prefix, Class valueType) {
-        final Object target = mTargetRef == null ? null : mTargetRef.get();
-        if (target == null) return null;
-
         // TODO: faster implementation...
         Method returnVal = null;
         String firstLetter = mPropertyName.substring(0, 1);
@@ -120,7 +114,7 @@
             args[0] = valueType;
         }
         try {
-            returnVal = target.getClass().getMethod(setterName, args);
+            returnVal = mTarget.getClass().getMethod(setterName, args);
         } catch (NoSuchMethodException e) {
             Log.e("ObjectAnimator",
                     "Couldn't find setter/getter for property " + mPropertyName + ": " + e);
@@ -140,14 +134,13 @@
      * A constructor that takes a single property name and set of values. This constructor is
      * used in the simple case of animating a single property.
      *
-     * @param target The object whose property is to be animated. It will be weakly referenced
-     * from the newly-created ObjectAnimator. This object should have a public method on it called
-     * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
-     * parameter.
+     * @param target The object whose property is to be animated. This object should
+     * have a public method on it called <code>setName()</code>, where <code>name</code> is
+     * the value of the <code>propertyName</code> parameter.
      * @param propertyName The name of the property being animated.
      */
     private ObjectAnimator(Object target, String propertyName) {
-        mTargetRef = new WeakReference<Object>(target);
+        mTarget = target;
         setPropertyName(propertyName);
     }
 
@@ -159,10 +152,9 @@
      * from the target object and property being animated). Therefore, there should typically
      * be two or more values.
      *
-     * @param target The object whose property is to be animated. It will be weakly referenced
-     * from the newly-created ObjectAnimator. This object should have a public method on it called
-     * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
-     * parameter.
+     * @param target The object whose property is to be animated. This object should
+     * have a public method on it called <code>setName()</code>, where <code>name</code> is
+     * the value of the <code>propertyName</code> parameter.
      * @param propertyName The name of the property being animated.
      * @param values A set of values that the animation will animate between over time.
      * @return A ValueAnimator object that is set up to animate between the given values.
@@ -181,10 +173,9 @@
      * from the target object and property being animated). Therefore, there should typically
      * be two or more values.
      *
-     * @param target The object whose property is to be animated. It will be weakly referenced
-     * from the newly-created ObjectAnimator. This object should have a public method on it called
-     * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
-     * parameter.
+     * @param target The object whose property is to be animated. This object should
+     * have a public method on it called <code>setName()</code>, where <code>name</code> is
+     * the value of the <code>propertyName</code> parameter.
      * @param propertyName The name of the property being animated.
      * @param values A set of values that the animation will animate between over time.
      * @return A ValueAnimator object that is set up to animate between the given values.
@@ -201,10 +192,10 @@
      * PropertyValuesHolder allows you to associate a set of animation values with a property
      * name.
      *
-     * @param target The object whose property is to be animated. It will be weakly referenced
-     * from the newly-created ObjectAnimator. This object should have public methods on it called
-     * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
-     * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
+     * @param target The object whose property is to be animated. This object should
+     * have public methods on it called <code>setName()</code>, where <code>name</code> is
+     * the name of the property passed in as the <code>propertyName</code> parameter for
+     * each of the PropertyValuesHolder objects.
      * @param propertyName The name of the property being animated.
      * @param evaluator A TypeEvaluator that will be called on each animation frame to
      * provide the ncessry interpolation between the Object values to derive the animated
@@ -227,10 +218,10 @@
      * PropertyValuesHolder allows you to associate a set of animation values with a property
      * name.
      *
-     * @param target The object whose property is to be animated. It will be weakly referenced
-     * from the newly-created ObjectAnimator. This object should have public methods on it called
-     * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
-     * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
+     * @param target The object whose property is to be animated. This object should
+     * have public methods on it called <code>setName()</code>, where <code>name</code> is
+     * the name of the property passed in as the <code>propertyName</code> parameter for
+     * each of the PropertyValuesHolder objects.
      * @param values A set of PropertyValuesHolder objects whose values will be animated
      * between over time.
      * @return A ValueAnimator object that is set up to animate between the given values.
@@ -238,7 +229,7 @@
     public static ObjectAnimator ofPropertyValuesHolder(Object target,
             PropertyValuesHolder... values) {
         ObjectAnimator anim = new ObjectAnimator();
-        anim.mTargetRef = new WeakReference<Object>(target);
+        anim.mTarget = target;
         anim.setValues(values);
         return anim;
     }
@@ -279,8 +270,7 @@
     @Override
     public void start() {
         if (DBG) {
-            final Object target = mTargetRef == null ? null : mTargetRef.get();
-            Log.d("ObjectAnimator", "Anim target, duration" + target + ", " + getDuration());
+            Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
             for (int i = 0; i < mValues.length; ++i) {
                 PropertyValuesHolder pvh = mValues[i];
                 ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
@@ -307,14 +297,11 @@
     @Override
     void initAnimation() {
         if (!mInitialized) {
-            final Object target = mTargetRef == null ? null : mTargetRef.get();
-            if (target == null) return;
-
             // mValueType may change due to setter/getter setup; do this before calling super.init(),
             // which uses mValueType to set up the default type evaluator.
             int numValues = mValues.length;
             for (int i = 0; i < numValues; ++i) {
-                mValues[i].setupSetterAndGetter(target);
+                mValues[i].setupSetterAndGetter(mTarget);
             }
             super.initAnimation();
         }
@@ -339,26 +326,23 @@
     /**
      * The target object whose property will be animated by this animation
      *
-     * @return The object being animated, or null if the object has been garbage collected.
+     * @return The object being animated
      */
     public Object getTarget() {
-        return mTargetRef == null ? null : mTargetRef.get();
+        return mTarget;
     }
 
     /**
-     * Sets the target object whose property will be animated by this animation. The target
-     * will be weakly referenced from this object.
+     * Sets the target object whose property will be animated by this animation
      *
      * @param target The object being animated
      */
     @Override
     public void setTarget(Object target) {
-        final Object currentTarget = mTargetRef == null ? null : mTargetRef.get();
-
-        if (currentTarget != target) {
-            mTargetRef = new WeakReference<Object>(target);
-            if (currentTarget != null && target != null
-                    && currentTarget.getClass() == target.getClass()) {
+        if (mTarget != target) {
+            final Object oldTarget = mTarget;
+            mTarget = target;
+            if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) {
                 return;
             }
             // New target type should cause re-initialization prior to starting
@@ -368,25 +352,19 @@
 
     @Override
     public void setupStartValues() {
-        final Object target = mTargetRef == null ? null : mTargetRef.get();
-        if (target == null) return;
-
         initAnimation();
         int numValues = mValues.length;
         for (int i = 0; i < numValues; ++i) {
-            mValues[i].setupStartValue(target);
+            mValues[i].setupStartValue(mTarget);
         }
     }
 
     @Override
     public void setupEndValues() {
-        final Object target = mTargetRef == null ? null : mTargetRef.get();
-        if (target == null) return;
-
         initAnimation();
         int numValues = mValues.length;
         for (int i = 0; i < numValues; ++i) {
-            mValues[i].setupEndValue(target);
+            mValues[i].setupEndValue(mTarget);
         }
     }
 
@@ -405,13 +383,9 @@
     @Override
     void animateValue(float fraction) {
         super.animateValue(fraction);
-
-        final Object target = mTargetRef == null ? null : mTargetRef.get();
-        if (target == null) return;
-
         int numValues = mValues.length;
         for (int i = 0; i < numValues; ++i) {
-            mValues[i].setAnimatedValue(target);
+            mValues[i].setAnimatedValue(mTarget);
         }
     }
 
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 0254924..0c30aad 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -67,10 +67,9 @@
     KeyframeSet mKeyframeSet = null;
 
 
-    // type evaluators for the three primitive types handled by this implementation
+    // type evaluators for the primitive types handled by this implementation
     private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
     private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
-    private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator();
 
     // We try several different types when searching for appropriate setter/getter functions.
     // The caller may have supplied values in a type that does not match the setter/getter
@@ -104,7 +103,7 @@
     /**
      * The type evaluator used to calculate the animated values. This evaluator is determined
      * automatically based on the type of the start/end objects passed into the constructor,
-     * but the system only knows about the primitive types int, double, and float. Any other
+     * but the system only knows about the primitive types int and float. Any other
      * type will need to set the evaluator to a custom evaluator for that type.
      */
     private TypeEvaluator mEvaluator;
@@ -501,7 +500,7 @@
      */
     void init() {
         if (mEvaluator == null) {
-            // We already handle int, float, long, double automatically, but not their Object
+            // We already handle int and float automatically, but not their Object
             // equivalents
             mEvaluator = (mValueType == Integer.class) ? sIntEvaluator :
                     (mValueType == Float.class) ? sFloatEvaluator :
@@ -509,7 +508,7 @@
         }
         if (mEvaluator != null) {
             // KeyframeSet knows how to evaluate the common types - only give it a custom
-            // evaulator if one has been set on this class
+            // evaluator if one has been set on this class
             mKeyframeSet.setEvaluator(mEvaluator);
         }
     }
@@ -520,7 +519,7 @@
      * desired. This may be important in cases where either the type of the values supplied
      * do not match the way that they should be interpolated between, or if the values
      * are of a custom type or one not currently understood by the animation system. Currently,
-     * only values of type float, double, and int (and their Object equivalents, Float, Double,
+     * only values of type float and int (and their Object equivalents: Float
      * and Integer) are  correctly interpolated; all other types require setting a TypeEvaluator.
      * @param evaluator
      */
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index f884473..5705057 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -143,10 +143,9 @@
     private static final TimeInterpolator sDefaultInterpolator =
             new AccelerateDecelerateInterpolator();
 
-    // type evaluators for the three primitive types handled by this implementation
+    // type evaluators for the primitive types handled by this implementation
     private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
     private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
-    private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator();
 
     /**
      * Used to indicate whether the animation is currently playing in reverse. This causes the
@@ -858,7 +857,7 @@
 
     /**
      * The type evaluator to be used when calculating the animated values of this animation.
-     * The system will automatically assign a float, int, or double evaluator based on the type
+     * The system will automatically assign a float or int evaluator based on the type
      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
      * are not one of these primitive types, or if different evaluation is desired (such as is
      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
@@ -1193,4 +1192,16 @@
     public static int getCurrentAnimationsCount() {
         return sAnimations.get().size();
     }
+
+    /**
+     * Clear all animations on this thread, without canceling or ending them.
+     * This should be used with caution.
+     *
+     * @hide
+     */
+    public static void clearAllAnimations() {
+        sAnimations.get().clear();
+        sPendingAnimations.get().clear();
+        sDelayedAnims.get().clear();
+    }
 }
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 44db50f..4eae14b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -77,6 +77,9 @@
      * This may be the same size as {@link #getMemoryClass()} on memory
      * constrained devices, or it may be significantly larger on devices with
      * a large amount of available RAM.
+     *
+     * <p>The is the size of the application's Dalvik heap if it has
+     * specified <code>android:largeHeap="true"</code> in its manifest.
      */
     public int getLargeMemoryClass() {
         return staticGetLargeMemoryClass();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index cc94aa0..db046ef 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -45,7 +45,6 @@
 import android.net.IConnectivityManager;
 import android.net.Proxy;
 import android.net.ProxyProperties;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
@@ -3463,6 +3462,10 @@
             mInstrumentation = new Instrumentation();
         }
 
+        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
+            // XXX bump up Dalvik's heap.
+        }
+
         // If the app is being launched for full backup or restore, bring it up in
         // a restricted environment with the base application class.
         Application app = data.info.makeApplication(data.restrictedBackupMode, null);
@@ -3471,7 +3474,7 @@
         List<ProviderInfo> providers = data.providers;
         if (providers != null) {
             installContentProviders(app, providers);
-            // For process that contain content providers, we want to
+            // For process that contains content providers, we want to
             // ensure that the JIT is enabled "at some point".
             mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
         }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index bb0ed6a..2d95781 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -270,19 +270,19 @@
     public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 1<<19;
     
     /**
-     * Value for {@link #flags}: this is true if the application has set
-     * its android:neverEncrypt to true, false otherwise. It is used to specify
-     * that this package specifically "opts-out" of a secured file system solution,
-     * and will always store its data in-the-clear.
-     *
-     * {@hide}
+     * Value for {@link #flags}: true when the application has requested a
+     * large heap for its processes.  Corresponds to
+     * {@link android.R.styleable#AndroidManifestApplication_largeHeap
+     * android:largeHeap}.
      */
-    public static final int FLAG_NEVER_ENCRYPT = 1<<30;
+    public static final int FLAG_LARGE_HEAP = 1<<20;
 
     /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
+     * NOTE: DO NOT CHANGE THIS VALUE!  It is saved in packages.xml.
+     * 
      * {@hide}
      */
     public static final int FLAG_FORWARD_LOCK = 1<<29;
@@ -298,7 +298,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_CANT_SAVE_STATE = 1<<27;
+    public static final int FLAG_CANT_SAVE_STATE = 1<<28;
 
     /**
      * Flags associated with the application.  Any combination of
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b2937ba..7676258 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -389,11 +389,15 @@
 
         XmlResourceParser parser = null;
         AssetManager assmgr = null;
+        Resources res = null;
         boolean assetError = true;
         try {
             assmgr = new AssetManager();
             int cookie = assmgr.addAssetPath(mArchiveSourcePath);
-            if(cookie != 0) {
+            if (cookie != 0) {
+                res = new Resources(assmgr, metrics, null);
+                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                        Build.VERSION.RESOURCES_SDK_INT);
                 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
                 assetError = false;
             } else {
@@ -403,7 +407,7 @@
             Log.w(TAG, "Unable to read AndroidManifest.xml of "
                     + mArchiveSourcePath, e);
         }
-        if(assetError) {
+        if (assetError) {
             if (assmgr != null) assmgr.close();
             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
             return null;
@@ -413,7 +417,6 @@
         Exception errorException = null;
         try {
             // XXXX todo: need to figure out correct configuration.
-            Resources res = new Resources(assmgr, metrics, null);
             pkg = parsePackage(res, parser, flags, errorText);
         } catch (Exception e) {
             errorException = e;
@@ -593,6 +596,8 @@
         AssetManager assmgr = null;
         try {
             assmgr = new AssetManager();
+            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                    Build.VERSION.RESOURCES_SDK_INT);
             int cookie = assmgr.addAssetPath(packageFilePath);
             parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
         } catch (Exception e) {
@@ -1574,9 +1579,9 @@
         }
 
         if (sa.getBoolean(
-                com.android.internal.R.styleable.AndroidManifestApplication_neverEncrypt,
+                com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
                 false)) {
-            ai.flags |= ApplicationInfo.FLAG_NEVER_ENCRYPT;
+            ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
         }
 
         String str;
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 9464321..28a2886 100755
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -19,20 +19,44 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Arrays;
-
 /**
  * implementation of PackageStats associated with a
  * application package.
  */
 public class PackageStats implements Parcelable {
+    /** Name of the package to which this stats applies. */
     public String packageName;
+
+    /** Size of the code (e.g., APK) */
     public long codeSize;
+
+    /**
+     * Size of the internal data size for the application. (e.g.,
+     * /data/data/<app>)
+     */
     public long dataSize;
+
+    /** Size of cache used by the application. (e.g., /data/data/<app>/cache) */
     public long cacheSize;
-    
+
+    /**
+     * Size of the external data used by the application (e.g.,
+     * <sdcard>/Android/data/<app>)
+     */
+    public long externalDataSize;
+
+    /**
+     * Size of the external cache used by the application (i.e., on the SD
+     * card). If this is a subdirectory of the data directory, this size will be
+     * subtracted out of the external data size.
+     */
+    public long externalCacheSize;
+
+    /** Size of the external media size used by the application. */
+    public long externalMediaSize;
+
     public static final Parcelable.Creator<PackageStats> CREATOR
-    = new Parcelable.Creator<PackageStats>() {
+            = new Parcelable.Creator<PackageStats>() {
         public PackageStats createFromParcel(Parcel in) {
             return new PackageStats(in);
         }
@@ -41,29 +65,49 @@
             return new PackageStats[size];
         }
     };
-    
+
     public String toString() {
-        return "PackageStats{"
-        + Integer.toHexString(System.identityHashCode(this))
-        + " " + packageName + "}";
+        final StringBuilder sb = new StringBuilder("PackageStats{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(" packageName=");
+        sb.append(packageName);
+        sb.append(",codeSize=");
+        sb.append(codeSize);
+        sb.append(",dataSize=");
+        sb.append(dataSize);
+        sb.append(",cacheSize=");
+        sb.append(cacheSize);
+        sb.append(",externalDataSize=");
+        sb.append(externalDataSize);
+        sb.append(",externalCacheSize=");
+        sb.append(externalCacheSize);
+        sb.append(",externalMediaSize=");
+        sb.append(externalMediaSize);
+        return sb.toString();
     }
-    
+
     public PackageStats(String pkgName) {
         packageName = pkgName;
     }
-    
+
     public PackageStats(Parcel source) {
         packageName = source.readString();
         codeSize = source.readLong();
         dataSize = source.readLong();
         cacheSize = source.readLong();
+        externalDataSize = source.readLong();
+        externalCacheSize = source.readLong();
+        externalMediaSize = source.readLong();
     }
-    
+
     public PackageStats(PackageStats pStats) {
         packageName = pStats.packageName;
         codeSize = pStats.codeSize;
         dataSize = pStats.dataSize;
         cacheSize = pStats.cacheSize;
+        externalDataSize = pStats.externalDataSize;
+        externalCacheSize = pStats.externalCacheSize;
+        externalMediaSize = pStats.externalMediaSize;
     }
 
     public int describeContents() {
@@ -75,5 +119,8 @@
         dest.writeLong(codeSize);
         dest.writeLong(dataSize);
         dest.writeLong(cacheSize);
+        dest.writeLong(externalDataSize);
+        dest.writeLong(externalCacheSize);
+        dest.writeLong(externalMediaSize);
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index b40a226..29bb004c 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -56,10 +56,6 @@
 
     private static final int ID_OTHER = 0x01000004;
 
-    // Use the current SDK version code.  If we are a development build,
-    // also allow the previous SDK version + 1.
-    private static final int sSdkVersion = Build.VERSION.SDK_INT
-            + ("REL".equals(Build.VERSION.CODENAME) ? 0 : 1);
     private static final Object mSync = new Object();
     private static Resources mSystem = null;
     
@@ -1427,14 +1423,14 @@
                     mConfiguration.touchscreen,
                     (int)(mMetrics.density*160), mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
-                    mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion);
+                    mConfiguration.screenLayout, mConfiguration.uiMode,
+                    Build.VERSION.RESOURCES_SDK_INT);
 
             clearDrawableCache(mDrawableCache, configChanges);
             clearDrawableCache(mColorDrawableCache, configChanges);
 
             mColorStateListCache.clear();
 
-
             flushLayoutCache();
         }
         synchronized (mSync) {
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index 9f7e31c..5a35eb0 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -16,9 +16,11 @@
 
 package android.os;
 
+import java.util.ArrayDeque;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CancellationException;
+import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.FutureTask;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -151,8 +153,6 @@
     private static final int MAXIMUM_POOL_SIZE = 128;
     private static final int KEEP_ALIVE = 1;
 
-    private static final BlockingQueue<Runnable> sWorkQueue =
-            new LinkedBlockingQueue<Runnable>(10);
 
     private static final ThreadFactory sThreadFactory = new ThreadFactory() {
         private final AtomicInteger mCount = new AtomicInteger(1);
@@ -162,8 +162,17 @@
         }
     };
 
-    private static final ThreadPoolExecutor sExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
-            MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue, sThreadFactory);
+    private static final BlockingQueue<Runnable> sPoolWorkQueue =
+            new LinkedBlockingQueue<Runnable>(10);
+
+    /**
+     * A {@link ThreadPoolExecutor} that can be used to execute tasks in parallel.
+     */
+    public static final ThreadPoolExecutor THREAD_POOL_EXECUTOR
+            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
+                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
+
+    private static final SerialExecutor sSerialExecutor = new SerialExecutor();
 
     private static final int MESSAGE_POST_RESULT = 0x1;
     private static final int MESSAGE_POST_PROGRESS = 0x2;
@@ -177,6 +186,32 @@
     
     private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
 
+    private static class SerialExecutor implements Executor {
+        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
+        Runnable mActive;
+
+        public synchronized void execute(final Runnable r) {
+            mTasks.offer(new Runnable() {
+                public void run() {
+                    try {
+                        r.run();
+                    } finally {
+                        scheduleNext();
+                    }
+                }
+            });
+            if (mActive == null) {
+                scheduleNext();
+            }
+        }
+
+        protected synchronized void scheduleNext() {
+            if ((mActive = mTasks.poll()) != null) {
+                THREAD_POOL_EXECUTOR.execute(mActive);
+            }
+        }
+    }
+
     /**
      * Indicates the current status of the task. Each status will be set only once
      * during the lifetime of a task.
@@ -433,7 +468,11 @@
 
     /**
      * Executes the task with the specified parameters. The task returns
-     * itself (this) so that the caller can keep a reference to it.
+     * itself (this) so that the caller can keep a reference to it.  The tasks
+     * started by all invocations of this method in a given process are run
+     * sequentially.  Call the executeOnExecutor(Executor,Params...)
+     * with a custom {@link Executor} to have finer grained control over how the
+     * tasks are run.
      *
      * This method must be invoked on the UI thread.
      *
@@ -445,6 +484,26 @@
      *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
      */
     public final AsyncTask<Params, Progress, Result> execute(Params... params) {
+        return executeOnExecutor(sSerialExecutor, params);
+    }
+
+    /**
+     * Executes the task with the specified parameters. The task returns
+     * itself (this) so that the caller can keep a reference to it.
+     *
+     * This method must be invoked on the UI thread.
+     *
+     * @param exec The executor to use.  {@link #THREAD_POOL_EXECUTOR} is available as a
+     *              convenient process-wide thread pool for tasks that are loosely coupled.
+     * @param params The parameters of the task.
+     *
+     * @return This instance of AsyncTask.
+     *
+     * @throws IllegalStateException If {@link #getStatus()} returns either
+     *         {@link AsyncTask.Status#RUNNING} or {@link AsyncTask.Status#FINISHED}.
+     */
+    public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
+            Params... params) {
         if (mStatus != Status.PENDING) {
             switch (mStatus) {
                 case RUNNING:
@@ -462,12 +521,20 @@
         onPreExecute();
 
         mWorker.mParams = params;
-        sExecutor.execute(mFuture);
+        exec.execute(mFuture);
 
         return this;
     }
 
     /**
+     * Schedules the {@link Runnable} in serial with the other AsyncTasks that were started
+     * with {@link #execute}.
+     */
+    public static void execute(Runnable runnable) {
+        sSerialExecutor.execute(runnable);
+    }
+
+    /**
      * This method can be invoked from {@link #doInBackground} to
      * publish updates on the UI thread while the background computation is
      * still running. Each call to this method will trigger the execution of
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 6e50e97..af7b28b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -100,6 +100,15 @@
          * a release build.
          */
         public static final String CODENAME = getString("ro.build.version.codename");
+
+        /**
+         * The SDK version to use when accessing resources.
+         * Use the current SDK version code.  If we are a development build,
+         * also allow the previous SDK version + 1.
+         * @hide
+         */
+        public static final int RESOURCES_SDK_INT = SDK_INT
+                + ("REL".equals(CODENAME) ? 0 : 1);
     }
 
     /**
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ad9e6863..e228537 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1780,7 +1780,7 @@
     }
 
     void dispatchDetachedFromWindow() {
-        if (mView != null) {
+        if (mView != null && mView.mAttachInfo != null) {
             mView.dispatchDetachedFromWindow();
         }
 
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 3d21048..472a335 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -22,7 +22,6 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -212,6 +211,9 @@
                 .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0);
         mIndicatorRight = a
                 .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0);
+        if (mIndicatorRight == 0) {
+            mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth();
+        }
         mChildIndicatorLeft = a.getDimensionPixelSize(
                 com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, CHILD_INDICATOR_INHERIT);
         mChildIndicatorRight = a.getDimensionPixelSize(
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index d4ef044..dfa94c7 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -56,7 +56,7 @@
     private static final int[] DEFAULT_STATES = new int[0];
 
     private static final int[] ATTRS = new int[] {
-        android.R.attr.textColorPrimary,
+        android.R.attr.fastScrollTextColor,
         android.R.attr.fastScrollThumbDrawable,
         android.R.attr.fastScrollTrackDrawable,
         android.R.attr.fastScrollPreviewBackgroundLeft,
@@ -64,7 +64,7 @@
         android.R.attr.fastScrollOverlayPosition
     };
 
-    private static final int PRIMARY_TEXT_COLOR = 0;
+    private static final int TEXT_COLOR = 0;
     private static final int THUMB_DRAWABLE = 1;
     private static final int TRACK_DRAWABLE = 2;
     private static final int PREVIEW_BACKGROUND_LEFT = 3;
@@ -247,7 +247,7 @@
         mPaint.setTextAlign(Paint.Align.CENTER);
         mPaint.setTextSize(mOverlaySize / 2);
 
-        ColorStateList textColor = ta.getColorStateList(PRIMARY_TEXT_COLOR);
+        ColorStateList textColor = ta.getColorStateList(TEXT_COLOR);
         int textColorNormal = textColor.getDefaultColor();
         mPaint.setColor(textColorNormal);
         mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 2c96056..585dcf2 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -83,6 +83,7 @@
     private CursorAdapter mSuggestionsAdapter;
     private View mSearchButton;
     private View mSubmitButton;
+    private View mSubmitArea;
     private ImageView mCloseButton;
     private View mSearchEditFrame;
     private View mVoiceButton;
@@ -92,6 +93,7 @@
     private boolean mQueryRefinement;
     private boolean mClearingFocus;
     private int mMaxWidth;
+    private boolean mVoiceButtonEnabled;
 
     private SearchableInfo mSearchable;
 
@@ -187,6 +189,7 @@
         mQueryTextView.setSearchView(this);
 
         mSearchEditFrame = findViewById(R.id.search_edit_frame);
+        mSubmitArea = findViewById(R.id.submit_area);
         mSubmitButton = findViewById(R.id.search_go_btn);
         mCloseButton = (ImageView) findViewById(R.id.search_close_btn);
         mVoiceButton = findViewById(R.id.search_voice_btn);
@@ -248,6 +251,8 @@
         if (mSearchable != null) {
             updateSearchAutoComplete();
         }
+        // Cache the voice search capability
+        mVoiceButtonEnabled = hasVoiceSearch();
         updateViewsVisibility(mIconifiedByDefault);
     }
 
@@ -513,18 +518,55 @@
         mIconified = collapsed;
         // Visibility of views that are visible when collapsed
         final int visCollapsed = collapsed ? VISIBLE : GONE;
-        // Visibility of views that are visible when expanded
-        final int visExpanded = collapsed ? GONE : VISIBLE;
         // Is there text in the query
         final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText());
 
         mSearchButton.setVisibility(visCollapsed);
-        mSubmitButton.setVisibility(mSubmitButtonEnabled && hasText ? visExpanded : GONE);
-        mSearchEditFrame.setVisibility(visExpanded);
+        updateSubmitButton(hasText);
+        mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE);
         updateCloseButton();
         updateVoiceButton(!hasText);
+        updateSubmitArea();
         requestLayout();
-        invalidate();
+    }
+
+    private boolean hasVoiceSearch() {
+        if (mSearchable != null && mSearchable.getVoiceSearchEnabled()) {
+            Intent testIntent = null;
+            if (mSearchable.getVoiceSearchLaunchWebSearch()) {
+                testIntent = mVoiceWebSearchIntent;
+            } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
+                testIntent = mVoiceAppSearchIntent;
+            }
+            if (testIntent != null) {
+                ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent,
+                        PackageManager.MATCH_DEFAULT_ONLY);
+                return ri != null;
+            }
+        }
+        return false;
+    }
+
+    private boolean isSubmitAreaEnabled() {
+        return (mSubmitButtonEnabled || mVoiceButtonEnabled) && !isIconified();
+    }
+
+    private void updateSubmitButton(boolean hasText) {
+        mSubmitButton.setVisibility(
+                isSubmitAreaEnabled() ? (hasText ? VISIBLE : INVISIBLE) : GONE);
+    }
+
+    private void updateSubmitArea() {
+        int visibility = GONE;
+        if (isSubmitAreaEnabled()) {
+            if (mSubmitButton.getVisibility() == VISIBLE
+                    || mVoiceButton.getVisibility() == VISIBLE) {
+                visibility = VISIBLE;
+            } else {
+                visibility = INVISIBLE;
+            }
+        }
+        mSubmitArea.setVisibility(visibility);
     }
 
     private void updateCloseButton() {
@@ -790,22 +832,14 @@
      * be visible - i.e., if the user has typed a query, remove the voice button.
      */
     private void updateVoiceButton(boolean empty) {
-        int visibility = View.GONE;
-        if (mSearchable != null && mSearchable.getVoiceSearchEnabled() && empty
-                && !isIconified()) {
-            Intent testIntent = null;
-            if (mSearchable.getVoiceSearchLaunchWebSearch()) {
-                testIntent = mVoiceWebSearchIntent;
-            } else if (mSearchable.getVoiceSearchLaunchRecognizer()) {
-                testIntent = mVoiceAppSearchIntent;
-            }
-            if (testIntent != null) {
-                ResolveInfo ri = getContext().getPackageManager().resolveActivity(testIntent,
-                        PackageManager.MATCH_DEFAULT_ONLY);
-                if (ri != null) {
-                    visibility = View.VISIBLE;
-                }
-            }
+        // If the voice button is to be visible, show it
+        // Else, make it gone if the submit button is enabled, otherwise invisible to
+        // avoid losing the real-estate
+        int visibility = mSubmitButtonEnabled ? GONE : INVISIBLE;
+
+        if (mVoiceButtonEnabled && !isIconified() && empty) {
+            visibility = VISIBLE;
+            mSubmitButton.setVisibility(GONE);
         }
         mVoiceButton.setVisibility(visibility);
     }
@@ -825,12 +859,11 @@
         CharSequence text = mQueryTextView.getText();
         boolean hasText = !TextUtils.isEmpty(text);
         if (isSubmitButtonEnabled()) {
-            mSubmitButton.setVisibility(hasText ? VISIBLE : GONE);
-            requestLayout();
-            invalidate();
+            updateSubmitButton(hasText);
         }
         updateVoiceButton(!hasText);
         updateCloseButton();
+        updateSubmitArea();
         if (mOnQueryChangeListener != null) {
             mOnQueryChangeListener.onQueryTextChanged(newText.toString());
         }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 264af71..2c10077 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1,5 +1,4 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
+/* Copyright (C) 2010 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -209,22 +208,19 @@
             }
         }
 
-        if (fromIndex == -1 && toIndex == NUM_ACTIVE_VIEWS -1) {
+        if (fromIndex == -1 && toIndex == getNumActiveViews() -1) {
             // Fade item in
             if (view.getAlpha() == 1) {
                 view.setAlpha(0);
             }
-            view.setScaleX(1 - PERSPECTIVE_SCALE_FACTOR);
-            view.setScaleY(1 - PERSPECTIVE_SCALE_FACTOR);
-            view.setTranslationX(mPerspectiveShiftX);
-            view.setTranslationY(0);
+            transformViewAtIndex(toIndex, view, false);
             view.setVisibility(VISIBLE);
 
             alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
             alphaOa.setDuration(FADE_IN_ANIMATION_DURATION);
             if (oldAlphaOa != null) oldAlphaOa.cancel();
             alphaOa.start();
-            view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation, 
+            view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
                     new WeakReference<ObjectAnimator>(alphaOa));
         } else if (fromIndex == 0 && toIndex == 1) {
             // Slide item in
@@ -270,7 +266,7 @@
             alphaOa.setDuration(STACK_RELAYOUT_DURATION);
             if (oldAlphaOa != null) oldAlphaOa.cancel();
             alphaOa.start();
-            view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation, 
+            view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
                     new WeakReference<ObjectAnimator>(alphaOa));
         }
 
@@ -284,16 +280,20 @@
         final float maxPerspectiveShiftY = mPerspectiveShiftY;
         final float maxPerspectiveShiftX = mPerspectiveShiftX;
 
-        index = mMaxNumActiveViews - index - 1;
-        if (index == mMaxNumActiveViews - 1) index--;
+        if (mStackMode == ITEMS_SLIDE_DOWN) {
+            index = mMaxNumActiveViews - index - 1;
+            if (index == mMaxNumActiveViews - 1) index--;
+        } else {
+            index--;
+            if (index < 0) index++;
+        }
 
         float r = (index * 1.0f) / (mMaxNumActiveViews - 2);
 
         final float scale = 1 - PERSPECTIVE_SCALE_FACTOR * (1 - r);
 
-        int stackDirection = (mStackMode == ITEMS_SLIDE_UP) ? 1 : -1;
-        float perspectiveTranslationY = -stackDirection * r * maxPerspectiveShiftY;
-        float scaleShiftCorrectionY = stackDirection * (1 - scale) *
+        float perspectiveTranslationY = r * maxPerspectiveShiftY;
+        float scaleShiftCorrectionY = (scale - 1) *
                 (getMeasuredHeight() * (1 - PERSPECTIVE_SHIFT_FACTOR_Y) / 2.0f);
         final float transY = perspectiveTranslationY + scaleShiftCorrectionY;
 
@@ -302,7 +302,7 @@
                 (getMeasuredWidth() * (1 - PERSPECTIVE_SHIFT_FACTOR_X) / 2.0f);
         final float transX = perspectiveTranslationX + scaleShiftCorrectionX;
 
-        // If this view is currently being animated for a certain position, we need to cancel 
+        // If this view is currently being animated for a certain position, we need to cancel
         // this animation so as not to interfere with the new transformation.
         Object tag = view.getTag(com.android.internal.R.id.viewAnimation);
         if (tag instanceof WeakReference<?>) {
@@ -515,11 +515,12 @@
 
     private void beginGestureIfNeeded(float deltaY) {
         if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) {
-            int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN;
+            final int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN;
             cancelLongPress();
             requestDisallowInterceptTouchEvent(true);
 
             if (mAdapter == null) return;
+            final int adapterCount = mAdapter.getCount();
 
             int activeIndex;
             if (mStackMode == ITEMS_SLIDE_UP) {
@@ -528,13 +529,20 @@
                 activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0;
             }
 
+            boolean endOfStack = mLoopViews && adapterCount == 1 && 
+                ((mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_UP) ||
+                 (mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_DOWN));
+            boolean beginningOfStack = mLoopViews && adapterCount == 1 && 
+                ((mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_UP) ||
+                 (mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_DOWN));
+
             int stackMode;
-            if (mLoopViews) {
+            if (mLoopViews && !beginningOfStack && !endOfStack) {
                 stackMode = StackSlider.NORMAL_MODE;
-            } else if (mCurrentWindowStartUnbounded + activeIndex == -1) {
+            } else if (mCurrentWindowStartUnbounded + activeIndex == -1 || beginningOfStack) {
                 activeIndex++;
                 stackMode = StackSlider.BEGINNING_OF_STACK_MODE;
-            } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount() - 1) {
+            } else if (mCurrentWindowStartUnbounded + activeIndex == adapterCount - 1 || endOfStack) {
                 stackMode = StackSlider.END_OF_STACK_MODE;
             } else {
                 stackMode = StackSlider.NORMAL_MODE;
@@ -989,6 +997,11 @@
     @Override
     public void advance() {
         long timeSinceLastInteraction = System.currentTimeMillis() - mLastInteractionTime;
+
+        if (mAdapter == null) return;
+        final int adapterCount = mAdapter.getCount();
+        if (adapterCount == 1 && mLoopViews) return;
+
         if (mSwipeGestureType == GESTURE_NONE &&
                 timeSinceLastInteraction > MIN_TIME_BETWEEN_INTERACTION_AND_AUTOADVANCE) {
             showNext();
@@ -1266,4 +1279,4 @@
             mask.recycle();
         }
     }
-}
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 8e491e9..8825c02 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -20,7 +20,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.Gravity;
 import android.view.View;
@@ -44,6 +43,7 @@
     private MenuBuilder mMenu;
 
     private int mMaxItems;
+    private int mWidthLimit;
     private boolean mReserveOverflow;
     private OverflowMenuButton mOverflowButton;
     private MenuPopupHelper mOverflowPopup;
@@ -91,6 +91,7 @@
         final int screen = res.getConfiguration().screenLayout;
         mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
                 Configuration.SCREENLAYOUT_SIZE_XLARGE;
+        mWidthLimit = res.getDisplayMetrics().widthPixels / 2;
         
         TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
         mDivider = a.getDrawable(com.android.internal.R.styleable.Theme_dividerVertical);
@@ -108,6 +109,7 @@
         mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
                 Configuration.SCREENLAYOUT_SIZE_XLARGE;
         mMaxItems = getMaxActionButtons();
+        mWidthLimit = getResources().getDisplayMetrics().widthPixels / 2;
         if (mMenu != null) {
             mMenu.setMaxActionItems(mMaxItems);
             updateChildren(false);
@@ -172,6 +174,19 @@
     }
 
     public void initialize(MenuBuilder menu, int menuType) {
+        int width = mWidthLimit;
+        if (mReserveOverflow) {
+            if (mOverflowButton == null) {
+                OverflowMenuButton button = new OverflowMenuButton(mContext);
+                mOverflowButton = button;
+            }
+            final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+            mOverflowButton.measure(spec, spec);
+            width -= mOverflowButton.getMeasuredWidth();
+        }
+
+        menu.setActionWidthLimit(width);
+
         menu.setMaxActionItems(mMaxItems);
         mMenu = menu;
         updateChildren(true);
@@ -219,9 +234,11 @@
                 if (itemCount > 0) {
                     addView(makeDividerView(), makeDividerLayoutParams());
                 }
-                OverflowMenuButton button = new OverflowMenuButton(mContext);
-                addView(button);
-                mOverflowButton = button;
+                if (mOverflowButton == null) {
+                    OverflowMenuButton button = new OverflowMenuButton(mContext);
+                    mOverflowButton = button;
+                }
+                addView(mOverflowButton);
             } else {
                 mOverflowButton = null;
             }
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 830c2c1..588b10c 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -27,9 +27,10 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcelable;
-import android.util.Log;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.TypedValue;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.ContextThemeWrapper;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -38,8 +39,8 @@
 import android.view.MenuItem;
 import android.view.SubMenu;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 
@@ -164,6 +165,10 @@
      */
     private int mMaxActionItems;
     /**
+     * The total width limit in pixels for all action items within a menu
+     */
+    private int mActionWidthLimit;
+    /**
      * Whether or not the items (or any one item's action state) has changed since it was
      * last fetched.
      */
@@ -208,6 +213,11 @@
     
     private boolean mOptionalIconsVisible = false;
 
+    private ViewGroup mMeasureActionButtonParent;
+
+    // Group IDs that have been added as actions - used temporarily, allocated here for reuse.
+    private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
+
     private static int getAlertDialogTheme(Context context) {
         TypedValue outValue = new TypedValue();
         context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
@@ -1035,6 +1045,44 @@
         return mVisibleItems;
     }
     
+    /**
+     * @return A fake action button parent view for obtaining child views.
+     */
+    private ViewGroup getMeasureActionButtonParent() {
+        if (mMeasureActionButtonParent == null) {
+            mMeasureActionButtonParent = (ViewGroup) mMenuTypes[TYPE_ACTION_BUTTON].getInflater()
+                    .inflate(LAYOUT_RES_FOR_TYPE[TYPE_ACTION_BUTTON], null, false);
+        }
+        return mMeasureActionButtonParent;
+    }
+
+    /**
+     * This method determines which menu items get to be 'action items' that will appear
+     * in an action bar and which items should be 'overflow items' in a secondary menu.
+     * The rules are as follows:
+     *
+     * <p>Items are considered for inclusion in the order specified within the menu.
+     * There is a limit of mMaxActionItems as a total count, optionally including the overflow
+     * menu button itself. This is a soft limit; if an item shares a group ID with an item
+     * previously included as an action item, the new item will stay with its group and become
+     * an action item itself even if it breaks the max item count limit. This is done to
+     * limit the conceptual complexity of the items presented within an action bar. Only a few
+     * unrelated concepts should be presented to the user in this space, and groups are treated
+     * as a single concept.
+     *
+     * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
+     * limit may be broken by a single item that exceeds the remaining space, but no further
+     * items may be added. If an item that is part of a group cannot fit within the remaining
+     * measured width, the entire group will be demoted to overflow. This is done to ensure room
+     * for navigation and other affordances in the action bar as well as reduce general UI clutter.
+     *
+     * <p>The space freed by demoting a full group cannot be consumed by future menu items.
+     * Once items begin to overflow, all future items become overflow items as well. This is
+     * to avoid inadvertent reordering that may break the app's intended design.
+     *
+     * @param reserveActionOverflow true if an overflow button should consume one space
+     *                              in the available item count
+     */
     private void flagActionItems(boolean reserveActionOverflow) {
         if (reserveActionOverflow != mReserveActionOverflow) {
             mReserveActionOverflow = reserveActionOverflow;
@@ -1048,9 +1096,13 @@
         final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
         final int itemsSize = visibleItems.size();
         int maxActions = mMaxActionItems;
+        int widthLimit = mActionWidthLimit;
+        final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final ViewGroup parent = getMeasureActionButtonParent();
 
         int requiredItems = 0;
         int requestedItems = 0;
+        int firstActionWidth = 0;
         boolean hasOverflow = false;
         for (int i = 0; i < itemsSize; i++) {
             MenuItemImpl item = visibleItems.get(i);
@@ -1070,12 +1122,68 @@
         }
         maxActions -= requiredItems;
 
+        final SparseBooleanArray seenGroups = mActionButtonGroups;
+        seenGroups.clear();
+
         // Flag as many more requested items as will fit.
         for (int i = 0; i < itemsSize; i++) {
             MenuItemImpl item = visibleItems.get(i);
-            if (item.requestsActionButton()) {
-                item.setIsActionButton(maxActions > 0);
+
+            if (item.requiresActionButton()) {
+                View v = item.getActionView();
+                if (v == null) {
+                    v = item.getItemView(TYPE_ACTION_BUTTON, parent);
+                }
+                v.measure(querySpec, querySpec);
+                final int measuredWidth = v.getMeasuredWidth();
+                widthLimit -= measuredWidth;
+                if (firstActionWidth == 0) {
+                    firstActionWidth = measuredWidth;
+                }
+                final int groupId = item.getGroupId();
+                if (groupId != 0) {
+                    seenGroups.put(groupId, true);
+                }
+            } else if (item.requestsActionButton()) {
+                // Items in a group with other items that already have an action slot
+                // can break the max actions rule, but not the width limit.
+                final int groupId = item.getGroupId();
+                final boolean inGroup = seenGroups.get(groupId);
+                boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0;
                 maxActions--;
+
+                if (isAction) {
+                    View v = item.getActionView();
+                    if (v == null) {
+                        v = item.getItemView(TYPE_ACTION_BUTTON, parent);
+                    }
+                    v.measure(querySpec, querySpec);
+                    final int measuredWidth = v.getMeasuredWidth();
+                    widthLimit -= measuredWidth;
+                    if (firstActionWidth == 0) {
+                        firstActionWidth = measuredWidth;
+                    }
+
+                    // Did this push the entire first item past halfway?
+                    if (widthLimit + firstActionWidth <= 0) {
+                        isAction = false;
+                    }
+                }
+
+                if (isAction && groupId != 0) {
+                    seenGroups.put(groupId, true);
+                } else if (inGroup) {
+                    // We broke the width limit. Demote the whole group, they all overflow now.
+                    seenGroups.put(groupId, false);
+                    for (int j = 0; j < i; j++) {
+                        MenuItemImpl areYouMyGroupie = visibleItems.get(j);
+                        if (areYouMyGroupie.getGroupId() == groupId) {
+                            areYouMyGroupie.setIsActionButton(false);
+                        }
+                    }
+                }
+
+                item.setIsActionButton(isAction);
             }
         }
 
@@ -1108,6 +1216,11 @@
         mIsActionItemsStale = true;
     }
 
+    void setActionWidthLimit(int widthLimit) {
+        mActionWidthLimit = widthLimit;
+        mIsActionItemsStale = true;
+    }
+
     public void clearHeader() {
         mHeaderIcon = null;
         mHeaderTitle = null;
diff --git a/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml b/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml
index 8a46546..4f5beff 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_glogin_unlock.xml
@@ -27,12 +27,11 @@
         android:layout_height="0px"
         android:layout_weight="1"
         android:layout_above="@+id/emergencyCall">
-        <RelativeLayout 
+        <RelativeLayout
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-                >
-        
-            <TextView 
+            android:layout_height="match_parent">
+
+            <TextView
                 android:id="@+id/topHeader"
                 android:layout_width="match_parent"
                 android:layout_height="64dip"
@@ -43,7 +42,7 @@
                 android:drawableLeft="@drawable/ic_lock_idle_lock"
                 android:drawablePadding="5dip"
                 />
-        
+
             <!-- spacer below header -->
             <View
                 android:id="@+id/spacerTop"
@@ -51,7 +50,7 @@
                 android:layout_height="1dip"
                 android:layout_below="@id/topHeader"
                 android:background="@drawable/divider_horizontal_dark"/>
-        
+
             <TextView
                 android:id="@+id/instructions"
                 android:layout_width="match_parent"
@@ -62,7 +61,7 @@
                 android:textAppearance="?android:attr/textAppearanceSmall"
                 android:text="@android:string/lockscreen_glogin_instructions"
                 />
-        
+
             <EditText
                 android:id="@+id/login"
                 android:layout_width="match_parent"
@@ -74,7 +73,7 @@
                 android:hint="@android:string/lockscreen_glogin_username_hint"
                 android:inputType="textEmailAddress"
                 />
-        
+
             <EditText
                 android:id="@+id/password"
                 android:layout_width="match_parent"
@@ -88,11 +87,11 @@
                 android:nextFocusRight="@+id/ok"
                 android:nextFocusDown="@+id/ok"
                 />
-        
+
             <!-- ok below password, aligned to right of screen -->
             <Button
                 android:id="@+id/ok"
-                android:layout_width="85dip"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_below="@id/password"
                 android:layout_marginTop="7dip"
@@ -100,10 +99,10 @@
                 android:layout_alignParentRight="true"
                 android:text="@android:string/lockscreen_glogin_submit_button"
                 />
-        
+
         </RelativeLayout>
     </ScrollView>
-    
+
     <!-- spacer above emergency call -->
     <View
         android:layout_width="match_parent"
@@ -121,6 +120,7 @@
         android:drawableLeft="@drawable/ic_emergency"
         android:drawablePadding="8dip"
         android:text="@android:string/lockscreen_emergency_call"
+        android:visibility="gone"
         />
 
 </LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 1002c4b..57eb9c7 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -27,7 +27,6 @@
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:minHeight="64dip"
         android:orientation="vertical">
         <ImageView android:id="@+id/titleDividerTop"
             android:layout_width="match_parent"
@@ -42,9 +41,8 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:gravity="center_vertical"
-            android:layout_marginTop="8dip"
-            android:layout_marginBottom="8dip"
+            android:gravity="center_vertical|left"
+            android:minHeight="60dip"
             android:layout_marginLeft="32dip"
             android:layout_marginRight="32dip">
             <ImageView android:id="@+id/icon"
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 46d0341..0a7cd3c 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -100,8 +100,8 @@
                 android:id="@+id/search_close_btn"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:paddingLeft="4dip"
-                android:paddingRight="4dip"
+                android:paddingLeft="8dip"
+                android:paddingRight="8dip"
                 android:layout_gravity="center_vertical"
                 android:background="?android:attr/selectableItemBackground"
                 android:src="?android:attr/searchViewCloseIcon"
@@ -111,26 +111,34 @@
 
     </LinearLayout>
 
-    <ImageView
-        android:id="@+id/search_go_btn"
+    <LinearLayout
+        android:id="@+id/submit_area"
+        android:orientation="horizontal"
         android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_gravity="center_vertical"
-        android:paddingLeft="4dip"
-        android:paddingRight="4dip"
-        android:background="?android:attr/selectableItemBackground"
-        android:src="?android:attr/searchViewGoIcon"
-    />
+        android:layout_height="match_parent">
 
-    <ImageView
-        android:id="@+id/search_voice_btn"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_gravity="center_vertical"
-        android:paddingLeft="4dip"
-        android:paddingRight="4dip"
-        android:src="?android:attr/searchViewVoiceIcon"
-        android:background="?android:attr/selectableItemBackground"
-        android:visibility="gone"
-    />
+        <ImageView
+            android:id="@+id/search_go_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical"
+            android:paddingLeft="16dip"
+            android:paddingRight="16dip"
+            android:background="?android:attr/selectableItemBackground"
+            android:src="?android:attr/searchViewGoIcon"
+            android:visibility="gone"
+        />
+
+        <ImageView
+            android:id="@+id/search_voice_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical"
+            android:paddingLeft="16dip"
+            android:paddingRight="16dip"
+            android:src="?android:attr/searchViewVoiceIcon"
+            android:background="?android:attr/selectableItemBackground"
+            android:visibility="gone"
+        />
+    </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout/simple_dropdown_item_1line.xml b/core/res/res/layout/simple_dropdown_item_1line.xml
index 18e7b88..3ec930c 100644
--- a/core/res/res/layout/simple_dropdown_item_1line.xml
+++ b/core/res/res/layout/simple_dropdown_item_1line.xml
@@ -20,7 +20,7 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@android:id/text1"
     style="?android:attr/dropDownItemStyle"
-    android:textAppearance="?android:attr/textAppearanceLargeInverse"
+    android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
     android:singleLine="true"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeight"
diff --git a/core/res/res/layout/simple_dropdown_item_2line.xml b/core/res/res/layout/simple_dropdown_item_2line.xml
index 903adb0..d6f911a 100644
--- a/core/res/res/layout/simple_dropdown_item_2line.xml
+++ b/core/res/res/layout/simple_dropdown_item_2line.xml
@@ -37,7 +37,7 @@
         <TextView
             android:id="@android:id/text1"
             style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceLargeInverse"
+            android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
             android:singleLine="true"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
@@ -45,7 +45,7 @@
         <TextView
             android:id="@android:id/text2"
             style="?android:attr/dropDownItemStyle"
-            android:textAppearance="?android:attr/textAppearanceSmallInverse"
+            android:textAppearance="?android:attr/textAppearanceSmallPopupMenu"
             android:textColor="#323232"
             android:singleLine="true"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/textview_hint.xml b/core/res/res/layout/textview_hint.xml
index 4978be5..20b08bf 100644
--- a/core/res/res/layout/textview_hint.xml
+++ b/core/res/res/layout/textview_hint.xml
@@ -18,5 +18,6 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@drawable/popup_inline_error"
-    android:textAppearance="?android:attr/textAppearanceSmallInverse"
+    android:textAppearance="?android:attr/textAppearanceSmall"
+    android:textColor="@color/primary_text_light"
 />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 02855b5..19e2b8d 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -544,6 +544,9 @@
             <enum name="floating" value="0" />
             <enum name="atThumb" value="1" />
         </attr>
+        <!-- Text color for the fast scroll index overlay. Make sure it
+             plays nicely with fastScrollPreviewBackground[Left|Right]. -->
+        <attr name="fastScrollTextColor" format="color" />
 
         <!-- =================== -->
         <!-- Action bar styles   -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 5ff6212..a9a7e4a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -778,6 +778,13 @@
         <attr name="restoreNeedsApplication" />
         <attr name="restoreAnyVersion" />
         <attr name="neverEncrypt" />
+        <!-- Request that your application's processes be created with
+             a large Dalvik heap.  This applies to <em>all</em> processes
+             created for the application.  It only applies to the first
+             application loaded into a process; if using a sharedUserId
+             to allow multiple applications to use a process, they all must
+             use this option consistently or will get unpredictable results. -->
+        <attr name="largeHeap" format="boolean" />
         <!-- Declare that this applicationn can't participate in the normal
              state save/restore mechanism.  Since it is not able to save and
              restore its state on demand,
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e5b6563..a51a26d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -68,4 +68,10 @@
          is along the minor axis (that is the screen is portrait).  This may
          be either a fraction or a dimension. -->
     <item type="dimen" name="dialog_min_width_minor">95%</item>
+
+    <!-- The width of the big icons in notifications. -->
+    <dimen name="notification_large_icon_width">60dp</dimen>
+    <!-- The width of the big icons in notifications. -->
+    <dimen name="notification_large_icon_height">60dp</dimen>
+
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9b88b01..3ad29c4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1425,6 +1425,8 @@
   <public type="attr" name="windowMinWidthMajor" />
   <public type="attr" name="windowMinWidthMinor" />
   <public type="attr" name="queryHint" />
+  <public type="attr" name="fastScrollTextColor" />
+  <public type="attr" name="largeHeap" />
 
   <!-- A simple fade-in animation. -->
   <public type="animator" name="fade_in" id="0x010b0000" />
@@ -1469,6 +1471,8 @@
 
   <public type="dimen" name="dialog_min_width_major" />
   <public type="dimen" name="dialog_min_width_minor" />
+  <public type="dimen" name="notification_large_icon_width" />
+  <public type="dimen" name="notification_large_icon_height" />
 
   <!-- Standard content view for a {@link android.app.ListFragment}.
        If you are implementing a subclass of ListFragment with your
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 971719e..744d0d8 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -114,7 +114,7 @@
                 ?android:attr/expandableListPreferredItemPaddingLeft</item>
 
         <item name="expandableListPreferredItemIndicatorLeft">3dip</item>
-        <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+        <item name="expandableListPreferredItemIndicatorRight">0dip</item>
         <item name="expandableListPreferredChildIndicatorLeft">
                 ?android:attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="expandableListPreferredChildIndicatorRight">
@@ -294,6 +294,7 @@
         <item name="fastScrollPreviewBackgroundRight">@android:drawable/menu_submenu_background</item>
         <item name="fastScrollPreviewBackgroundLeft">@android:drawable/menu_submenu_background</item>
         <item name="fastScrollOverlayPosition">floating</item>
+        <item name="fastScrollTextColor">@android:color/primary_text_dark</item>
 
     </style>
 
@@ -815,7 +816,7 @@
                 ?android:attr/expandableListPreferredItemPaddingLeft</item>
 
         <item name="expandableListPreferredItemIndicatorLeft">3dip</item>
-        <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+        <item name="expandableListPreferredItemIndicatorRight">0dip</item>
         <item name="expandableListPreferredChildIndicatorLeft">
                 ?android:attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="expandableListPreferredChildIndicatorRight">
@@ -1074,7 +1075,7 @@
                 ?android:attr/expandableListPreferredItemPaddingLeft</item>
 
         <item name="expandableListPreferredItemIndicatorLeft">3dip</item>
-        <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+        <item name="expandableListPreferredItemIndicatorRight">0dip</item>
         <item name="expandableListPreferredChildIndicatorLeft">
                 ?android:attr/expandableListPreferredItemIndicatorLeft</item>
         <item name="expandableListPreferredChildIndicatorRight">
@@ -1106,6 +1107,7 @@
         <item name="dialogTitleIconsDecorLayout">@layout/dialog_title_icons_holo</item>
         <item name="dialogCustomTitleDecorLayout">@layout/dialog_custom_title_holo</item>
         <item name="dialogTitleDecorLayout">@layout/dialog_title_holo</item>
+        <item name="alertDialogCenterButtons">false</item>
         <item name="alertDialogTheme">@android:style/Theme.Holo.Light.Dialog.Alert</item>
         <item name="alertDialogIcon">@android:drawable/ic_dialog_alert_holo_light</item>
         
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 579f314..852aabf 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -239,15 +239,13 @@
     }
 
     /**
-     * @hide
-     *
      * This is only intended to be used by auto-generate code reflected from the
      * renderscript script files.
      *
      * @param xoff
      * @param fp
      */
-    public void setOneElement(int xoff, FieldPacker fp) {
+    public void setFromFieldPacker(int xoff, FieldPacker fp) {
         int eSize = mType.mElement.getSizeBytes();
         final byte[] data = fp.getData();
 
@@ -262,8 +260,6 @@
 
 
     /**
-     * @hide
-     *
      * This is only intended to be used by auto-generate code reflected from the
      * renderscript script files.
      *
@@ -271,7 +267,7 @@
      * @param component_number
      * @param fp
      */
-    public void setOneComponent(int xoff, int component_number, FieldPacker fp) {
+    public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
         if (component_number >= mType.mElement.mElements.length) {
             throw new RSIllegalArgumentException("Component_number " + component_number + " out of range.");
         }
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index b3ad20a..56abba5 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -21,8 +21,6 @@
  **/
 public class Script extends BaseObj {
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param slot
@@ -32,8 +30,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param slot
@@ -54,8 +50,6 @@
 
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param va
@@ -71,8 +65,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
@@ -83,8 +75,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
@@ -95,8 +85,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
@@ -107,8 +95,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
@@ -119,8 +105,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
@@ -131,8 +115,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
@@ -143,8 +125,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by generated reflected code.
      *
      * @param index
diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java
index 14e4ab5..ff8f093 100644
--- a/graphics/java/android/renderscript/ScriptC.java
+++ b/graphics/java/android/renderscript/ScriptC.java
@@ -36,8 +36,6 @@
     private static final String TAG = "ScriptC";
 
     /**
-     * @hide
-     *
      * Only intended for use by the generated derived classes.
      *
      * @param id
@@ -48,8 +46,6 @@
     }
 
     /**
-     * @hide
-     *
      * Only intended for use by the generated derived classes.
      *
      *
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index bdd8e73..71ec760 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -37,6 +37,10 @@
 // Turn on to display vertex and tex coords data about 9patch objects
 // This flag requires DEBUG_PATCHES to be turned on
 #define DEBUG_PATCHES_VERTICES 0
+// Turn on to display vertex and tex coords data used by empty quads
+// in 9patch objects
+// This flag requires DEBUG_PATCHES to be turned on
+#define DEBUG_PATCHES_EMPTY_VERTICES 0
 
 // Turn on to display debug info about paths
 #define DEBUG_PATHS 0
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 7d54d3b..bb284379 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -27,6 +27,7 @@
 
 #include "Rect.h"
 #include "SkiaColorFilter.h"
+#include "Vertex.h"
 
 namespace android {
 namespace uirenderer {
@@ -41,6 +42,14 @@
 struct Layer {
     Layer(const uint32_t layerWidth, const uint32_t layerHeight):
             width(layerWidth), height(layerHeight) {
+        mesh = NULL;
+        meshIndices = NULL;
+        meshElementCount = 0;
+    }
+
+    ~Layer() {
+        if (mesh) delete mesh;
+        if (meshIndices) delete meshIndices;
     }
 
     /**
@@ -99,6 +108,13 @@
      * Color filter used to draw this layer. Optional.
      */
     SkiaColorFilter* colorFilter;
+
+    /**
+     * If the layer can be rendered as a mesh, this is non-null.
+     */
+    TextureVertex* mesh;
+    uint16_t* meshIndices;
+    GLsizei meshElementCount;
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index a25c95e..e6bea78 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -39,11 +39,100 @@
     OpenGLRenderer::finish();
     glBindFramebuffer(GL_FRAMEBUFFER, mPreviousFbo);
 
+    generateMesh();
+
     LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->mFbo);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-// Static functions
+// Dirty region tracking
+///////////////////////////////////////////////////////////////////////////////
+
+bool LayerRenderer::hasLayer() {
+    return true;
+}
+
+Region* LayerRenderer::getRegion() {
+#if RENDER_LAYERS_AS_REGIONS
+    if (getSnapshot()->flags & Snapshot::kFlagFboTarget) {
+        return OpenGLRenderer::getRegion();
+    }
+    return &mLayer->region;
+#else
+    return OpenGLRenderer::getRegion();
+#endif
+}
+
+void LayerRenderer::generateMesh() {
+#if RENDER_LAYERS_AS_REGIONS
+    if (mLayer->region.isRect() || mLayer->region.isEmpty()) {
+        if (mLayer->mesh) {
+            delete mLayer->mesh;
+            delete mLayer->meshIndices;
+
+            mLayer->mesh = NULL;
+            mLayer->meshIndices = NULL;
+            mLayer->meshElementCount = 0;
+        }
+        mLayer->region.clear();
+        return;
+    }
+
+    size_t count;
+    const android::Rect* rects = mLayer->region.getArray(&count);
+
+    GLsizei elementCount = count * 6;
+
+    if (mLayer->mesh && mLayer->meshElementCount < elementCount) {
+        delete mLayer->mesh;
+        delete mLayer->meshIndices;
+
+        mLayer->mesh = NULL;
+        mLayer->meshIndices = NULL;
+    }
+
+    if (!mLayer->mesh) {
+        mLayer->mesh = new TextureVertex[count * 4];
+        mLayer->meshIndices = new uint16_t[elementCount];
+        mLayer->meshElementCount = elementCount;
+    }
+
+    const float texX = 1.0f / float(mLayer->width);
+    const float texY = 1.0f / float(mLayer->height);
+    const float height = mLayer->layer.getHeight();
+
+    TextureVertex* mesh = mLayer->mesh;
+    uint16_t* indices = mLayer->meshIndices;
+
+    for (size_t i = 0; i < count; i++) {
+        const android::Rect* r = &rects[i];
+
+        const float u1 = r->left * texX;
+        const float v1 = (height - r->top) * texY;
+        const float u2 = r->right * texX;
+        const float v2 = (height - r->bottom) * texY;
+
+        TextureVertex::set(mesh++, r->left, r->top, u1, v1);
+        TextureVertex::set(mesh++, r->right, r->top, u2, v1);
+        TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
+        TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
+
+        uint16_t quad = i * 4;
+        int index = i * 6;
+        indices[index    ] = quad;       // top-left
+        indices[index + 1] = quad + 1;   // top-right
+        indices[index + 2] = quad + 2;   // bottom-left
+        indices[index + 3] = quad + 2;   // bottom-left
+        indices[index + 4] = quad + 1;   // top-right
+        indices[index + 5] = quad + 3;   // bottom-right
+    }
+
+    mLayer->region.clear();
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Layers management
 ///////////////////////////////////////////////////////////////////////////////
 
 Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) {
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index ed5d960..f2fb898 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -49,12 +49,17 @@
     void prepare(bool opaque);
     void finish();
 
+    bool hasLayer();
+    Region* getRegion();
+
     static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
     static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
     static void destroyLayer(Layer* layer);
     static void destroyLayerDeferred(Layer* layer);
 
 private:
+    void generateMesh();
+
     Layer* mLayer;
     GLuint mPreviousFbo;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index b933232..16a1de7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -615,6 +615,7 @@
         const float alpha = layer->alpha / 255.0f;
         const float texX = 1.0f / float(layer->width);
         const float texY = 1.0f / float(layer->height);
+        const float height = rect.getHeight();
 
         TextureVertex* mesh = mCaches.getRegionMesh();
         GLsizei numQuads = 0;
@@ -636,9 +637,9 @@
             const android::Rect* r = &rects[i];
 
             const float u1 = r->left * texX;
-            const float v1 = (rect.getHeight() - r->top) * texY;
+            const float v1 = (height - r->top) * texY;
             const float u2 = r->right * texX;
-            const float v2 = (rect.getHeight() - r->bottom) * texY;
+            const float v2 = (height - r->bottom) * texY;
 
             // TODO: Reject quads outside of the clip
             TextureVertex::set(mesh++, r->left, r->top, u1, v1);
@@ -694,10 +695,10 @@
 void OpenGLRenderer::dirtyLayer(const float left, const float top,
         const float right, const float bottom, const mat4 transform) {
 #if RENDER_LAYERS_AS_REGIONS
-    if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
+    if (hasLayer()) {
         Rect bounds(left, top, right, bottom);
         transform.mapRect(bounds);
-        dirtyLayerUnchecked(bounds, mSnapshot->region);
+        dirtyLayerUnchecked(bounds, getRegion());
     }
 #endif
 }
@@ -705,9 +706,9 @@
 void OpenGLRenderer::dirtyLayer(const float left, const float top,
         const float right, const float bottom) {
 #if RENDER_LAYERS_AS_REGIONS
-    if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
+    if (hasLayer()) {
         Rect bounds(left, top, right, bottom);
-        dirtyLayerUnchecked(bounds, mSnapshot->region);
+        dirtyLayerUnchecked(bounds, getRegion());
     }
 #endif
 }
@@ -1419,24 +1420,20 @@
     Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
 #if RENDER_LAYERS_AS_REGIONS
-    bool hasLayer = (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region;
+    bool hasActiveLayer = hasLayer();
 #else
-    bool hasLayer = false;
+    bool hasActiveLayer = false;
 #endif
 
     mCaches.unbindMeshBuffer();
     if (fontRenderer.renderText(paint, clip, text, 0, bytesCount, count, x, y,
-            hasLayer ? &bounds : NULL)) {
+            hasActiveLayer ? &bounds : NULL)) {
 #if RENDER_LAYERS_AS_REGIONS
-        if (hasLayer) {
+        if (hasActiveLayer) {
             if (!pureTranslate) {
                 mSnapshot->transform->mapRect(bounds);
             }
-            bounds.intersect(*mSnapshot->clipRect);
-            bounds.snapToPixelBoundaries();
-
-            android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
-            mSnapshot->region->orSelf(dirty);
+            dirtyLayerUnchecked(bounds, getRegion());
         }
 #endif
     }
@@ -1501,8 +1498,36 @@
     layer->alpha = alpha;
     layer->mode = mode;
 
+
+#if RENDER_LAYERS_AS_REGIONS
+    if (layer->region.isRect()) {
+        const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
+        composeLayerRect(layer, r);
+    } else if (!layer->region.isEmpty() && layer->mesh) {
+        const Rect& rect = layer->layer;
+
+        setupDraw();
+        setupDrawWithTexture();
+        setupDrawColor(alpha, alpha, alpha, alpha);
+        setupDrawColorFilter();
+        setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+        setupDrawProgram();
+        setupDrawDirtyRegionsDisabled();
+        setupDrawPureColorUniforms();
+        setupDrawColorFilterUniforms();
+        setupDrawTexture(layer->texture);
+        setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
+        setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]);
+
+        glDrawElements(GL_TRIANGLES, layer->meshElementCount,
+                GL_UNSIGNED_SHORT, layer->meshIndices);
+
+        finishDrawTexture();
+    }
+#else
     const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
     composeLayerRect(layer, r);
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 56be134..7387b92 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -133,19 +133,24 @@
     virtual void composeLayer(sp<Snapshot> current, sp<Snapshot> previous);
 
     /**
-     * Mark the layer as dirty at the specified coordinates. The coordinates
-     * are transformed with the supplied matrix.
+     * Marks the specified region as dirty at the specified bounds.
      */
-    virtual void dirtyLayer(const float left, const float top,
-            const float right, const float bottom, const mat4 transform);
+    void dirtyLayerUnchecked(Rect& bounds, Region* region);
 
     /**
-     * Mark the layer as dirty at the specified coordinates.
+     * Returns the current snapshot.
      */
-    virtual void dirtyLayer(const float left, const float top,
-            const float right, const float bottom);
+    sp<Snapshot> getSnapshot() {
+        return mSnapshot;
+    }
 
-    void dirtyLayerUnchecked(Rect& bounds, Region* region);
+    virtual Region* getRegion() {
+        return mSnapshot->region;
+    }
+
+    virtual bool hasLayer() {
+        return (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region;
+    }
 
 private:
     /**
@@ -225,6 +230,19 @@
     void clearLayerRegions();
 
     /**
+     * Mark the layer as dirty at the specified coordinates. The coordinates
+     * are transformed with the supplied matrix.
+     */
+    void dirtyLayer(const float left, const float top,
+            const float right, const float bottom, const mat4 transform);
+
+    /**
+     * Mark the layer as dirty at the specified coordinates.
+     */
+    void dirtyLayer(const float left, const float top,
+            const float right, const float bottom);
+
+    /**
      * Draws a colored rectangle with the specified color. The specified coordinates
      * are transformed by the current snapshot's transform matrix.
      *
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index e5cb67b..77cbb80 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -212,7 +212,7 @@
         }
         float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;
 
-        generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
+        bool valid = generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
 
         x1 = x2;
         u1 = (stepX + 0.5f) / bitmapWidth;
@@ -223,17 +223,22 @@
     generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount);
 }
 
-void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
+bool Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2, uint32_t& quadCount) {
     const uint32_t oldQuadCount = quadCount;
-    const bool valid = x2 - x1 > 0.9999f && y2 - y1 > 0.9999f;
+    const bool valid = x2 >= x1 && y2 >= y1;
     if (valid) {
         quadCount++;
     }
 
     // Skip degenerate and transparent (empty) quads
     if (!valid || ((mColorKey >> oldQuadCount) & 0x1) == 1) {
-        return;
+#if DEBUG_PATCHES_EMPTY_VERTICES
+        PATCH_LOGD("    quad %d (empty)", oldQuadCount);
+        PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1);
+        PATCH_LOGD("        right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2);
+#endif
+        return false;
     }
 
 #if RENDER_LAYERS_AS_REGIONS
@@ -262,6 +267,8 @@
     PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.2f, %.2f", x1, y1, u1, v1);
     PATCH_LOGD("        right, bottom = %.2f, %.2f\t\tu2, v2 = %.2f, %.2f", x2, y2, u2, v2);
 #endif
+
+    return true;
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 0f0ffa2..45ce998 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -71,7 +71,7 @@
     void generateRow(TextureVertex*& vertex, float y1, float y2,
             float v1, float v2, float stretchX, float width, float bitmapWidth,
             uint32_t& quadCount);
-    void generateQuad(TextureVertex*& vertex,
+    bool generateQuad(TextureVertex*& vertex,
             float x1, float y1, float x2, float y2,
             float u1, float v1, float u2, float v2,
             uint32_t& quadCount);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 9898df4..595ad4e 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -268,7 +268,7 @@
     Rect* clipRect;
 
     /**
-     * The ancestor layer's dirty region..
+     * The ancestor layer's dirty region.
      */
     Region* region;
 
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
index aa4cf2d..4615e1f 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/vertical_blur.rs
@@ -56,7 +56,7 @@
 }
 
 //sliao
-uchar3 convert2uchar3(float3 xyz);
+extern uchar3 __attribute__((overloadable)) convert2uchar3(float3 xyz);
 
 void root(const void *v_in, void *v_out, const void *usrData, uint32_t x, uint32_t y) {
     uchar4 *output = (uchar4 *)v_out;
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 2ed7774..41c9fe2 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -188,12 +188,7 @@
         isFirstUpload = true;
     }
 
-    GLenum target = (GLenum)getGLTarget();
-    if (target == GL_TEXTURE_2D) {
-        upload2DTexture(isFirstUpload, mPtr);
-    } else if (target == GL_TEXTURE_CUBE_MAP) {
-        uploadCubeTexture(isFirstUpload);
-    }
+    upload2DTexture(isFirstUpload);
 
     if (!(mUsageFlags & RS_ALLOCATION_USAGE_SCRIPT)) {
         freeScriptMemory();
@@ -202,18 +197,32 @@
     rsc->checkError("Allocation::uploadToTexture");
 }
 
+const static GLenum gFaceOrder[] = {
+    GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+    GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+    GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+    GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+};
+
 void Allocation::update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
                                  uint32_t lod, RsAllocationCubemapFace face,
                                  uint32_t w, uint32_t h) {
     GLenum type = mType->getElement()->getComponent().getGLType();
     GLenum format = mType->getElement()->getComponent().getGLFormat();
     GLenum target = (GLenum)getGLTarget();
+    rsAssert(mTextureID);
     glBindTexture(target, mTextureID);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-    glTexSubImage2D(GL_TEXTURE_2D, lod, xoff, yoff, w, h, format, type, ptr);
+    GLenum t = GL_TEXTURE_2D;
+    if (mType->getDimFaces()) {
+        t = gFaceOrder[face];
+    }
+    glTexSubImage2D(t, lod, xoff, yoff, w, h, format, type, ptr);
 }
 
-void Allocation::upload2DTexture(bool isFirstUpload, const void *ptr) {
+void Allocation::upload2DTexture(bool isFirstUpload) {
     GLenum type = mType->getElement()->getComponent().getGLType();
     GLenum format = mType->getElement()->getComponent().getGLFormat();
 
@@ -221,62 +230,29 @@
     glBindTexture(target, mTextureID);
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 
-    for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
-        const uint8_t *p = (const uint8_t *)ptr;
-        p += mType->getLODOffset(lod);
-
-        if (isFirstUpload) {
-            glTexImage2D(GL_TEXTURE_2D, lod, format,
-                         mType->getLODDimX(lod), mType->getLODDimY(lod),
-                         0, format, type, p);
-        } else {
-            glTexSubImage2D(GL_TEXTURE_2D, lod, 0, 0,
-                            mType->getLODDimX(lod), mType->getLODDimY(lod),
-                            format, type, p);
-        }
+    uint32_t faceCount = 1;
+    if (mType->getDimFaces()) {
+        faceCount = 6;
     }
 
-    if (mMipmapControl == RS_ALLOCATION_MIPMAP_ON_SYNC_TO_TEXTURE) {
-#ifndef ANDROID_RS_BUILD_FOR_HOST
-        glGenerateMipmap(target);
-#endif //ANDROID_RS_BUILD_FOR_HOST
-    }
-}
-
-void Allocation::uploadCubeTexture(bool isFirstUpload) {
-    GLenum type = mType->getElement()->getComponent().getGLType();
-    GLenum format = mType->getElement()->getComponent().getGLFormat();
-
-    GLenum target = (GLenum)getGLTarget();
-    glBindTexture(target, mTextureID);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
-    GLenum faceOrder[] = {
-        GL_TEXTURE_CUBE_MAP_POSITIVE_X,
-        GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
-        GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
-        GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
-        GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-        GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
-    };
-
-    Adapter2D adapt(getContext(), this);
-    for (uint32_t face = 0; face < 6; face ++) {
-        adapt.setFace(face);
-
+    for (uint32_t face = 0; face < faceCount; face ++) {
         for (uint32_t lod = 0; lod < mType->getLODCount(); lod++) {
-            adapt.setLOD(lod);
+            const uint8_t *p = (const uint8_t *)mPtr;
+            p += mType->getLODFaceOffset(lod, (RsAllocationCubemapFace)face, 0, 0);
 
-            uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
+            GLenum t = GL_TEXTURE_2D;
+            if (mType->getDimFaces()) {
+                t = gFaceOrder[face];
+            }
 
             if (isFirstUpload) {
-                glTexImage2D(faceOrder[face], lod, format,
-                             adapt.getDimX(), adapt.getDimY(),
-                             0, format, type, ptr);
+                glTexImage2D(t, lod, format,
+                             mType->getLODDimX(lod), mType->getLODDimY(lod),
+                             0, format, type, p);
             } else {
-                glTexSubImage2D(faceOrder[face], lod, 0, 0,
-                                adapt.getDimX(), adapt.getDimY(),
-                                format, type, ptr);
+                glTexSubImage2D(t, lod, 0, 0,
+                                mType->getLODDimX(lod), mType->getLODDimY(lod),
+                                format, type, p);
             }
         }
     }
@@ -364,7 +340,7 @@
     if (mPtr) {
         const uint8_t *src = static_cast<const uint8_t *>(data);
         uint8_t *dst = static_cast<uint8_t *>(mPtr);
-        dst += mType->getLODOffset(lod, xoff, yoff);
+        dst += mType->getLODFaceOffset(lod, face, xoff, yoff);
 
         //LOGE("            %p  %p  %i  ", dst, src, eSize);
         for (uint32_t line=yoff; line < (yoff+h); line++) {
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
index a160765..4f5d5a8 100644
--- a/libs/rs/rsAllocation.h
+++ b/libs/rs/rsAllocation.h
@@ -105,9 +105,6 @@
         return mMipmapControl != RS_ALLOCATION_MIPMAP_NONE;
     }
 
-    void upload2DTexture(bool isFirstUpload, const void *ptr);
-    void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
-                         uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
 
 protected:
     ObjectBaseRef<const Type> mType;
@@ -149,7 +146,9 @@
 
 private:
     void init(Context *rsc, const Type *);
-    void uploadCubeTexture(bool isFirstUpload);
+    void upload2DTexture(bool isFirstUpload);
+    void update2DTexture(const void *ptr, uint32_t xoff, uint32_t yoff,
+                         uint32_t lod, RsAllocationCubemapFace face, uint32_t w, uint32_t h);
 
     void allocScriptMemory();
     void freeScriptMemory();
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 872e7a6..1ab2109 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -462,8 +462,10 @@
     return NULL;
 }
 
+#if 0
 extern const char rs_runtime_lib_bc[];
 extern unsigned rs_runtime_lib_bc_size;
+#endif
 
 void ScriptCState::runCompiler(Context *rsc,
                                ScriptC *s,
@@ -484,11 +486,13 @@
             // Handle Fatal Error
         }
 
-#if 0
+#if 1
         if (bccLinkBC(s->mBccScript,
                       resName,
-                      rs_runtime_lib_bc,
-                      rs_runtime_lib_bc_size, 0) != 0) {
+                      NULL /*rs_runtime_lib_bc*/,
+                      1 /*rs_runtime_lib_bc_size*/
+                        /*"1" means skip buffer here, and let libbcc decide*/,
+                      0) != 0) {
             LOGE("bcc: FAILS to link bitcode");
             // Handle Fatal Error
         }
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 1c6c5ac..001ac55 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -53,6 +53,10 @@
         waitForCommand = false;
         //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize);
 
+        if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
+            rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
+            LOGE("playCoreCommands error con %p, cmd %i", con, cmdID);
+        }
         gPlaybackFuncs[cmdID](con, data);
         mToCore.next();
     }
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 670ea33..d7b5f12 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -132,6 +132,17 @@
     return offset;
 }
 
+uint32_t Type::getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const {
+    uint32_t offset = mLODs[lod].mOffset;
+    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
+
+    if (face != 0) {
+        uint32_t faceOffset = getSizeBytes() / 6;
+        offset += faceOffset * face;
+    }
+    return offset;
+}
+
 void Type::dumpLOGV(const char *prefix) const {
     char buf[1024];
     ObjectBase::dumpLOGV(prefix);
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 34498f0..90ae039 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -44,12 +44,14 @@
     uint32_t getLODDimX(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mX;}
     uint32_t getLODDimY(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mY;}
     uint32_t getLODDimZ(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mZ;}
-    uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;}
 
+    uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;}
     uint32_t getLODOffset(uint32_t lod, uint32_t x) const;
     uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const;
     uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const;
 
+    uint32_t getLODFaceOffset(uint32_t lod, RsAllocationCubemapFace face, uint32_t x, uint32_t y) const;
+
     uint32_t getLODCount() const {return mLODCount;}
     bool getIsNp2() const;
 
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 1e468bb..4ac5b7f 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -219,7 +219,7 @@
         fprintf(f, "};\n\n");
     }
 
-    fprintf(f, "RsPlaybackFunc gPlaybackFuncs[] = {\n");
+    fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
     fprintf(f, "    NULL,\n");
     for (ct=0; ct < apiCount; ct++) {
         fprintf(f, "    %s%s,\n", "rsp_", apis[ct].name);
@@ -265,7 +265,7 @@
             printFuncDecls(f, "rsi_", 1);
             printPlaybackFuncs(f, "rsp_");
             fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *);\n");
-            fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[];\n");
+            fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1);
 
             fprintf(f, "}\n");
             fprintf(f, "}\n");
diff --git a/native/android/looper.cpp b/native/android/looper.cpp
index 9f5cda9..615493f 100644
--- a/native/android/looper.cpp
+++ b/native/android/looper.cpp
@@ -19,9 +19,11 @@
 
 #include <android/looper.h>
 #include <utils/Looper.h>
+#include <binder/IPCThreadState.h>
 
 using android::Looper;
 using android::sp;
+using android::IPCThreadState;
 
 ALooper* ALooper_forThread() {
     return Looper::getForThread().get();
@@ -46,6 +48,7 @@
         return ALOOPER_POLL_ERROR;
     }
 
+    IPCThreadState::self()->flushCommands();
     return looper->pollOnce(timeoutMillis, outFd, outEvents, outData);
 }
 
@@ -55,7 +58,8 @@
         LOGE("ALooper_pollAll: No looper for this thread!");
         return ALOOPER_POLL_ERROR;
     }
-    
+
+    IPCThreadState::self()->flushCommands();
     return looper->pollAll(timeoutMillis, outFd, outEvents, outData);
 }
 
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 386cc5d..ed36171 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -62,6 +62,8 @@
         "EGL_KHR_image_base "
         "EGL_KHR_image_pixmap "
         "EGL_KHR_gl_texture_2D_image "
+        "EGL_KHR_gl_texture_cubemap_image "
+        "EGL_KHR_gl_renderbuffer_image "
         "EGL_KHR_fence_sync "
         "EGL_ANDROID_image_native_buffer "
         "EGL_ANDROID_swap_rectangle "
@@ -1471,6 +1473,29 @@
     return result;
 }
 
+// Note: Similar implementations of these functions also exist in
+// gl2.cpp and gl.cpp, and are used by applications that call the
+// exported entry points directly.
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
+static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
+
+static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage =
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    glEGLImageTargetTexture2DOES_impl(target, implImage);
+}
+
+static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
+{
+    GLeglImageOES implImage =
+        (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+    glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
+}
+
 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
 {
     // eglGetProcAddress() could be the very first function called
@@ -1531,6 +1556,16 @@
             }
             if (found) {
                 addr = gExtensionForwarders[slot];
+
+                if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
+                    glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
+                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
+                }
+                if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
+                    glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
+                    addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
+                }
+
                 gGLExtentionMap.add(name, addr);
                 gGLExtentionSlot++;
             }
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 0c85af8..2ec2226 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -165,8 +165,13 @@
         }
 
         @Override
-        public long calculateDirectorySize(String directory) throws RemoteException {
-            return MeasurementUtils.measureDirectory(directory);
+        public long calculateDirectorySize(String path) throws RemoteException {
+            final File directory = new File(path);
+            if (directory.exists() && directory.isDirectory()) {
+                return MeasurementUtils.measureDirectory(path);
+            } else {
+                return 0L;
+            }
         }
     };
 
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
index 4991a40..e97345b 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
@@ -18,8 +18,8 @@
 
     <ImageView
         android:id="@+id/large_icon"
-        android:layout_width="@dimen/notification_large_icon_width"
-        android:layout_height="@dimen/notification_large_icon_height"
+        android:layout_width="@android:dimen/notification_large_icon_width"
+        android:layout_height="@android:dimen/notification_large_icon_height"
         android:layout_alignParentTop="true"
         android:layout_alignParentLeft="true"
         android:scaleType="center"
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_ticker_compat.xml b/packages/SystemUI/res/layout-xlarge/status_bar_ticker_compat.xml
index 5d9a680..6de7697 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_ticker_compat.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_ticker_compat.xml
@@ -25,8 +25,8 @@
 
     <ImageView
         android:id="@+id/large_icon"
-        android:layout_width="@dimen/notification_large_icon_width"
-        android:layout_height="@dimen/notification_large_icon_height"
+        android:layout_width="@android:dimen/notification_large_icon_width"
+        android:layout_height="@android:dimen/notification_large_icon_height"
         android:scaleType="center"
         android:visibility="gone"
         />
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_ticker_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_ticker_panel.xml
index cae6a77..d570ace 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_ticker_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_ticker_panel.xml
@@ -29,8 +29,8 @@
 
     <ImageView
         android:id="@+id/large_icon"
-        android:layout_width="@dimen/notification_large_icon_height"
-        android:layout_height="@dimen/notification_large_icon_width"
+        android:layout_width="@android:dimen/notification_large_icon_height"
+        android:layout_height="@android:dimen/notification_large_icon_width"
         android:scaleType="center"
         android:visibility="gone"
         />
diff --git a/packages/SystemUI/res/values-xlarge/dimens.xml b/packages/SystemUI/res/values-xlarge/dimens.xml
index b9f5837..9d89e21 100644
--- a/packages/SystemUI/res/values-xlarge/dimens.xml
+++ b/packages/SystemUI/res/values-xlarge/dimens.xml
@@ -16,10 +16,6 @@
 */
 -->
 <resources>
-    <!-- The width of the big icons in notifications. -->
-    <dimen name="notification_large_icon_width">60dp</dimen>
-    <!-- The width of the big icons in notifications. -->
-    <dimen name="notification_large_icon_height">60dp</dimen>
     <!-- The width of the ticker, including the icon -->
     <dimen name="notification_ticker_width">360dp</dimen>
     <!-- Status bar panel bottom offset (height of status bar - overlap) -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 73b6723..dfe0262 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -668,7 +668,8 @@
             if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
                 iconLevel = getEvdoLevel();
                 if (false) {
-                    Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
+                    Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level="
+                            + getCdmaLevel());
                 }
             } else {
                 iconLevel = getCdmaLevel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
index da60f0d..0d2538d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.AsyncTask;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
@@ -54,7 +55,6 @@
     }
 
     public void onCheckedChanged(CompoundButton view, boolean checked) {
-        Slog.d(TAG, "onCheckedChanged checked=" + checked + " mAirplaneMode=" + mAirplaneMode);
         if (checked != mAirplaneMode) {
             mAirplaneMode = checked;
             unsafe(checked);
@@ -78,15 +78,19 @@
 
     // TODO: Fix this racy API by adding something better to TelephonyManager or
     // ConnectivityService.
-    private void unsafe(boolean enabled) {
-        Settings.System.putInt(
-                mContext.getContentResolver(),
-                Settings.System.AIRPLANE_MODE_ON,
-                enabled ? 1 : 0);
-        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
-        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-        intent.putExtra("state", enabled);
-        mContext.sendBroadcast(intent);
+    private void unsafe(final boolean enabled) {
+        AsyncTask.execute(new Runnable() {
+                public void run() {
+                    Settings.System.putInt(
+                            mContext.getContentResolver(),
+                            Settings.System.AIRPLANE_MODE_ON,
+                            enabled ? 1 : 0);
+                    Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+                    intent.putExtra("state", enabled);
+                    mContext.sendBroadcast(intent);
+                }
+            });
     }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
index 866e5fc..b0a6d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AutoRotateController.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.os.AsyncTask;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.provider.Settings;
@@ -45,7 +46,6 @@
     }
 
     public void onCheckedChanged(CompoundButton view, boolean checked) {
-        Slog.d(TAG, "onCheckedChanged checked=" + checked + " mLockRotation=" + mLockRotation);
         if (checked != mLockRotation) {
             setLockRotation(checked);
         }
@@ -56,18 +56,22 @@
         return 0 == Settings.System.getInt(cr, Settings.System.ACCELEROMETER_ROTATION, 0);
     }
 
-    private void setLockRotation(boolean locked) {
+    private void setLockRotation(final boolean locked) {
         mLockRotation = locked;
-        try {
-            IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService(
-                        Context.WINDOW_SERVICE));
-            ContentResolver cr = mContext.getContentResolver();
-            if (locked) {
-                wm.freezeRotation();
-            } else {
-                wm.thawRotation();
-            }
-        } catch (RemoteException exc) {
-        }
+        AsyncTask.execute(new Runnable() {
+                public void run() {
+                    try {
+                        IWindowManager wm = IWindowManager.Stub.asInterface(
+                                ServiceManager.getService(Context.WINDOW_SERVICE));
+                        ContentResolver cr = mContext.getContentResolver();
+                        if (locked) {
+                            wm.freezeRotation();
+                        } else {
+                            wm.thawRotation();
+                        }
+                    } catch (RemoteException exc) {
+                    }
+                }
+            });
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
index c11d04e..521467a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
@@ -18,6 +18,7 @@
 
 import android.content.ContentResolver;
 import android.content.Context;
+import android.os.AsyncTask;
 import android.os.IPowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -79,7 +80,16 @@
         setMode(automatic ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
                 : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
         if (!automatic) {
-            setBrightness(value + MINIMUM_BACKLIGHT);
+            final int val = value + value + MINIMUM_BACKLIGHT;
+            setBrightness(val);
+            if (!tracking) {
+                AsyncTask.execute(new Runnable() {
+                        public void run() {
+                            Settings.System.putInt(mContext.getContentResolver(), 
+                                    Settings.System.SCREEN_BRIGHTNESS, val);
+                        }
+                    });
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 3a7bd90..e80e37d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -47,7 +47,6 @@
     int mRepeat;
     Runnable mCheckLongPress = new Runnable() {
         public void run() {
-            Slog.d("KeyButtonView", "longpress");
             if (isPressed()) {
                 mLongPressed = true;
                 mRepeat++;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
index 5616159..90c9568 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
@@ -73,12 +73,10 @@
     private void setPlugged(boolean plugged) {
         final Resources res = mContext.getResources();
 
-        Slog.d(TAG, "plugged=" + plugged);
         int height = -1;
         if (plugged) {
             final DisplayMetrics metrics = new DisplayMetrics();
             mWindowManager.getDefaultDisplay().getMetrics(metrics);
-            Slog.d(TAG, "metrics=" + metrics);
             height = metrics.heightPixels - 720;
         }
 
@@ -87,7 +85,8 @@
         if (height < minHeight) {
             height = minHeight;
         }
-        Slog.d(TAG, "using height=" + height + " old=" + mHeight);
+        Slog.i(TAG, "Resizing status bar plugged=" + plugged + " height="
+                + height + " old=" + mHeight);
         mHeight = height;
 
         final int N = mListeners.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index a2f6e3a..45a22b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -269,7 +269,8 @@
                 // fully closed, no animation necessary
             } else if (mVisible) {
                 if (DEBUG) {
-                    Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
+                    Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim"
+                            + " to open fully");
                 }
                 startAnimation(true);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index 07af466..9ca83e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -95,7 +95,6 @@
     // Network
     // ----------------------------
     private void onClickNetwork() {
-        Slog.d(TAG, "onClickNetwork");
         getContext().startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)
                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
         getStatusBarManager().collapse();
@@ -104,7 +103,6 @@
     // Settings
     // ----------------------------
     private void onClickSettings() {
-        Slog.d(TAG, "onClickSettings");
         getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
                 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
         getStatusBarManager().collapse();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 2ebd067..e864577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -143,7 +143,6 @@
                 hideWindow();
                 return true;
             } else if (action == MotionEvent.ACTION_DOWN) {
-                Slog.d(TAG, "ACTION_DOWN");
                 final ClipData clip = mClipping;
                 if (clip != null) {
                     final Bitmap icon = clip.getIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index d8e3053..825877a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -596,7 +596,7 @@
             // TODO: immersive mode popups for tablet
         } else if (notification.notification.fullScreenIntent != null) {
             // not immersive & a full-screen alert should be shown
-            Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
+            Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
                     + " sending fullScreenIntent");
             try {
                 notification.notification.fullScreenIntent.send();
@@ -732,28 +732,28 @@
         // act accordingly
         if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
             boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
-            Slog.d(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
+            Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
             showClock(show);
         }
         if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
             boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
-            Slog.d(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
+            Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
             mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
         }
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
-                Slog.d(TAG, "DISABLE_EXPAND: yes");
+                Slog.i(TAG, "DISABLE_EXPAND: yes");
                 animateCollapse();
             }
         }
         if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
-                Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
+                Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
                 // synchronize with current shadow state
                 mNotificationIconArea.setVisibility(View.GONE);
                 mTicker.halt();
             } else {
-                Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
+                Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no");
                 // synchronize with current shadow state
                 mNotificationIconArea.setVisibility(View.VISIBLE);
             }
@@ -764,11 +764,11 @@
         }
         if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
             if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
-                Slog.d(TAG, "DISABLE_NAVIGATION: yes");
+                Slog.i(TAG, "DISABLE_NAVIGATION: yes");
                 mNavigationArea.setVisibility(View.GONE);
                 mInputMethodSwitchButton.setScreenLocked(true);
             } else {
-                Slog.d(TAG, "DISABLE_NAVIGATION: no");
+                Slog.i(TAG, "DISABLE_NAVIGATION: no");
                 mNavigationArea.setVisibility(View.VISIBLE);
                 mInputMethodSwitchButton.setScreenLocked(false);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index 4ee985d..98f718b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -65,7 +65,9 @@
                 }
             }
         }
-        Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
+        if (TabletStatusBar.DEBUG) {
+            Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
+        }
         return super.onInterceptTouchEvent(ev);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index 7705dfc..440d680 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -111,7 +111,6 @@
 
     public void remove(IBinder key, boolean advance) {
         if (mCurrentKey == key) {
-            Slog.d(TAG, "removed current");
             // Showing now
             if (advance) {
                 removeMessages(MSG_ADVANCE);
@@ -121,7 +120,6 @@
             // In the queue
             for (int i=0; i<QUEUE_LENGTH; i++) {
                 if (mKeys[i] == key) {
-                    Slog.d(TAG, "removed from queue: " + i);
                     for (; i<QUEUE_LENGTH-1; i++) {
                         mKeys[i] = mKeys[i+1];
                         mQueue[i] = mQueue[i+1];
@@ -208,7 +206,8 @@
         final Resources res = mContext.getResources();
         final FrameLayout view = new FrameLayout(mContext);
         final int width = res.getDimensionPixelSize(R.dimen.notification_ticker_width);
-        final int height = res.getDimensionPixelSize(R.dimen.notification_large_icon_height);
+        final int height = res.getDimensionPixelSize(
+                android.R.dimen.notification_large_icon_height);
         int windowFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 79fbe0e..1b810d5 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -311,8 +311,8 @@
         setFocusableInTouchMode(true);
         setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
 
-        updateMonitor.registerInfoCallback(this);
-        updateMonitor.registerSimStateCallback(this);
+        mUpdateMonitor.registerInfoCallback(this);
+        mUpdateMonitor.registerSimStateCallback(this);
 
         mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
         mSilentMode = isSilentMode();
@@ -414,6 +414,9 @@
     public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
             int batteryLevel) {
         if (DBG) Log.d(TAG, "onRefreshBatteryInfo(" + showBatteryInfo + ", " + pluggedIn + ")");
+
+        mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel);
+
         mShowingBatteryInfo = showBatteryInfo;
         mPluggedIn = pluggedIn;
         mBatteryLevel = batteryLevel;
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index 9db86aa..b789288 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -109,22 +109,21 @@
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton);
 
         mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
+        // TODO: re-enable on phones with keyboards
+        boolean isPhysicalKbShowing = false;
+        //mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
         if (mKeyboardViewAlpha == null || !mIsAlpha) {
             mKeyboardHelper.setKeyboardMode(mIsAlpha ?
                     PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
                     : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
-            mKeyboardView.setVisibility(
-                    mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO
-                    ? View.INVISIBLE : View.VISIBLE);
+            mKeyboardView.setVisibility(isPhysicalKbShowing ? View.INVISIBLE : View.VISIBLE);
         } else {
             mKeyboardHelperAlpha = new PasswordEntryKeyboardHelper(context, mKeyboardViewAlpha,
                     this, false);
             mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
             mKeyboardHelperAlpha.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
             mKeyboardView.setVisibility(View.GONE);
-            mKeyboardViewAlpha.setVisibility(
-                    mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO
-                    ? View.INVISIBLE : View.VISIBLE);
+            mKeyboardViewAlpha.setVisibility(isPhysicalKbShowing ? View.INVISIBLE : View.VISIBLE);
             mPasswordEntry.setWidth(mKeyboardViewAlpha.getLayoutParams().width);
         }
 
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 5d1455e..6815d50 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -169,6 +169,9 @@
         }
 
         mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
+        // This shows up when no other information is required on status1
+        mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,
+                StatusView.LOCK_ICON);
 
         mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
 
@@ -216,8 +219,8 @@
         // assume normal footer mode for now
         updateFooter(FooterMode.Normal);
 
-        updateMonitor.registerInfoCallback(this);
-        updateMonitor.registerSimStateCallback(this);
+        mUpdateMonitor.registerInfoCallback(this);
+        mUpdateMonitor.registerSimStateCallback(this);
         setFocusableInTouchMode(true);
 
         // until we get an update...
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 2a39322..6b559cf 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -191,9 +191,6 @@
     static final int APPLICATION_PANEL_SUBLAYER = 1;
     static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
     
-    // Debugging: set this to have the system act like there is no hard keyboard.
-    static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
-    
     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -914,38 +911,44 @@
     }
     
     private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
-        if (KEYBOARD_ALWAYS_HIDDEN) {
-            return hiddenValue;
-        }
-        if (mLidOpen == LID_ABSENT) {
-            return visibleValue;
-        }
-
-        switch (mode) {
-            case 1:
-                return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
-            case 2:
-                return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
+        if (mLidOpen != LID_ABSENT) {
+            switch (mode) {
+                case 1:
+                    return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
+                case 2:
+                    return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
+            }
         }
         return visibleValue;
     }
-    
+
     /** {@inheritDoc} */
     public void adjustConfigurationLw(Configuration config) {
         readLidState();
+
         mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
-        config.hardKeyboardHidden = determineHiddenState(
-                mLidKeyboardAccessibility, Configuration.HARDKEYBOARDHIDDEN_YES,
-                Configuration.HARDKEYBOARDHIDDEN_NO);
-        config.navigationHidden = determineHiddenState(
-                mLidNavigationAccessibility, Configuration.NAVIGATIONHIDDEN_YES,
-                Configuration.NAVIGATIONHIDDEN_NO);
-        config.keyboardHidden = (config.hardKeyboardHidden
-                        == Configuration.HARDKEYBOARDHIDDEN_NO || mHasSoftInput)
-                ? Configuration.KEYBOARDHIDDEN_NO
-                : Configuration.KEYBOARDHIDDEN_YES;
+
+        if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
+            config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
+        } else {
+            config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
+                    Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
+        }
+
+        if (config.navigation == Configuration.NAVIGATION_NONAV) {
+            config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
+        } else {
+            config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
+                    Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
+        }
+
+        if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
+            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
+        } else {
+            config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
+        }
     }
-    
+
     /** {@inheritDoc} */
     public int windowTypeToLayerLw(int type) {
         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 1caf0b7..5d32cf4 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -19,10 +19,10 @@
 import android.widget.TextView;
 
 class StatusView {
-    private static final int LOCK_ICON = R.drawable.ic_lock_idle_lock;
-    private static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
-    private static final int CHARGING_ICON = R.drawable.ic_lock_idle_charging;
-    private static final int BATTERY_LOW_ICON = R.drawable.ic_lock_idle_low_battery;
+    public static final int LOCK_ICON = R.drawable.ic_lock_idle_lock;
+    public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
+    public static final int CHARGING_ICON = R.drawable.ic_lock_idle_charging;
+    public static final int BATTERY_LOW_ICON = R.drawable.ic_lock_idle_low_battery;
 
     private String mDateFormatString;
 
@@ -49,6 +49,8 @@
 
     private TextView mAlarmStatus;
     private LockPatternUtils mLockPatternUtils;
+    private int mHelpMessageId;
+    private int mHelpIconId;
 
     private View findViewById(int id) {
         return mView.findViewById(id);
@@ -148,8 +150,8 @@
      */
     void updateStatusLines(boolean showStatusLines) {
         if (!showStatusLines) {
-            mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
-            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
+            mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
+            mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
             return;
         }
 
@@ -171,7 +173,7 @@
             mAlarmStatus.setText(nextAlarm);
             mAlarmStatus.setVisibility(View.VISIBLE);
         } else {
-            mAlarmStatus.setVisibility(View.GONE);
+            mAlarmStatus.setVisibility(View.INVISIBLE);
         }
 
         // Update Status1
@@ -199,13 +201,22 @@
             }
             mStatus1.setVisibility(View.VISIBLE);
         } else {
-            // nothing specific to show; show general instructions
-            mStatus1.setText(R.string.lockscreen_pattern_instructions);
-            mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0,0, 0);
-            mStatus1.setVisibility(View.VISIBLE);
+            // nothing specific to show; show help message and icon, if provided
+            if (mHelpMessageId != 0) {
+                mStatus1.setText(mHelpMessageId);
+                mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
+                mStatus1.setVisibility(View.VISIBLE);
+            } else {
+                mStatus1.setVisibility(View.INVISIBLE);
+            }
         }
     }
 
+    void setHelpMessage(int messageId, int iconId) {
+        mHelpMessageId = messageId;
+        mHelpIconId = iconId;
+    }
+
     void refreshTimeAndDateDisplay() {
         if (mHasDate) {
             mDate.setText(DateFormat.format(mDateFormatString, new Date()));
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 1efc645..19667d4 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -1050,7 +1050,7 @@
     void cleanupInstallFailedPackage(PackageSetting ps) {
         Slog.i(TAG, "Cleaning up incompletely installed app: " + ps.name);
         if (mInstaller != null) {
-            boolean useSecureFS = useEncryptedFilesystemForPackage(ps.pkg);
+            boolean useSecureFS = false;
             int retCode = mInstaller.remove(ps.name, useSecureFS);
             if (retCode < 0) {
                 Slog.w(TAG, "Couldn't remove app data directory for package: "
@@ -2780,11 +2780,6 @@
         return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
     }
 
-    private static boolean useEncryptedFilesystemForPackage(PackageParser.Package pkg) {
-        return Environment.isEncryptedFilesystemEnabled() &&
-                ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_NEVER_ENCRYPT) == 0);
-    }
-    
     private boolean verifyPackageUpdate(PackageSetting oldPkg, PackageParser.Package newPkg) {
         if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
             Slog.w(TAG, "Unable to update from " + oldPkg.name
@@ -2801,7 +2796,7 @@
     }
 
     private File getDataPathForPackage(PackageParser.Package pkg) {
-        boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
+        boolean useEncryptedFSDir = false;
         File dataPath;
         if (useEncryptedFSDir) {
             dataPath = new File(mSecureAppDataDir, pkg.packageName);
@@ -3157,7 +3152,7 @@
             pkg.applicationInfo.dataDir = dataPath.getPath();
         } else {
             // This is a normal package, need to make its data directory.
-            boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
+            boolean useEncryptedFSDir = false;
             dataPath = getDataPathForPackage(pkg);
             
             boolean uidError = false;
@@ -4811,6 +4806,74 @@
         abstract void handleReturnCode();
     }
 
+    class MeasureParams extends HandlerParams {
+        private final PackageStats mStats;
+        private boolean mSuccess;
+
+        private final IPackageStatsObserver mObserver;
+
+        public MeasureParams(PackageStats stats, boolean success,
+                IPackageStatsObserver observer) {
+            mObserver = observer;
+            mStats = stats;
+            mSuccess = success;
+        }
+
+        @Override
+        void handleStartCopy() throws RemoteException {
+            final boolean mounted;
+
+            if (Environment.isExternalStorageEmulated()) {
+                mounted = true;
+            } else {
+                final String status = Environment.getExternalStorageState();
+
+                mounted = status.equals(Environment.MEDIA_MOUNTED)
+                        || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
+            }
+
+            if (mounted) {
+                final File externalCacheDir = Environment
+                        .getExternalStorageAppCacheDirectory(mStats.packageName);
+                final long externalCacheSize = mContainerService
+                        .calculateDirectorySize(externalCacheDir.getPath());
+                mStats.externalCacheSize = externalCacheSize;
+
+                final File externalDataDir = Environment
+                        .getExternalStorageAppDataDirectory(mStats.packageName);
+                long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
+                        .getPath());
+
+                if (externalCacheDir.getParentFile().equals(externalDataDir)) {
+                    externalDataSize -= externalCacheSize;
+                }
+                mStats.externalDataSize = externalDataSize;
+
+                final File externalMediaDir = Environment
+                        .getExternalStorageAppMediaDirectory(mStats.packageName);
+                mStats.externalMediaSize = mContainerService
+                        .calculateDirectorySize(externalCacheDir.getPath());
+            }
+        }
+
+        @Override
+        void handleReturnCode() {
+            if (mObserver != null) {
+                try {
+                    mObserver.onGetStatsCompleted(mStats, mSuccess);
+                } catch (RemoteException e) {
+                    Slog.i(TAG, "Observer no longer exists.");
+                }
+            }
+        }
+
+        @Override
+        void handleServiceError() {
+            Slog.e(TAG, "Could not measure application " + mStats.packageName
+                            + " external storage");
+        }
+    }
+
     class InstallParams extends HandlerParams {
         final IPackageInstallObserver observer;
         int flags;
@@ -6296,7 +6359,7 @@
             deletedPs = mSettings.mPackages.get(packageName);
         }
         if ((flags&PackageManager.DONT_DELETE_DATA) == 0) {
-            boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
+            boolean useEncryptedFSDir = false;
             if (mInstaller != null) {
                 int retCode = mInstaller.remove(packageName, useEncryptedFSDir);
                 if (retCode < 0) {
@@ -6540,7 +6603,7 @@
         }
         boolean useEncryptedFSDir = false;
 
-        if(!dataOnly) {
+        if (!dataOnly) {
             //need to check this only for fully installed applications
             if (p == null) {
                 Slog.w(TAG, "Package named '" + packageName +"' doesn't exist.");
@@ -6551,7 +6614,6 @@
                 Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
                 return false;
             }
-            useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
         }
         if (mInstaller != null) {
             int retCode = mInstaller.clearUserData(packageName, useEncryptedFSDir);
@@ -6605,7 +6667,7 @@
             Slog.w(TAG, "Package " + packageName + " has no applicationInfo.");
             return false;
         }
-        boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
+        boolean useEncryptedFSDir = false;
         if (mInstaller != null) {
             int retCode = mInstaller.deleteCacheFiles(packageName, useEncryptedFSDir);
             if (retCode < 0) {
@@ -6625,18 +6687,16 @@
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
-                PackageStats lStats = new PackageStats(packageName);
-                final boolean succeded;
+                PackageStats stats = new PackageStats(packageName);
+
+                final boolean success;
                 synchronized (mInstallLock) {
-                    succeded = getPackageSizeInfoLI(packageName, lStats);
+                    success = getPackageSizeInfoLI(packageName, stats);
                 }
-                if(observer != null) {
-                    try {
-                        observer.onGetStatsCompleted(lStats, succeded);
-                    } catch (RemoteException e) {
-                        Log.i(TAG, "Observer no longer exists.");
-                    }
-                } //end if observer
+
+                Message msg = mHandler.obtainMessage(INIT_COPY);
+                msg.obj = new MeasureParams(stats, success, observer);
+                mHandler.sendMessage(msg);
             } //end run
         });
     }
@@ -6669,7 +6729,7 @@
             }
             publicSrcDir = isForwardLocked(p) ? applicationInfo.publicSourceDir : null;
         }
-        boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(p);
+        boolean useEncryptedFSDir = false;
         if (mInstaller != null) {
             int res = mInstaller.getSizeInfo(packageName, p.mPath,
                     publicSrcDir, pStats, useEncryptedFSDir);
@@ -7842,8 +7902,7 @@
             this.pkgFlags = pkgFlags & (
                     ApplicationInfo.FLAG_SYSTEM |
                     ApplicationInfo.FLAG_FORWARD_LOCK |
-                    ApplicationInfo.FLAG_EXTERNAL_STORAGE |
-                    ApplicationInfo.FLAG_NEVER_ENCRYPT);
+                    ApplicationInfo.FLAG_EXTERNAL_STORAGE);
         }
     }
 
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 1b590ba..cf07239 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -37,6 +37,7 @@
 import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WpsConfiguration;
+import android.net.wifi.WpsResult;
 import android.net.ConnectivityManager;
 import android.net.InterfaceConfiguration;
 import android.net.DhcpInfo;
@@ -841,13 +842,13 @@
         mWifiStateMachine.forgetNetwork(netId);
     }
 
-    public String startWps(WpsConfiguration config) {
+    public WpsResult startWps(WpsConfiguration config) {
         enforceChangePermission();
         if (mChannel != null) {
             return mWifiStateMachine.startWps(mChannel, config);
         } else {
             Slog.e(TAG, "mChannel is not initialized");
-            return "";
+            return new WpsResult(WpsResult.Status.FAILURE);
         }
     }
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 154b822..65ad956 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2132,6 +2132,9 @@
     sh = (!sh) ? hw_h : sh;
     const size_t size = sw * sh * 4;
 
+    LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
+            sw, sh, minLayerZ, maxLayerZ);
+
     // make sure to clear all GL error flags
     while ( glGetError() != GL_NO_ERROR ) ;
 
@@ -2146,6 +2149,9 @@
             GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
 
     GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+
+    LOGD("screenshot: FBO created, status=0x%x", status);
+
     if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
 
         // invert everything, b/c glReadPixel() below will invert the FB
@@ -2161,6 +2167,8 @@
         glClearColor(0,0,0,1);
         glClear(GL_COLOR_BUFFER_BIT);
 
+        LOGD("screenshot: glClear() issued");
+
         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; ++i) {
@@ -2171,6 +2179,8 @@
             }
         }
 
+        LOGD("screenshot: All layers rendered");
+
         // XXX: this is needed on tegra
         glScissor(0, 0, sw, sh);
 
@@ -2185,6 +2195,10 @@
                     new MemoryHeapBase(size, 0, "screen-capture") );
             void* const ptr = base->getBase();
             if (ptr) {
+
+                LOGD("screenshot: about to call glReadPixels(0,0,%d,%d,...,%p)",
+                        sw, sh, ptr);
+
                 // capture the screen with glReadPixels()
                 glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
                 if (glGetError() == GL_NO_ERROR) {
@@ -2197,25 +2211,32 @@
             } else {
                 result = NO_MEMORY;
             }
+
+            LOGD("screenshot: glReadPixels() returned %s", strerror(result));
+
         }
         glEnable(GL_SCISSOR_TEST);
         glViewport(0, 0, hw_w, hw_h);
         glMatrixMode(GL_PROJECTION);
         glPopMatrix();
         glMatrixMode(GL_MODELVIEW);
-
-
     } else {
         result = BAD_VALUE;
     }
 
+    LOGD("screenshot: about to release FBO resources");
+
     // release FBO resources
     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
     glDeleteRenderbuffersOES(1, &tname);
     glDeleteFramebuffersOES(1, &name);
 
+    LOGD("screenshot: about to call compositionComplete()");
+
     hw.compositionComplete();
 
+    LOGD("screenshot: result = %s", strerror(result));
+
     return result;
 }
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index e73afa0..7099ab5 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -25,6 +25,16 @@
         android:hardwareAccelerated="true">
 
         <activity
+                android:name="SimplePatchActivity"
+                android:label="_SimplePatch"
+                android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="ViewLayersActivity"
                 android:label="_ViewLayers">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png
new file mode 100644
index 0000000..d5c3276
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png
new file mode 100644
index 0000000..4515b42
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable-mdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java
new file mode 100644
index 0000000..a9b4d1c
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SimplePatchActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.View;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class SimplePatchActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        
+        setContentView(new PatchView(this));
+    }
+
+    private static class PatchView extends View {
+        private final Drawable mDrawable;
+
+        public PatchView(Context context) {
+            super(context);
+            setBackgroundColor(0xff000000);
+            mDrawable = context.getResources().getDrawable(R.drawable.expander_ic_minimized);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            super.onDraw(canvas);
+            canvas.save();
+            canvas.translate(200, 200);
+            mDrawable.setBounds(3, 0, 33, 64);
+            mDrawable.draw(canvas);
+            mDrawable.setBounds(63, 0, 94, 64);
+            mDrawable.draw(canvas);
+            canvas.restore();
+        }
+    }
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 9dbba20..847577f 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -19,6 +19,7 @@
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WpsConfiguration;
+import android.net.wifi.WpsResult;
 import android.net.wifi.ScanResult;
 import android.net.DhcpInfo;
 
@@ -109,6 +110,6 @@
 
     void forgetNetwork(int networkId);
 
-    String startWps(in WpsConfiguration config);
+    WpsResult startWps(in WpsConfiguration config);
 }
 
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 56bc5d7..73c24cf 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -370,44 +370,52 @@
      * Start WPS pin method configuration with pin obtained
      * from the access point
      */
-    static boolean startWpsWithPinFromAccessPoint(WpsConfiguration config) {
+    static WpsResult startWpsWithPinFromAccessPoint(WpsConfiguration config) {
+        WpsResult result = new WpsResult();
         if (WifiNative.startWpsWithPinFromAccessPointCommand(config.BSSID, config.pin)) {
             /* WPS leaves all networks disabled */
             markAllNetworksDisabled();
-            return true;
+            result.status = WpsResult.Status.SUCCESS;
+        } else {
+            Log.e(TAG, "Failed to start WPS pin method configuration");
+            result.status = WpsResult.Status.FAILURE;
         }
-        Log.e(TAG, "Failed to start WPS pin method configuration");
-        return false;
+        return result;
     }
 
     /**
      * Start WPS pin method configuration with pin obtained
      * from the device
-     * @return empty string on failure. null is never returned.
+     * @return WpsResult indicating status and pin
      */
-    static String startWpsWithPinFromDevice(WpsConfiguration config) {
-        String pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID);
+    static WpsResult startWpsWithPinFromDevice(WpsConfiguration config) {
+        WpsResult result = new WpsResult();
+        result.pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID);
         /* WPS leaves all networks disabled */
-        if (!TextUtils.isEmpty(pin)) {
+        if (!TextUtils.isEmpty(result.pin)) {
             markAllNetworksDisabled();
+            result.status = WpsResult.Status.SUCCESS;
         } else {
             Log.e(TAG, "Failed to start WPS pin method configuration");
-            pin = "";
+            result.status = WpsResult.Status.FAILURE;
         }
-        return pin;
+        return result;
     }
 
     /**
      * Start WPS push button configuration
      */
-    static boolean startWpsPbc(WpsConfiguration config) {
+    static WpsResult startWpsPbc(WpsConfiguration config) {
+        WpsResult result = new WpsResult();
         if (WifiNative.startWpsPbcCommand(config.BSSID)) {
             /* WPS leaves all networks disabled */
             markAllNetworksDisabled();
-            return true;
+            result.status = WpsResult.Status.SUCCESS;
+        } else {
+            Log.e(TAG, "Failed to start WPS push button configuration");
+            result.status = WpsResult.Status.FAILURE;
         }
-        Log.e(TAG, "Failed to start WPS push button configuration");
-        return false;
+        return result;
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4623721..d05918f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -274,6 +274,25 @@
      * @see #ERROR_AUTHENTICATING
      */
     public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+
+    /**
+     * Broadcast intent action for reporting errors
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ERROR_ACTION = "android.net.wifi.ERROR";
+    /**
+     * The type of error being reported
+     * @hide
+     */
+    public static final String EXTRA_ERROR_CODE = "errorCode";
+
+    /**
+     * Valid error codes
+     * @hide
+     */
+    public static final int WPS_OVERLAP_ERROR = 1;
+
     /**
      * Broadcast intent action indicating that the configured networks changed.
      * This can be as a result of adding/updating/deleting a network
@@ -1074,15 +1093,15 @@
      * Start Wi-fi Protected Setup
      *
      * @param config WPS configuration
-     * @return pin generated by device, if any
+     * @return WpsResult containing pin and status
      * @hide
      * TODO: with use of AsyncChannel, return value should go away
      */
-    public String startWps(WpsConfiguration config) {
+    public WpsResult startWps(WpsConfiguration config) {
         try {
             return mService.startWps(config);
         } catch (RemoteException e) {
-            return null;
+            return new WpsResult(WpsResult.Status.FAILURE);
         }
     }
 
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index 934e509..090ad3b 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -53,6 +53,9 @@
     private static final String passwordKeyMayBeIncorrectEvent =
        "pre-shared key may be incorrect";
 
+    /* WPS events */
+    private static final String wpsOverlapEvent = "WPS-OVERLAP-DETECTED";
+
     /**
      * Names of events from wpa_supplicant (minus the prefix). In the
      * format descriptions, * &quot;<code>x</code>&quot;
@@ -174,6 +177,8 @@
                     if (eventStr.startsWith(wpaEventPrefix) &&
                             0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) {
                         handlePasswordKeyMayBeIncorrect();
+                    } else if (eventStr.startsWith(wpsOverlapEvent)) {
+                        mWifiStateMachine.notifyWpsOverlap();
                     }
                     continue;
                 }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 8718117..0548b4d 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -47,6 +47,7 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.LinkProperties;
 import android.net.wifi.NetworkUpdateResult;
+import android.net.wifi.WpsResult.Status;
 import android.os.Binder;
 import android.os.Message;
 import android.os.IBinder;
@@ -214,6 +215,9 @@
     static final int SUPPLICANT_STATE_CHANGE_EVENT        = 39;
     /* Password may be incorrect */
     static final int PASSWORD_MAY_BE_INCORRECT_EVENT      = 40;
+    /* WPS overlap detected */
+    static final int WPS_OVERLAP_EVENT                    = 41;
+
 
     /* Supplicant commands */
     /* Is supplicant alive ? */
@@ -302,10 +306,11 @@
     /* Reset the supplicant state tracker */
     static final int CMD_RESET_SUPPLICANT_STATE           = 111;
 
-
     /* Commands/events reported by WpsStateMachine */
     /* Indicates the completion of WPS activity */
     static final int WPS_COMPLETED_EVENT                  = 121;
+    /* Reset the WPS state machine */
+    static final int CMD_RESET_WPS_STATE                  = 122;
 
     private static final int CONNECT_MODE   = 1;
     private static final int SCAN_ONLY_MODE = 2;
@@ -793,18 +798,19 @@
         sendMessage(obtainMessage(CMD_FORGET_NETWORK, netId, 0));
     }
 
-    public String startWps(AsyncChannel channel, WpsConfiguration config) {
-        String result = null;
+    public WpsResult startWps(AsyncChannel channel, WpsConfiguration config) {
+        WpsResult result;
         switch (config.setup) {
             case PIN_FROM_DEVICE:
-                //TODO: will go away with AsyncChannel use from settings
-                Message resultMsg = channel.sendMessageSynchronously(CMD_START_WPS, config);
-                result = (String) resultMsg.obj;
-                resultMsg.recycle();
-                break;
             case PBC:
             case PIN_FROM_ACCESS_POINT:
-                sendMessage(obtainMessage(CMD_START_WPS, config));
+                //TODO: will go away with AsyncChannel use from settings
+                Message resultMsg = channel.sendMessageSynchronously(CMD_START_WPS, config);
+                result = (WpsResult) resultMsg.obj;
+                resultMsg.recycle();
+                break;
+            default:
+                result = new WpsResult(Status.FAILURE);
                 break;
         }
         return result;
@@ -1284,6 +1290,13 @@
         mContext.sendStickyBroadcast(intent);
     }
 
+    private void sendErrorBroadcast(int errorCode) {
+        Intent intent = new Intent(WifiManager.ERROR_ACTION);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(WifiManager.EXTRA_ERROR_CODE, errorCode);
+        mContext.sendBroadcast(intent);
+    }
+
     private void sendLinkConfigurationChangedBroadcast() {
         Intent intent = new Intent(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -1379,6 +1392,14 @@
     }
 
     /**
+     * Send a notification that the supplicant has detected overlapped
+     * WPS sessions
+     */
+    void notifyWpsOverlap() {
+        sendMessage(WPS_OVERLAP_EVENT);
+    }
+
+    /**
      * Send the tracker a notification that a connection to the supplicant
      * daemon has been established.
      */
@@ -1496,6 +1517,7 @@
                 case SCAN_RESULTS_EVENT:
                 case SUPPLICANT_STATE_CHANGE_EVENT:
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
+                case WPS_OVERLAP_EVENT:
                 case CMD_BLACKLIST_NETWORK:
                 case CMD_CLEAR_BLACKLIST:
                 case CMD_SET_SCAN_MODE:
@@ -1511,13 +1533,9 @@
                 case CMD_ENABLE_ALL_NETWORKS:
                     break;
                 case CMD_START_WPS:
-                    WpsConfiguration config = (WpsConfiguration) message.obj;
-                    switch (config.setup) {
-                        case PIN_FROM_DEVICE:
-                            String pin = "";
-                            mReplyChannel.replyToMessage(message, message.what, pin);
-                            break;
-                    }
+                    /* Return failure when the state machine cannot handle WPS initiation*/
+                    mReplyChannel.replyToMessage(message, message.what,
+                                new WpsResult(Status.FAILURE));
                     break;
                 default:
                     Log.e(TAG, "Error! unhandled message" + message);
@@ -1803,6 +1821,7 @@
                     /* Reset the supplicant state to indicate the supplicant
                      * state is not known at this time */
                     mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
+                    mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE);
                     /* Initialize data structures */
                     mLastBssid = null;
                     mLastNetworkId = -1;
@@ -1884,6 +1903,7 @@
                     setWifiState(WIFI_STATE_DISABLING);
                     sendSupplicantConnectionChangedBroadcast(false);
                     mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
+                    mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE);
                     transitionTo(mSupplicantStoppingState);
                     break;
                 case SUP_DISCONNECTION_EVENT:  /* Supplicant connection lost */
@@ -1894,6 +1914,7 @@
                     handleNetworkDisconnect();
                     sendSupplicantConnectionChangedBroadcast(false);
                     mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
+                    mWpsStateMachine.sendMessage(CMD_RESET_WPS_STATE);
                     transitionTo(mDriverLoadedState);
                     sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
                     break;
@@ -2040,6 +2061,7 @@
                 case NETWORK_CONNECTION_EVENT:
                 case NETWORK_DISCONNECTION_EVENT:
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
+                case WPS_OVERLAP_EVENT:
                 case CMD_SET_SCAN_TYPE:
                 case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_COUNTRY_CODE:
@@ -2274,6 +2296,10 @@
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
                     mSupplicantStateTracker.sendMessage(PASSWORD_MAY_BE_INCORRECT_EVENT);
                     break;
+                case WPS_OVERLAP_EVENT:
+                    /* We just need to broadcast the error */
+                    sendErrorBroadcast(WifiManager.WPS_OVERLAP_ERROR);
+                    break;
                 case SUPPLICANT_STATE_CHANGE_EVENT:
                     stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
diff --git a/wifi/java/android/net/wifi/WpsResult.aidl b/wifi/java/android/net/wifi/WpsResult.aidl
new file mode 100644
index 0000000..eb4c4f5
--- /dev/null
+++ b/wifi/java/android/net/wifi/WpsResult.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable WpsResult;
diff --git a/wifi/java/android/net/wifi/WpsResult.java b/wifi/java/android/net/wifi/WpsResult.java
new file mode 100644
index 0000000..d4fd3e2
--- /dev/null
+++ b/wifi/java/android/net/wifi/WpsResult.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class representing the result of a WPS request
+ * @hide
+ */
+public class WpsResult implements Parcelable {
+
+    public enum Status {
+        SUCCESS,
+        FAILURE,
+        IN_PROGRESS,
+    }
+
+    public Status status;
+
+    public String pin;
+
+    public WpsResult() {
+        status = Status.FAILURE;
+        pin = null;
+    }
+
+    public WpsResult(Status s) {
+        status = s;
+        pin = null;
+    }
+
+    public String toString() {
+        StringBuffer sbuf = new StringBuffer();
+        sbuf.append(" status: ").append(status.toString());
+        sbuf.append('\n');
+        sbuf.append(" pin: ").append(pin);
+        sbuf.append("\n");
+        return sbuf.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** copy constructor {@hide} */
+    public WpsResult(WpsResult source) {
+        if (source != null) {
+            status = source.status;
+            pin = source.pin;
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(status.name());
+        dest.writeString(pin);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WpsResult> CREATOR =
+        new Creator<WpsResult>() {
+            public WpsResult createFromParcel(Parcel in) {
+                WpsResult result = new WpsResult();
+                result.status = Status.valueOf(in.readString());
+                result.pin = in.readString();
+                return result;
+            }
+
+            public WpsResult[] newArray(int size) {
+                return new WpsResult[size];
+            }
+        };
+}
diff --git a/wifi/java/android/net/wifi/WpsStateMachine.java b/wifi/java/android/net/wifi/WpsStateMachine.java
index 381444c..92f9f57 100644
--- a/wifi/java/android/net/wifi/WpsStateMachine.java
+++ b/wifi/java/android/net/wifi/WpsStateMachine.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.wifi.WifiStateMachine.StateChangeResult;
+import android.net.wifi.WpsResult.Status;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Parcelable;
@@ -93,29 +94,32 @@
             switch (message.what) {
                 case WifiStateMachine.CMD_START_WPS:
                     mWpsConfig = (WpsConfiguration) message.obj;
-                    boolean success = false;
+                    WpsResult result;
                     switch (mWpsConfig.setup) {
                         case PBC:
-                            success = WifiConfigStore.startWpsPbc(mWpsConfig);
+                            result = WifiConfigStore.startWpsPbc(mWpsConfig);
                             break;
                         case PIN_FROM_ACCESS_POINT:
-                            success = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig);
+                            result = WifiConfigStore.startWpsWithPinFromAccessPoint(mWpsConfig);
                             break;
                         case PIN_FROM_DEVICE:
-                            String pin = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig);
-                            success = (pin != null);
-                            mReplyChannel.replyToMessage(message, message.what, pin);
+                            result = WifiConfigStore.startWpsWithPinFromDevice(mWpsConfig);
                             break;
                         default:
+                            result = new WpsResult(Status.FAILURE);
                             Log.e(TAG, "Invalid setup for WPS");
                             break;
                     }
-                    if (success) {
+                    mReplyChannel.replyToMessage(message, message.what, result);
+                    if (result.status == Status.SUCCESS) {
                         transitionTo(mActiveState);
                     } else {
                         Log.e(TAG, "Failed to start WPS with config " + mWpsConfig.toString());
                     }
                     break;
+                case WifiStateMachine.CMD_RESET_WPS_STATE:
+                    transitionTo(mInactiveState);
+                    break;
                 default:
                     Log.e(TAG, "Failed to handle " + message);
                     break;
@@ -167,7 +171,9 @@
                     }
                     break;
                 case WifiStateMachine.CMD_START_WPS:
-                    deferMessage(message);
+                    /* Ignore request and send an in progress message */
+                    mReplyChannel.replyToMessage(message, message.what,
+                                new WpsResult(Status.IN_PROGRESS));
                     break;
                 default:
                     retValue = NOT_HANDLED;
@@ -197,4 +203,4 @@
         }
     }
 
-}
\ No newline at end of file
+}