Merge "Fix rendering of digitalClock/Gallery in Eclipse editors."
diff --git a/api/current.xml b/api/current.xml
index 715b49a..bac65eb 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -40322,13 +40322,15 @@
 </method>
 </class>
 <class name="ClipData"
- extends="android.content.ClipDescription"
+ extends="java.lang.Object"
  abstract="false"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
 <constructor name="ClipData"
  type="android.content.ClipData"
  static="false"
@@ -40345,6 +40347,20 @@
 <parameter name="item" type="android.content.ClipData.Item">
 </parameter>
 </constructor>
+<constructor name="ClipData"
+ type="android.content.ClipData"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="description" type="android.content.ClipDescription">
+</parameter>
+<parameter name="icon" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="item" type="android.content.ClipData.Item">
+</parameter>
+</constructor>
 <method name="addItem"
  return="void"
  abstract="false"
@@ -40358,6 +40374,28 @@
 <parameter name="item" type="android.content.ClipData.Item">
 </parameter>
 </method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDescription"
+ return="android.content.ClipDescription"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getIcon"
  return="android.graphics.Bitmap"
  abstract="false"
@@ -40463,6 +40501,21 @@
 <parameter name="uri" type="android.net.Uri">
 </parameter>
 </method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <field name="CREATOR"
  type="android.os.Parcelable.Creator"
  transient="false"
diff --git a/core/java/android/content/ClipData.java b/core/java/android/content/ClipData.java
index a19b132..6f4d098 100644
--- a/core/java/android/content/ClipData.java
+++ b/core/java/android/content/ClipData.java
@@ -37,8 +37,9 @@
  * each of which can hold one or more representations of an item of data.
  * For display to the user, it also has a label and iconic representation.</p>
  *
- * <p>A ClipData is a sub-class of {@link ClipDescription}, which describes
- * important meta-data about the clip.  In particular, its {@link #getMimeType(int)}
+ * <p>A ClipData contains a {@link ClipDescription}, which describes
+ * important meta-data about the clip.  In particular, its
+ * {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)}
  * must return correct MIME type(s) describing the data in the clip.  For help
  * in correctly constructing a clip with the correct MIME type, use
  * {@link #newPlainText(CharSequence, Bitmap, CharSequence)},
@@ -62,8 +63,8 @@
  * <p>If all you want is the textual representation of the clipped data, you
  * can use the convenience method {@link Item#coerceToText Item.coerceToText}.
  * In this case there is generally no need to worry about the MIME types
- * reported by {@link #getMimeType(int)}, since any clip item an always be
- * converted to a string.
+ * reported by {@link ClipDescription#getMimeType(int) getDescription().getMimeType(int)},
+ * since any clip item an always be converted to a string.
  *
  * <p>More complicated exchanges will be done through URIs, in particular
  * "content:" URIs.  A content URI allows the recipient of a ClippedData item
@@ -133,11 +134,16 @@
  * into an editor), then {@link Item#coerceToText(Context)} will ask the content
  * provider for the clip URI as text and successfully paste the entire note.
  */
-public class ClipData extends ClipDescription {
-    static final String[] MIMETYPES_TEXT_PLAIN = new String[] { MIMETYPE_TEXT_PLAIN };
-    static final String[] MIMETYPES_TEXT_URILIST = new String[] { MIMETYPE_TEXT_URILIST };
-    static final String[] MIMETYPES_TEXT_INTENT = new String[] { MIMETYPE_TEXT_INTENT };
+public class ClipData implements Parcelable {
+    static final String[] MIMETYPES_TEXT_PLAIN = new String[] {
+        ClipDescription.MIMETYPE_TEXT_PLAIN };
+    static final String[] MIMETYPES_TEXT_URILIST = new String[] {
+        ClipDescription.MIMETYPE_TEXT_URILIST };
+    static final String[] MIMETYPES_TEXT_INTENT = new String[] {
+        ClipDescription.MIMETYPE_TEXT_INTENT };
 
+    final ClipDescription mClipDescription;
+    
     final Bitmap mIcon;
 
     final ArrayList<Item> mItems = new ArrayList<Item>();
@@ -320,7 +326,7 @@
      * @param item The contents of the first item in the clip.
      */
     public ClipData(CharSequence label, String[] mimeTypes, Bitmap icon, Item item) {
-        super(label, mimeTypes);
+        mClipDescription = new ClipDescription(label, mimeTypes);
         if (item == null) {
             throw new NullPointerException("item is null");
         }
@@ -329,7 +335,25 @@
     }
 
     /**
-     * Create a new ClipData holding data of the type {@link #MIMETYPE_TEXT_PLAIN}.
+     * Create a new clip.
+     *
+     * @param description The ClipDescription describing the clip contents.
+     * @param icon Bitmap providing the user with an iconing representation of
+     * the clip.
+     * @param item The contents of the first item in the clip.
+     */
+    public ClipData(ClipDescription description, Bitmap icon, Item item) {
+        mClipDescription = description;
+        if (item == null) {
+            throw new NullPointerException("item is null");
+        }
+        mIcon = icon;
+        mItems.add(item);
+    }
+
+    /**
+     * Create a new ClipData holding data of the type
+     * {@link ClipDescription#MIMETYPE_TEXT_PLAIN}.
      *
      * @param label User-visible label for the clip data.
      * @param icon Iconic representation of the clip data.
@@ -342,7 +366,8 @@
     }
 
     /**
-     * Create a new ClipData holding an Intent with MIME type {@link #MIMETYPE_TEXT_INTENT}.
+     * Create a new ClipData holding an Intent with MIME type
+     * {@link ClipDescription#MIMETYPE_TEXT_INTENT}.
      *
      * @param label User-visible label for the clip data.
      * @param icon Iconic representation of the clip data.
@@ -358,7 +383,7 @@
      * Create a new ClipData holding a URI.  If the URI is a content: URI,
      * this will query the content provider for the MIME type of its data and
      * use that as the MIME type.  Otherwise, it will use the MIME type
-     * {@link #MIMETYPE_TEXT_URILIST}.
+     * {@link ClipDescription#MIMETYPE_TEXT_URILIST}.
      *
      * @param resolver ContentResolver used to get information about the URI.
      * @param label User-visible label for the clip data.
@@ -375,7 +400,7 @@
             mimeTypes = resolver.getStreamTypes(uri, "*/*");
             if (mimeTypes == null) {
                 if (realType != null) {
-                    mimeTypes = new String[] { realType, MIMETYPE_TEXT_URILIST };
+                    mimeTypes = new String[] { realType, ClipDescription.MIMETYPE_TEXT_URILIST };
                 }
             } else {
                 String[] tmp = new String[mimeTypes.length + (realType != null ? 2 : 1)];
@@ -385,7 +410,7 @@
                     i++;
                 }
                 System.arraycopy(mimeTypes, 0, tmp, i, mimeTypes.length);
-                tmp[i + mimeTypes.length] = MIMETYPE_TEXT_URILIST;
+                tmp[i + mimeTypes.length] = ClipDescription.MIMETYPE_TEXT_URILIST;
                 mimeTypes = tmp;
             }
         }
@@ -396,7 +421,8 @@
     }
 
     /**
-     * Create a new ClipData holding an URI with MIME type {@link #MIMETYPE_TEXT_URILIST}.
+     * Create a new ClipData holding an URI with MIME type
+     * {@link ClipDescription#MIMETYPE_TEXT_URILIST}.
      * Unlike {@link #newUri(ContentResolver, CharSequence, Bitmap, Uri)}, nothing
      * is inferred about the URI -- if it is a content: URI holding a bitmap,
      * the reported type will still be uri-list.  Use this with care!
@@ -411,6 +437,14 @@
         return new ClipData(label, MIMETYPES_TEXT_URILIST, icon, item);
     }
 
+    /**
+     * Return the {@link ClipDescription} associated with this data, describing
+     * what it contains.
+     */
+    public ClipDescription getDescription() {
+        return mClipDescription;
+    }
+    
     public void addItem(Item item) {
         if (item == null) {
             throw new NullPointerException("item is null");
@@ -437,7 +471,7 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
+        mClipDescription.writeToParcel(dest, flags);
         if (mIcon != null) {
             dest.writeInt(1);
             mIcon.writeToParcel(dest, flags);
@@ -465,7 +499,7 @@
     }
 
     ClipData(Parcel in) {
-        super(in);
+        mClipDescription = new ClipDescription(in);
         if (in.readInt() != 0) {
             mIcon = Bitmap.CREATOR.createFromParcel(in);
         } else {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0456463..87e03cf 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7579,6 +7579,11 @@
      * the auto scaling to true. Doing so, however, will generate a bitmap of a different
      * size than the view. This implies that your application must be able to handle this
      * size.</p>
+     * 
+     * <p>You should avoid calling this method when hardware acceleration is enabled. If
+     * you do not need the drawing cache bitmap, calling this method will increase memory
+     * usage and cause the view to be rendered in software once, thus negatively impacting 
+     * performance.</p>
      *
      * @see #getDrawingCache()
      * @see #destroyDrawingCache()
@@ -7699,7 +7704,9 @@
             canvas.translate(-mScrollX, -mScrollY);
 
             mPrivateFlags |= DRAWN;
-            mPrivateFlags |= DRAWING_CACHE_VALID;
+            if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated) {
+                mPrivateFlags |= DRAWING_CACHE_VALID;
+            }
 
             // Fast path for layouts with no backgrounds
             if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7b2703b..b881bdd 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1867,12 +1867,15 @@
         if ((mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE) {
             final int count = mChildrenCount;
             final View[] children = mChildren;
+            final boolean buildCache = !isHardwareAccelerated();
 
             for (int i = 0; i < count; i++) {
                 final View child = children[i];
                 if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
                     child.setDrawingCacheEnabled(true);
-                    child.buildDrawingCache(true);
+                    if (buildCache) {
+                        child.buildDrawingCache(true);
+                    }
                 }
             }
 
@@ -1933,6 +1936,7 @@
         if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {
             final boolean cache = (mGroupFlags & FLAG_ANIMATION_CACHE) == FLAG_ANIMATION_CACHE;
 
+            final boolean buildCache = !isHardwareAccelerated();
             for (int i = 0; i < count; i++) {
                 final View child = children[i];
                 if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {
@@ -1941,7 +1945,9 @@
                     bindLayoutAnimation(child);
                     if (cache) {
                         child.setDrawingCacheEnabled(true);
-                        child.buildDrawingCache(true);
+                        if (buildCache) {                        
+                            child.buildDrawingCache(true);
+                        }
                     }
                 }
             }
@@ -2205,8 +2211,7 @@
             if (!canvas.isHardwareAccelerated()) {
                 cache = child.getDrawingCache(true);
             } else {
-                // TODO: bring back
-                // displayList = child.getDisplayList();
+                displayList = child.getDisplayList();
             }
         }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 2e368b8..06261bb 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -561,6 +561,11 @@
             scheduleTraversals();
         }
     }
+    
+    void invalidate() {
+        mDirty.set(0, 0, mWidth, mHeight);
+        scheduleTraversals();
+    }
 
     public ViewParent getParent() {
         return null;
diff --git a/core/java/android/widget/SlidingDrawer.java b/core/java/android/widget/SlidingDrawer.java
index 11d72de..bdeb5c2 100644
--- a/core/java/android/widget/SlidingDrawer.java
+++ b/core/java/android/widget/SlidingDrawer.java
@@ -652,7 +652,7 @@
         // Try only once... we should really loop but it's not a big deal
         // if the draw was cancelled, it will only be temporary anyway
         content.getViewTreeObserver().dispatchOnPreDraw();
-        content.buildDrawingCache();
+        if (!content.isHardwareAccelerated()) content.buildDrawingCache();
 
         content.setVisibility(View.GONE);        
     }
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 0e92eeb..e6d5984 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -114,6 +114,7 @@
     private int mTouchSlop;
     private int mMaximumVelocity;
     private VelocityTracker mVelocityTracker;
+    private boolean mTransitionIsSetup = false;
 
     private static HolographicHelper sHolographicHelper;
     private ImageView mHighlight;
@@ -225,6 +226,48 @@
         }
     }
 
+    private void setupStackSlider(View v, int mode) {
+        mStackSlider.setMode(mode);
+        if (v != null) {
+            mHighlight.setImageBitmap(sHolographicHelper.createOutline(v));
+            mHighlight.setRotation(v.getRotation());
+            mHighlight.setTranslationY(v.getTranslationY());
+            mHighlight.bringToFront();
+            v.bringToFront();
+            mStackSlider.setView(v);
+
+            v.setVisibility(VISIBLE);
+        }
+    }
+
+    @Override
+    @android.view.RemotableViewMethod
+    public void showNext() {
+        if (!mTransitionIsSetup) {
+            View v = getViewAtRelativeIndex(1);
+            if (v != null) {
+                setupStackSlider(v, StackSlider.NORMAL_MODE);
+                mStackSlider.setYProgress(0);
+                mStackSlider.setXProgress(0);
+            }
+        }
+        super.showNext();
+    }
+
+    @Override
+    @android.view.RemotableViewMethod
+    public void showPrevious() {
+        if (!mTransitionIsSetup) {
+            View v = getViewAtRelativeIndex(0);
+            if (v != null) {
+                setupStackSlider(v, StackSlider.NORMAL_MODE);
+                mStackSlider.setYProgress(1);
+                mStackSlider.setXProgress(0);
+            }
+        }
+        super.showPrevious();
+    }
+
     private void transformViewAtIndex(int index, View view) {
         float maxPerpectiveShift = mMeasuredHeight * PERSPECTIVE_SHIFT_FACTOR;
 
@@ -256,11 +299,12 @@
         super.showOnly(childIndex, animate, onLayout);
 
         // Here we need to make sure that the z-order of the children is correct
-	for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
+        for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
             int index = modulo(i, getWindowSize());
             View v = mViewsMap.get(index).view;
             if (v != null) v.bringToFront();
         }
+        mTransitionIsSetup = false;
     }
 
     private void updateChildTransforms() {
@@ -364,29 +408,24 @@
                 activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0;
             }
 
+            int stackMode;
             if (mLoopViews) {
-                mStackSlider.setMode(StackSlider.NORMAL_MODE);
+                stackMode = StackSlider.NORMAL_MODE;
             } else if (mCurrentWindowStartUnbounded + activeIndex == -1) {
                 activeIndex++;
-                mStackSlider.setMode(StackSlider.BEGINNING_OF_STACK_MODE);
+                stackMode = StackSlider.BEGINNING_OF_STACK_MODE;
             } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount() - 1) {
-                mStackSlider.setMode(StackSlider.END_OF_STACK_MODE);
+                stackMode = StackSlider.END_OF_STACK_MODE;
             } else {
-                mStackSlider.setMode(StackSlider.NORMAL_MODE);
+                stackMode = StackSlider.NORMAL_MODE;
             }
 
+            mTransitionIsSetup = stackMode == StackSlider.NORMAL_MODE;
+
             View v = getViewAtRelativeIndex(activeIndex);
             if (v == null) return;
 
-            mHighlight.setImageBitmap(sHolographicHelper.createOutline(v));
-            mHighlight.setRotation(v.getRotation());
-            mHighlight.setTranslationY(v.getTranslationY());
-            mHighlight.bringToFront();
-            v.bringToFront();
-            mStackSlider.setView(v);
-
-            if (swipeGestureType == GESTURE_SLIDE_DOWN)
-                v.setVisibility(VISIBLE);
+            setupStackSlider(v, stackMode);
 
             // We only register this gesture if we've made it this far without a problem
             mSwipeGestureType = swipeGestureType;
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 27d4b9e..a024420 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -571,6 +571,15 @@
     return doBooleanCommand("BLACKLIST clear", "OK");
 }
 
+static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject clazz, jboolean enabled)
+{
+    char cmdstr[BUF_SIZE];
+
+    snprintf(cmdstr, sizeof(cmdstr), "DRIVER SETSUSPENDOPT %d", enabled ? 0 : 1);
+    return doBooleanCommand(cmdstr, "OK");
+}
+
+
 static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info)
 {
     jint ipaddr, gateway, mask, dns1, dns2, server, lease;
@@ -657,6 +666,8 @@
         (void*) android_net_wifi_wpsPinFromAccessPointCommand },
     { "startWpsWithPinFromDeviceCommand", "(Ljava/lang/String;)I",
         (void*) android_net_wifi_wpsPinFromDeviceCommand },
+    { "setSuspendOptimizationsCommand", "(Z)Z",
+        (void*) android_net_wifi_setSuspendOptimizationsCommand},
     { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
 };
diff --git a/drm/drmserver/DrmManagerService.cpp b/drm/drmserver/DrmManagerService.cpp
index 843dddb..cf9bab12f 100644
--- a/drm/drmserver/DrmManagerService.cpp
+++ b/drm/drmserver/DrmManagerService.cpp
@@ -28,25 +28,10 @@
 using namespace android;
 
 #define SUCCESS 0
-#define DRM_DIRECTORY_PERMISSION 0700
-#define DRM_PLUGINS_ROOT "/data/drm/plugins"
-#define DRM_PLUGINS_NATIVE "/data/drm/plugins/native"
-#define DRM_PLUGINS_NATIVE_DATABASES "/data/drm/plugins/native/databases"
 
 void DrmManagerService::instantiate() {
     LOGV("instantiate");
-
-    int res = mkdir(DRM_PLUGINS_ROOT, DRM_DIRECTORY_PERMISSION);
-    if (SUCCESS == res || EEXIST == errno) {
-        res = mkdir(DRM_PLUGINS_NATIVE, DRM_DIRECTORY_PERMISSION);
-        if (SUCCESS == res || EEXIST == errno) {
-            res = mkdir(DRM_PLUGINS_NATIVE_DATABASES, DRM_DIRECTORY_PERMISSION);
-            if (SUCCESS == res || EEXIST == errno) {
-                defaultServiceManager()
-                    ->addService(String16("drm.drmManager"), new DrmManagerService());
-            }
-        }
-    }
+    defaultServiceManager()->addService(String16("drm.drmManager"), new DrmManagerService());
 }
 
 DrmManagerService::DrmManagerService() {
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 6c08ce5..f8ad5cc 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -194,11 +194,15 @@
         mRS.nAllocationRead(mID, d);
     }
 
-    public void resize(int dimX) {
+    public synchronized void resize(int dimX) {
         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) {
             throw new IllegalStateException("Resize only support for 1D allocations at this time.");
         }
         mRS.nAllocationResize1D(mID, dimX);
+
+        int typeID = mRS.nAllocationGetType(mID);
+        mType = new Type(typeID, mRS);
+        mType.updateFromNative();
     }
 
     /*
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 53a33e4..430789a 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -112,12 +112,10 @@
 
     public static class FieldBase {
         protected Element mElement;
-        protected Type mType;
         protected Allocation mAllocation;
 
         protected void init(RenderScript rs, int dimx) {
             mAllocation = Allocation.createSized(rs, mElement, dimx);
-            mType = mAllocation.getType();
         }
 
         protected FieldBase() {
@@ -128,7 +126,7 @@
         }
 
         public Type getType() {
-            return mType;
+            return mAllocation.getType();
         }
 
         public Allocation getAllocation() {
@@ -138,19 +136,6 @@
         //@Override
         public void updateAllocation() {
         }
-
-
-        //
-        /*
-        public class ScriptField_UserField
-            extends android.renderscript.Script.FieldBase {
-
-            protected
-
-        }
-
-        */
-
     }
 }
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 16d5bfe..dd108c0 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -377,7 +377,7 @@
 nAllocationCreateTyped(JNIEnv *_env, jobject _this, RsContext con, jint e)
 {
     LOG_API("nAllocationCreateTyped, con(%p), e(%p)", con, (RsElement)e);
-    return (jint) rsAllocationCreateTyped(con, (RsElement)e);
+    return (jint) rsaAllocationCreateTyped(con, (RsElement)e);
 }
 
 static void
@@ -428,7 +428,7 @@
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsaAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
@@ -488,7 +488,7 @@
         const int w = bitmap.width();
         const int h = bitmap.height();
         const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
+        jint id = (jint)rsaAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr);
         bitmap.unlockPixels();
         return id;
     }
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index e0094d8..0994d82 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -43,6 +43,8 @@
     glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
     glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
 
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
+
     mCurrentBuffer = meshBuffer;
 }
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index aff5366..ca22867 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -23,6 +23,7 @@
 
 #include <utils/Singleton.h>
 
+#include "Extensions.h"
 #include "FontRenderer.h"
 #include "GammaFontRenderer.h"
 #include "TextureCache.h"
@@ -93,8 +94,15 @@
     GLenum lastDstMode;
     Program* currentProgram;
 
+    // VBO to draw with
     GLuint meshBuffer;
 
+    // GL extensions
+    Extensions extensions;
+
+    // Misc
+    GLint maxTextureSize;
+
     TextureCache textureCache;
     LayerCache layerCache;
     GradientCache gradientCache;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 8592511..b167131 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -107,8 +107,6 @@
     memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
 
     mFirstSnapshot = new Snapshot;
-
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
 }
 
 OpenGLRenderer::~OpenGLRenderer() {
@@ -129,6 +127,8 @@
 
     mFirstSnapshot->height = height;
     mFirstSnapshot->viewport.set(0, 0, width, height);
+
+    mDirtyClip = false;
 }
 
 void OpenGLRenderer::prepare(bool opaque) {
@@ -139,16 +139,18 @@
     glViewport(0, 0, mWidth, mHeight);
 
     glDisable(GL_DITHER);
-    glDisable(GL_SCISSOR_TEST);
 
     if (!opaque) {
+        glDisable(GL_SCISSOR_TEST);
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
+        glEnable(GL_SCISSOR_TEST);
+    } else {
+        glEnable(GL_SCISSOR_TEST);
+        glScissor(0, 0, mWidth, mHeight);
+        dirtyClip();
     }
 
-    glEnable(GL_SCISSOR_TEST);
-    glScissor(0, 0, mWidth, mHeight);
-
     mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
 }
 
@@ -175,7 +177,7 @@
     glViewport(0, 0, mSnapshot->viewport.getWidth(), mSnapshot->viewport.getHeight());
 
     glEnable(GL_SCISSOR_TEST);
-    setScissorFromClip();
+    dirtyClip();
 
     glDisable(GL_DITHER);
 
@@ -241,7 +243,7 @@
     }
 
     if (restoreClip) {
-        setScissorFromClip();
+        dirtyClip();
     }
 
     return restoreClip;
@@ -261,7 +263,7 @@
 
     if (p) {
         alpha = p->getAlpha();
-        if (!mExtensions.hasFramebufferFetch()) {
+        if (!mCaches.extensions.hasFramebufferFetch()) {
             const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
             if (!isMode) {
                 // Assume SRC_OVER
@@ -371,8 +373,8 @@
         bounds.intersect(snapshot->previous->viewport);
     }
 
-    if (bounds.isEmpty() || bounds.getWidth() > mMaxTextureSize ||
-            bounds.getHeight() > mMaxTextureSize) {
+    if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize ||
+            bounds.getHeight() > mCaches.maxTextureSize) {
         snapshot->invisible = true;
     } else {
         // TODO: Should take the mode into account
@@ -448,7 +450,7 @@
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        setScissorFromClip();
+        dirtyClip();
 
         // Change the ortho projection
         glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
@@ -506,6 +508,7 @@
     mCaches.unbindMeshBuffer();
     resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom);
 
+    glActiveTexture(gTextureUnits[0]);
     if (fboLayer) {
         drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
                 layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
@@ -528,6 +531,8 @@
         mCaches.fboCache.put(current->fbo);
     }
 
+    dirtyClip();
+
     // Failing to add the layer to the cache should happen only if the layer is too large
     if (!mCaches.layerCache.put(layer)) {
         LAYER_LOGD("Deleting layer");
@@ -536,6 +541,13 @@
     }
 }
 
+void OpenGLRenderer::setupDraw() {
+    clearLayerRegions();
+    if (mDirtyClip) {
+        setScissorFromClip();
+    }
+}
+
 void OpenGLRenderer::clearLayerRegions() {
     if (mLayers.size() == 0 || mSnapshot->invisible) return;
 
@@ -553,7 +565,7 @@
     mLayers.clear();
 
     // Restore the clip
-    setScissorFromClip();
+    dirtyClip();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -602,6 +614,7 @@
     Rect clip(*mSnapshot->clipRect);
     clip.snapToPixelBoundaries();
     glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight());
+    mDirtyClip = false;
 }
 
 const Rect& OpenGLRenderer::getClipBounds() {
@@ -626,7 +639,7 @@
 bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
     bool clipped = mSnapshot->clip(left, top, right, bottom, op);
     if (clipped) {
-        setScissorFromClip();
+        dirtyClip();
     }
     return !mSnapshot->clipRect->isEmpty();
 }
@@ -676,7 +689,7 @@
         return;
     }
 
-    glActiveTexture(GL_TEXTURE0);
+    glActiveTexture(gTextureUnits[0]);
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -711,7 +724,7 @@
         return;
     }
 
-    glActiveTexture(GL_TEXTURE0);
+    glActiveTexture(gTextureUnits[0]);
     Texture* texture = mCaches.textureCache.get(bitmap);
     if (!texture) return;
     const AutoTexture autoCleanup(texture);
@@ -749,6 +762,7 @@
     const bool isAA = paint->isAntiAlias();
     if (isAA) {
         GLuint textureUnit = 0;
+        glActiveTexture(gTextureUnits[textureUnit]);
         setupTextureAlpha8(mCaches.line.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a,
                 mode, false, true, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
                 mCaches.line.getMeshBuffer());
@@ -812,7 +826,7 @@
     }
 
     SkXfermode::Mode mode;
-    if (!mExtensions.hasFramebufferFetch()) {
+    if (!mCaches.extensions.hasFramebufferFetch()) {
         const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode);
         if (!isMode) {
             // Assume SRC_OVER
@@ -869,10 +883,7 @@
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
-    Rect clipRect(*mSnapshot->clipRect);
-    clipRect.snapToPixelBoundaries();
-    glScissor(clipRect.left, mSnapshot->height - clipRect.bottom,
-            clipRect.getWidth(), clipRect.getHeight());
+    setupDraw();
 
     if (mHasShadow) {
         glActiveTexture(gTextureUnits[0]);
@@ -897,7 +908,6 @@
             x, y, r, g, b, a, mode, false, true, NULL, NULL);
 
     const Rect& clip = mSnapshot->getLocalClip();
-    clearLayerRegions();
 
     mCaches.unbindMeshBuffer();
     fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
@@ -906,8 +916,6 @@
     glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
 
     drawTextDecorations(text, bytesCount, length, x, y, paint);
-
-    setScissorFromClip();
 }
 
 void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
@@ -939,7 +947,7 @@
 
     setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true);
 
-    clearLayerRegions();
+    setupDraw();
 
     // Draw the mesh
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -1035,10 +1043,10 @@
 
      if (applyFilters) {
          if (mShader) {
-             mShader->describe(description, mExtensions);
+             mShader->describe(description, mCaches.extensions);
          }
          if (mColorFilter) {
-             mColorFilter->describe(description, mExtensions);
+             mColorFilter->describe(description, mCaches.extensions);
          }
      }
 
@@ -1048,7 +1056,7 @@
      // Build and use the appropriate shader
      useProgram(mCaches.programCache.get(description));
 
-     bindTexture(texture, textureUnit);
+     bindTexture(texture);
      glUniform1i(mCaches.currentProgram->getUniform("sampler"), textureUnit);
 
      int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords");
@@ -1155,7 +1163,7 @@
 
 void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
         int color, SkXfermode::Mode mode, bool ignoreTransform) {
-    clearLayerRegions();
+    setupDraw();
 
     // If a shader is set, preserve only the alpha
     if (mShader) {
@@ -1184,10 +1192,10 @@
     const bool setColor = description.setColor(r, g, b, a);
 
     if (mShader) {
-        mShader->describe(description, mExtensions);
+        mShader->describe(description, mCaches.extensions);
     }
     if (mColorFilter) {
-        mColorFilter->describe(description, mExtensions);
+        mColorFilter->describe(description, mCaches.extensions);
     }
 
     // Setup the blending mode
@@ -1244,13 +1252,13 @@
         GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
         GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
         bool swapSrcDst, bool ignoreTransform, GLuint vbo) {
-    clearLayerRegions();
+    setupDraw();
 
     ProgramDescription description;
     description.hasTexture = true;
     const bool setColor = description.setColor(alpha, alpha, alpha, alpha);
     if (mColorFilter) {
-        mColorFilter->describe(description, mExtensions);
+        mColorFilter->describe(description, mCaches.extensions);
     }
 
     mModelView.loadTranslate(left, top, 0.0f);
@@ -1318,7 +1326,7 @@
             // These blend modes are not supported by OpenGL directly and have
             // to be implemented using shaders. Since the shader will perform
             // the blending, turn blending off here
-            if (mExtensions.hasFramebufferFetch()) {
+            if (mCaches.extensions.hasFramebufferFetch()) {
                 description.framebufferMode = mode;
                 description.swapSrcDst = swapSrcDst;
             }
@@ -1354,7 +1362,7 @@
 
 void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
     if (paint) {
-        if (!mExtensions.hasFramebufferFetch()) {
+        if (!mCaches.extensions.hasFramebufferFetch()) {
             const bool isMode = SkXfermode::IsMode(paint->getXfermode(), mode);
             if (!isMode) {
                 // Assume SRC_OVER
@@ -1384,16 +1392,9 @@
     return mode->fMode;
 }
 
-void OpenGLRenderer::bindTexture(GLuint texture, GLuint textureUnit) {
-    glActiveTexture(gTextureUnits[textureUnit]);
-    glBindTexture(GL_TEXTURE_2D, texture);
-}
-
-void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT,
-        GLuint textureUnit) {
+void OpenGLRenderer::setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT) {
     bool bound = false;
     if (wrapS != texture->wrapS) {
-        glActiveTexture(gTextureUnits[textureUnit]);
         glBindTexture(GL_TEXTURE_2D, texture->id);
         bound = true;
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
@@ -1401,7 +1402,6 @@
     }
     if (wrapT != texture->wrapT) {
         if (!bound) {
-            glActiveTexture(gTextureUnits[textureUnit]);
             glBindTexture(GL_TEXTURE_2D, texture->id);
         }
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 07188d4..3492d2c 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -259,7 +259,8 @@
             bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0);
 
     /**
-     * Prepares the renderer to draw the specified shadow.
+     * Prepares the renderer to draw the specified shadow. The active texture
+     * unit must be 0 and the other units must be unbound.
      *
      * @param texture The shadow texture
      * @param x The x coordinate of the shadow
@@ -360,11 +361,18 @@
     inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode);
 
     /**
-     * Binds the specified texture to the specified texture unit.
+     * Binds the specified texture. The texture unit must have been selected
+     * prior to calling this method.
      */
-    inline void bindTexture(GLuint texture, GLuint textureUnit = 0);
-    inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT,
-            GLuint textureUnit = 0);
+    inline void bindTexture(GLuint texture) {
+        glBindTexture(GL_TEXTURE_2D, texture);
+    }
+
+    /**
+     * Sets the wrap modes for the specified texture. The wrap modes are modified
+     * only when needed.
+     */
+    inline void setTextureWrapModes(Texture* texture, GLenum wrapS, GLenum wrapT);
 
     /**
      * Enable or disable blending as necessary. This function sets the appropriate
@@ -391,6 +399,18 @@
      */
     inline bool useProgram(Program* program);
 
+    /**
+     * Invoked before any drawing operation. This sets required state.
+     */
+    void setupDraw();
+
+    /**
+     * Should be invoked every time the glScissor is modified.
+     */
+    inline void dirtyClip() {
+        mDirtyClip = true;
+    }
+
     // Dimensions of the drawing surface
     int mWidth, mHeight;
 
@@ -416,9 +436,6 @@
     // Used to draw textured quads
     TextureVertex mMeshVertices[4];
 
-    // GL extensions
-    Extensions mExtensions;
-
     // Drop shadow
     bool mHasShadow;
     float mShadowRadius;
@@ -432,12 +449,12 @@
     // List of rectangles to clear due to calls to saveLayer()
     Vector<Rect*> mLayers;
 
-    // Misc
-    GLint mMaxTextureSize;
-
     // Indentity matrix
     const mat4 mIdentity;
 
+    // Indicates whether the clip must be restored
+    bool mDirtyClip;
+
     friend class DisplayListRenderer;
 
 }; // class OpenGLRenderer
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index d078d46..1d67329 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -290,6 +290,8 @@
 // Async commands for returning new IDS
 RsType rsaTypeCreate(RsContext, RsElement, uint32_t dimCount,
                      const RsDimension *dims, const uint32_t *vals);
+RsAllocation rsaAllocationCreateTyped(RsContext rsc, RsType vtype);
+RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data);
 
 
 #ifndef NO_RS_FUNCS
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index eb2942e..3e131b2 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -104,17 +104,6 @@
 	param uint32_t typeDataSize
 	}
 
-AllocationCreateTyped {
-	param RsType type
-	ret RsAllocation
-	}
-
-AllocationCreateSized {
-	param RsElement e
-	param size_t count
-	ret RsAllocation
-	}
-
 AllocationUpdateFromBitmap {
 	param RsAllocation alloc
 	param RsElement srcFmt
@@ -129,17 +118,6 @@
 	ret RsAllocation
 	}
 
-AllocationCreateFromBitmap {
-	param uint32_t width
-	param uint32_t height
-	param RsElement dstFmt
-	param RsElement srcFmt
-	param bool genMips
-	param const void * data
-	ret RsAllocation
-	}
-
-
 AllocationUploadToTexture {
 	param RsAllocation alloc
 	param bool genMipMaps
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index fc41a722..b4872e3 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -563,24 +563,6 @@
 namespace android {
 namespace renderscript {
 
-RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
-{
-    const Type * type = static_cast<const Type *>(vtype);
-
-    Allocation * alloc = new Allocation(rsc, type);
-    alloc->incUserRef();
-    return alloc;
-}
-
-RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
-{
-    Type * type = new Type(rsc);
-    type->setDimX(count);
-    type->setElement(static_cast<Element *>(e));
-    type->compute();
-    return rsi_AllocationCreateTyped(rsc, type);
-}
-
 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel)
 {
     Allocation *alloc = static_cast<Allocation *>(va);
@@ -786,42 +768,6 @@
     }
 }
 
-RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
-{
-    const Element *src = static_cast<const Element *>(_src);
-    const Element *dst = static_cast<const Element *>(_dst);
-
-    //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
-    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
-    uint32_t dimValues[] = {w, h, genMips};
-    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
-
-    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
-    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
-    if (texAlloc == NULL) {
-        LOGE("Memory allocation failure");
-        return NULL;
-    }
-
-    ElementConverter_t cvt = pickConverter(dst, src);
-    if (cvt) {
-        cvt(texAlloc->getPtr(), data, w * h);
-        if (genMips) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
-    } else {
-        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
-    }
-
-    return texAlloc;
-}
-
 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
 {
     Allocation *a = static_cast<Allocation *>(va);
@@ -882,3 +828,49 @@
 
 }
 }
+
+RsAllocation rsaAllocationCreateTyped(RsContext con, RsType vtype)
+{
+    Context *rsc = static_cast<Context *>(con);
+    Allocation * alloc = new Allocation(rsc, static_cast<Type *>(vtype));
+    alloc->incUserRef();
+    return alloc;
+}
+
+RsAllocation rsaAllocationCreateFromBitmap(RsContext con, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
+{
+    Context *rsc = static_cast<Context *>(con);
+    const Element *src = static_cast<const Element *>(_src);
+    const Element *dst = static_cast<const Element *>(_dst);
+
+    //LOGE("%p rsi_AllocationCreateFromBitmap %i %i %i", rsc, w, h, genMips);
+    RsDimension dims[] = {RS_DIMENSION_X, RS_DIMENSION_Y, RS_DIMENSION_LOD};
+    uint32_t dimValues[] = {w, h, genMips};
+    RsType type = rsaTypeCreate(rsc, _dst, 3, dims, dimValues);
+
+    RsAllocation vTexAlloc = rsaAllocationCreateTyped(rsc, type);
+    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
+    if (texAlloc == NULL) {
+        LOGE("Memory allocation failure");
+        return NULL;
+    }
+
+    ElementConverter_t cvt = pickConverter(dst, src);
+    if (cvt) {
+        cvt(texAlloc->getPtr(), data, w * h);
+        if (genMips) {
+            Adapter2D adapt(rsc, texAlloc);
+            Adapter2D adapt2(rsc, texAlloc);
+            for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+                adapt.setLOD(lod);
+                adapt2.setLOD(lod + 1);
+                mip(adapt2, adapt);
+            }
+        }
+    } else {
+        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
+    }
+
+    return texAlloc;
+}
+
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index dc021fc..096115c 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -399,6 +399,7 @@
     rsAssert(e->getFieldCount() == dataSize);
 
     for(uint32_t i = 0; i < dataSize; i ++) {
+        e->getField(i)->incUserRef();
         ids[i] = (uint32_t)e->getField(i);
         names[i] = e->getFieldName(i);
     }
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index d171a48..9e76215 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -511,10 +511,7 @@
     mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
     const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
 
-    Type *inputType = new Type(mRSC);
-    inputType->setElement(constInput);
-    inputType->setDimX(1);
-    inputType->compute();
+    Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false);
 
     uint32_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
@@ -546,11 +543,7 @@
     const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
 
     // We will allocate a texture to initially hold 32 character bitmaps
-    Type *texType = new Type(mRSC);
-    texType->setElement(alphaElem);
-    texType->setDimX(1024);
-    texType->setDimY(256);
-    texType->compute();
+    Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false);
 
     Allocation *cacheAlloc = new Allocation(mRSC, texType);
     mTextTexture.set(cacheAlloc);
@@ -578,11 +571,8 @@
 {
     // Now lets write index data
     const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
-    Type *indexType = new Type(mRSC);
     uint32_t numIndicies = mMaxNumberOfQuads * 6;
-    indexType->setDimX(numIndicies);
-    indexType->setElement(indexElem);
-    indexType->compute();
+    Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false);
 
     Allocation *indexAlloc = new Allocation(mRSC, indexType);
     uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
@@ -612,10 +602,9 @@
     mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1);
     const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC);
 
-    Type *vertexDataType = new Type(mRSC);
-    vertexDataType->setDimX(mMaxNumberOfQuads * 4);
-    vertexDataType->setElement(vertexDataElem);
-    vertexDataType->compute();
+    Type *vertexDataType = Type::getType(mRSC, vertexDataElem,
+                                         mMaxNumberOfQuads * 4,
+                                         0, 0, false, false);
 
     Allocation *vertexAlloc = new Allocation(mRSC, vertexDataType);
     mTextMeshPtr = (float*)vertexAlloc->getPtr();
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 724172e..44dc042 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -120,8 +120,15 @@
 
 bool ObjectBase::decUserRef() const
 {
-    //LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
     rsAssert(mUserRefCount > 0);
+#if RS_OBJECT_DEBUG
+    LOGV("ObjectBase %p decU ref %i, %i", this, mUserRefCount, mSysRefCount);
+    if (mUserRefCount <= 0) {
+        mStack.dump();
+    }
+#endif
+
+
     if ((android_atomic_dec(&mUserRefCount) <= 1) &&
         (android_atomic_acquire_load(&mSysRefCount) <= 0)) {
         return checkDelete(this);
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index 5f03db5..5cc275a 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -21,9 +21,7 @@
 
 #define RS_OBJECT_DEBUG 0
 
-#if RS_OBJECT_DEBUG
-    #include <utils/CallStack.h>
-#endif
+#include <utils/CallStack.h>
 
 namespace android {
 namespace renderscript {
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 33399d5..800854b 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -198,10 +198,7 @@
     rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
     const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc);
 
-    Type *inputType = new Type(rsc);
-    inputType->setElement(constInput);
-    inputType->setDimX(1);
-    inputType->compute();
+    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
 
     uint32_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index d12439f..4e64008 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -257,10 +257,7 @@
     rsc->mStateElement.elementBuilderAdd(f2Elem, "texture0", 1);
     const Element *attrElem = rsc->mStateElement.elementBuilderCreate(rsc);
 
-    Type *inputType = new Type(rsc);
-    inputType->setElement(constInput);
-    inputType->setDimX(1);
-    inputType->compute();
+    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
 
     String8 shaderString(RS_SHADER_INTERNAL);
     shaderString.append("varying vec4 varColor;\n");
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 82ad33e..7ef2464 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -276,20 +276,12 @@
         return NULL;
     }
 
-    Type *type = new Type(rsc);
-    type->mDimX = stream->loadU32();
-    type->mDimY = stream->loadU32();
-    type->mDimZ = stream->loadU32();
-
-    uint8_t temp = stream->loadU8();
-    type->mDimLOD = temp != 0;
-
-    temp = stream->loadU8();
-    type->mFaces = temp != 0;
-
-    type->setElement(elem);
-
-    return type;
+    uint32_t x = stream->loadU32();
+    uint32_t y = stream->loadU32();
+    uint32_t z = stream->loadU32();
+    uint8_t lod = stream->loadU8();
+    uint8_t faces = stream->loadU8();
+    return Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 );
 }
 
 bool Type::getIsNp2() const
@@ -325,56 +317,55 @@
     return false;
 }
 
-Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
+Type * Type::getType(Context *rsc, const Element *e,
+                     uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                     bool dimLOD, bool dimFaces)
 {
     TypeState * stc = &rsc->mStateType;
+
+    ObjectBase::asyncLock();
     for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
         Type *t = stc->mTypes[ct];
-        if (t->getElement() != mElement.get()) continue;
+        if (t->getElement() != e) continue;
         if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != mDimY) continue;
-        if (t->getDimZ() != mDimZ) continue;
-        if (t->getDimLOD() != mDimLOD) continue;
-        if (t->getDimFaces() != mFaces) continue;
+        if (t->getDimY() != dimY) continue;
+        if (t->getDimZ() != dimZ) continue;
+        if (t->getDimLOD() != dimLOD) continue;
+        if (t->getDimFaces() != dimFaces) continue;
         t->incUserRef();
+        ObjectBase::asyncUnlock();
         return t;
     }
+    ObjectBase::asyncUnlock();
+
 
     Type *nt = new Type(rsc);
-    nt->mElement.set(mElement);
+    nt->mElement.set(e);
     nt->mDimX = dimX;
-    nt->mDimY = mDimY;
-    nt->mDimZ = mDimZ;
-    nt->mDimLOD = mDimLOD;
-    nt->mFaces = mFaces;
+    nt->mDimY = dimY;
+    nt->mDimZ = dimZ;
+    nt->mDimLOD = dimLOD;
+    nt->mFaces = dimFaces;
     nt->compute();
+    nt->incUserRef();
+
+    ObjectBase::asyncLock();
+    stc->mTypes.push(nt);
+    ObjectBase::asyncUnlock();
+
     return nt;
 }
 
+Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
+{
+    return getType(rsc, mElement.get(), dimX,
+                   mDimY, mDimZ, mDimLOD, mFaces);
+}
+
 Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const
 {
-    TypeState * stc = &rsc->mStateType;
-    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
-        Type *t = stc->mTypes[ct];
-        if (t->getElement() != mElement.get()) continue;
-        if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != dimY) continue;
-        if (t->getDimZ() != mDimZ) continue;
-        if (t->getDimLOD() != mDimLOD) continue;
-        if (t->getDimFaces() != mFaces) continue;
-        t->incUserRef();
-        return t;
-    }
-
-    Type *nt = new Type(rsc);
-    nt->mElement.set(mElement);
-    nt->mDimX = dimX;
-    nt->mDimY = dimY;
-    nt->mDimZ = mDimZ;
-    nt->mDimLOD = mDimLOD;
-    nt->mFaces = mFaces;
-    nt->compute();
-    return nt;
+    return getType(rsc, mElement.get(), dimX, dimY,
+                   mDimZ, mDimLOD, mFaces);
 }
 
 
@@ -396,7 +387,7 @@
     (*typeData++) = t->getDimLOD();
     (*typeData++) = t->getDimFaces() ? 1 : 0;
     (*typeData++) = (uint32_t)t->getElement();
-
+    t->getElement()->incUserRef();
 }
 
 
@@ -430,34 +421,6 @@
         }
     }
 
-    ObjectBase::asyncLock();
-    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
-        Type *t = stc->mTypes[ct];
-        if (t->getElement() != e) continue;
-        if (t->getDimX() != dimX) continue;
-        if (t->getDimY() != dimY) continue;
-        if (t->getDimZ() != dimZ) continue;
-        if (t->getDimLOD() != dimLOD) continue;
-        if (t->getDimFaces() != dimFaces) continue;
-        t->incUserRef();
-        ObjectBase::asyncUnlock();
-        return t;
-    }
-    ObjectBase::asyncUnlock();
-
-    Type * st = new Type(rsc);
-    st->incUserRef();
-    st->setDimX(dimX);
-    st->setDimY(dimY);
-    st->setDimZ(dimZ);
-    st->setElement(e);
-    st->setDimLOD(dimLOD);
-    st->setDimFaces(dimFaces);
-    st->compute();
-
-    ObjectBase::asyncLock();
-    stc->mTypes.push(st);
-    ObjectBase::asyncUnlock();
-    return st;
+    return Type::getType(rsc, e, dimX, dimY, dimZ, dimLOD, dimFaces);
 }
 
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 6b89413..0ca5bb6 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -28,9 +28,6 @@
 class Type : public ObjectBase
 {
 public:
-    Type(Context *);
-    virtual ~Type();
-
     Type * createTex2D(const Element *, size_t w, size_t h, bool mip);
 
 
@@ -58,15 +55,6 @@
     uint32_t getLODCount() const {return mLODCount;}
     bool getIsNp2() const;
 
-
-    void setElement(const Element *e) {mElement.set(e);}
-    void setDimX(uint32_t v) {mDimX = v;}
-    void setDimY(uint32_t v) {mDimY = v;}
-    void setDimZ(uint32_t v) {mDimZ = v;}
-    void setDimFaces(bool v) {mFaces = v;}
-    void setDimLOD(bool v) {mDimLOD = v;}
-
-
     void clear();
     void compute();
 
@@ -82,6 +70,10 @@
     Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const;
     Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
 
+    static Type * getType(Context *rsc, const Element *e,
+                      uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                      bool dimLOD, bool dimFaces);
+
 protected:
     struct LOD {
         size_t mX;
@@ -124,10 +116,13 @@
     bool isValidGLComponent(uint32_t fieldIdx);
     void makeGLComponents();
 
+
 protected:
     virtual void preDestroy();
+    virtual ~Type();
 
 private:
+    Type(Context *);
     Type(const Type &);
 };
 
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
index 703b41e..e14fb95 100644
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
@@ -112,7 +112,12 @@
 
     mAnchorTimeUs = 0;
     mNumFramesOutput = 0;
-    mNumFramesLeftOnPage = 0;
+
+    // If the source never limits the number of valid frames contained
+    // in the input data, we'll assume that all of the decoded frames are
+    // valid.
+    mNumFramesLeftOnPage = -1;
+
     mStarted = true;
 
     return OK;
@@ -193,12 +198,14 @@
         }
     }
 
-    if (numFrames > mNumFramesLeftOnPage) {
-        LOGV("discarding %d frames at end of page",
-             numFrames - mNumFramesLeftOnPage);
-        numFrames = mNumFramesLeftOnPage;
+    if (mNumFramesLeftOnPage >= 0) {
+        if (numFrames > mNumFramesLeftOnPage) {
+            LOGV("discarding %d frames at end of page",
+                 numFrames - mNumFramesLeftOnPage);
+            numFrames = mNumFramesLeftOnPage;
+        }
+        mNumFramesLeftOnPage -= numFrames;
     }
-    mNumFramesLeftOnPage -= numFrames;
 
     out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels);
 
@@ -241,6 +248,7 @@
     int32_t numPageSamples;
     if (inputBuffer->meta_data()->findInt32(
                 kKeyValidSamples, &numPageSamples)) {
+        CHECK(numPageSamples >= 0);
         mNumFramesLeftOnPage = numPageSamples;
     }
 
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 10b52f2..7ee3c19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -116,7 +116,7 @@
         mClipping = clipping;
         if (mClipping != null) {
             Bitmap icon = mClipping.getIcon();
-            mDescription.setText(mClipping.getLabel());
+            mDescription.setText(mClipping.getDescription().getLabel());
             if (icon != null) {
                 mPreviewIcon.setImageBitmap(icon);
                 mPreviewIcon.setVisibility(View.VISIBLE);
diff --git a/services/java/com/android/server/ClipboardService.java b/services/java/com/android/server/ClipboardService.java
index bdf313c..30ea48c 100644
--- a/services/java/com/android/server/ClipboardService.java
+++ b/services/java/com/android/server/ClipboardService.java
@@ -115,7 +115,7 @@
 
     public ClipDescription getPrimaryClipDescription() {
         synchronized (this) {
-            return new ClipDescription(mPrimaryClip);
+            return mPrimaryClip.getDescription();
         }
     }
 
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 92588fc..210fe8a 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -102,6 +102,8 @@
 
     private final LockList mLocks = new LockList();
     // some wifi lock statistics
+    private int mFullHighPerfLocksAcquired;
+    private int mFullHighPerfLocksReleased;
     private int mFullLocksAcquired;
     private int mFullLocksReleased;
     private int mScanLocksAcquired;
@@ -1040,12 +1042,15 @@
         boolean wifiEnabled = getPersistedWifiEnabled();
         boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden.get();
         boolean lockHeld = mLocks.hasLocks();
-        int strongestLockMode;
+        int strongestLockMode = WifiManager.WIFI_MODE_FULL;
         boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode;
         boolean wifiShouldBeStarted = !mDeviceIdle || lockHeld;
-        if (mDeviceIdle && lockHeld) {
+
+        if (lockHeld) {
             strongestLockMode = mLocks.getStrongestLockMode();
-        } else {
+        }
+        /* If device is not idle, lockmode cannot be scan only */
+        if (!mDeviceIdle && strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY) {
             strongestLockMode = WifiManager.WIFI_MODE_FULL;
         }
 
@@ -1067,6 +1072,8 @@
                 mWifiStateMachine.setDriverStart(true);
                 mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
                         System.currentTimeMillis() + scanMs, scanMs, mScanIntent);
+                mWifiStateMachine.setHighPerfModeEnabled(strongestLockMode
+                        == WifiManager.WIFI_MODE_FULL_HIGH_PERF);
             } else {
                 mWifiStateMachine.requestCmWakeLock();
                 mWifiStateMachine.setDriverStart(false);
@@ -1145,8 +1152,10 @@
         }
         pw.println();
         pw.println("Locks acquired: " + mFullLocksAcquired + " full, " +
+                mFullHighPerfLocksAcquired + " full high perf, " +
                 mScanLocksAcquired + " scan");
         pw.println("Locks released: " + mFullLocksReleased + " full, " +
+                mFullHighPerfLocksReleased + " full high perf, " +
                 mScanLocksReleased + " scan");
         pw.println();
         pw.println("Locks held:");
@@ -1184,11 +1193,15 @@
             if (mList.isEmpty()) {
                 return WifiManager.WIFI_MODE_FULL;
             }
-            for (WifiLock l : mList) {
-                if (l.mMode == WifiManager.WIFI_MODE_FULL) {
-                    return WifiManager.WIFI_MODE_FULL;
-                }
+
+            if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) {
+                return WifiManager.WIFI_MODE_FULL_HIGH_PERF;
             }
+
+            if (mFullLocksAcquired > mFullLocksReleased) {
+                return WifiManager.WIFI_MODE_FULL;
+            }
+
             return WifiManager.WIFI_MODE_SCAN_ONLY;
         }
 
@@ -1235,7 +1248,11 @@
 
     public boolean acquireWifiLock(IBinder binder, int lockMode, String tag, WorkSource ws) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
-        if (lockMode != WifiManager.WIFI_MODE_FULL && lockMode != WifiManager.WIFI_MODE_SCAN_ONLY) {
+        if (lockMode != WifiManager.WIFI_MODE_FULL &&
+                lockMode != WifiManager.WIFI_MODE_SCAN_ONLY &&
+                lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
+            Slog.e(TAG, "Illegal argument, lockMode= " + lockMode);
+            if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
             return false;
         }
         if (ws != null && ws.size() == 0) {
@@ -1256,6 +1273,7 @@
     private void noteAcquireWifiLock(WifiLock wifiLock) throws RemoteException {
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
+            case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
                 mBatteryStats.noteFullWifiLockAcquiredFromSource(wifiLock.mWorkSource);
                 break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
@@ -1267,6 +1285,7 @@
     private void noteReleaseWifiLock(WifiLock wifiLock) throws RemoteException {
         switch(wifiLock.mMode) {
             case WifiManager.WIFI_MODE_FULL:
+            case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
                 mBatteryStats.noteFullWifiLockReleasedFromSource(wifiLock.mWorkSource);
                 break;
             case WifiManager.WIFI_MODE_SCAN_ONLY:
@@ -1287,6 +1306,10 @@
             case WifiManager.WIFI_MODE_FULL:
                 ++mFullLocksAcquired;
                 break;
+            case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+                ++mFullHighPerfLocksAcquired;
+                break;
+
             case WifiManager.WIFI_MODE_SCAN_ONLY:
                 ++mScanLocksAcquired;
                 break;
@@ -1356,6 +1379,9 @@
                     case WifiManager.WIFI_MODE_FULL:
                         ++mFullLocksReleased;
                         break;
+                    case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+                        ++mFullHighPerfLocksReleased;
+                        break;
                     case WifiManager.WIFI_MODE_SCAN_ONLY:
                         ++mScanLocksReleased;
                         break;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 9bc24d2..c29e4a9 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -569,7 +569,7 @@
         void broadcastDragStartedLw(final float touchX, final float touchY) {
             // Cache a base-class instance of the clip metadata so that parceling
             // works correctly in calling out to the apps.
-            mDataDescription = new ClipDescription(mData);
+            mDataDescription = mData.getDescription();
             mNotifiedWindows.clear();
             mDragInProgress = true;
 
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 84d615c..356a0bd 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -339,6 +339,16 @@
     public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
 
     /**
+     * In this Wi-Fi lock mode, Wi-Fi will behave as in the mode
+     * {@link #WIFI_MODE_FULL} but it operates at high performance
+     * at the expense of power. This mode should be used
+     * only when the wifi connection needs to have minimum loss and low
+     * latency as it can impact the battery life.
+     * @hide
+     */
+    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
+
+    /**
      * In this Wi-Fi lock mode, Wi-Fi will be kept active,
      * and will behave normally, i.e., it will attempt to automatically
      * establish a connection to a remembered access point that is
@@ -1261,8 +1271,8 @@
     /**
      * Creates a new WifiLock.
      *
-     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and
-     * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
+     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL},
+     * and {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
      * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is 
      *            never shown to the user under normal conditions, but should be descriptive 
      *            enough to identify your application and the specific WifiLock within it, if it
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 313ae0b..3d8157c 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -161,6 +161,8 @@
 
     public native static String getDhcpError();
 
+    public native static boolean setSuspendOptimizationsCommand(boolean enabled);
+
     /**
      * Wait for the supplicant to send an event, returning the event string.
      * @return the event string sent by the supplicant.
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index faafb7a..6bd67cc 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -246,11 +246,20 @@
     private static final int CMD_RECONNECT                        = 75;
     /* Reassociate to a network */
     private static final int CMD_REASSOCIATE                      = 76;
-    /* Set power mode
-     * POWER_MODE_ACTIVE
-     * POWER_MODE_AUTO
+    /* Controls power mode and suspend mode optimizations
+     *
+     * When high perf mode is enabled, power mode is set to
+     * POWER_MODE_ACTIVE and suspend mode optimizations are disabled
+     *
+     * When high perf mode is disabled, power mode is set to
+     * POWER_MODE_AUTO and suspend mode optimizations are enabled
+     *
+     * Suspend mode optimizations include:
+     * - packet filtering
+     * - turn off roaming
+     * - DTIM wake up settings
      */
-    private static final int CMD_SET_POWER_MODE                   = 77;
+    private static final int CMD_SET_HIGH_PERF_MODE               = 77;
     /* Set bluetooth co-existence
      * BLUETOOTH_COEXISTENCE_MODE_ENABLED
      * BLUETOOTH_COEXISTENCE_MODE_DISABLED
@@ -335,8 +344,8 @@
      */
     private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
 
-    private static final int DRIVER_POWER_MODE_ACTIVE = 1;
-    private static final int DRIVER_POWER_MODE_AUTO = 0;
+    private static final int POWER_MODE_ACTIVE = 1;
+    private static final int POWER_MODE_AUTO = 0;
 
     /* Default parent state */
     private HierarchicalState mDefaultState = new DefaultState();
@@ -856,13 +865,13 @@
     }
 
     /**
-     * Set power mode
-     * @param mode
-     *     DRIVER_POWER_MODE_AUTO
-     *     DRIVER_POWER_MODE_ACTIVE
+     * Set high performance mode of operation.
+     * Enabling would set active power mode and disable suspend optimizations;
+     * disabling would set auto power mode and enable suspend optimizations
+     * @param enable true if enable, false otherwise
      */
-    public void setPowerMode(int mode) {
-        sendMessage(obtainMessage(CMD_SET_POWER_MODE, mode, 0));
+    public void setHighPerfModeEnabled(boolean enable) {
+        sendMessage(obtainMessage(CMD_SET_HIGH_PERF_MODE, enable ? 1 : 0, 0));
     }
 
     /**
@@ -1269,6 +1278,21 @@
         return null;
     }
 
+    private void setHighPerfModeEnabledNative(boolean enable) {
+        if(!WifiNative.setSuspendOptimizationsCommand(!enable)) {
+            Log.e(TAG, "set suspend optimizations failed!");
+        }
+        if (enable) {
+            if (!WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE)) {
+                Log.e(TAG, "set power mode active failed!");
+            }
+        } else {
+            if (!WifiNative.setPowerModeCommand(POWER_MODE_AUTO)) {
+                Log.e(TAG, "set power mode auto failed!");
+            }
+        }
+    }
+
     private void configureLinkProperties() {
         if (WifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
             mLinkProperties = WifiConfigStore.getLinkProperties(mLastNetworkId);
@@ -1654,7 +1678,7 @@
                 case CMD_CLEAR_BLACKLIST:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -1756,7 +1780,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -1884,7 +1908,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -1981,7 +2005,7 @@
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_MODE:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -2138,7 +2162,7 @@
                 case NETWORK_DISCONNECTION_EVENT:
                 case PASSWORD_MAY_BE_INCORRECT_EVENT:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -2192,8 +2216,8 @@
                         WifiNative.setScanModeCommand(false);
                     }
                     break;
-                case CMD_SET_POWER_MODE:
-                    WifiNative.setPowerModeCommand(message.arg1);
+                case CMD_SET_HIGH_PERF_MODE:
+                    setHighPerfModeEnabledNative(message.arg1 == 1);
                     break;
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                     WifiNative.setBluetoothCoexistenceModeCommand(message.arg1);
@@ -2256,7 +2280,7 @@
                 case CMD_START_DRIVER:
                 case CMD_STOP_DRIVER:
                 case CMD_SET_SCAN_TYPE:
-                case CMD_SET_POWER_MODE:
+                case CMD_SET_HIGH_PERF_MODE:
                 case CMD_SET_BLUETOOTH_COEXISTENCE:
                 case CMD_SET_BLUETOOTH_SCAN_MODE:
                 case CMD_SET_NUM_ALLOWED_CHANNELS:
@@ -2505,7 +2529,7 @@
             if (!mUseStaticIp) {
                 mDhcpThread = null;
                 mModifiedBluetoothCoexistenceMode = false;
-                mPowerMode = DRIVER_POWER_MODE_AUTO;
+                mPowerMode = POWER_MODE_AUTO;
 
                 if (shouldDisableCoexistenceMode()) {
                     /*
@@ -2535,10 +2559,10 @@
                 if (mPowerMode < 0) {
                   // Handle the case where supplicant driver does not support
                   // getPowerModeCommand.
-                    mPowerMode = DRIVER_POWER_MODE_AUTO;
+                    mPowerMode = POWER_MODE_AUTO;
                 }
-                if (mPowerMode != DRIVER_POWER_MODE_ACTIVE) {
-                    WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_ACTIVE);
+                if (mPowerMode != POWER_MODE_ACTIVE) {
+                    WifiNative.setPowerModeCommand(POWER_MODE_ACTIVE);
                 }
 
                 Log.d(TAG, "DHCP request started");
@@ -2639,6 +2663,10 @@
               case CMD_RECONFIGURE_IP:
                   deferMessage(message);
                   break;
+                  /* Defer any power mode changes since we must keep active power mode at DHCP */
+              case CMD_SET_HIGH_PERF_MODE:
+                  deferMessage(message);
+                  break;
               default:
                 return NOT_HANDLED;
           }
@@ -2650,7 +2678,7 @@
       public void exit() {
           /* reset power state & bluetooth coexistence if on DHCP */
           if (!mUseStaticIp) {
-              if (mPowerMode != DRIVER_POWER_MODE_ACTIVE) {
+              if (mPowerMode != POWER_MODE_ACTIVE) {
                   WifiNative.setPowerModeCommand(mPowerMode);
               }