Merge "SurfaceTexture: fix queues-to-composer"
diff --git a/Android.mk b/Android.mk
index 752a5f8..fdf0933 100644
--- a/Android.mk
+++ b/Android.mk
@@ -183,7 +183,7 @@
 	media/java/android/media/IAudioFocusDispatcher.aidl \
 	media/java/android/media/IMediaScannerListener.aidl \
 	media/java/android/media/IMediaScannerService.aidl \
-	media/java/android/media/IRemoteControlClient.aidl \
+	media/java/android/media/IRemoteControlClientDispatcher.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
@@ -319,6 +319,9 @@
 # include definition of libcore_to_document
 include $(LOCAL_PATH)/../../libcore/Docs.mk
 
+# include definition of libfilterfw_to_document
+include $(LOCAL_PATH)/../../system/media/mca/Docs.mk
+
 non_base_dirs := \
 	../../external/apache-http/src/org/apache/http
 
@@ -335,7 +338,8 @@
 framework_docs_LOCAL_SRC_FILES := \
 	$(call find-other-java-files, $(dirs_to_document)) \
 	$(call find-other-html-files, $(html_dirs)) \
-	$(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore))
+	$(addprefix ../../libcore/, $(call libcore_to_document, $(LOCAL_PATH)/../../libcore)) \
+	$(addprefix ../../system/media/mca/, $(call libfilterfw_to_document, $(LOCAL_PATH)/../../system/media/mca))
 
 # This is used by ide.mk as the list of source files that are
 # always included.
diff --git a/CleanSpec.mk b/CleanSpec.mk
index bf47314..2593065 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -104,6 +104,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/SystemUI_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/R/com/android/systemui/R.java)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 3ea70b7..d377109 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11267,6 +11267,37 @@
 
 }
 
+package android.media.effect {
+
+  public abstract class Effect {
+    ctor public Effect();
+    method public abstract void apply(int, int, int, int);
+    method public abstract java.lang.String getName();
+    method public abstract void release();
+    method public abstract void setParameter(java.lang.String, java.lang.Object);
+    method public void setUpdateListener(android.media.effect.EffectUpdateListener);
+  }
+
+  public class EffectContext {
+    method public static android.media.effect.EffectContext createWithCurrentGlContext();
+    method public android.media.effect.EffectFactory getFactory();
+    method public void release();
+  }
+
+  public class EffectFactory {
+    method public android.media.effect.Effect createEffect(java.lang.String);
+    method public static boolean isEffectSupported(java.lang.String);
+    field public static final java.lang.String EFFECT_BRIGHTNESS = "BrightnessEffect";
+    field public static final java.lang.String EFFECT_CONTRAST = "ContrastEffect";
+    field public static final java.lang.String EFFECT_FISHEYE = "FisheyeEffect";
+  }
+
+  public abstract interface EffectUpdateListener {
+    method public abstract void onEffectUpdated(android.media.effect.Effect, java.lang.Object);
+  }
+
+}
+
 package android.mtp {
 
   public final class MtpConstants {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index cab8457..d3dbb8d 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1613,17 +1613,34 @@
 
         /**
          * Continuous auto focus mode intended for video recording. The camera
-         * continuously tries to focus. This is ideal for shooting video.
-         * Applications still can call {@link
-         * #takePicture(Camera.ShutterCallback, Camera.PictureCallback,
-         * Camera.PictureCallback)} in this mode but the subject may not be in
-         * focus. Auto focus starts when the parameter is set. Applications
-         * should not call {@link #autoFocus(AutoFocusCallback)} in this mode.
-         * To stop continuous focus, applications should change the focus mode
-         * to other modes.
+         * continuously tries to focus. This is the best choice for video
+         * recording because the focus changes smoothly . Applications still can
+         * call {@link #takePicture(Camera.ShutterCallback,
+         * Camera.PictureCallback, Camera.PictureCallback)} in this mode but the
+         * subject may not be in focus. Auto focus starts when the parameter is
+         * set. Applications should not call {@link
+         * #autoFocus(AutoFocusCallback)} in this mode. To stop continuous
+         * focus, applications should change the focus mode to other modes.
          */
         public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video";
 
+        /**
+         * Continuous auto focus mode intended for taking pictures. The camera
+         * continuously tries to focus. The speed of focus change is more
+         * aggressive than {@link #FOCUS_MODE_CONTINUOUS_VIDEO}. Auto focus
+         * starts when the parameter is set. If applications call {@link
+         * #autoFocus(AutoFocusCallback)} in this mode, the focus callback will
+         * immediately return with a boolean that indicates whether the focus is
+         * sharp or not. The apps can then decide if they want to take a picture
+         * immediately or to change the focus mode to auto, and run a full
+         * autofocus cycle. To stop continuous focus, applications should change
+         * the focus mode to other modes.
+         *
+         * @see #FOCUS_MODE_CONTINUOUS_VIDEO
+         * @hide
+         */
+        public static final String FOCUS_MODE_CONTINUOUS_PICTURE = "continuous-picture";
+
         // Indices for focus distance array.
         /**
          * The array index of near focus distance for use with
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 78c9010..1029161 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -589,8 +589,6 @@
             mPreferenceManager.setOnPreferenceTreeClickListener(this);
         }
 
-        getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
-
         // see if we should show Back/Next buttons
         Intent intent = getIntent();
         if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index f6ba7f7..bdd858b 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -159,7 +159,6 @@
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
-        getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
 
         if (mHavePrefs) {
             bindPreferences();
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 5a244f1..77cd71e 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -280,7 +280,7 @@
                 }
             }
 
-            if (textDir.isRtl(temp, 0, n)) {
+            if (textDir != null && textDir.isRtl(temp, 0, n)) {
                boring = false;
                break outer;
             }
diff --git a/core/java/android/text/TextDirectionHeuristic.java b/core/java/android/text/TextDirectionHeuristic.java
index 130f879..0bf64e4 100644
--- a/core/java/android/text/TextDirectionHeuristic.java
+++ b/core/java/android/text/TextDirectionHeuristic.java
@@ -1,4 +1,18 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
+/*
+ * 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 android.text;
 
@@ -8,6 +22,5 @@
  * @hide
  */
 public interface TextDirectionHeuristic {
-    /** @hide */ boolean isRtl(CharSequence text, int start, int end);
     /** @hide */ boolean isRtl(char[] text, int start, int count);
 }
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index 5f9ffc5..5ed2df4 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -1,4 +1,18 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
+/*
+ * 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 android.text;
 
@@ -36,12 +50,12 @@
         new TextDirectionHeuristicInternal(FirstStrong.INSTANCE, true);
 
     /**
-     * If the text contains any strong right to left non-format character, determines
-     * that the direction is right to left, falling back to left to right if it
+     * If the text contains any strong left to right non-format character, determines
+     * that the direction is left to right, falling back to left to right if it
      * finds none.
      */
-    public static final TextDirectionHeuristic ANYRTL_LTR =
-        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
+    public static final TextDirectionHeuristic ANYLTR_LTR =
+        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_LTR, false);
 
     /**
      * If the text contains any strong left to right non-format character, determines
@@ -52,6 +66,22 @@
         new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_LTR, true);
 
     /**
+     * If the text contains any strong right to left non-format character, determines
+     * that the direction is right to left, falling back to left to right if it
+     * finds none.
+     */
+    public static final TextDirectionHeuristic ANYRTL_LTR =
+        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, false);
+
+    /**
+     * If the text contains any strong right to left non-format character, determines
+     * that the direction is right to left, falling back to right to left if it
+     * finds none.
+     */
+    public static final TextDirectionHeuristic ANYRTL_RTL =
+        new TextDirectionHeuristicInternal(AnyStrong.INSTANCE_RTL, true);
+
+    /**
      * Examines only the strong directional non-format characters, and if either
      * left to right or right to left characters are 60% or more of this total,
      * determines that the direction follows the majority of characters.  Falls
@@ -92,19 +122,6 @@
         abstract protected boolean defaultIsRtl();
 
         @Override
-        public boolean isRtl(CharSequence text, int start, int end) {
-            if (text == null || start < 0 || end < start || text.length() < end) {
-                throw new IllegalArgumentException();
-            }
-            if (mAlgorithm == null) {
-                return defaultIsRtl();
-            }
-            text = text.subSequence(start, end);
-            char[] chars = text.toString().toCharArray();
-            return doCheck(chars, 0, chars.length);
-        }
-
-        @Override
         public boolean isRtl(char[] chars, int start, int count) {
             if (chars == null || start < 0 || count < 0 || chars.length - count < start) {
                 throw new IllegalArgumentException();
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 29c9853..83ef6ce 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -259,6 +259,17 @@
     }
 
     /**
+     * Returns list of multiple {@link CharSequence} joined into a single
+     * {@link CharSequence} separated by localized delimiter such as ", ".
+     *
+     * @hide
+     */
+    public static CharSequence join(Iterable<CharSequence> list) {
+        final CharSequence delimiter = Resources.getSystem().getText(R.string.list_delimeter);
+        return join(delimiter, list);
+    }
+
+    /**
      * Returns a string containing the tokens joined by delimiters.
      * @param tokens an array objects to be joined. Strings will be formed from
      *     the objects by calling object.toString().
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6627bf6..abd9ad6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9165,6 +9165,7 @@
             mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
         }
         jumpDrawablesToCurrentState();
+        // Order is important here: LayoutDirection should be resolved before Padding and TextDirection
         resolveLayoutDirectionIfNeeded();
         resolvePadding();
         resolveTextDirection();
@@ -9185,6 +9186,10 @@
         // Clear any previous layout direction resolution
         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_RTL;
 
+        // Reset also TextDirection as a change into LayoutDirection may impact the selected
+        // TextDirectionHeuristic
+        resetResolvedTextDirection();
+
         // Set resolved depending on layout direction
         switch (getLayoutDirection()) {
             case LAYOUT_DIRECTION_INHERIT:
@@ -12663,13 +12668,15 @@
      * Request that the visibility of the status bar be changed.
      * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
      * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
+     *
+     * This value will be re-applied immediately, even if the flags have not changed, so a view may
+     * easily reassert a particular SystemUiVisibility condition even if the system UI itself has
+     * since countermanded the original request.
      */
     public void setSystemUiVisibility(int visibility) {
-        if (visibility != mSystemUiVisibility) {
-            mSystemUiVisibility = visibility;
-            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
-                mParent.recomputeViewAttributes(this);
-            }
+        mSystemUiVisibility = visibility;
+        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
+            mParent.recomputeViewAttributes(this);
         }
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 08cb270..8fa1922 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5012,7 +5012,9 @@
      */
     public void requestTransitionStart(LayoutTransition transition) {
         ViewRootImpl viewAncestor = getViewRootImpl();
-        viewAncestor.requestTransitionStart(transition);
+        if (viewAncestor != null) {
+            viewAncestor.requestTransitionStart(transition);
+        }
     }
 
     @Override
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6374b47..17dfbe05 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -9036,15 +9036,6 @@
     }
 
     /**
-     * Enable expanded tiles bound for smoother scrolling.
-     *
-     * @hide only used by the Browser
-     */
-    public void setExpandedTileBounds(boolean enabled) {
-        nativeSetExpandedTileBounds(enabled);
-    }
-
-    /**
      * Set the time to wait between passing touches to WebCore. See also the
      * TOUCH_SENT_INTERVAL member for further discussion.
      *
@@ -9273,7 +9264,6 @@
     static final int NO_LEFTEDGE = -1;
     native int nativeGetBlockLeftEdge(int x, int y, float scale);
 
-    private native void     nativeSetExpandedTileBounds(boolean enabled);
     private native void     nativeUseHardwareAccelSkia(boolean enabled);
 
     // Returns a pointer to the scrollable LayerAndroid at the given point.
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index fc60949..b92130d 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -83,7 +83,6 @@
     // Avoid allocations...
     private RectF mTempSrc = new RectF();
     private RectF mTempDst = new RectF();
-    private float[] mTempPoints;
 
     private boolean mCropToPadding;
 
@@ -347,29 +346,13 @@
         if (mDrawable != drawable) {
             mResource = 0;
             mUri = null;
+
             int oldWidth = mDrawableWidth;
             int oldHeight = mDrawableHeight;
+
             updateDrawable(drawable);
 
-            boolean needsLayout;
-            if (mScaleType == ScaleType.CENTER) {
-                needsLayout = mDrawableWidth != oldWidth || mDrawableHeight != oldHeight;
-            } else {
-                if (mTempPoints == null) {
-                    mTempPoints = new float[4];
-                }
-                float[] points = mTempPoints;
-                points[0] = oldWidth;
-                points[1] = oldHeight;
-                points[2] = mDrawableWidth;
-                points[3] = mDrawableHeight;
-                if (!mMatrix.isIdentity()) {
-                    mMatrix.mapPoints(points);
-                }
-                needsLayout = points[0] != points[2] || points[1] != points[3];
-            }
-
-            if (needsLayout) {
+            if (oldWidth != mDrawableWidth || oldHeight != mDrawableHeight) {
                 requestLayout();
             }
             invalidate();
@@ -621,6 +604,8 @@
             mDrawableHeight = d.getIntrinsicHeight();
             applyColorMod();
             configureBounds();
+        } else {
+            mDrawableWidth = mDrawableHeight = -1;
         }
     }
 
@@ -679,14 +664,14 @@
             h = mDrawableHeight;
             if (w <= 0) w = 1;
             if (h <= 0) h = 1;
-            
+
             // We are supposed to adjust view bounds to match the aspect
             // ratio of our drawable. See if that is possible.
             if (mAdjustViewBounds) {
                 resizeWidth = widthSpecMode != MeasureSpec.EXACTLY;
                 resizeHeight = heightSpecMode != MeasureSpec.EXACTLY;
                 
-                desiredAspect = (float)w/(float)h;
+                desiredAspect = (float) w / (float) h;
             }
         }
         
@@ -705,13 +690,11 @@
             */
 
             // Get the max possible width given our constraints
-            widthSize = resolveAdjustedSize(w + pleft + pright,
-                                                 mMaxWidth, widthMeasureSpec);
-            
+            widthSize = resolveAdjustedSize(w + pleft + pright, mMaxWidth, widthMeasureSpec);
+
             // Get the max possible height given our constraints
-            heightSize = resolveAdjustedSize(h + ptop + pbottom,
-                                                mMaxHeight, heightMeasureSpec);
-            
+            heightSize = resolveAdjustedSize(h + ptop + pbottom, mMaxHeight, heightMeasureSpec);
+
             if (desiredAspect != 0.0f) {
                 // See what our actual aspect ratio is
                 float actualAspect = (float)(widthSize - pleft - pright) /
@@ -723,9 +706,8 @@
                     
                     // Try adjusting width to be proportional to height
                     if (resizeWidth) {
-                        int newWidth = (int)(desiredAspect *
-                                            (heightSize - ptop - pbottom))
-                                            + pleft + pright;
+                        int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
+                                pleft + pright;
                         if (newWidth <= widthSize) {
                             widthSize = newWidth;
                             done = true;
@@ -734,8 +716,8 @@
                     
                     // Try adjusting height to be proportional to width
                     if (!done && resizeHeight) {
-                        int newHeight = (int)((widthSize - pleft - pright)
-                                            / desiredAspect) + ptop + pbottom;
+                        int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
+                                ptop + pbottom;
                         if (newHeight <= heightSize) {
                             heightSize = newHeight;
                         }
@@ -859,7 +841,7 @@
                 if (dwidth <= vwidth && dheight <= vheight) {
                     scale = 1.0f;
                 } else {
-                    scale = Math.min((float) vwidth / (float) dwidth, 
+                    scale = Math.min((float) vwidth / (float) dwidth,
                             (float) vheight / (float) dheight);
                 }
                 
@@ -874,8 +856,7 @@
                 mTempDst.set(0, 0, vwidth, vheight);
                 
                 mDrawMatrix = mMatrix;
-                mDrawMatrix.setRectToRect(mTempSrc, mTempDst,
-                                          scaleTypeToScaleToFit(mScaleType));
+                mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));
             }
         }
     }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index aa23ad0..2a299bd 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1208,7 +1208,10 @@
         float textGapCount = selectorIndices.length - 1;
         int selectorTextGapHeight = (int) (totalTextGapHeight / textGapCount + 0.5f);
         mSelectorElementHeight = mTextSize + selectorTextGapHeight;
-        mInitialScrollOffset = mTextSize - 3 * (mSelectorElementHeight % 2);
+        // Ensure that the middle item is positioned the same as the text in mInputText
+        int editTextTextPosition = mInputText.getBaseline() + mInputText.getTop();
+        mInitialScrollOffset = editTextTextPosition -
+                (mSelectorElementHeight * SELECTOR_MIDDLE_ITEM_INDEX);
         mCurrentScrollOffset = mInitialScrollOffset;
         updateInputTextView();
     }
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index aba6834..99f2765 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -35,6 +35,7 @@
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.Handler;
 import android.speech.RecognizerIntent;
 import android.text.Editable;
 import android.text.InputType;
@@ -138,6 +139,12 @@
         }
     };
 
+    private Runnable mUpdateDrawableStateRunnable = new Runnable() {
+        public void run() {
+            updateFocusedState();
+        }
+    };
+
     // For voice searching
     private final Intent mVoiceWebSearchIntent;
     private final Intent mVoiceAppSearchIntent;
@@ -624,6 +631,12 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        // Let the standard measurements take effect in iconified state.
+        if (isIconified()) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+            return;
+        }
+
         int widthMode = MeasureSpec.getMode(widthMeasureSpec);
         int width = MeasureSpec.getSize(widthMeasureSpec);
 
@@ -720,9 +733,21 @@
         mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET);
     }
 
-    private void updateFocusedState(boolean focused) {
+    private void postUpdateFocusedState() {
+        post(mUpdateDrawableStateRunnable);
+    }
+
+    private void updateFocusedState() {
+        boolean focused = mQueryTextView.hasFocus();
         mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
         mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET);
+        invalidate();
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        removeCallbacks(mUpdateDrawableStateRunnable);
+        super.onDetachedFromWindow();
     }
 
     private void setImeVisibility(final boolean visible) {
@@ -1118,15 +1143,19 @@
 
     void onTextFocusChanged() {
         updateViewsVisibility(isIconified());
-        updateFocusedState(mQueryTextView.hasFocus());
+        // Delayed update to make sure that the focus has settled down and window focus changes
+        // don't affect it. A synchronous update was not working.
+        postUpdateFocusedState();
         if (mQueryTextView.hasFocus()) {
             forceSuggestionQuery();
         }
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+
+        postUpdateFocusedState();
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d6cb61d..7a5a091 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9499,8 +9499,7 @@
     public boolean isSuggestionsEnabled() {
         if (!mSuggestionsEnabled) return false;
         if ((mInputType & InputType.TYPE_MASK_CLASS) != InputType.TYPE_CLASS_TEXT) return false;
-        final int variation =
-                mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
+        final int variation = mInputType & EditorInfo.TYPE_MASK_VARIATION;
         if (variation == EditorInfo.TYPE_TEXT_VARIATION_NORMAL ||
                 variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_SUBJECT ||
                 variation == EditorInfo.TYPE_TEXT_VARIATION_LONG_MESSAGE ||
@@ -10729,42 +10728,29 @@
         return mInBatchEditControllers;
     }
 
-    private class TextViewDirectionHeuristic extends TextDirectionHeuristicImpl {
-        private TextViewDirectionHeuristic(TextDirectionAlgorithm algorithm) {
-            super(algorithm);
-        }
-        @Override
-        protected boolean defaultIsRtl() {
-            return getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL;
-        }
-    }
-
-    /**
-     * Resolve the text direction.
-     *
-     * Text direction of paragraphs in a TextView is determined using a heuristic. If the correct
-     * text direction cannot be determined by the heuristic, the view's resolved layout direction
-     * determines the direction.
-     *
-     * This heuristic and result is applied individually to each paragraph in a TextView, based on
-     * the text and style content of that paragraph. Paragraph text styles can also be used to force
-     * a particular direction.
-     */
     @Override
     protected void resolveTextDirection() {
+        // Always need to resolve layout direction first
+        final boolean defaultIsRtl = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
+
+        // Then resolve text direction on the parent
         super.resolveTextDirection();
 
+        // Now, we can select the heuristic
         int textDir = getResolvedTextDirection();
         switch (textDir) {
             default:
             case TEXT_DIRECTION_FIRST_STRONG:
-                mTextDir = new TextViewDirectionHeuristic(FirstStrong.INSTANCE);
+                mTextDir = (defaultIsRtl ? TextDirectionHeuristics.FIRSTSTRONG_RTL :
+                        TextDirectionHeuristics.FIRSTSTRONG_LTR);
                 break;
             case TEXT_DIRECTION_ANY_RTL:
-                mTextDir = new TextViewDirectionHeuristic(AnyStrong.INSTANCE_RTL);
+                mTextDir = (defaultIsRtl ? TextDirectionHeuristics.ANYRTL_RTL:
+                        TextDirectionHeuristics.ANYRTL_LTR);
                 break;
             case TEXT_DIRECTION_CHAR_COUNT:
-                mTextDir = new TextViewDirectionHeuristic(CharCount.INSTANCE_DEFAULT);
+                mTextDir = (defaultIsRtl ? TextDirectionHeuristics.CHARCOUNT_RTL:
+                        TextDirectionHeuristics.CHARCOUNT_LTR);
                 break;
             case TEXT_DIRECTION_LTR:
                 mTextDir = TextDirectionHeuristics.LTR;
@@ -10773,7 +10759,6 @@
                 mTextDir = TextDirectionHeuristics.RTL;
                 break;
         }
-
     }
 
     /**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 7b65964..df5071f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -67,12 +67,13 @@
     private static final String TAG = "BatteryStatsImpl";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_HISTORY = false;
+    private static final boolean USE_OLD_HISTORY = false;   // for debugging.
 
     // In-memory Parcel magic number, used to detect attempts to unmarshall bad data
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 60;
+    private static final int VERSION = 61 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -1285,6 +1286,10 @@
     void addHistoryRecordLocked(long curTime) {
         addHistoryBufferLocked(curTime);
 
+        if (!USE_OLD_HISTORY) {
+            return;
+        }
+
         if (!mHaveBatteryLevel || !mRecordingHistory) {
             return;
         }
@@ -1363,12 +1368,15 @@
 
     void clearHistoryLocked() {
         if (DEBUG_HISTORY) Slog.i(TAG, "********** CLEARING HISTORY!");
-        if (mHistory != null) {
-            mHistoryEnd.next = mHistoryCache;
-            mHistoryCache = mHistory;
-            mHistory = mHistoryLastEnd = mHistoryEnd = null;
+        if (USE_OLD_HISTORY) {
+            if (mHistory != null) {
+                mHistoryEnd.next = mHistoryCache;
+                mHistoryCache = mHistory;
+                mHistory = mHistoryLastEnd = mHistoryEnd = null;
+            }
+            mNumHistoryItems = 0;
         }
-        mNumHistoryItems = 0;
+
         mHistoryBaseTime = 0;
         mLastHistoryTime = 0;
 
@@ -4863,7 +4871,9 @@
         }
 
         long now = SystemClock.elapsedRealtime();
-        addHistoryRecordLocked(now, HistoryItem.CMD_START);
+        if (USE_OLD_HISTORY) {
+            addHistoryRecordLocked(now, HistoryItem.CMD_START);
+        }
         addHistoryBufferLocked(now, HistoryItem.CMD_START);
     }
 
@@ -4923,6 +4933,9 @@
     }
 
     void readOldHistory(Parcel in) {
+        if (!USE_OLD_HISTORY) {
+            return;
+        }
         mHistory = mHistoryEnd = mHistoryCache = null;
         long time;
         while (in.dataAvail() > 0 && (time=in.readLong()) >= 0) {
@@ -4952,6 +4965,9 @@
     }
 
     void writeOldHistory(Parcel out) {
+        if (!USE_OLD_HISTORY) {
+            return;
+        }
         HistoryItem rec = mHistory;
         while (rec != null) {
             if (rec.time >= 0) rec.writeToParcel(out, 0);
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index aaae691..5c42579 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -173,7 +173,8 @@
     public void updateMenuView(boolean cleared) {
         super.updateMenuView(cleared);
 
-        final boolean hasOverflow = mReserveOverflow && mMenu.getNonActionItems().size() > 0;
+        final boolean hasOverflow = mReserveOverflow && mMenu != null &&
+                mMenu.getNonActionItems().size() > 0;
         if (hasOverflow) {
             if (mOverflowButton == null) {
                 mOverflowButton = new OverflowMenuButton(mContext);
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index ed9d34a..bec437a 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -74,20 +74,24 @@
      * Reuses item views when it can
      */
     public void updateMenuView(boolean cleared) {
-        mMenu.flagActionItems();
-        ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
-        final int itemCount = visibleItems.size();
         final ViewGroup parent = (ViewGroup) mMenuView;
+        if (parent == null) return;
+
         int childIndex = 0;
-        for (int i = 0; i < itemCount; i++) {
-            MenuItemImpl item = visibleItems.get(i);
-            if (shouldIncludeItem(childIndex, item)) {
-                final View convertView = parent.getChildAt(childIndex);
-                final View itemView = getItemView(item, convertView, parent);
-                if (itemView != convertView) {
-                    addItemView(itemView, childIndex);
+        if (mMenu != null) {
+            mMenu.flagActionItems();
+            ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
+            final int itemCount = visibleItems.size();
+            for (int i = 0; i < itemCount; i++) {
+                MenuItemImpl item = visibleItems.get(i);
+                if (shouldIncludeItem(childIndex, item)) {
+                    final View convertView = parent.getChildAt(childIndex);
+                    final View itemView = getItemView(item, convertView, parent);
+                    if (itemView != convertView) {
+                        addItemView(itemView, childIndex);
+                    }
+                    childIndex++;
                 }
-                childIndex++;
             }
         }
 
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 6b5ea60..792766b 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -52,6 +52,7 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.Window;
+import android.view.ViewGroup.LayoutParams;
 import android.widget.AdapterView;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -373,8 +374,7 @@
             mActionMenuPresenter.setExpandedActionViewsExclusive(
                     getResources().getBoolean(
                     com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
-            builder.addMenuPresenter(mActionMenuPresenter);
-            builder.addMenuPresenter(mExpandedMenuPresenter);
+            configPresenters(builder);
             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
             final ViewGroup oldParent = (ViewGroup) menuView.getParent();
             if (oldParent != null && oldParent != this) {
@@ -390,8 +390,7 @@
             mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
             // Span the whole width
             layoutParams.width = LayoutParams.MATCH_PARENT;
-            builder.addMenuPresenter(mActionMenuPresenter);
-            builder.addMenuPresenter(mExpandedMenuPresenter);
+            configPresenters(builder);
             menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
             if (mSplitView != null) {
                 final ViewGroup oldParent = (ViewGroup) menuView.getParent();
@@ -407,6 +406,18 @@
         mMenuView = menuView;
     }
 
+    private void configPresenters(MenuBuilder builder) {
+        if (builder != null) {
+            builder.addMenuPresenter(mActionMenuPresenter);
+            builder.addMenuPresenter(mExpandedMenuPresenter);
+        } else {
+            mActionMenuPresenter.initForMenu(mContext, null);
+            mExpandedMenuPresenter.initForMenu(mContext, null);
+            mActionMenuPresenter.updateMenuView(true);
+            mExpandedMenuPresenter.updateMenuView(true);
+        }
+    }
+
     public boolean hasExpandedActionView() {
         return mExpandedMenuPresenter != null &&
                 mExpandedMenuPresenter.mCurrentExpandedItem != null;
@@ -1025,6 +1036,8 @@
                 } else if (centeredLeft + navWidth > menuLeft) {
                     hgravity = Gravity.RIGHT;
                 }
+            } else if (gravity == -1) {
+                hgravity = Gravity.LEFT;
             }
 
             int xpos = 0;
@@ -1040,8 +1053,14 @@
                     break;
             }
 
+            int vgravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+            if (gravity == -1) {
+                vgravity = Gravity.CENTER_VERTICAL;
+            }
+
             int ypos = 0;
-            switch (gravity & Gravity.VERTICAL_GRAVITY_MASK) {
+            switch (vgravity) {
                 case Gravity.CENTER_VERTICAL:
                     final int paddedTop = getPaddingTop();
                     final int paddedBottom = mBottom - mTop - getPaddingBottom();
@@ -1070,6 +1089,11 @@
     }
 
     @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new ActionBar.LayoutParams(getContext(), attrs);
+    }
+
+    @Override
     public LayoutParams generateLayoutParams(LayoutParams lp) {
         if (lp == null) {
             lp = generateDefaultLayoutParams();
@@ -1263,12 +1287,15 @@
             // Make sure the expanded item we have is still there.
             if (mCurrentExpandedItem != null) {
                 boolean found = false;
-                final int count = mMenu.size();
-                for (int i = 0; i < count; i++) {
-                    final MenuItem item = mMenu.getItem(i);
-                    if (item == mCurrentExpandedItem) {
-                        found = true;
-                        break;
+
+                if (mMenu != null) {
+                    final int count = mMenu.size();
+                    for (int i = 0; i < count; i++) {
+                        final MenuItem item = mMenu.getItem(i);
+                        if (item == mCurrentExpandedItem) {
+                            found = true;
+                            break;
+                        }
                     }
                 }
 
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index 23af37e..9f6ab31 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -115,7 +115,8 @@
 
     private void unTagSocketFd(FileDescriptor fd) throws IOException {
         int fdNum = fd.getInt$();
-        if (fdNum == -1) return;
+        final SocketTags options = threadSocketTags.get();
+        if (fdNum == -1 || (options.statsTag == -1 && options.statsUid == -1)) return;
         String cmd = "u " + fdNum;
         internalModuleCtrl(cmd);
     }
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 45b7f27..b369efb 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -507,6 +507,7 @@
 #define EVENT_LOOP_EXIT 1
 #define EVENT_LOOP_ADD  2
 #define EVENT_LOOP_REMOVE 3
+#define EVENT_LOOP_WAKEUP 4
 
 dbus_bool_t dbusAddWatch(DBusWatch *watch, void *data) {
     native_data_t *nat = (native_data_t *)data;
@@ -551,6 +552,13 @@
     }
 }
 
+void dbusWakeup(void *data) {
+    native_data_t *nat = (native_data_t *)data;
+
+    char control = EVENT_LOOP_WAKEUP;
+    write(nat->controlFdW, &control, sizeof(char));
+}
+
 static void handleWatchAdd(native_data_t *nat) {
     DBusWatch *watch;
     int newFD;
@@ -634,6 +642,7 @@
 
     dbus_connection_set_watch_functions(nat->conn, dbusAddWatch,
             dbusRemoveWatch, dbusToggleWatch, ptr, NULL);
+    dbus_connection_set_wakeup_main_function(nat->conn, dbusWakeup, ptr, NULL);
 
     nat->running = true;
 
@@ -669,6 +678,11 @@
                         handleWatchRemove(nat);
                         break;
                     }
+                    case EVENT_LOOP_WAKEUP:
+                    {
+                        // noop
+                        break;
+                    }
                     }
                 }
             } else {
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
index 5b67d71..08f6453 100644
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ b/core/res/res/layout-sw600dp/preference_list_content.xml
@@ -44,8 +44,11 @@
                 android:layout_width="match_parent"
                 android:layout_height="0px"
                 android:layout_weight="1"
-                android:paddingTop="16dp"
-                android:paddingBottom="16dp"
+                android:paddingLeft="@dimen/preference_screen_header_padding_side"
+                android:paddingRight="@dimen/preference_screen_header_padding_side"
+                android:paddingTop="@dimen/preference_screen_header_vertical_padding"
+                android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
+                android:scrollbarStyle="@integer/preference_screen_header_scrollbarStyle"
                 android:drawSelectorOnTop="false"
                 android:cacheColorHint="@android:color/transparent"
                 android:listPreferredItemHeight="48dp"
diff --git a/core/res/res/layout/breadcrumbs_in_fragment.xml b/core/res/res/layout/breadcrumbs_in_fragment.xml
index 98fffb7..9c12618 100644
--- a/core/res/res/layout/breadcrumbs_in_fragment.xml
+++ b/core/res/res/layout/breadcrumbs_in_fragment.xml
@@ -13,10 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
+
 <!-- This layout disables breadcrumbs in the fragment area and causes PreferenceActivity to
     put the breadcrumbs in the action bar. -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_height="@dimen/preference_fragment_padding_side"
-        android:layout_width="match_parent">
-</LinearLayout>
\ No newline at end of file
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="0dip"
+    android:layout_height="0dip"
+    android:visibility="gone" />
diff --git a/core/res/res/layout/preference_list_content.xml b/core/res/res/layout/preference_list_content.xml
index 4e7981a..62181b5 100644
--- a/core/res/res/layout/preference_list_content.xml
+++ b/core/res/res/layout/preference_list_content.xml
@@ -44,8 +44,11 @@
                 android:layout_width="match_parent"
                 android:layout_height="0px"
                 android:layout_weight="1"
+                android:paddingLeft="@dimen/preference_screen_header_padding_side"
+                android:paddingRight="@dimen/preference_screen_header_padding_side"
                 android:paddingTop="@dimen/preference_screen_header_vertical_padding"
                 android:paddingBottom="@dimen/preference_screen_header_vertical_padding"
+                android:scrollbarStyle="@integer/preference_screen_header_scrollbarStyle"
                 android:drawSelectorOnTop="false"
                 android:cacheColorHint="@android:color/transparent"
                 android:listPreferredItemHeight="48dp"
diff --git a/core/res/res/layout/preference_list_fragment.xml b/core/res/res/layout/preference_list_fragment.xml
index 315f708..fdef4fc 100644
--- a/core/res/res/layout/preference_list_fragment.xml
+++ b/core/res/res/layout/preference_list_fragment.xml
@@ -32,11 +32,19 @@
         android:paddingBottom="@dimen/preference_fragment_padding_bottom"
         android:paddingLeft="@dimen/preference_fragment_padding_side"
         android:paddingRight="@dimen/preference_fragment_padding_side"
+        android:scrollbarStyle="@integer/preference_fragment_scrollbarStyle"
         android:clipToPadding="false"
         android:drawSelectorOnTop="false"
         android:cacheColorHint="@android:color/transparent"
         android:scrollbarAlwaysDrawVerticalTrack="true" />
 
+    <TextView android:id="@android:id/empty"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:padding="@dimen/preference_fragment_padding_side"
+        android:gravity="center"
+        android:visibility="gone" />
+
     <RelativeLayout android:id="@+id/button_bar"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml
index 0ffd571..f699a46 100644
--- a/core/res/res/layout/search_view.xml
+++ b/core/res/res/layout/search_view.xml
@@ -40,12 +40,11 @@
 
     <ImageView
         android:id="@+id/search_button"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:layout_gravity="center_vertical"
-        android:background="?android:attr/selectableItemBackground"
-        android:src="?android:attr/searchViewSearchIcon"
         style="?android:attr/actionButtonStyle"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical"
+        android:src="?android:attr/searchViewSearchIcon"
         android:contentDescription="@string/searchview_description_search"
     />
 
diff --git a/core/res/res/values-h720dp/dimens.xml b/core/res/res/values-h720dp/dimens.xml
index 37dee8e..7efe322 100644
--- a/core/res/res/values-h720dp/dimens.xml
+++ b/core/res/res/values-h720dp/dimens.xml
@@ -25,4 +25,10 @@
     <dimen name="preference_screen_top_margin">16dp</dimen>
     <!-- Preference activity bottom margin -->
     <dimen name="preference_screen_bottom_margin">16dp</dimen>
+
+    <dimen name="preference_screen_header_padding_side">0dip</dimen>
+
+    <integer name="preference_screen_header_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
+    <integer name="preference_fragment_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
+
 </resources>
diff --git a/core/res/res/values-w720dp/dimens.xml b/core/res/res/values-w720dp/dimens.xml
index 3d10103..c62c3f5 100644
--- a/core/res/res/values-w720dp/dimens.xml
+++ b/core/res/res/values-w720dp/dimens.xml
@@ -29,4 +29,9 @@
         This helps in aligning titles when some items have icons and some don't. When space is
         at a premium, we don't pre-allocate any space. -->
     <dimen name="preference_icon_minWidth">56dp</dimen>
+
+    <dimen name="preference_screen_header_padding_side">0dip</dimen>
+
+    <integer name="preference_screen_header_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
+    <integer name="preference_fragment_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 8855645..83e86939 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -76,9 +76,9 @@
     <dimen name="multiwaveview_hit_radius">60dip</dimen>
 
     <!-- Preference activity side margins -->
-    <dimen name="preference_screen_side_margin">16dp</dimen>
+    <dimen name="preference_screen_side_margin">0dp</dimen>
     <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">16dp</dimen>
+    <dimen name="preference_screen_side_margin_negative">0dp</dimen>
     <!-- Preference activity top margin -->
     <dimen name="preference_screen_top_margin">0dp</dimen>
     <!-- Preference activity bottom margin -->
@@ -88,7 +88,7 @@
     <!-- Preference fragment padding, bottom -->
     <dimen name="preference_fragment_padding_bottom">0dp</dimen>
     <!-- Preference fragment padding, sides -->
-    <dimen name="preference_fragment_padding_side">0dp</dimen>
+    <dimen name="preference_fragment_padding_side">16dp</dimen>
     <!-- Weight of the left pane in a multi-pane preference layout. -->
     <integer name="preferences_left_pane_weight">4</integer>
     <!-- Weight of the right pane in a multi-pane preference layout. So the split is 40:60 -->
@@ -108,6 +108,11 @@
     <!-- Preference activity, vertical padding for the header list -->
     <dimen name="preference_screen_header_vertical_padding">0dp</dimen>
 
+    <dimen name="preference_screen_header_padding_side">16dip</dimen>
+    <integer name="preference_screen_header_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
+
+    <integer name="preference_fragment_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
+
     <dimen name="preference_item_padding_side">8dip</dimen>
     <dimen name="preference_item_padding_inner">8dip</dimen>
     <dimen name="preference_child_padding_side">16dip</dimen>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index feb7846..128889c 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -225,7 +225,7 @@
     <!-- Displayed when a web request failed because there was a connection error. -->
     <string name="httpErrorConnect">The connection to the server was unsuccessful.</string>
     <!-- Displayed when a web request failed because there was an input or output error. -->
-    <string name="httpErrorIO">The server failed to communicate. Try again later.</string>
+    <string name="httpErrorIO">The server couldn\'t communicate. Try again later.</string>
     <!-- Displayed when a web request failed because the request timed out -->
     <string name="httpErrorTimeout">The connection to the server timed out.</string>
     <!-- Displayed when a web request failed because the site tried to redirect us one too many times -->
@@ -2500,10 +2500,10 @@
     <!-- Title of the alert when an application has crashed. -->
     <string name="aerr_title"></string>
     <!-- Text of the alert that is displayed when an application has crashed. -->
-    <string name="aerr_application"><xliff:g id="application">%1$s</xliff:g> has stopped by mistake.</string>
+    <string name="aerr_application">Unfortunately, <xliff:g id="application">%1$s</xliff:g> has stopped.</string>
     <!-- Text of the alert that is displayed when an application has crashed. -->
-    <string name="aerr_process">The process <xliff:g id="process">%1$s</xliff:g> has
-        stopped by mistake.</string>
+    <string name="aerr_process">Unfortunately, the process <xliff:g id="process">%1$s</xliff:g> has
+        stopped.</string>
     <!-- Title of the alert when an application is not responding. -->
     <string name="anr_title"></string>
     <!-- Text of the alert that is displayed when an application is not responding. -->
@@ -2629,7 +2629,7 @@
     <!-- Wi-Fi p2p dialog title-->
     <string name="wifi_p2p_dialog_title">Wi-Fi Direct</string>
     <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct operation. This will turn off Wi-Fi client/hotspot operation.</string>
-    <string name="wifi_p2p_failed_message">Failed to start Wi-Fi Direct</string>
+    <string name="wifi_p2p_failed_message">Couldn\'t start Wi-Fi Direct</string>
     <string name="wifi_p2p_pbc_go_negotiation_request_message">Wi-Fi Direct connection setup request from <xliff:g id="p2p_device_address">%1$s</xliff:g>. Click OK to accept. </string>
     <string name="wifi_p2p_pin_go_negotiation_request_message">Wi-Fi Direct connection setup request from <xliff:g id="p2p_device_address">%1$s</xliff:g>. Enter pin to proceed. </string>
     <string name="wifi_p2p_pin_display_message">WPS pin <xliff:g id="p2p_wps_pin">%1$s</xliff:g> needs to be entered on the peer device <xliff:g id="p2p_client_address">%2$s</xliff:g> for connection setup to proceed </string>
@@ -2728,7 +2728,7 @@
     <!-- USB_STORAGE_KILL_STORAGE_USERS dialog message text -->
     <string name="dlg_confirm_kill_storage_users_text">If you turn on USB storage, some applications you are using will stop and may be unavailable until you turn off USB storage.</string>
     <!-- USB_STORAGE_ERROR dialog  dialog-->
-    <string name="dlg_error_title">USB operation failed</string>
+    <string name="dlg_error_title">USB operation unsuccessful</string>
     <!-- USB_STORAGE_ERROR dialog  ok button-->
     <string name="dlg_ok">OK</string>
 
@@ -2982,9 +2982,9 @@
     <!-- Text for progress dialog while erasing SD card [CHAR LIMIT=NONE] -->
     <string name="progress_erasing" product="default">Erasing SD card...</string>
     <!-- Text for message to user that an error happened when formatting USB storage [CHAR LIMIT=NONE] -->
-    <string name="format_error" product="nosdcard">Failed to erase USB storage.</string>
+    <string name="format_error" product="nosdcard">Couldn\'t erase USB storage.</string>
     <!-- Text for message to user that an error happened when formatting SD card [CHAR LIMIT=NONE] -->
-    <string name="format_error" product="default">Failed to erase SD card.</string>
+    <string name="format_error" product="default">Couldn\'t erase SD card.</string>
     <!-- Text for message to user that SD card has been removed while in use [CHAR LIMIT=NONE] -->
     <string name="media_bad_removal">SD card was removed before being unmounted.</string>
     <!-- Text for message to user USB storage is currently being checked [CHAR LIMIT=NONE] -->
@@ -3153,4 +3153,7 @@
     <!-- Description of for the status bar's icon that the device is locked for accessibility. [CHAR LIMIT=NONE] -->
     <string name="status_bar_device_locked">Device locked.</string>
 
+    <!-- Delimeter used between each item in a textual list; for example "Alpha, Beta". [CHAR LIMIT=3] -->
+    <string name="list_delimeter">", "</string>
+
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 6f2f1e5..94c6e41 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -2363,7 +2363,7 @@
 
     <style name="Widget.Holo.PreferenceFrameLayout">
         <item name="android:borderTop">0dip</item>
-        <item name="android:borderBottom">@dimen/preference_fragment_padding_side</item>
+        <item name="android:borderBottom">@dimen/preference_fragment_padding_bottom</item>
         <item name="android:borderLeft">@dimen/preference_fragment_padding_side</item>
         <item name="android:borderRight">@dimen/preference_fragment_padding_side</item>
     </style>
diff --git a/core/tests/coretests/src/android/provider/SettingsProviderTest.java b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
index b82e698..3e96dc4 100644
--- a/core/tests/coretests/src/android/provider/SettingsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsProviderTest.java
@@ -20,11 +20,16 @@
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.Settings;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import java.util.List;
 
 /** Unit test for SettingsProvider. */
 public class SettingsProviderTest extends AndroidTestCase {
@@ -191,4 +196,49 @@
         assertEquals("test1,test2",
                 Settings.Secure.getString(r, Settings.Secure.LOCATION_PROVIDERS_ALLOWED));
      }
+
+     @SmallTest
+     public void testSettings() {
+        assertCanBeHandled(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_ADD_ACCOUNT));
+        assertCanBeHandled(new Intent(Settings.ACTION_AIRPLANE_MODE_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_APN_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                .setData(Uri.parse("package:" + getContext().getPackageName())));
+        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_APPLICATION_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_DATA_ROAMING_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_DATE_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_LOCALE_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_MEMORY_CARD_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_NETWORK_OPERATOR_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_PRIVACY_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_QUICK_LAUNCH_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_SEARCH_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_SECURITY_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_SOUND_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_SYNC_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_USER_DICTIONARY_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_IP_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_WIFI_SETTINGS));
+        assertCanBeHandled(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
+    }
+
+    private void assertCanBeHandled(final Intent intent) {
+        PackageManager packageManager = mContext.getPackageManager();
+        List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
+        assertNotNull(resolveInfoList);
+        // one or more activity can handle this intent.
+        assertTrue(resolveInfoList.size() > 0);
+    }
 }
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 05bd626..0353a47 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -155,6 +155,7 @@
     <assign-permission name="android.permission.DEVICE_POWER" uid="shell" />
     <assign-permission name="android.permission.INSTALL_LOCATION_PROVIDER" uid="shell" />
     <assign-permission name="android.permission.BACKUP" uid="shell" />
+    <assign-permission name="android.permission.FORCE_STOP_PACKAGES" uid="shell" />
 
     <assign-permission name="android.permission.MODIFY_AUDIO_SETTINGS" uid="media" />
     <assign-permission name="android.permission.ACCESS_DRM" uid="media" />
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 49dbbca..6698d31 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -277,10 +277,19 @@
      */
     public boolean setDrawableByLayerId(int id, Drawable drawable) {
         final ChildDrawable[] layers = mLayerState.mChildren;
-        drawable.setCallback(this);
         
         for (int i = mLayerState.mNum - 1; i >= 0; i--) {
             if (layers[i].mId == id) {
+                if (layers[i].mDrawable != null) {
+                    if (drawable != null) {
+                        Rect bounds = layers[i].mDrawable.getBounds();
+                        drawable.setBounds(bounds);
+                    }
+                    layers[i].mDrawable.setCallback(null);
+                }
+                if (drawable != null) {
+                    drawable.setCallback(this);
+                }
                 layers[i].mDrawable = drawable;
                 return true;
             }
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index b661496..6c91dfc 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -597,13 +597,24 @@
     // CameraHardwareInterface.autoFocus in this mode.
     static const char FOCUS_MODE_EDOF[];
     // Continuous auto focus mode intended for video recording. The camera
-    // continuously tries to focus. This is ideal for shooting video.
-    // Applications still can call CameraHardwareInterface.takePicture in this
-    // mode but the subject may not be in focus. Auto focus starts when the
-    // parameter is set. Applications should not call
-    // CameraHardwareInterface.autoFocus in this mode. To stop continuous focus,
-    // applications should change the focus mode to other modes.
+    // continuously tries to focus. This is the best choice for video
+    // recording because the focus changes smoothly . Applications still can
+    // call CameraHardwareInterface.takePicture in this mode but the subject may
+    // not be in focus. Auto focus starts when the parameter is set.
+    // Applications should not call CameraHardwareInterface.autoFocus in this
+    // mode. To stop continuous focus, applications should change the focus mode
+    // to other modes.
     static const char FOCUS_MODE_CONTINUOUS_VIDEO[];
+    // Continuous auto focus mode intended for taking pictures. The camera
+    // continuously tries to focus. The speed of focus change is more aggressive
+    // than FOCUS_MODE_CONTINUOUS_VIDEO. Auto focus starts when the parameter is
+    // set. If applications call autoFocus in this mode, the focus callback will
+    // immediately return with a boolean that indicates the focus is sharp or
+    // not. The apps can then decide if they want to take a picture immediately
+    // or to change the focus mode to auto, and run a full autofocus cycle. To
+    // stop continuous focus, applications should change the focus mode to other
+    // modes.
+    static const char FOCUS_MODE_CONTINUOUS_PICTURE[];
 
 private:
     DefaultKeyedVector<String8,String8>    mMap;
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index a6fb12e..493993d 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -275,7 +275,7 @@
         enum BufferState {
             // FREE indicates that the buffer is not currently being used and
             // will not be used in the future until it gets dequeued and
-            // subseqently queued by the client.
+            // subsequently queued by the client.
             FREE = 0,
 
             // DEQUEUED indicates that the buffer has been dequeued by the
diff --git a/include/utils/String16.h b/include/utils/String16.h
index 584f53f..360f407 100644
--- a/include/utils/String16.h
+++ b/include/utils/String16.h
@@ -156,7 +156,7 @@
 
 inline String16 String16::operator+(const String16& other) const
 {
-    String16 tmp;
+    String16 tmp(*this);
     tmp += other;
     return tmp;
 }
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 51b96c1..0eb5d50 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -160,6 +160,7 @@
 const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
 const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
 const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE[] = "continuous-picture";
 
 CameraParameters::CameraParameters()
                 : mMap()
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 7ac4343..ac9b33b 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -36,6 +36,10 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 
+
+#define ALLOW_DEQUEUE_CURRENT_BUFFER    false
+
+
 namespace android {
 
 // Transform matrices
@@ -294,9 +298,22 @@
             if (state == BufferSlot::DEQUEUED) {
                 dequeuedCount++;
             }
-            if (state == BufferSlot::FREE /*|| i == mCurrentTexture*/) {
-                foundSync = i;
-                if (i != mCurrentTexture) {
+
+            // if buffer is FREE it CANNOT be current
+            LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
+                    "dequeueBuffer: buffer %d is both FREE and current!", i);
+
+            if (ALLOW_DEQUEUE_CURRENT_BUFFER) {
+                if (state == BufferSlot::FREE || i == mCurrentTexture) {
+                    foundSync = i;
+                    if (i != mCurrentTexture) {
+                        found = i;
+                        break;
+                    }
+                }
+            } else {
+                if (state == BufferSlot::FREE) {
+                    foundSync = i;
                     found = i;
                     break;
                 }
@@ -325,7 +342,7 @@
         }
 
         // we're in synchronous mode and didn't find a buffer, we need to wait
-        // for for some buffers to be consumed
+        // for some buffers to be consumed
         tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
         if (tryAgain) {
             mDequeueCondition.wait(mMutex);
@@ -482,17 +499,16 @@
         mSlots[buf].mScalingMode = mNextScalingMode;
         mSlots[buf].mTimestamp = timestamp;
         mDequeueCondition.signal();
+
+        *outWidth = mDefaultWidth;
+        *outHeight = mDefaultHeight;
+        *outTransform = 0;
     } // scope for the lock
 
     // call back without lock held
     if (listener != 0) {
         listener->onFrameAvailable();
     }
-
-    *outWidth = mDefaultWidth;
-    *outHeight = mDefaultHeight;
-    *outTransform = 0;
-
     return OK;
 }
 
@@ -847,6 +863,7 @@
 void SurfaceTexture::freeAllBuffersLocked() {
     LOGW_IF(!mQueue.isEmpty(),
             "freeAllBuffersLocked called but mQueue is not empty");
+    mCurrentTexture = INVALID_BUFFER_SLOT;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         freeBufferLocked(i);
     }
@@ -860,6 +877,7 @@
         Fifo::iterator front(mQueue.begin());
         head = *front;
     }
+    mCurrentTexture = INVALID_BUFFER_SLOT;
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         if (i != head) {
             freeBufferLocked(i);
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index fb2df37..176dd18 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -182,6 +182,7 @@
     const Allocation * ain;
     Allocation * aout;
     const void * usr;
+    size_t usrLen;
 
     uint32_t mSliceSize;
     volatile int mSliceNum;
@@ -209,6 +210,10 @@
 
 static void wc_xy(void *usr, uint32_t idx) {
     MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
+    RsForEachStubParamStruct p;
+    memset(&p, 0, sizeof(p));
+    p.usr = mtls->usr;
+    p.usr_len = mtls->usrLen;
 
     while (1) {
         uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
@@ -221,13 +226,15 @@
 
         //LOGE("usr idx %i, x %i,%i  y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
         //LOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
-        for (uint32_t y = yStart; y < yEnd; y++) {
-            uint32_t offset = mtls->dimX * y;
+        for (p.y = yStart; p.y < yEnd; p.y++) {
+            uint32_t offset = mtls->dimX * p.y;
             uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
             const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * offset);
 
-            for (uint32_t x = mtls->xStart; x < mtls->xEnd; x++) {
-                ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, y, 0, 0);
+            for (p.x = mtls->xStart; p.x < mtls->xEnd; p.x++) {
+                p.in = xPtrIn;
+                p.out = xPtrOut;
+                ((rs_t)mtls->script->mHal.info.root) (p.in, p.out, p.usr, p.x, p.y, 0, 0);
                 xPtrIn += mtls->eStrideIn;
                 xPtrOut += mtls->eStrideOut;
             }
@@ -237,6 +244,10 @@
 
 static void wc_x(void *usr, uint32_t idx) {
     MTLaunchStruct *mtls = (MTLaunchStruct *)usr;
+    RsForEachStubParamStruct p;
+    memset(&p, 0, sizeof(p));
+    p.usr = mtls->usr;
+    p.usr_len = mtls->usrLen;
 
     while (1) {
         uint32_t slice = (uint32_t)android_atomic_inc(&mtls->mSliceNum);
@@ -251,8 +262,10 @@
         //LOGE("usr ptr in %p,  out %p", mtls->ptrIn, mtls->ptrOut);
         uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * xStart);
         const uint8_t *xPtrIn = mtls->ptrIn + (mtls->eStrideIn * xStart);
-        for (uint32_t x = xStart; x < xEnd; x++) {
-            ((rs_t)mtls->script->mHal.info.root) (xPtrIn, xPtrOut, mtls->usr, x, 0, 0, 0);
+        for (p.x = xStart; p.x < xEnd; p.x++) {
+            p.in = xPtrIn;
+            p.out = xPtrOut;
+            ((rs_t)mtls->script->mHal.info.root) (p.in, p.out, p.usr, p.x, 0, 0, 0);
             xPtrIn += mtls->eStrideIn;
             xPtrOut += mtls->eStrideOut;
         }
@@ -325,6 +338,7 @@
     mtls.aout = aout;
     mtls.script = s;
     mtls.usr = usr;
+    mtls.usrLen = usrLen;
     mtls.mSliceSize = 10;
     mtls.mSliceNum = 0;
 
@@ -351,18 +365,25 @@
 
         //LOGE("launch 1");
     } else {
+        RsForEachStubParamStruct p;
+        memset(&p, 0, sizeof(p));
+        p.usr = mtls.usr;
+        p.usr_len = mtls.usrLen;
+
         //LOGE("launch 3");
-        for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
-            for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
-                for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
-                    uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * ar +
-                                      mtls.dimX * mtls.dimY * z +
-                                      mtls.dimX * y;
+        for (p.ar[0] = mtls.arrayStart; p.ar[0] < mtls.arrayEnd; p.ar[0]++) {
+            for (p.z = mtls.zStart; p.z < mtls.zEnd; p.z++) {
+                for (p.y = mtls.yStart; p.y < mtls.yEnd; p.y++) {
+                    uint32_t offset = mtls.dimX * mtls.dimY * mtls.dimZ * p.ar[0] +
+                                      mtls.dimX * mtls.dimY * p.z +
+                                      mtls.dimX * p.y;
                     uint8_t *xPtrOut = mtls.ptrOut + (mtls.eStrideOut * offset);
                     const uint8_t *xPtrIn = mtls.ptrIn + (mtls.eStrideIn * offset);
 
-                    for (uint32_t x = mtls.xStart; x < mtls.xEnd; x++) {
-                        ((rs_t)s->mHal.info.root) (xPtrIn, xPtrOut, usr, x, y, z, ar);
+                    for (p.x = mtls.xStart; p.x < mtls.xEnd; p.x++) {
+                        p.in = xPtrIn;
+                        p.out = xPtrOut;
+                        ((rs_t)s->mHal.info.root) (p.in, p.out, p.usr, p.x, p.y, p.z, p.ar[0]);
                         xPtrIn += mtls.eStrideIn;
                         xPtrOut += mtls.eStrideOut;
                     }
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 0dea971..f277582 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -127,6 +127,7 @@
 	}
 
 ElementCreate {
+        direct
 	param RsDataType mType
 	param RsDataKind mKind
 	param bool mNormalized
@@ -135,6 +136,7 @@
 	}
 
 ElementCreate2 {
+        direct
 	param const RsElement * elements
 	param const char ** names
 	param const uint32_t * arraySize
@@ -226,6 +228,7 @@
 	}
 
 SamplerCreate {
+    direct
     param RsSamplerValue magFilter
     param RsSamplerValue minFilter
     param RsSamplerValue wrapS
@@ -311,6 +314,7 @@
 
 
 ProgramStoreCreate {
+	direct
 	param bool colorMaskR
 	param bool colorMaskG
 	param bool colorMaskB
@@ -324,6 +328,7 @@
 	}
 
 ProgramRasterCreate {
+	direct
 	param bool pointSmooth
 	param bool lineSmooth
 	param bool pointSprite
@@ -352,12 +357,14 @@
 	}
 
 ProgramFragmentCreate {
+	direct
 	param const char * shaderText
 	param const uint32_t * params
 	ret RsProgramFragment
 	}
 
 ProgramVertexCreate {
+	direct
 	param const char * shaderText
 	param const uint32_t * params
 	ret RsProgramVertex
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index b59ade8..a366d49 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -252,6 +252,7 @@
 
     Allocation *alloc = Allocation::createAllocation(rsc, type, RS_ALLOCATION_USAGE_SCRIPT);
     alloc->setName(name.string(), name.size());
+    type->decUserRef();
 
     uint32_t count = dataSize / type->getElementSizeBytes();
 
@@ -307,12 +308,12 @@
         return;
     }
 
-    Type *t = mHal.state.type->cloneAndResize1D(rsc, dimX);
+    ObjectBaseRef<Type> t = mHal.state.type->cloneAndResize1D(rsc, dimX);
     if (dimX < oldDimX) {
         decRefs(getPtr(), oldDimX - dimX, dimX);
     }
-    rsc->mHal.funcs.allocation.resize(rsc, this, t, mHal.state.hasReferences);
-    mHal.state.type.set(t);
+    rsc->mHal.funcs.allocation.resize(rsc, this, t.get(), mHal.state.hasReferences);
+    mHal.state.type.set(t.get());
     updateCache();
 }
 
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index e65febb..ce06306 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -176,36 +176,6 @@
     return (mType >= RS_TYPE_ELEMENT);
 }
 
-String8 Component::getGLSLType() const {
-    if (mType == RS_TYPE_SIGNED_32) {
-        switch (mVectorSize) {
-        case 1: return String8("int");
-        case 2: return String8("ivec2");
-        case 3: return String8("ivec3");
-        case 4: return String8("ivec4");
-        }
-    }
-    if (mType == RS_TYPE_FLOAT_32) {
-        switch (mVectorSize) {
-        case 1: return String8("float");
-        case 2: return String8("vec2");
-        case 3: return String8("vec3");
-        case 4: return String8("vec4");
-        }
-    }
-    if ((mType == RS_TYPE_MATRIX_4X4) && (mVectorSize == 1)) {
-        return String8("mat4");
-    }
-    if ((mType == RS_TYPE_MATRIX_3X3) && (mVectorSize == 1)) {
-        return String8("mat3");
-    }
-    if ((mType == RS_TYPE_MATRIX_2X2) && (mVectorSize == 1)) {
-        return String8("mat2");
-    }
-    return String8();
-}
-
-
 static const char * gTypeBasicStrings[] = {
     "NONE",
     "F16",
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
index a448f0e..6ddc990 100644
--- a/libs/rs/rsComponent.h
+++ b/libs/rs/rsComponent.h
@@ -32,10 +32,8 @@
 
     void set(RsDataType dt, RsDataKind dk, bool norm, uint32_t vecSize=1);
 
-    String8 getGLSLType() const;
     void dumpLOGV(const char *prefix) const;
 
-
     RsDataType getType() const {return mType;}
     RsDataKind getKind() const {return mKind;}
     bool getIsNormalized() const {return mNormalized;}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index bffe3c0..8996ad1 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -240,6 +240,7 @@
         rsc->setProgramStore(NULL);
         rsc->mStateFont.init(rsc);
         rsc->setFont(NULL);
+        rsc->mStateSampler.init(rsc);
         rsc->mFBOCache.init(rsc);
     }
 
@@ -251,10 +252,11 @@
     while (!rsc->mExit) {
         uint64_t waitTime = 0;
         uint64_t now = rsc->getTime();
-        if (now < targetTime) {
-            waitTime = targetTime - now;
-        } else {
-            doWait = false;
+        if (!doWait) {
+            if (now < targetTime) {
+                waitTime = targetTime - now;
+                doWait = true;
+            }
         }
 
         mDraw |= rsc->mIO.playCoreCommands(rsc, doWait, waitTime);
@@ -264,7 +266,7 @@
         if (mDraw && rsc->mIsGraphicsContext) {
             uint64_t delay = rsc->runRootScript() * 1000000;
             targetTime = rsc->getTime() + delay;
-            doWait = delay != 0;
+            doWait = (delay == 0);
 
             if (rsc->props.mLogVisual) {
                 rsc->displayDebugStats();
@@ -307,6 +309,7 @@
          mStateFragment.deinit(this);
          mStateFragmentStore.deinit(this);
          mStateFont.deinit(this);
+         mStateSampler.deinit(this);
          mFBOCache.deinit(this);
     }
     //LOGV("destroyWorkerThreadResources 2");
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index b77b18a..36bbdf0 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -29,13 +29,16 @@
 }
 
 Element::~Element() {
+    clear();
+}
+
+void Element::preDestroy() const {
     for (uint32_t ct = 0; ct < mRSC->mStateElement.mElements.size(); ct++) {
         if (mRSC->mStateElement.mElements[ct] == this) {
             mRSC->mStateElement.mElements.removeAt(ct);
             break;
         }
     }
-    clear();
 }
 
 void Element::clear() {
@@ -60,6 +63,7 @@
 void Element::dumpLOGV(const char *prefix) const {
     ObjectBase::dumpLOGV(prefix);
     LOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
+    mComponent.dumpLOGV(prefix);
     for (uint32_t ct = 0; ct < mFieldCount; ct++) {
         LOGV("%s Element field index: %u ------------------", prefix, ct);
         LOGV("%s name: %s, offsetBits: %u, arraySize: %u",
@@ -97,60 +101,46 @@
     String8 name;
     stream->loadString(&name);
 
-    Element *elem = new Element(rsc);
-    elem->mComponent.loadFromStream(stream);
+    Component component;
+    component.loadFromStream(stream);
 
-    elem->mFieldCount = stream->loadU32();
-    if (elem->mFieldCount) {
-        elem->mFields = new ElementField_t [elem->mFieldCount];
-        for (uint32_t ct = 0; ct < elem->mFieldCount; ct ++) {
-            stream->loadString(&elem->mFields[ct].name);
-            elem->mFields[ct].arraySize = stream->loadU32();
-            Element *fieldElem = Element::createFromStream(rsc, stream);
-            elem->mFields[ct].e.set(fieldElem);
-        }
+    uint32_t fieldCount = stream->loadU32();
+    if (!fieldCount) {
+        return (Element *)Element::create(rsc,
+                                          component.getType(),
+                                          component.getKind(),
+                                          component.getIsNormalized(),
+                                          component.getVectorSize());;
     }
 
-    // We need to check if this already exists
-    for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
-        Element *ee = rsc->mStateElement.mElements[ct];
-        if (ee->isEqual(elem)) {
-            ObjectBase::checkDelete(elem);
-            ee->incUserRef();
-            return ee;
-        }
+    const Element **subElems = new const Element *[fieldCount];
+    const char **subElemNames = new const char *[fieldCount];
+    size_t *subElemNamesLengths = new size_t[fieldCount];
+    uint32_t *arraySizes = new uint32_t[fieldCount];
+
+    String8 elemName;
+    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
+        stream->loadString(&elemName);
+        subElemNamesLengths[ct] = elemName.length();
+        char *tmpName = new char[subElemNamesLengths[ct]];
+        memcpy(tmpName, elemName.string(), subElemNamesLengths[ct]);
+        subElemNames[ct] = tmpName;
+        arraySizes[ct] = stream->loadU32();
+        subElems[ct] = Element::createFromStream(rsc, stream);
     }
 
-    elem->compute();
-    rsc->mStateElement.mElements.push(elem);
-    return elem;
-}
+    const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames,
+                                          subElemNamesLengths, arraySizes);
+    for (uint32_t ct = 0; ct < fieldCount; ct ++) {
+        delete [] subElemNames[ct];
+        subElems[ct]->decUserRef();
+    }
+    delete[] subElems;
+    delete[] subElemNames;
+    delete[] subElemNamesLengths;
+    delete[] arraySizes;
 
-bool Element::isEqual(const Element *other) const {
-    if (other == NULL) {
-        return false;
-    }
-    if (!other->getFieldCount() && !mFieldCount) {
-        if ((other->getType() == getType()) &&
-           (other->getKind() == getKind()) &&
-           (other->getComponent().getIsNormalized() == getComponent().getIsNormalized()) &&
-           (other->getComponent().getVectorSize() == getComponent().getVectorSize())) {
-            return true;
-        }
-        return false;
-    }
-    if (other->getFieldCount() == mFieldCount) {
-        for (uint32_t i=0; i < mFieldCount; i++) {
-            if ((!other->mFields[i].e->isEqual(mFields[i].e.get())) ||
-                (other->mFields[i].name.length() != mFields[i].name.length()) ||
-                (other->mFields[i].name != mFields[i].name) ||
-                (other->mFields[i].arraySize != mFields[i].arraySize)) {
-                return false;
-            }
-        }
-        return true;
-    }
-    return false;
+    return (Element *)elem;
 }
 
 void Element::compute() {
@@ -172,9 +162,11 @@
 
 }
 
-const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
+ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk,
                                 bool isNorm, uint32_t vecSize) {
+    ObjectBaseRef<const Element> returnRef;
     // Look for an existing match.
+    ObjectBase::asyncLock();
     for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
         const Element *ee = rsc->mStateElement.mElements[ct];
         if (!ee->getFieldCount() &&
@@ -183,21 +175,31 @@
             (ee->getComponent().getIsNormalized() == isNorm) &&
             (ee->getComponent().getVectorSize() == vecSize)) {
             // Match
-            ee->incUserRef();
+            returnRef.set(ee);
+            ObjectBase::asyncUnlock();
             return ee;
         }
     }
+    ObjectBase::asyncUnlock();
 
     Element *e = new Element(rsc);
+    returnRef.set(e);
     e->mComponent.set(dt, dk, isNorm, vecSize);
     e->compute();
+
+    ObjectBase::asyncLock();
     rsc->mStateElement.mElements.push(e);
-    return e;
+    ObjectBase::asyncUnlock();
+
+    return returnRef;
 }
 
-const Element * Element::create(Context *rsc, size_t count, const Element **ein,
+ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
                             const char **nin, const size_t * lengths, const uint32_t *asin) {
+
+    ObjectBaseRef<const Element> returnRef;
     // Look for an existing match.
+    ObjectBase::asyncLock();
     for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
         const Element *ee = rsc->mStateElement.mElements[ct];
         if (ee->getFieldCount() == count) {
@@ -212,13 +214,16 @@
                 }
             }
             if (match) {
-                ee->incUserRef();
-                return ee;
+                returnRef.set(ee);
+                ObjectBase::asyncUnlock();
+                return returnRef;
             }
         }
     }
+    ObjectBase::asyncUnlock();
 
     Element *e = new Element(rsc);
+    returnRef.set(e);
     e->mFields = new ElementField_t [count];
     e->mFieldCount = count;
     for (size_t ct=0; ct < count; ct++) {
@@ -228,26 +233,11 @@
     }
     e->compute();
 
+    ObjectBase::asyncLock();
     rsc->mStateElement.mElements.push(e);
-    return e;
-}
+    ObjectBase::asyncUnlock();
 
-String8 Element::getGLSLType(uint32_t indent) const {
-    String8 s;
-    for (uint32_t ct=0; ct < indent; ct++) {
-        s.append(" ");
-    }
-
-    if (!mFieldCount) {
-        // Basic component.
-        s.append(mComponent.getGLSLType());
-    } else {
-        rsAssert(0);
-        //s.append("struct ");
-        //s.append(getCStructBody(indent));
-    }
-
-    return s;
+    return returnRef;
 }
 
 void Element::incRefs(const void *ptr) const {
@@ -294,6 +284,23 @@
     }
 }
 
+void Element::Builder::add(const Element *e, const char *nameStr, uint32_t arraySize) {
+    mBuilderElementRefs.push(ObjectBaseRef<const Element>(e));
+    mBuilderElements.push(e);
+    mBuilderNameStrings.push(nameStr);
+    mBuilderNameLengths.push(strlen(nameStr));
+    mBuilderArrays.push(arraySize);
+
+}
+
+ObjectBaseRef<const Element> Element::Builder::create(Context *rsc) {
+    return Element::createRef(rsc, mBuilderElements.size(),
+                              &(mBuilderElements.editArray()[0]),
+                              &(mBuilderNameStrings.editArray()[0]),
+                              mBuilderNameLengths.editArray(),
+                              mBuilderArrays.editArray());
+}
+
 
 ElementState::ElementState() {
     const uint32_t initialCapacity = 32;
@@ -324,10 +331,10 @@
 
 const Element *ElementState::elementBuilderCreate(Context *rsc) {
     return Element::create(rsc, mBuilderElements.size(),
-                                &(mBuilderElements.editArray()[0]),
-                                &(mBuilderNameStrings.editArray()[0]),
-                                mBuilderNameLengths.editArray(),
-                                mBuilderArrays.editArray());
+                           &(mBuilderElements.editArray()[0]),
+                           &(mBuilderNameStrings.editArray()[0]),
+                           mBuilderNameLengths.editArray(),
+                           mBuilderArrays.editArray());
 }
 
 
@@ -342,9 +349,7 @@
                             RsDataKind dk,
                             bool norm,
                             uint32_t vecSize) {
-    const Element *e = Element::create(rsc, dt, dk, norm, vecSize);
-    e->incUserRef();
-    return (RsElement)e;
+    return (RsElement)Element::create(rsc, dt, dk, norm, vecSize);
 }
 
 
@@ -358,15 +363,15 @@
 
                              const uint32_t * arraySizes,
                              size_t arraySizes_length) {
-    const Element *e = Element::create(rsc, ein_length, (const Element **)ein, names, nameLengths, arraySizes);
-    e->incUserRef();
-    return (RsElement)e;
+    return (RsElement)Element::create(rsc, ein_length, (const Element **)ein,
+                                      names, nameLengths, arraySizes);
 }
 
 }
 }
 
-void rsaElementGetNativeData(RsContext con, RsElement elem, uint32_t *elemData, uint32_t elemDataSize) {
+void rsaElementGetNativeData(RsContext con, RsElement elem,
+                             uint32_t *elemData, uint32_t elemDataSize) {
     rsAssert(elemDataSize == 5);
     // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
     Element *e = static_cast<Element *>(elem);
@@ -378,7 +383,8 @@
     (*elemData++) = e->getFieldCount();
 }
 
-void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids, const char **names, uint32_t dataSize) {
+void rsaElementGetSubElements(RsContext con, RsElement elem, uint32_t *ids,
+                              const char **names, uint32_t dataSize) {
     Element *e = static_cast<Element *>(elem);
     rsAssert(e->getFieldCount() == dataSize);
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index 26e2760..c3ef250 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -28,8 +28,17 @@
 // An element is a group of Components that occupies one cell in a structure.
 class Element : public ObjectBase {
 public:
-    ~Element();
-
+    class Builder {
+    public:
+        void add(const Element *e, const char *nameStr, uint32_t arraySize);
+        ObjectBaseRef<const Element> create(Context *rsc);
+    private:
+        Vector<ObjectBaseRef<const Element> > mBuilderElementRefs;
+        Vector<const Element *> mBuilderElements;
+        Vector<const char*> mBuilderNameStrings;
+        Vector<size_t> mBuilderNameLengths;
+        Vector<uint32_t> mBuilderArrays;
+    };
     uint32_t getGLType() const;
     uint32_t getGLFormat() const;
 
@@ -55,24 +64,45 @@
     RsDataKind getKind() const {return mComponent.getKind();}
     uint32_t getBits() const {return mBits;}
 
-    String8 getGLSLType(uint32_t indent=0) const;
-
     void dumpLOGV(const char *prefix) const;
     virtual void serialize(OStream *stream) const;
     virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_ELEMENT; }
     static Element *createFromStream(Context *rsc, IStream *stream);
 
-    static const Element * create(Context *rsc, RsDataType dt, RsDataKind dk,
-                            bool isNorm, uint32_t vecSize);
-    static const Element * create(Context *rsc, size_t count, const Element **,
-                            const char **, const size_t * lengths, const uint32_t *asin);
+    static ObjectBaseRef<const Element> createRef(Context *rsc,
+                                                  RsDataType dt,
+                                                  RsDataKind dk,
+                                                  bool isNorm,
+                                                  uint32_t vecSize);
+    static ObjectBaseRef<const Element> createRef(Context *rsc, size_t count,
+                                                  const Element **,
+                                                  const char **,
+                                                  const size_t * lengths,
+                                                  const uint32_t *asin);
+
+    static const Element* create(Context *rsc,
+                                 RsDataType dt,
+                                 RsDataKind dk,
+                                 bool isNorm,
+                                 uint32_t vecSize) {
+        ObjectBaseRef<const Element> elem = createRef(rsc, dt, dk, isNorm, vecSize);
+        elem->incUserRef();
+        return elem.get();
+    }
+    static const Element* create(Context *rsc, size_t count,
+                                 const Element **ein,
+                                 const char **nin,
+                                 const size_t * lengths,
+                                 const uint32_t *asin) {
+        ObjectBaseRef<const Element> elem = createRef(rsc, count, ein, nin, lengths, asin);
+        elem->incUserRef();
+        return elem.get();
+    }
 
     void incRefs(const void *) const;
     void decRefs(const void *) const;
     bool getHasReferences() const {return mHasReference;}
 
-    bool isEqual(const Element *other) const;
-
 protected:
     // deallocate any components that are part of this element.
     void clear();
@@ -88,12 +118,15 @@
     bool mHasReference;
 
 
+    virtual ~Element();
     Element(Context *);
 
     Component mComponent;
     uint32_t mBits;
 
     void compute();
+
+    virtual void preDestroy() const;
 };
 
 
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index cd02c24..df5dc12 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -68,7 +68,7 @@
     for (uint32_t i = 0; i < numIndexEntries; i ++) {
         A3DIndexEntry *entry = new A3DIndexEntry();
         headerStream->loadString(&entry->mObjectName);
-        LOGV("Header data, entry name = %s", entry->mObjectName.string());
+        //LOGV("Header data, entry name = %s", entry->mObjectName.string());
         entry->mType = (RsA3DClassID)headerStream->loadU32();
         if (mUse64BitOffsets){
             entry->mOffset = headerStream->loadOffset();
@@ -369,7 +369,7 @@
     }
 
     ObjectBase *obj = fa3d->initializeFromEntry(index);
-    LOGV("Returning object with name %s", obj->getName());
+    //LOGV("Returning object with name %s", obj->getName());
 
     return obj;
 }
diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp
index 3917ca1..7efed9d 100644
--- a/libs/rs/rsFont.cpp
+++ b/libs/rs/rsFont.cpp
@@ -490,49 +490,47 @@
     shaderString.append("  gl_FragColor = col;\n");
     shaderString.append("}\n");
 
-    const Element *colorElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
-    const Element *gammaElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
-    mRSC->mStateElement.elementBuilderBegin();
-    mRSC->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
-    mRSC->mStateElement.elementBuilderAdd(gammaElem, "Gamma", 1);
-    const Element *constInput = mRSC->mStateElement.elementBuilderCreate(mRSC);
+    ObjectBaseRef<const Element> colorElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
+    ObjectBaseRef<const Element> gammaElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 1);
+    Element::Builder builder;
+    builder.add(colorElem.get(), "Color", 1);
+    builder.add(gammaElem.get(), "Gamma", 1);
+    ObjectBaseRef<const Element> constInput = builder.create(mRSC);
 
-    Type *inputType = Type::getType(mRSC, constInput, 1, 0, 0, false, false);
+    ObjectBaseRef<Type> inputType = Type::getTypeRef(mRSC, constInput.get(), 1, 0, 0, false, false);
 
     uint32_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
-    tmp[1] = (uint32_t)inputType;
+    tmp[1] = (uint32_t)inputType.get();
     tmp[2] = RS_PROGRAM_PARAM_TEXTURE_TYPE;
     tmp[3] = RS_TEXTURE_2D;
 
-    mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType,
+    mFontShaderFConstant.set(Allocation::createAllocation(mRSC, inputType.get(),
                                             RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS));
     ProgramFragment *pf = new ProgramFragment(mRSC, shaderString.string(),
                                               shaderString.length(), tmp, 4);
     mFontShaderF.set(pf);
     mFontShaderF->bindAllocation(mRSC, mFontShaderFConstant.get(), 0);
 
-    Sampler *sampler = new Sampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
-                                      RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP);
-    mFontSampler.set(sampler);
-    mFontShaderF->bindSampler(mRSC, 0, sampler);
+    mFontSampler.set(Sampler::getSampler(mRSC, RS_SAMPLER_NEAREST, RS_SAMPLER_NEAREST,
+                                         RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP, RS_SAMPLER_CLAMP).get());
+    mFontShaderF->bindSampler(mRSC, 0, mFontSampler.get());
 
-    ProgramStore *fontStore = new ProgramStore(mRSC, true, true, true, true,
-                                               false, false,
-                                               RS_BLEND_SRC_SRC_ALPHA,
-                                               RS_BLEND_DST_ONE_MINUS_SRC_ALPHA,
-                                               RS_DEPTH_FUNC_ALWAYS);
-    mFontProgramStore.set(fontStore);
+    mFontProgramStore.set(ProgramStore::getProgramStore(mRSC, true, true, true, true,
+                                                        false, false,
+                                                        RS_BLEND_SRC_SRC_ALPHA,
+                                                        RS_BLEND_DST_ONE_MINUS_SRC_ALPHA,
+                                                        RS_DEPTH_FUNC_ALWAYS).get());
     mFontProgramStore->init();
 }
 
 void FontState::initTextTexture() {
-    const Element *alphaElem = Element::create(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
+    ObjectBaseRef<const Element> alphaElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_8, RS_KIND_PIXEL_A, true, 1);
 
     // We will allocate a texture to initially hold 32 character bitmaps
-    Type *texType = Type::getType(mRSC, alphaElem, 1024, 256, 0, false, false);
+    ObjectBaseRef<Type> texType = Type::getTypeRef(mRSC, alphaElem.get(), 1024, 256, 0, false, false);
 
-    Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType,
+    Allocation *cacheAlloc = Allocation::createAllocation(mRSC, texType.get(),
                                 RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE);
     mTextTexture.set(cacheAlloc);
     mTextTexture->syncAll(mRSC, RS_ALLOCATION_USAGE_SCRIPT);
@@ -557,11 +555,11 @@
 // Avoid having to reallocate memory and render quad by quad
 void FontState::initVertexArrayBuffers() {
     // Now lets write index data
-    const Element *indexElem = Element::create(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
+    ObjectBaseRef<const Element> indexElem = Element::createRef(mRSC, RS_TYPE_UNSIGNED_16, RS_KIND_USER, false, 1);
     uint32_t numIndicies = mMaxNumberOfQuads * 6;
-    Type *indexType = Type::getType(mRSC, indexElem, numIndicies, 0, 0, false, false);
+    ObjectBaseRef<Type> indexType = Type::getTypeRef(mRSC, indexElem.get(), numIndicies, 0, 0, false, false);
 
-    Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType,
+    Allocation *indexAlloc = Allocation::createAllocation(mRSC, indexType.get(),
                                                           RS_ALLOCATION_USAGE_SCRIPT |
                                                           RS_ALLOCATION_USAGE_GRAPHICS_VERTEX);
     uint16_t *indexPtr = (uint16_t*)indexAlloc->getPtr();
@@ -582,19 +580,19 @@
 
     indexAlloc->sendDirty(mRSC);
 
-    const Element *posElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
-    const Element *texElem = Element::create(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
+    ObjectBaseRef<const Element> posElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
+    ObjectBaseRef<const Element> texElem = Element::createRef(mRSC, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
 
-    mRSC->mStateElement.elementBuilderBegin();
-    mRSC->mStateElement.elementBuilderAdd(posElem, "position", 1);
-    mRSC->mStateElement.elementBuilderAdd(texElem, "texture0", 1);
-    const Element *vertexDataElem = mRSC->mStateElement.elementBuilderCreate(mRSC);
+    Element::Builder builder;
+    builder.add(posElem.get(), "position", 1);
+    builder.add(texElem.get(), "texture0", 1);
+    ObjectBaseRef<const Element> vertexDataElem = builder.create(mRSC);
 
-    Type *vertexDataType = Type::getType(mRSC, vertexDataElem,
-                                         mMaxNumberOfQuads * 4,
-                                         0, 0, false, false);
+    ObjectBaseRef<Type> vertexDataType = Type::getTypeRef(mRSC, vertexDataElem.get(),
+                                                          mMaxNumberOfQuads * 4,
+                                                          0, 0, false, false);
 
-    Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType,
+    Allocation *vertexAlloc = Allocation::createAllocation(mRSC, vertexDataType.get(),
                                                            RS_ALLOCATION_USAGE_SCRIPT);
     mTextMeshPtr = (float*)vertexAlloc->getPtr();
 
diff --git a/libs/rs/rsFont.h b/libs/rs/rsFont.h
index b0e1430..679591c 100644
--- a/libs/rs/rsFont.h
+++ b/libs/rs/rsFont.h
@@ -146,7 +146,6 @@
     void deinit(Context *rsc);
 
     ObjectBaseRef<Font> mDefault;
-    ObjectBaseRef<Font> mLast;
 
     void renderText(const char *text, uint32_t len, int32_t x, int32_t y,
                     uint32_t startIndex = 0, int numGlyphs = -1,
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
index 01850f1..c7cfb0e 100644
--- a/libs/rs/rsObjectBase.h
+++ b/libs/rs/rsObjectBase.h
@@ -114,7 +114,10 @@
     }
 
     ObjectBaseRef & operator= (const ObjectBaseRef &ref) {
-        return ObjectBaseRef(ref);
+        if (&ref != this) {
+            set(ref);
+        }
+        return *this;
     }
 
     ~ObjectBaseRef() {
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
index b1d8f48..33eb422e 100644
--- a/libs/rs/rsProgram.cpp
+++ b/libs/rs/rsProgram.cpp
@@ -116,7 +116,7 @@
             rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
             return;
         }
-        if (!alloc->getType()->isEqual(mHal.state.constantTypes[slot].get())) {
+        if (alloc->getType() != mHal.state.constantTypes[slot].get()) {
             LOGE("Attempt to bind alloc at slot %u, on shader id %u, but types mismatch",
                  slot, (uint32_t)this);
             rsc->setError(RS_ERROR_BAD_SHADER, "Cannot bind allocation");
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 356ff77..ff29520 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -97,18 +97,18 @@
     shaderString.append("  gl_FragColor = col;\n");
     shaderString.append("}\n");
 
-    const Element *colorElem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
-    rsc->mStateElement.elementBuilderBegin();
-    rsc->mStateElement.elementBuilderAdd(colorElem, "Color", 1);
-    const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc);
+    ObjectBaseRef<const Element> colorElem = Element::createRef(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
+    Element::Builder builder;
+    builder.add(colorElem.get(), "Color", 1);
+    ObjectBaseRef<const Element> constInput = builder.create(rsc);
 
-    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
+    ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false);
 
     uint32_t tmp[2];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
-    tmp[1] = (uint32_t)inputType;
+    tmp[1] = (uint32_t)inputType.get();
 
-    Allocation *constAlloc = Allocation::createAllocation(rsc, inputType,
+    Allocation *constAlloc = Allocation::createAllocation(rsc, inputType.get(),
                               RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
     ProgramFragment *pf = new ProgramFragment(rsc, shaderString.string(),
                                               shaderString.length(), tmp, 2);
diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp
index 435561d..945b5ec 100644
--- a/libs/rs/rsProgramRaster.cpp
+++ b/libs/rs/rsProgramRaster.cpp
@@ -37,6 +37,15 @@
     rsc->mHal.funcs.raster.init(rsc, this);
 }
 
+void ProgramRaster::preDestroy() const {
+    for (uint32_t ct = 0; ct < mRSC->mStateRaster.mRasterPrograms.size(); ct++) {
+        if (mRSC->mStateRaster.mRasterPrograms[ct] == this) {
+            mRSC->mStateRaster.mRasterPrograms.removeAt(ct);
+            break;
+        }
+    }
+}
+
 ProgramRaster::~ProgramRaster() {
     mRSC->mHal.funcs.raster.destroy(mRSC, this);
 }
@@ -65,8 +74,8 @@
 }
 
 void ProgramRasterState::init(Context *rsc) {
-    ProgramRaster *pr = new ProgramRaster(rsc, false, false, false, 1.f, RS_CULL_BACK);
-    mDefault.set(pr);
+    mDefault.set(ProgramRaster::getProgramRaster(rsc, false, false,
+                                                 false, 1.f, RS_CULL_BACK).get());
 }
 
 void ProgramRasterState::deinit(Context *rsc) {
@@ -74,19 +83,47 @@
     mLast.clear();
 }
 
+ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc,
+                                                             bool pointSmooth,
+                                                             bool lineSmooth,
+                                                             bool pointSprite,
+                                                             float lineWidth,
+                                                             RsCullMode cull) {
+    ObjectBaseRef<ProgramRaster> returnRef;
+    ObjectBase::asyncLock();
+    for (uint32_t ct = 0; ct < rsc->mStateRaster.mRasterPrograms.size(); ct++) {
+        ProgramRaster *existing = rsc->mStateRaster.mRasterPrograms[ct];
+        if (existing->mHal.state.pointSmooth != pointSmooth) continue;
+        if (existing->mHal.state.lineSmooth != lineSmooth) continue;
+        if (existing->mHal.state.pointSprite != pointSprite) continue;
+        if (existing->mHal.state.lineWidth != lineWidth) continue;
+        if (existing->mHal.state.cull != cull) continue;
+        returnRef.set(existing);
+        ObjectBase::asyncUnlock();
+        return returnRef;
+    }
+    ObjectBase::asyncUnlock();
+
+    ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth,
+                                          lineSmooth, pointSprite, lineWidth, cull);
+    returnRef.set(pr);
+
+    ObjectBase::asyncLock();
+    rsc->mStateRaster.mRasterPrograms.push(pr);
+    ObjectBase::asyncUnlock();
+
+    return returnRef;
+}
+
 namespace android {
 namespace renderscript {
 
-RsProgramRaster rsi_ProgramRasterCreate(Context * rsc,
-                                      bool pointSmooth,
-                                      bool lineSmooth,
-                                      bool pointSprite,
-                                      float lineWidth,
-                                      RsCullMode cull) {
-    ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth,
-                                          lineSmooth, pointSprite, lineWidth, cull);
+RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSmooth, bool lineSmooth,
+                                        bool pointSprite, float lineWidth, RsCullMode cull) {
+    ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSmooth, lineSmooth,
+                                                                      pointSprite, lineWidth, cull);
     pr->incUserRef();
-    return pr;
+    return pr.get();
 }
 
 }
diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h
index efdb948..09d7d54 100644
--- a/libs/rs/rsProgramRaster.h
+++ b/libs/rs/rsProgramRaster.h
@@ -27,19 +27,17 @@
 
 class ProgramRaster : public ProgramBase {
 public:
-    ProgramRaster(Context *rsc,
-                  bool pointSmooth,
-                  bool lineSmooth,
-                  bool pointSprite,
-                  float lineWidth,
-                  RsCullMode cull);
-    virtual ~ProgramRaster();
-
     virtual void setup(const Context *, ProgramRasterState *);
     virtual void serialize(OStream *stream) const;
     virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_RASTER; }
     static ProgramRaster *createFromStream(Context *rsc, IStream *stream);
 
+    static ObjectBaseRef<ProgramRaster> getProgramRaster(Context *rsc,
+                                                         bool pointSmooth,
+                                                         bool lineSmooth,
+                                                         bool pointSprite,
+                                                         float lineWidth,
+                                                         RsCullMode cull);
     struct Hal {
         mutable void *drv;
 
@@ -55,6 +53,17 @@
     Hal mHal;
 
 protected:
+    virtual void preDestroy() const;
+    virtual ~ProgramRaster();
+
+private:
+    ProgramRaster(Context *rsc,
+                  bool pointSmooth,
+                  bool lineSmooth,
+                  bool pointSprite,
+                  float lineWidth,
+                  RsCullMode cull);
+
 };
 
 class ProgramRasterState {
@@ -66,6 +75,9 @@
 
     ObjectBaseRef<ProgramRaster> mDefault;
     ObjectBaseRef<ProgramRaster> mLast;
+
+    // Cache of all existing raster programs.
+    Vector<ProgramRaster *> mRasterPrograms;
 };
 
 
diff --git a/libs/rs/rsProgramStore.cpp b/libs/rs/rsProgramStore.cpp
index 8fe890b..7e25a22 100644
--- a/libs/rs/rsProgramStore.cpp
+++ b/libs/rs/rsProgramStore.cpp
@@ -41,6 +41,15 @@
     mHal.state.depthFunc = depthFunc;
 }
 
+void ProgramStore::preDestroy() const {
+    for (uint32_t ct = 0; ct < mRSC->mStateFragmentStore.mStorePrograms.size(); ct++) {
+        if (mRSC->mStateFragmentStore.mStorePrograms[ct] == this) {
+            mRSC->mStateFragmentStore.mStorePrograms.removeAt(ct);
+            break;
+        }
+    }
+}
+
 ProgramStore::~ProgramStore() {
     mRSC->mHal.funcs.store.destroy(mRSC, this);
 }
@@ -71,14 +80,58 @@
 ProgramStoreState::~ProgramStoreState() {
 }
 
+ObjectBaseRef<ProgramStore> ProgramStore::getProgramStore(Context *rsc,
+                                                          bool colorMaskR,
+                                                          bool colorMaskG,
+                                                          bool colorMaskB,
+                                                          bool colorMaskA,
+                                                          bool depthMask, bool ditherEnable,
+                                                          RsBlendSrcFunc srcFunc,
+                                                          RsBlendDstFunc destFunc,
+                                                          RsDepthFunc depthFunc) {
+    ObjectBaseRef<ProgramStore> returnRef;
+    ObjectBase::asyncLock();
+    for (uint32_t ct = 0; ct < rsc->mStateFragmentStore.mStorePrograms.size(); ct++) {
+        ProgramStore *existing = rsc->mStateFragmentStore.mStorePrograms[ct];
+        if (existing->mHal.state.ditherEnable != ditherEnable) continue;
+        if (existing->mHal.state.colorRWriteEnable != colorMaskR) continue;
+        if (existing->mHal.state.colorGWriteEnable != colorMaskG) continue;
+        if (existing->mHal.state.colorBWriteEnable != colorMaskB) continue;
+        if (existing->mHal.state.colorAWriteEnable != colorMaskA) continue;
+        if (existing->mHal.state.blendSrc != srcFunc) continue;
+        if (existing->mHal.state.blendDst != destFunc) continue;
+        if (existing->mHal.state.depthWriteEnable != depthMask) continue;
+        if (existing->mHal.state.depthFunc != depthFunc) continue;
+
+        returnRef.set(existing);
+        ObjectBase::asyncUnlock();
+        return returnRef;
+    }
+    ObjectBase::asyncUnlock();
+
+    ProgramStore *pfs = new ProgramStore(rsc,
+                                         colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+                                         depthMask, ditherEnable,
+                                         srcFunc, destFunc, depthFunc);
+    returnRef.set(pfs);
+
+    pfs->init();
+
+    ObjectBase::asyncLock();
+    rsc->mStateFragmentStore.mStorePrograms.push(pfs);
+    ObjectBase::asyncUnlock();
+
+    return returnRef;
+}
+
+
+
 void ProgramStoreState::init(Context *rsc) {
-    ProgramStore *ps = new ProgramStore(rsc,
-                                        true, true, true, true,
-                                        true, true,
-                                        RS_BLEND_SRC_ONE, RS_BLEND_DST_ZERO,
-                                        RS_DEPTH_FUNC_LESS);
-    ps->init();
-    mDefault.set(ps);
+    mDefault.set(ProgramStore::getProgramStore(rsc,
+                                               true, true, true, true,
+                                               true, true,
+                                               RS_BLEND_SRC_ONE, RS_BLEND_DST_ZERO,
+                                               RS_DEPTH_FUNC_LESS).get());
 }
 
 void ProgramStoreState::deinit(Context *rsc) {
@@ -96,13 +149,14 @@
                                       RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
                                       RsDepthFunc depthFunc) {
 
-    ProgramStore *pfs = new ProgramStore(rsc,
-                                         colorMaskR, colorMaskG, colorMaskB, colorMaskA,
-                                         depthMask, ditherEnable,
-                                         srcFunc, destFunc, depthFunc);
-    pfs->init();
-    pfs->incUserRef();
-    return pfs;
+
+    ObjectBaseRef<ProgramStore> ps = ProgramStore::getProgramStore(rsc,
+                                                                   colorMaskR, colorMaskG,
+                                                                   colorMaskB, colorMaskA,
+                                                                   depthMask, ditherEnable,
+                                                                   srcFunc, destFunc, depthFunc);
+    ps->incUserRef();
+    return ps.get();
 }
 
 }
diff --git a/libs/rs/rsProgramStore.h b/libs/rs/rsProgramStore.h
index 77b3881..e21f039 100644
--- a/libs/rs/rsProgramStore.h
+++ b/libs/rs/rsProgramStore.h
@@ -28,18 +28,17 @@
 
 class ProgramStore : public ProgramBase {
 public:
-    ProgramStore(Context *,
-                 bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
-                 bool depthMask, bool ditherEnable,
-                 RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
-                 RsDepthFunc depthFunc);
-    virtual ~ProgramStore();
-
     virtual void setup(const Context *, ProgramStoreState *);
 
     virtual void serialize(OStream *stream) const;
     virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_PROGRAM_STORE; }
     static ProgramStore *createFromStream(Context *rsc, IStream *stream);
+    static ObjectBaseRef<ProgramStore> getProgramStore(Context *,
+                                                       bool colorMaskR, bool colorMaskG,
+                                                       bool colorMaskB, bool colorMaskA,
+                                                       bool depthMask, bool ditherEnable,
+                                                       RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
+                                                       RsDepthFunc depthFunc);
 
     void init();
 
@@ -66,6 +65,15 @@
     Hal mHal;
 
 protected:
+    virtual void preDestroy() const;
+    virtual ~ProgramStore();
+
+private:
+    ProgramStore(Context *,
+                 bool colorMaskR, bool colorMaskG, bool colorMaskB, bool colorMaskA,
+                 bool depthMask, bool ditherEnable,
+                 RsBlendSrcFunc srcFunc, RsBlendDstFunc destFunc,
+                 RsDepthFunc depthFunc);
 };
 
 class ProgramStoreState {
@@ -77,6 +85,9 @@
 
     ObjectBaseRef<ProgramStore> mDefault;
     ObjectBaseRef<ProgramStore> mLast;
+
+    // Cache of all existing store programs.
+    Vector<ProgramStore *> mStorePrograms;
 };
 
 }
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 058a456..51cb2a8a 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -150,26 +150,30 @@
 }
 
 void ProgramVertexState::init(Context *rsc) {
-    const Element *matrixElem = Element::create(rsc, RS_TYPE_MATRIX_4X4, RS_KIND_USER, false, 1);
-    const Element *f2Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 2);
-    const Element *f3Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 3);
-    const Element *f4Elem = Element::create(rsc, RS_TYPE_FLOAT_32, RS_KIND_USER, false, 4);
+    ObjectBaseRef<const Element> matrixElem = Element::createRef(rsc, RS_TYPE_MATRIX_4X4,
+                                                                 RS_KIND_USER, false, 1);
+    ObjectBaseRef<const Element> f2Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32,
+                                                             RS_KIND_USER, false, 2);
+    ObjectBaseRef<const Element> f3Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32,
+                                                             RS_KIND_USER, false, 3);
+    ObjectBaseRef<const Element> f4Elem = Element::createRef(rsc, RS_TYPE_FLOAT_32,
+                                                             RS_KIND_USER, false, 4);
 
-    rsc->mStateElement.elementBuilderBegin();
-    rsc->mStateElement.elementBuilderAdd(matrixElem, "MV", 1);
-    rsc->mStateElement.elementBuilderAdd(matrixElem, "P", 1);
-    rsc->mStateElement.elementBuilderAdd(matrixElem, "TexMatrix", 1);
-    rsc->mStateElement.elementBuilderAdd(matrixElem, "MVP", 1);
-    const Element *constInput = rsc->mStateElement.elementBuilderCreate(rsc);
+    Element::Builder constBuilder;
+    constBuilder.add(matrixElem.get(), "MV", 1);
+    constBuilder.add(matrixElem.get(), "P", 1);
+    constBuilder.add(matrixElem.get(), "TexMatrix", 1);
+    constBuilder.add(matrixElem.get(), "MVP", 1);
+    ObjectBaseRef<const Element> constInput = constBuilder.create(rsc);
 
-    rsc->mStateElement.elementBuilderBegin();
-    rsc->mStateElement.elementBuilderAdd(f4Elem, "position", 1);
-    rsc->mStateElement.elementBuilderAdd(f4Elem, "color", 1);
-    rsc->mStateElement.elementBuilderAdd(f3Elem, "normal", 1);
-    rsc->mStateElement.elementBuilderAdd(f2Elem, "texture0", 1);
-    const Element *attrElem = rsc->mStateElement.elementBuilderCreate(rsc);
+    Element::Builder inputBuilder;
+    inputBuilder.add(f4Elem.get(), "position", 1);
+    inputBuilder.add(f4Elem.get(), "color", 1);
+    inputBuilder.add(f3Elem.get(), "normal", 1);
+    inputBuilder.add(f2Elem.get(), "texture0", 1);
+    ObjectBaseRef<const Element> attrElem = inputBuilder.create(rsc);
 
-    Type *inputType = Type::getType(rsc, constInput, 1, 0, 0, false, false);
+    ObjectBaseRef<Type> inputType = Type::getTypeRef(rsc, constInput.get(), 1, 0, 0, false, false);
 
     String8 shaderString(RS_SHADER_INTERNAL);
     shaderString.append("varying vec4 varColor;\n");
@@ -183,13 +187,13 @@
 
     uint32_t tmp[4];
     tmp[0] = RS_PROGRAM_PARAM_CONSTANT;
-    tmp[1] = (uint32_t)inputType;
+    tmp[1] = (uint32_t)inputType.get();
     tmp[2] = RS_PROGRAM_PARAM_INPUT;
-    tmp[3] = (uint32_t)attrElem;
+    tmp[3] = (uint32_t)attrElem.get();
 
     ProgramVertex *pv = new ProgramVertex(rsc, shaderString.string(),
                                           shaderString.length(), tmp, 4);
-    Allocation *alloc = Allocation::createAllocation(rsc, inputType,
+    Allocation *alloc = Allocation::createAllocation(rsc, inputType.get(),
                               RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS);
     pv->bindAllocation(rsc, alloc, 0);
 
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index 2a05d16..5fc64a4 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -48,6 +48,15 @@
     mRSC->mHal.funcs.sampler.destroy(mRSC, this);
 }
 
+void Sampler::preDestroy() const {
+    for (uint32_t ct = 0; ct < mRSC->mStateSampler.mAllSamplers.size(); ct++) {
+        if (mRSC->mStateSampler.mAllSamplers[ct] == this) {
+            mRSC->mStateSampler.mAllSamplers.removeAt(ct);
+            break;
+        }
+    }
+}
+
 void Sampler::bindToContext(SamplerState *ss, uint32_t slot) {
     ss->mSamplers[slot].set(this);
     mBoundSlot = slot;
@@ -66,6 +75,39 @@
     return NULL;
 }
 
+ObjectBaseRef<Sampler> Sampler::getSampler(Context *rsc,
+                                           RsSamplerValue magFilter,
+                                           RsSamplerValue minFilter,
+                                           RsSamplerValue wrapS,
+                                           RsSamplerValue wrapT,
+                                           RsSamplerValue wrapR,
+                                           float aniso) {
+    ObjectBaseRef<Sampler> returnRef;
+    ObjectBase::asyncLock();
+    for (uint32_t ct = 0; ct < rsc->mStateSampler.mAllSamplers.size(); ct++) {
+        Sampler *existing = rsc->mStateSampler.mAllSamplers[ct];
+        if (existing->mHal.state.magFilter != magFilter) continue;
+        if (existing->mHal.state.minFilter != minFilter ) continue;
+        if (existing->mHal.state.wrapS != wrapS) continue;
+        if (existing->mHal.state.wrapT != wrapT) continue;
+        if (existing->mHal.state.wrapR != wrapR) continue;
+        if (existing->mHal.state.aniso != aniso) continue;
+        returnRef.set(existing);
+        ObjectBase::asyncUnlock();
+        return returnRef;
+    }
+    ObjectBase::asyncUnlock();
+
+    Sampler *s = new Sampler(rsc, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
+    returnRef.set(s);
+
+    ObjectBase::asyncLock();
+    rsc->mStateSampler.mAllSamplers.push(s);
+    ObjectBase::asyncUnlock();
+
+    return returnRef;
+}
+
 ////////////////////////////////
 
 namespace android {
@@ -78,9 +120,10 @@
                             RsSamplerValue wrapT,
                             RsSamplerValue wrapR,
                             float aniso) {
-    Sampler * s = new Sampler(rsc, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
+    ObjectBaseRef<Sampler> s = Sampler::getSampler(rsc, magFilter, minFilter,
+                                                   wrapS, wrapT, wrapR, aniso);
     s->incUserRef();
-    return s;
+    return s.get();
 }
 
 }}
diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h
index 90b6082..e698132 100644
--- a/libs/rs/rsSampler.h
+++ b/libs/rs/rsSampler.h
@@ -30,16 +30,13 @@
 
 class Sampler : public ObjectBase {
 public:
-    Sampler(Context *,
-            RsSamplerValue magFilter,
-            RsSamplerValue minFilter,
-            RsSamplerValue wrapS,
-            RsSamplerValue wrapT,
-            RsSamplerValue wrapR,
-            float aniso = 1.0f);
-
-    virtual ~Sampler();
-
+    static ObjectBaseRef<Sampler> getSampler(Context *,
+                                             RsSamplerValue magFilter,
+                                             RsSamplerValue minFilter,
+                                             RsSamplerValue wrapS,
+                                             RsSamplerValue wrapT,
+                                             RsSamplerValue wrapR,
+                                             float aniso = 1.0f);
     void bindToContext(SamplerState *, uint32_t slot);
     void unbindFromContext(SamplerState *);
 
@@ -65,14 +62,33 @@
 protected:
     int32_t mBoundSlot;
 
+    virtual void preDestroy() const;
+    virtual ~Sampler();
+
 private:
     Sampler(Context *);
+    Sampler(Context *,
+            RsSamplerValue magFilter,
+            RsSamplerValue minFilter,
+            RsSamplerValue wrapS,
+            RsSamplerValue wrapT,
+            RsSamplerValue wrapR,
+            float aniso = 1.0f);
 };
 
 
 class SamplerState {
 public:
     ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT];
+    void init(Context *rsc) {
+    }
+    void deinit(Context *rsc) {
+        for (uint32_t i = 0; i < RS_MAX_SAMPLER_SLOT; i ++) {
+            mSamplers[i].clear();
+        }
+    }
+    // Cache of all existing raster programs.
+    Vector<Sampler *> mAllSamplers;
 };
 
 }
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 10e3182..9a6a31b 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -25,7 +25,7 @@
     clear();
 }
 
-void Type::preDestroy() {
+void Type::preDestroy() const {
     for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
         if (mRSC->mStateType.mTypes[ct] == this) {
             mRSC->mStateType.mTypes.removeAt(ct);
@@ -58,6 +58,7 @@
 }
 
 TypeState::~TypeState() {
+    rsAssert(!mTypes.size());
 }
 
 size_t Type::getOffsetForFace(uint32_t face) const {
@@ -183,7 +184,9 @@
     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 );
+    Type *type = Type::getType(rsc, elem, x, y, z, lod != 0, faces !=0 );
+    elem->decUserRef();
+    return type;
 }
 
 bool Type::getIsNp2() const {
@@ -203,24 +206,11 @@
     return false;
 }
 
-bool Type::isEqual(const Type *other) const {
-    if (other == NULL) {
-        return false;
-    }
-    if (other->getElement()->isEqual(getElement()) &&
-        other->getDimX() == mDimX &&
-        other->getDimY() == mDimY &&
-        other->getDimZ() == mDimZ &&
-        other->getDimLOD() == mDimLOD &&
-        other->getDimFaces() == mFaces) {
-        return true;
-    }
-    return false;
-}
+ObjectBaseRef<Type> Type::getTypeRef(Context *rsc, const Element *e,
+                                     uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                                     bool dimLOD, bool dimFaces) {
+    ObjectBaseRef<Type> returnRef;
 
-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();
@@ -232,14 +222,15 @@
         if (t->getDimZ() != dimZ) continue;
         if (t->getDimLOD() != dimLOD) continue;
         if (t->getDimFaces() != dimFaces) continue;
-        t->incUserRef();
+        returnRef.set(t);
         ObjectBase::asyncUnlock();
-        return t;
+        return returnRef;
     }
     ObjectBase::asyncUnlock();
 
 
     Type *nt = new Type(rsc);
+    returnRef.set(nt);
     nt->mElement.set(e);
     nt->mDimX = dimX;
     nt->mDimY = dimY;
@@ -247,25 +238,24 @@
     nt->mDimLOD = dimLOD;
     nt->mFaces = dimFaces;
     nt->compute();
-    nt->incUserRef();
 
     ObjectBase::asyncLock();
     stc->mTypes.push(nt);
     ObjectBase::asyncUnlock();
 
-    return nt;
+    return returnRef;
 }
 
-Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
-    return getType(rsc, mElement.get(), dimX,
-                   mDimY, mDimZ, mDimLOD, mFaces);
+ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
+    return getTypeRef(rsc, mElement.get(), dimX,
+                      mDimY, mDimZ, mDimLOD, mFaces);
 }
 
-Type * Type::cloneAndResize2D(Context *rsc,
+ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc,
                               uint32_t dimX,
                               uint32_t dimY) const {
-    return getType(rsc, mElement.get(), dimX, dimY,
-                   mDimZ, mDimLOD, mFaces);
+    return getTypeRef(rsc, mElement.get(), dimX, dimY,
+                      mDimZ, mDimLOD, mFaces);
 }
 
 
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
index 086db33..bc0d9ff 100644
--- a/libs/rs/rsType.h
+++ b/libs/rs/rsType.h
@@ -62,14 +62,20 @@
     virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_TYPE; }
     static Type *createFromStream(Context *rsc, IStream *stream);
 
-    bool isEqual(const Type *other) const;
+    ObjectBaseRef<Type> cloneAndResize1D(Context *rsc, uint32_t dimX) const;
+    ObjectBaseRef<Type> cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
 
-    Type * cloneAndResize1D(Context *rsc, uint32_t dimX) const;
-    Type * cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const;
+    static ObjectBaseRef<Type> getTypeRef(Context *rsc, const Element *e,
+                                          uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                                          bool dimLOD, bool dimFaces);
 
-    static Type * getType(Context *rsc, const Element *e,
-                      uint32_t dimX, uint32_t dimY, uint32_t dimZ,
-                      bool dimLOD, bool dimFaces);
+    static Type* getType(Context *rsc, const Element *e,
+                         uint32_t dimX, uint32_t dimY, uint32_t dimZ,
+                         bool dimLOD, bool dimFaces) {
+        ObjectBaseRef<Type> type = getTypeRef(rsc, e, dimX, dimY, dimZ, dimLOD, dimFaces);
+        type->incUserRef();
+        return type.get();
+    }
 
 protected:
     struct LOD {
@@ -105,7 +111,7 @@
     uint32_t mLODCount;
 
 protected:
-    virtual void preDestroy();
+    virtual void preDestroy() const;
     virtual ~Type();
 
 private:
diff --git a/libs/rs/rs_hal.h b/libs/rs/rs_hal.h
index 6a4537b..21dff218 100644
--- a/libs/rs/rs_hal.h
+++ b/libs/rs/rs_hal.h
@@ -40,6 +40,19 @@
 
 typedef void *(*RsHalSymbolLookupFunc)(void *usrptr, char const *symbolName);
 
+typedef struct {
+    const void *in;
+    void *out;
+    const void *usr;
+    size_t usr_len;
+    uint32_t x;
+    uint32_t y;
+    uint32_t z;
+    uint32_t lod;
+    RsAllocationCubemapFace face;
+    uint32_t ar[16];
+} RsForEachStubParamStruct;
+
 /**
  * Script management functions
  */
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7a92b35..f9efd3c 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -21,6 +21,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.graphics.Bitmap;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -1715,29 +1716,103 @@
     }
 
     /**
+     * Acts as a proxy between AudioService and the RemoteControlClient
+     */
+    private IRemoteControlClientDispatcher mRcClientDispatcher =
+            new IRemoteControlClientDispatcher.Stub() {
+
+        public String getMetadataStringForClient(String clientName, int field) {
+            RemoteControlClient realClient;
+            synchronized(mRcClientMap) {
+                realClient = mRcClientMap.get(clientName);
+            }
+            if (realClient != null) {
+                return realClient.getMetadataString(field);
+            } else {
+                return null;
+            }
+        }
+
+        public int getPlaybackStateForClient(String clientName) {
+            RemoteControlClient realClient;
+            synchronized(mRcClientMap) {
+                realClient = mRcClientMap.get(clientName);
+            }
+            if (realClient != null) {
+                return realClient.getPlaybackState();
+            } else {
+                return 0;
+            }
+        }
+
+        public int getTransportControlFlagsForClient(String clientName) {
+            RemoteControlClient realClient;
+            synchronized(mRcClientMap) {
+                realClient = mRcClientMap.get(clientName);
+            }
+            if (realClient != null) {
+                return realClient.getTransportControlFlags();
+            } else {
+                return 0;
+            }
+        }
+
+        public Bitmap getAlbumArtForClient(String clientName, int maxWidth, int maxHeight) {
+            RemoteControlClient realClient;
+            synchronized(mRcClientMap) {
+                realClient = mRcClientMap.get(clientName);
+            }
+            if (realClient != null) {
+                return realClient.getAlbumArt(maxWidth, maxHeight);
+            } else {
+                return null;
+            }
+        }
+    };
+
+    private HashMap<String, RemoteControlClient> mRcClientMap =
+            new HashMap<String, RemoteControlClient>();
+
+    private String getIdForRcClient(RemoteControlClient client) {
+        // client is guaranteed to be non-null
+        return client.toString();
+    }
+
+    /**
      * @hide
-     * Registers the remote control client for providing information to display on the remotes.
+     * Registers the remote control client for providing information to display on the remote
+     * controls.
      * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
      *      that will receive the media button intent, and associated with the remote control
      *      client. This method has no effect if
      *      {@link #registerMediaButtonEventReceiver(ComponentName)} hasn't been called
      *      with the same eventReceiver, or if
      *      {@link #unregisterMediaButtonEventReceiver(ComponentName)} has been called.
-     * @param rcClient the client associated with the event receiver, responsible for providing
-     *      the information to display on the remote control.
+     * @param rcClient the remote control client associated with the event receiver, responsible
+     *      for providing the information to display on the remote control.
      */
     public void registerRemoteControlClient(ComponentName eventReceiver,
-            IRemoteControlClient rcClient) {
-        if (eventReceiver == null) {
+            RemoteControlClient rcClient) {
+        if ((eventReceiver == null) || (rcClient == null)) {
             return;
         }
+        String clientKey = getIdForRcClient(rcClient);
+        synchronized(mRcClientMap) {
+            if (mRcClientMap.containsKey(clientKey)) {
+                return;
+            }
+            mRcClientMap.put(clientKey, rcClient);
+        }
         IAudioService service = getService();
         try {
-            service.registerRemoteControlClient(eventReceiver, rcClient,
+            service.registerRemoteControlClient(eventReceiver, mRcClientDispatcher, clientKey,
                     // used to match media button event receiver and audio focus
                     mContext.getPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in registerRemoteControlClient"+e);
+            synchronized(mRcClientMap) {
+                mRcClientMap.remove(clientKey);
+            }
         }
     }
 
@@ -1748,17 +1823,28 @@
      * @param eventReceiver identifier of a {@link android.content.BroadcastReceiver}
      *      that receives the media button intent, and associated with the remote control
      *      client.
-     * @see #registerRemoteControlClient(ComponentName)
-
+     * @param rcClient the remote control client to unregister
+     * @see #registerRemoteControlClient(ComponentName, RemoteControlClient)
      */
-    public void unregisterRemoteControlClient(ComponentName eventReceiver) {
-        if (eventReceiver == null) {
+    public void unregisterRemoteControlClient(ComponentName eventReceiver,
+            RemoteControlClient rcClient) {
+        if ((eventReceiver == null) || (rcClient == null)) {
             return;
         }
         IAudioService service = getService();
         try {
-            // unregistering a IRemoteControlClient is equivalent to setting it to null
-            service.registerRemoteControlClient(eventReceiver, null, mContext.getPackageName());
+            // remove locally
+            boolean unregister = true;
+            synchronized(mRcClientMap) {
+                if (mRcClientMap.remove(getIdForRcClient(rcClient)) == null) {
+                    unregister = false;
+                }
+            }
+            if (unregister) {
+                // unregistering a RemoteControlClient is equivalent to setting it to null
+                service.registerRemoteControlClient(eventReceiver, null, null,
+                        mContext.getPackageName());
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);
         }
@@ -1767,17 +1853,17 @@
     /**
      * @hide
      * Returns the current remote control client.
-     * @param rcClientId the counter value that matches the extra
-     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT} in the
+     * @param rcClientId the generation counter that matches the extra
+     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT_GENERATION} in the
      *     {@link AudioManager#REMOTE_CONTROL_CLIENT_CHANGED} event
-     * @return the current IRemoteControlClient from which information to display on the remote
+     * @return the current RemoteControlClient from which information to display on the remote
      *     control can be retrieved, or null if rcClientId doesn't match the current generation
      *     counter.
      */
-    public IRemoteControlClient getRemoteControlClient(int rcClientId) {
+    public IRemoteControlClientDispatcher getRemoteControlClientDispatcher(int rcClientId) {
         IAudioService service = getService();
         try {
-            return service.getRemoteControlClient(rcClientId);
+            return service.getRemoteControlClientDispatcher(rcClientId);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in getRemoteControlClient "+e);
             return null;
@@ -1786,160 +1872,6 @@
 
     /**
      * @hide
-     * Definitions of constants to be used in {@link android.media.IRemoteControlClient}.
-     */
-    public final class RemoteControlParameters {
-        /**
-         * Playback state of an IRemoteControlClient which is stopped.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_STOPPED            = 1;
-        /**
-         * Playback state of an IRemoteControlClient which is paused.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_PAUSED             = 2;
-        /**
-         * Playback state of an IRemoteControlClient which is playing media.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_PLAYING            = 3;
-        /**
-         * Playback state of an IRemoteControlClient which is fast forwarding in the media
-         *    it is currently playing.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_FAST_FORWARDING    = 4;
-        /**
-         * Playback state of an IRemoteControlClient which is fast rewinding in the media
-         *    it is currently playing.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_REWINDING          = 5;
-        /**
-         * Playback state of an IRemoteControlClient which is skipping to the next
-         *    logical chapter (such as a song in a playlist) in the media it is currently playing.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_SKIPPING_FORWARDS  = 6;
-        /**
-         * Playback state of an IRemoteControlClient which is skipping back to the previous
-         *    logical chapter (such as a song in a playlist) in the media it is currently playing.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7;
-        /**
-         * Playback state of an IRemoteControlClient which is buffering data to play before it can
-         *    start or resume playback.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_BUFFERING          = 8;
-        /**
-         * Playback state of an IRemoteControlClient which cannot perform any playback related
-         *    operation because of an internal error. Examples of such situations are no network
-         *    connectivity when attempting to stream data from a server, or expired user credentials
-         *    when trying to play subscription-based content.
-         *
-         * @see android.media.IRemoteControlClient#getPlaybackState()
-         */
-        public final static int PLAYSTATE_ERROR              = 9;
-
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "previous" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS
-         */
-        public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "rewing" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND
-         */
-        public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "play" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY
-         */
-        public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "play/pause" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE
-         */
-        public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "pause" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE
-         */
-        public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "stop" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP
-         */
-        public final static int FLAG_KEY_MEDIA_STOP = 1 << 5;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "fast forward" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD
-         */
-        public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6;
-        /**
-         * Flag indicating an IRemoteControlClient makes use of the "next" media key.
-         *
-         * @see android.media.IRemoteControlClient#getTransportControlFlags()
-         * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT
-         */
-        public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7;
-
-        /**
-         * Flag used to signal that the metadata exposed by the IRemoteControlClient has changed.
-         *
-         * @see #notifyRemoteControlInformationChanged(ComponentName, int)
-         */
-        public final static int FLAG_INFORMATION_CHANGED_METADATA = 1 << 0;
-        /**
-         * Flag used to signal that the transport control buttons supported by the
-         * IRemoteControlClient have changed.
-         * This can for instance happen when playback is at the end of a playlist, and the "next"
-         * operation is not supported anymore.
-         *
-         * @see #notifyRemoteControlInformationChanged(ComponentName, int)
-         */
-        public final static int FLAG_INFORMATION_CHANGED_KEY_MEDIA = 1 << 1;
-        /**
-         * Flag used to signal that the playback state of the IRemoteControlClient has changed.
-         *
-         * @see #notifyRemoteControlInformationChanged(ComponentName, int)
-         */
-        public final static int FLAG_INFORMATION_CHANGED_PLAYSTATE = 1 << 2;
-        /**
-         * Flag used to signal that the album art for the IRemoteControlClient has changed.
-         *
-         * @see #notifyRemoteControlInformationChanged(ComponentName, int)
-         */
-        public final static int FLAG_INFORMATION_CHANGED_ALBUM_ART = 1 << 3;
-    }
-
-    /**
-     * @hide
      * Broadcast intent action indicating that the displays on the remote controls
      * should be updated because a new remote control client is now active. If there is no
      * {@link #EXTRA_REMOTE_CONTROL_CLIENT}, the remote control display should be cleared
@@ -1952,16 +1884,27 @@
 
     /**
      * @hide
-     * The IRemoteControlClient monotonically increasing generation counter.
+     * The IRemoteControlClientDispatcher monotonically increasing generation counter.
      *
      * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
      */
-    public static final String EXTRA_REMOTE_CONTROL_CLIENT =
-            "android.media.EXTRA_REMOTE_CONTROL_CLIENT";
+    public static final String EXTRA_REMOTE_CONTROL_CLIENT_GENERATION =
+            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION";
 
     /**
      * @hide
-     * The media button event receiver associated with the IRemoteControlClient.
+     * The name of the RemoteControlClient.
+     * This String is passed as the client name when calling methods from the
+     * IRemoteControlClientDispatcher interface.
+     *
+     * @see #REMOTE_CONTROL_CLIENT_CHANGED_ACTION
+     */
+    public static final String EXTRA_REMOTE_CONTROL_CLIENT_NAME =
+            "android.media.EXTRA_REMOTE_CONTROL_CLIENT_NAME";
+
+    /**
+     * @hide
+     * The media button event receiver associated with the RemoteControlClient.
      * The {@link android.content.ComponentName} value of the event receiver can be retrieved with
      * {@link android.content.ComponentName#unflattenFromString(String)}
      *
@@ -1992,10 +1935,10 @@
      * @param infoFlag the type of information that has changed since this method was last called,
      *      or the event receiver was registered. Use one or multiple of the following flags to
      *      describe what changed:
-     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_METADATA},
-     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_KEY_MEDIA},
-     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_PLAYSTATE},
-     *      {@link RemoteControlParameters#FLAG_INFORMATION_CHANGED_ALBUM_ART}.
+     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_METADATA},
+     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_KEY_MEDIA},
+     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_PLAYSTATE},
+     *      {@link RemoteControlClient#FLAG_INFORMATION_CHANGED_ALBUM_ART}.
      */
     public void notifyRemoteControlInformationChanged(ComponentName eventReceiver, int infoFlag) {
         IAudioService service = getService();
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 179b8a4..85c7dba 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -34,6 +34,7 @@
 import android.database.ContentObserver;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
+import android.media.IRemoteControlClientDispatcher;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
@@ -521,6 +522,10 @@
              (!mVoiceCapable && streamType != AudioSystem.STREAM_VOICE_CALL &&
                streamType != AudioSystem.STREAM_BLUETOOTH_SCO) ||
                 (mVoiceCapable && streamType == AudioSystem.STREAM_RING)) {
+            //  do not vibrate if already in silent mode
+            if (mRingerMode != AudioManager.RINGER_MODE_NORMAL) {
+                flags &= ~AudioManager.FLAG_VIBRATE;
+            }
             // Check if the ringer mode changes with this volume adjustment. If
             // it does, it will handle adjusting the volume, so we won't below
             adjustVolume = checkForRingerModeChange(oldIndex, direction);
@@ -2168,7 +2173,7 @@
                     // TODO remove log before release
                     Log.i(TAG, "Clear remote control display");
                     Intent clearIntent = new Intent(AudioManager.REMOTE_CONTROL_CLIENT_CHANGED);
-                    // no extra means no IRemoteControlClient, which is a request to clear
+                    // no extra means no IRemoteControlClientDispatcher, which is a request to clear
                     clearIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                     mContext.sendBroadcast(clearIntent);
                     break;
@@ -2188,7 +2193,8 @@
                             Log.i(TAG, "Display/update remote control ");
                             Intent rcClientIntent = new Intent(
                                     AudioManager.REMOTE_CONTROL_CLIENT_CHANGED);
-                            rcClientIntent.putExtra(AudioManager.EXTRA_REMOTE_CONTROL_CLIENT,
+                            rcClientIntent.putExtra(
+                                    AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_GENERATION,
                                     mCurrentRcClientGen);
                             rcClientIntent.putExtra(
                                     AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_INFO_CHANGED,
@@ -2196,6 +2202,9 @@
                             rcClientIntent.putExtra(
                                     AudioManager.EXTRA_REMOTE_CONTROL_EVENT_RECEIVER,
                                     rcse.mReceiverComponent.flattenToString());
+                            rcClientIntent.putExtra(
+                                    AudioManager.EXTRA_REMOTE_CONTROL_CLIENT_NAME,
+                                    rcse.mRcClientName);
                             rcClientIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                             mContext.sendBroadcast(rcClientIntent);
                         }
@@ -2891,14 +2900,14 @@
      * This object may be null.
      * Access protected by mCurrentRcLock.
      */
-    private IRemoteControlClient mCurrentRcClient = null;
+    private IRemoteControlClientDispatcher mCurrentRcClient = null;
 
     private final static int RC_INFO_NONE = 0;
     private final static int RC_INFO_ALL =
-        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_ALBUM_ART |
-        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_KEY_MEDIA |
-        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_METADATA |
-        AudioManager.RemoteControlParameters.FLAG_INFORMATION_CHANGED_PLAYSTATE;
+        RemoteControlClient.FLAG_INFORMATION_CHANGED_ALBUM_ART |
+        RemoteControlClient.FLAG_INFORMATION_CHANGED_KEY_MEDIA |
+        RemoteControlClient.FLAG_INFORMATION_CHANGED_METADATA |
+        RemoteControlClient.FLAG_INFORMATION_CHANGED_PLAYSTATE;
 
     /**
      * A monotonically increasing generation counter for mCurrentRcClient.
@@ -2910,13 +2919,13 @@
     /**
      * Returns the current remote control client.
      * @param rcClientId the counter value that matches the extra
-     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT} in the
+     *     {@link AudioManager#EXTRA_REMOTE_CONTROL_CLIENT_GENERATION} in the
      *     {@link AudioManager#REMOTE_CONTROL_CLIENT_CHANGED} event
-     * @return the current IRemoteControlClient from which information to display on the remote
-     *     control can be retrieved, or null if rcClientId doesn't match the current generation
-     *     counter.
+     * @return the current IRemoteControlClientDispatcher from which information to display on the
+     *     remote control can be retrieved, or null if rcClientId doesn't match the current
+     *     generation counter.
      */
-    public IRemoteControlClient getRemoteControlClient(int rcClientId) {
+    public IRemoteControlClientDispatcher getRemoteControlClientDispatcher(int rcClientId) {
         synchronized(mCurrentRcLock) {
             if (rcClientId == mCurrentRcClientGen) {
                 return mCurrentRcClient;
@@ -2943,7 +2952,7 @@
             Log.w(TAG, "  RemoteControlClient died");
             // remote control client died, make sure the displays don't use it anymore
             //  by setting its remote control client to null
-            registerRemoteControlClient(mRcEventReceiver, null, null/*ignored*/);
+            registerRemoteControlClient(mRcEventReceiver, null, null, null/*ignored*/);
         }
 
         public IBinder getBinder() {
@@ -2955,10 +2964,11 @@
         /** the target for the ACTION_MEDIA_BUTTON events */
         public ComponentName mReceiverComponent;// always non null
         public String mCallingPackageName;
+        public String mRcClientName;
         public int mCallingUid;
 
         /** provides access to the information to display on the remote control */
-        public IRemoteControlClient mRcClient;
+        public IRemoteControlClientDispatcher mRcClient;
         public RcClientDeathHandler mRcClientDeathHandler;
 
         public RemoteControlStackEntry(ComponentName r) {
@@ -3213,7 +3223,7 @@
 
     /** see AudioManager.registerRemoteControlClient(ComponentName eventReceiver, ...) */
     public void registerRemoteControlClient(ComponentName eventReceiver,
-            IRemoteControlClient rcClient, String callingPackageName) {
+            IRemoteControlClientDispatcher rcClient, String clientName, String callingPackageName) {
         synchronized(mAudioFocusLock) {
             synchronized(mRCStack) {
                 // store the new display information
@@ -3229,8 +3239,10 @@
                         // save the new remote control client
                         rcse.mRcClient = rcClient;
                         rcse.mCallingPackageName = callingPackageName;
+                        rcse.mRcClientName = clientName;
                         rcse.mCallingUid = Binder.getCallingUid();
                         if (rcClient == null) {
+                            rcse.mRcClientDeathHandler = null;
                             break;
                         }
                         // monitor the new client's death
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index c259aa3..7f9ced9 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -18,9 +18,7 @@
 
 import android.content.ComponentName;
 import android.media.IAudioFocusDispatcher;
-import android.media.IRemoteControlClient;
-import android.net.Uri;
-import android.os.Bundle;
+import android.media.IRemoteControlClientDispatcher;
 
 /**
  * {@hide}
@@ -91,9 +89,10 @@
     void unregisterMediaButtonEventReceiver(in ComponentName eventReceiver);
 
     void registerRemoteControlClient(in ComponentName eventReceiver,
-           in IRemoteControlClient rcClient, in String callingPackageName);
+           in IRemoteControlClientDispatcher rcClient, in String clientName,
+           in String callingPackageName);
 
-    IRemoteControlClient getRemoteControlClient(in int rcClientId);
+    IRemoteControlClientDispatcher getRemoteControlClientDispatcher(in int rcClientId);
 
     void notifyRemoteControlInformationChanged(in ComponentName eventReceiver, int infoFlag);
 
diff --git a/media/java/android/media/IRemoteControlClient.aidl b/media/java/android/media/IRemoteControlClientDispatcher.aidl
similarity index 88%
rename from media/java/android/media/IRemoteControlClient.aidl
rename to media/java/android/media/IRemoteControlClientDispatcher.aidl
index 76d178c..98142cc 100644
--- a/media/java/android/media/IRemoteControlClient.aidl
+++ b/media/java/android/media/IRemoteControlClientDispatcher.aidl
@@ -20,13 +20,11 @@
 
 /**
  * @hide
- * Interface for an object that exposes information meant to be consumed by remote controls
- * capable of displaying metadata, album art and media transport control buttons.
- * Such a remote control client object is associated with a media button event receiver
- * when registered through
- * {@link AudioManager#registerRemoteControlClient(ComponentName, IRemoteControlClient)}.
+ * Interface registered by AudioManager to dispatch remote control information requests
+ * to the RemoteControlClient implementation. This is used by AudioService.
+ * {@see AudioManager#registerRemoteControlClient(ComponentName, RemoteControlClient)}.
  */
-interface IRemoteControlClient
+interface IRemoteControlClientDispatcher
 {
     /**
      * Called by a remote control to retrieve a String of information to display.
@@ -49,7 +47,7 @@
      * @return null if the requested field is not supported, or the String matching the
      *       metadata field.
      */
-    String getMetadataString(int field);
+    String getMetadataStringForClient(String clientName, int field);
 
     /**
      * Called by a remote control to retrieve the current playback state.
@@ -64,7 +62,7 @@
      *       {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_BUFFERING},
      *       {@link android.media.AudioManager.RemoteControlParameters#PLAYSTATE_ERROR}.
      */
-    int getPlaybackState();
+    int getPlaybackStateForClient(String clientName);
 
     /**
      * Called by a remote control to retrieve the flags for the media transport control buttons
@@ -78,7 +76,7 @@
      *      {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_FAST_FORWARD},
      *      {@link android.media.AudioManager.RemoteControlParameters#FLAG_KEY_MEDIA_NEXT}
      */
-    int getTransportControlFlags();
+    int getTransportControlFlagsForClient(String clientName);
 
     /**
      * Called by a remote control to retrieve the album art picture at the requested size.
@@ -90,5 +88,5 @@
      * @return the bitmap for the album art, or null if there isn't any.
      * @see android.graphics.Bitmap
      */
-    Bitmap getAlbumArt(int maxWidth, int maxHeight);
+    Bitmap getAlbumArtForClient(String clientName, int maxWidth, int maxHeight);
 }
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
new file mode 100644
index 0000000..c384636
--- /dev/null
+++ b/media/java/android/media/RemoteControlClient.java
@@ -0,0 +1,243 @@
+/*
+ * 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 android.media;
+
+import android.content.ComponentName;
+import android.graphics.Bitmap;
+
+/**
+ * @hide
+ * Interface for an object that exposes information meant to be consumed by remote controls
+ * capable of displaying metadata, album art and media transport control buttons.
+ * Such a remote control client object is associated with a media button event receiver
+ * when registered through
+ * {@link AudioManager#registerRemoteControlClient(ComponentName, RemoteControlClient)}.
+ */
+public interface RemoteControlClient
+{
+    /**
+     * Playback state of a RemoteControlClient which is stopped.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_STOPPED            = 1;
+    /**
+     * Playback state of a RemoteControlClient which is paused.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_PAUSED             = 2;
+    /**
+     * Playback state of a RemoteControlClient which is playing media.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_PLAYING            = 3;
+    /**
+     * Playback state of a RemoteControlClient which is fast forwarding in the media
+     *    it is currently playing.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_FAST_FORWARDING    = 4;
+    /**
+     * Playback state of a RemoteControlClient which is fast rewinding in the media
+     *    it is currently playing.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_REWINDING          = 5;
+    /**
+     * Playback state of a RemoteControlClient which is skipping to the next
+     *    logical chapter (such as a song in a playlist) in the media it is currently playing.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_SKIPPING_FORWARDS  = 6;
+    /**
+     * Playback state of a RemoteControlClient which is skipping back to the previous
+     *    logical chapter (such as a song in a playlist) in the media it is currently playing.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_SKIPPING_BACKWARDS = 7;
+    /**
+     * Playback state of a RemoteControlClient which is buffering data to play before it can
+     *    start or resume playback.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_BUFFERING          = 8;
+    /**
+     * Playback state of a RemoteControlClient which cannot perform any playback related
+     *    operation because of an internal error. Examples of such situations are no network
+     *    connectivity when attempting to stream data from a server, or expired user credentials
+     *    when trying to play subscription-based content.
+     *
+     * @see android.media.RemoteControlClient#getPlaybackState()
+     */
+    public final static int PLAYSTATE_ERROR              = 9;
+
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "previous" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_PREVIOUS
+     */
+    public final static int FLAG_KEY_MEDIA_PREVIOUS = 1 << 0;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "rewing" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_REWIND
+     */
+    public final static int FLAG_KEY_MEDIA_REWIND = 1 << 1;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "play" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY
+     */
+    public final static int FLAG_KEY_MEDIA_PLAY = 1 << 2;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "play/pause" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_PLAY_PAUSE
+     */
+    public final static int FLAG_KEY_MEDIA_PLAY_PAUSE = 1 << 3;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "pause" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_PAUSE
+     */
+    public final static int FLAG_KEY_MEDIA_PAUSE = 1 << 4;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "stop" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_STOP
+     */
+    public final static int FLAG_KEY_MEDIA_STOP = 1 << 5;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "fast forward" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_FAST_FORWARD
+     */
+    public final static int FLAG_KEY_MEDIA_FAST_FORWARD = 1 << 6;
+    /**
+     * Flag indicating a RemoteControlClient makes use of the "next" media key.
+     *
+     * @see android.media.RemoteControlClient#getTransportControlFlags()
+     * @see android.view.KeyEvent#KEYCODE_MEDIA_NEXT
+     */
+    public final static int FLAG_KEY_MEDIA_NEXT = 1 << 7;
+
+    /**
+     * Flag used to signal that the metadata exposed by the RemoteControlClient has changed.
+     *
+     * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+     */
+    public final static int FLAG_INFORMATION_CHANGED_METADATA = 1 << 0;
+    /**
+     * Flag used to signal that the transport control buttons supported by the
+     * RemoteControlClient have changed.
+     * This can for instance happen when playback is at the end of a playlist, and the "next"
+     * operation is not supported anymore.
+     *
+     * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+     */
+    public final static int FLAG_INFORMATION_CHANGED_KEY_MEDIA = 1 << 1;
+    /**
+     * Flag used to signal that the playback state of the RemoteControlClient has changed.
+     *
+     * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+     */
+    public final static int FLAG_INFORMATION_CHANGED_PLAYSTATE = 1 << 2;
+    /**
+     * Flag used to signal that the album art for the RemoteControlClient has changed.
+     *
+     * @see #notifyRemoteControlInformationChanged(ComponentName, int)
+     */
+    public final static int FLAG_INFORMATION_CHANGED_ALBUM_ART = 1 << 3;
+
+    /**
+     * Called by a remote control to retrieve a String of information to display.
+     * @param field the identifier for a metadata field to retrieve. Valid values are
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUM},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_ARTIST},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_AUTHOR},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPILATION},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_COMPOSER},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DATE},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_DURATION},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_GENRE},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_TITLE},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_WRITER},
+     *      {@link android.media.MediaMetadataRetriever#METADATA_KEY_YEAR}.
+     * @return null if the requested field is not supported, or the String matching the
+     *       metadata field.
+     */
+    String getMetadataString(int field);
+
+    /**
+     * Called by a remote control to retrieve the current playback state.
+     * @return one of the following values:
+     *       {@link #PLAYSTATE_STOPPED},
+     *       {@link #PLAYSTATE_PAUSED},
+     *       {@link #PLAYSTATE_PLAYING},
+     *       {@link #PLAYSTATE_FAST_FORWARDING},
+     *       {@link #PLAYSTATE_REWINDING},
+     *       {@link #PLAYSTATE_SKIPPING_FORWARDS},
+     *       {@link #PLAYSTATE_SKIPPING_BACKWARDS},
+     *       {@link #PLAYSTATE_BUFFERING},
+     *       {@link #PLAYSTATE_ERROR}.
+     */
+    int getPlaybackState();
+
+    /**
+     * Called by a remote control to retrieve the flags for the media transport control buttons
+     * that this client supports.
+     * @see {@link #FLAG_KEY_MEDIA_PREVIOUS},
+     *      {@link #FLAG_KEY_MEDIA_REWIND},
+     *      {@link #FLAG_KEY_MEDIA_PLAY},
+     *      {@link #FLAG_KEY_MEDIA_PLAY_PAUSE},
+     *      {@link #FLAG_KEY_MEDIA_PAUSE},
+     *      {@link #FLAG_KEY_MEDIA_STOP},
+     *      {@link #FLAG_KEY_MEDIA_FAST_FORWARD},
+     *      {@link #FLAG_KEY_MEDIA_NEXT}
+     */
+    int getTransportControlFlags();
+
+    /**
+     * Called by a remote control to retrieve the album art picture at the requested size.
+     * Note that returning a bitmap smaller than the maximum requested dimension is accepted
+     * and it will be scaled as needed, but exceeding the maximum dimensions may produce
+     * unspecified results, such as the image being cropped or simply not being displayed.
+     * @param maxWidth the maximum width of the requested bitmap expressed in pixels.
+     * @param maxHeight the maximum height of the requested bitmap expressed in pixels.
+     * @return the bitmap for the album art, or null if there isn't any.
+     * @see android.graphics.Bitmap
+     */
+    Bitmap getAlbumArt(int maxWidth, int maxHeight);
+}
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 7d0f56f..5dda8d3 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -2499,7 +2499,7 @@
             //initialize the first char. so that strcat works.
             M4OSA_Char *ptmpChar = (M4OSA_Char*)pContext->initParams.pTempPath;
             ptmpChar[0] = 0x00;
-            strncat((char *)pContext->initParams.pTempPath, (const char *)tmpString, 
+            strncat((char *)pContext->initParams.pTempPath, (const char *)tmpString,
                 (size_t)strlen((const char *)tmpString));
             strncat((char *)pContext->initParams.pTempPath, (const char *)"/", (size_t)1);
             free(tmpString);
@@ -2631,7 +2631,8 @@
     ManualEditState    completionState  = ManualEditState_OPENED;
     ManualEditState    errorState       = ManualEditState_ANALYZING_ERROR;
 
-    // While analyzing progress goes from 0 to 50
+    // While analyzing progress goes from 0 to 10 (except Kenburn clip
+    // generation, which goes from 0 to 50)
     progressBase     = 0;
 
     // Set the text rendering function.
@@ -2667,6 +2668,7 @@
     // Check if a task is being performed.
     // ??? ADD STOPPING MECHANISM
     LOGV("videoEditor_processClip Entering processing loop");
+    M4OSA_UInt8 prevReportedProgress = 0;
     while((result == M4NO_ERROR)
         &&(pContext->state!=ManualEditState_SAVED)
         &&(pContext->state!=ManualEditState_STOPPING)) {
@@ -2674,19 +2676,35 @@
             // Perform the next processing step.
             //LOGV("LVME_processClip Entering M4xVSS_Step()");
             result = M4xVSS_Step(pContext->engineContext, &progress);
-            //LOGV("LVME_processClip M4xVSS_Step() returned 0x%x", (unsigned int)result);
 
-            // Log the the 1 % .. 100 % progress after processing.
-            progress = progressBase + progress/2;
-            if (progress != lastProgress)
-            {
-                // Send a progress notification.
-                LOGV("videoEditor_processClip ITEM %d Progress indication %d",
-                    unuseditemID, progress);
-                pEnv->CallVoidMethod(pContext->engine,
-                    pContext->onProgressUpdateMethodId,
-                    unuseditemID, progress);
-                lastProgress = progress;
+            if (progress != prevReportedProgress) {
+                prevReportedProgress = progress;
+                // Log the 1 % .. 100 % progress after processing.
+                if (M4OSA_TRUE ==
+                    pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) {
+                    // For KenBurn clip generation, return 0 to 50
+                    // for Analysis phase and 50 to 100 for Saving phase
+                    progress = progressBase + progress/2;
+                } else {
+                    // For export/transition clips, 0 to 10 for Analysis phase
+                    // and 10 to 100 for Saving phase
+                    if (ManualEditState_INITIALIZED == pContext->state) {
+                        progress = 0.1*progress;
+                    } else {
+                        progress = progressBase + 0.9*progress;
+                    }
+                }
+
+                if (progress > lastProgress)
+                {
+                    // Send a progress notification.
+                    LOGV("videoEditor_processClip ITEM %d Progress indication %d",
+                        unuseditemID, progress);
+                    pEnv->CallVoidMethod(pContext->engine,
+                        pContext->onProgressUpdateMethodId,
+                        unuseditemID, progress);
+                    lastProgress = progress;
+                }
             }
 
             // Check if processing has been completed.
@@ -2719,20 +2737,26 @@
                     completionResult = M4VSS3GPP_WAR_SAVING_DONE;
                     errorState       = ManualEditState_SAVING_ERROR;
 
-                    // While saving progress goes from 50 to 100
-                    progressBase     = 50;
+                    // While saving, progress goes from 10 to 100
+                    // except for Kenburn clip which goes from 50 to 100
+                    if (M4OSA_TRUE ==
+                            pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) {
+                        progressBase = 50;
+                    } else {
+                        progressBase     = 10;
+                    }
                 }
                 // Check if we encoding is ongoing
                 else if (pContext->state == ManualEditState_SAVED) {
-                    if (progress != 100) {
-                        // Send a progress notification.
-                        progress = 100;
-                        LOGI("videoEditor_processClip ITEM %d Last progress indication %d",
-                            unuseditemID, progress);
-                        pEnv->CallVoidMethod(pContext->engine,
-                            pContext->onProgressUpdateMethodId,
-                            unuseditemID, progress);
-                    }
+
+                    // Send a progress notification.
+                    progress = 100;
+                    LOGV("videoEditor_processClip ITEM %d Last progress indication %d",
+                        unuseditemID, progress);
+                    pEnv->CallVoidMethod(pContext->engine,
+                        pContext->onProgressUpdateMethodId,
+                        unuseditemID, progress);
+
 
                     // Stop the encoding.
                     LOGV("videoEditor_processClip Calling M4xVSS_SaveStop()");
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 99242ab..8b23da7 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -59,6 +59,7 @@
 #include <cutils/properties.h>
 
 #define USE_SURFACE_ALLOC 1
+#define FRAME_DROP_FREQ 0
 
 namespace android {
 
@@ -820,7 +821,12 @@
         return;
     }
 
-    if (mFlags & (LOOPING | AUTO_LOOPING)) {
+    if ((mFlags & LOOPING)
+            || ((mFlags & AUTO_LOOPING)
+                && (mAudioSink == NULL || mAudioSink->realtime()))) {
+        // Don't AUTO_LOOP if we're being recorded, since that cannot be
+        // turned off and recording would go on indefinitely.
+
         seekTo_l(0);
 
         if (mVideoSource != NULL) {
@@ -1518,14 +1524,29 @@
     }
 
     if (mVideoSource != NULL) {
-        Mutex::Autolock autoLock(mStatsLock);
-        TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
-
-        const char *component;
+        const char *componentName;
         CHECK(mVideoSource->getFormat()
-                ->findCString(kKeyDecoderComponent, &component));
+                ->findCString(kKeyDecoderComponent, &componentName));
 
-        stat->mDecoderName = component;
+        {
+            Mutex::Autolock autoLock(mStatsLock);
+            TrackStat *stat = &mStats.mTracks.editItemAt(mStats.mVideoTrackIndex);
+
+            stat->mDecoderName = componentName;
+        }
+
+        static const char *kPrefix = "OMX.Nvidia.";
+        static const char *kSuffix = ".decode";
+        static const size_t kSuffixLength = strlen(kSuffix);
+
+        size_t componentNameLength = strlen(componentName);
+
+        if (!strncmp(componentName, kPrefix, strlen(kPrefix))
+                && componentNameLength >= kSuffixLength
+                && !strcmp(&componentName[
+                    componentNameLength - kSuffixLength], kSuffix)) {
+            modifyFlags(SLOW_DECODER_HACK, SET);
+        }
     }
 
     return mVideoSource != NULL ? OK : UNKNOWN_ERROR;
@@ -1705,6 +1726,7 @@
 
     if (mFlags & FIRST_FRAME) {
         modifyFlags(FIRST_FRAME, CLEAR);
+        mSinceLastDropped = 0;
         mTimeSourceDeltaUs = ts->getRealTimeUs() - timeUs;
     }
 
@@ -1751,18 +1773,28 @@
 
         if (latenessUs > 40000) {
             // We're more than 40ms late.
-            LOGV("we're late by %lld us (%.2f secs), dropping frame",
+            LOGV("we're late by %lld us (%.2f secs)",
                  latenessUs, latenessUs / 1E6);
-            mVideoBuffer->release();
-            mVideoBuffer = NULL;
 
+            if (!(mFlags & SLOW_DECODER_HACK)
+                    || mSinceLastDropped > FRAME_DROP_FREQ)
             {
-                Mutex::Autolock autoLock(mStatsLock);
-                ++mStats.mNumVideoFramesDropped;
-            }
+                LOGV("we're late by %lld us (%.2f secs) dropping "
+                     "one after %d frames",
+                     latenessUs, latenessUs / 1E6, mSinceLastDropped);
 
-            postVideoEvent_l();
-            return;
+                mSinceLastDropped = 0;
+                mVideoBuffer->release();
+                mVideoBuffer = NULL;
+
+                {
+                    Mutex::Autolock autoLock(mStatsLock);
+                    ++mStats.mNumVideoFramesDropped;
+                }
+
+                postVideoEvent_l();
+                return;
+            }
         }
 
         if (latenessUs < -10000) {
@@ -1781,6 +1813,7 @@
     }
 
     if (mVideoRenderer != NULL) {
+        mSinceLastDropped++;
         mVideoRenderer->render(mVideoBuffer);
     }
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 73a05a5..3b79f06 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1687,6 +1687,11 @@
         }
     }
 
+    if (!track->sampleTable->isValid()) {
+        // Make sure we have all the metadata we need.
+        return ERROR_MALFORMED;
+    }
+
     return OK;
 }
 
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index a8a094e..2b9d99b 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -84,6 +84,13 @@
     mSampleIterator = NULL;
 }
 
+bool SampleTable::isValid() const {
+    return mChunkOffsetOffset >= 0
+        && mSampleToChunkOffset >= 0
+        && mSampleSizeOffset >= 0
+        && mTimeToSample != NULL;
+}
+
 status_t SampleTable::setChunkOffsetParams(
         uint32_t type, off64_t data_offset, size_t data_size) {
     if (mChunkOffsetOffset >= 0) {
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 95f2ae8..14476d3 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -141,6 +141,8 @@
 
         TEXT_RUNNING        = 0x10000,
         TEXTPLAYER_STARTED  = 0x20000,
+
+        SLOW_DECODER_HACK   = 0x40000,
     };
 
     mutable Mutex mLock;
@@ -181,6 +183,7 @@
 
     uint32_t mFlags;
     uint32_t mExtractorFlags;
+    uint32_t mSinceLastDropped;
 
     int64_t mTimeSourceDeltaUs;
     int64_t mVideoTimeUs;
diff --git a/media/libstagefright/include/SampleTable.h b/media/libstagefright/include/SampleTable.h
index f44e0a2..a6a6524 100644
--- a/media/libstagefright/include/SampleTable.h
+++ b/media/libstagefright/include/SampleTable.h
@@ -34,6 +34,8 @@
 public:
     SampleTable(const sp<DataSource> &source);
 
+    bool isValid() const;
+
     // type can be 'stco' or 'co64'.
     status_t setChunkOffsetParams(
             uint32_t type, off64_t data_offset, size_t data_size);
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2080fad..d10911f 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -29,6 +29,7 @@
         <!-- started from PhoneWindowManager
              TODO: Should have an android:permission attribute -->
         <service android:name=".screenshot.TakeScreenshotService"
+            android:process=":screenshot"
             android:exported="false" />
 
         <service android:name=".LoadAverageService"
diff --git a/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml b/packages/SystemUI/res/anim/recent_appear.xml
similarity index 64%
rename from packages/SystemUI/res/drawable/recents_thumbnail_layers.xml
rename to packages/SystemUI/res/anim/recent_appear.xml
index 6cae2c4..4400d9d 100644
--- a/packages/SystemUI/res/drawable/recents_thumbnail_layers.xml
+++ b/packages/SystemUI/res/anim/recent_appear.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
@@ -13,7 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
-    <item android:drawable="@drawable/recents_thumbnail_bg" android:id="@+id/base_layer"/>
-    <item android:drawable="@drawable/recents_thumbnail_overlay" android:id="@+id/overlay_layer"/>
-</layer-list>
\ No newline at end of file
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+    android:fromAlpha="0.0" android:toAlpha="1.0"
+    android:duration="@android:integer/config_shortAnimTime"
+    />
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index 8c29042..16008a3 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -32,8 +32,14 @@
         android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
         android:scaleType="center"
         android:clickable="true"
-        android:background="@drawable/recents_thumbnail_layers"
-    />
+        android:background="@drawable/recents_thumbnail_bg"
+        android:foreground="@drawable/recents_thumbnail_overlay">
+        <ImageView android:id="@+id/app_thumbnail_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="invisible"
+        />
+    </FrameLayout>
 
     <ImageView android:id="@+id/app_icon"
         android:layout_width="wrap_content"
@@ -45,6 +51,7 @@
         android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width"
         android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height"
         android:adjustViewBounds="true"
+        android:visibility="invisible"
     />
 
     <TextView android:id="@+id/app_label"
@@ -60,6 +67,7 @@
         android:layout_marginLeft="@dimen/recents_thumbnail_bg_padding_left"
         android:singleLine="true"
         android:ellipsize="marquee"
+        android:visibility="invisible"
     />
 
     <TextView android:id="@+id/app_description"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
index c705a69..c0fce71 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
@@ -32,8 +32,14 @@
         android:clickable="true"
         android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
         android:scaleType="center"
-        android:background="@drawable/recents_thumbnail_layers"
-    />
+        android:background="@drawable/recents_thumbnail_bg"
+        android:foreground="@drawable/recents_thumbnail_overlay">
+        <ImageView android:id="@+id/app_thumbnail_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="invisible"
+        />
+    </FrameLayout>
 
     <ImageView android:id="@+id/app_icon"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar.xml b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
index a204f17..125c87e 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar.xml
@@ -44,24 +44,23 @@
                 />
 
             <!-- navigation controls -->
-            <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
-                android:layout_width="80dip"
-                android:layout_height="match_parent"
-                android:src="@drawable/ic_sysbar_back"
-                android:layout_alignParentLeft="true"
-                systemui:keyCode="4"
-                android:contentDescription="@string/accessibility_back"
-                systemui:glowBackground="@drawable/ic_sysbar_highlight"
-                />
             <LinearLayout
                 android:id="@+id/navigationArea"
                 android:layout_width="wrap_content"
                 android:layout_height="match_parent"
-                android:layout_toRightOf="@+id/back"
+                android:layout_alignParentLeft="true"
                 android:orientation="horizontal"
                 android:clipChildren="false"
                 android:clipToPadding="false"
                 >
+                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
+                    android:layout_width="80dip"
+                    android:layout_height="match_parent"
+                    android:src="@drawable/ic_sysbar_back"
+                    systemui:keyCode="4"
+                    android:contentDescription="@string/accessibility_back"
+                    systemui:glowBackground="@drawable/ic_sysbar_highlight"
+                    />
                 <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/home"
                     android:layout_width="80dip"
                     android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index 386ce30..5306508 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -32,8 +32,14 @@
         android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin"
         android:scaleType="center"
         android:clickable="true"
-        android:background="@drawable/recents_thumbnail_layers"
-    />
+        android:background="@drawable/recents_thumbnail_bg"
+        android:foreground="@drawable/recents_thumbnail_overlay">
+        <ImageView android:id="@+id/app_thumbnail_image"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:visibility="invisible"
+        />
+    </FrameLayout>
 
     <ImageView android:id="@+id/app_icon"
         android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index d1919ca..6c4c9c1 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -37,6 +37,7 @@
             android:orientation="horizontal"
             android:clipChildren="false"
             android:clipToPadding="false"
+            android:id="@+id/nav_buttons"
             >
 
             <!-- navigation controls -->
@@ -119,6 +120,7 @@
             android:orientation="vertical"
             android:clipChildren="false"
             android:clipToPadding="false"
+            android:id="@+id/nav_buttons"
             >
             
             <!-- navigation controls -->
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 529a5bc..33eb223 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"No hi ha cap targeta SIM."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Connexió Bluetooth mitjançant dispositiu portàtil"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode d\'avió."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Bateria: <xliff:g id="NUMBER">%d</xliff:g> %."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Botó Configuració."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Botó de notificacions."</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Elimina la notificació."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 8093de1..543bb9e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Žádná karta SIM."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering přes Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim V letadle."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> %."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Tlačítko Nastavení."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Tlačítko upozornění."</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Odebrat oznámení"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 8168f74..ea9b8d2 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -60,8 +60,7 @@
     <string name="compat_mode_help_header" msgid="7020175705401506719">"Kompatibilitätszoom"</string>
     <string name="compat_mode_help_body" msgid="4946726776359270040">"Wenn eine App für einen kleineren Bildschirm ausgelegt ist, wird ein Zoom-Steuerelement neben der Uhr angezeigt."</string>
     <string name="screenshot_saving_toast" msgid="8592630119048713208">"Screenshot in Galerie gespeichert"</string>
-    <!-- no translation found for screenshot_failed_toast (1990979819772906912) -->
-    <skip />
+    <!-- outdated translation 655180965533683356 -->     <string name="screenshot_failed_toast" msgid="1990979819772906912">"Screenshot konnte nicht gespeichert werden."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Als Kamera (PTP) bereitstellen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 76dadd4..ee3e671 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Δεν υπάρχει SIM."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Σύνδεση Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Λειτουργία πτήσης."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Μπαταρία <xliff:g id="NUMBER">%d</xliff:g> %."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Κουμπί ρυθμίσεων."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Κουμπί ειδοοποιήσεων"</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Κατάργηση ειδοποίησης."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 86470e4..a8bbd96 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -60,8 +60,7 @@
     <string name="compat_mode_help_header" msgid="7020175705401506719">"Zoom de compatibilidad"</string>
     <string name="compat_mode_help_body" msgid="4946726776359270040">"Si la aplicación se ha diseñado para una pantalla más pequeña, aparecerá un control de zoom junto al reloj."</string>
     <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de pantalla guardada en la galería"</string>
-    <!-- no translation found for screenshot_failed_toast (1990979819772906912) -->
-    <skip />
+    <!-- outdated translation 655180965533683356 -->     <string name="screenshot_failed_toast" msgid="1990979819772906912">"No se ha podido guardar la captura de pantalla."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Activar como cámara (PTP)"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c2098b1..aa0b487 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -60,8 +60,7 @@
     <string name="compat_mode_help_header" msgid="7020175705401506719">"Yhteensopivuustilan zoomaus"</string>
     <string name="compat_mode_help_body" msgid="4946726776359270040">"Jos sovellus on suunniteltu pienemmälle näytölle, kellon viereen tulee näkyviin zoomaussäädin."</string>
     <string name="screenshot_saving_toast" msgid="8592630119048713208">"Kuvakaappaus on tallennettu galleriaan"</string>
-    <!-- no translation found for screenshot_failed_toast (1990979819772906912) -->
-    <skip />
+    <!-- outdated translation 655180965533683356 -->     <string name="screenshot_failed_toast" msgid="1990979819772906912">"Kuvakaappausta ei voitu tallentaa"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Käytä kamerana (PTP)"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 858305f..b97ac2f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Aucune carte SIM"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Partage de connexion Bluetooth"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode Avion"</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Batterie : <xliff:g id="NUMBER">%d</xliff:g> %"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Bouton \"Paramètres\""</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Bouton \"Notifications\""</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Supprimer la notification"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index d4d5117..c7ef3f6 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Nessuna SIM presente."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Tethering Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modalità aereo."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Batteria: <xliff:g id="NUMBER">%d</xliff:g>%."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Pulsante Impostazioni."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Pulsante per le notifiche."</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Rimuovi la notifica."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 2f3509a..5ad4e2d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIMがありません。"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetoothテザリング。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"機内モード。"</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"電池残量: <xliff:g id="NUMBER">%d</xliff:g>%"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"設定ボタン。"</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"通知ボタン。"</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"通知を削除。"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f264ef4..10d5611 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -60,8 +60,7 @@
     <string name="compat_mode_help_header" msgid="7020175705401506719">"Compatibilidade de zoom"</string>
     <string name="compat_mode_help_body" msgid="4946726776359270040">"Sempre que uma aplicação tiver sido concebida para ecrãs mais pequenos, aparecerá um controlo de zoom junto ao relógio."</string>
     <string name="screenshot_saving_toast" msgid="8592630119048713208">"Captura de ecrã guardada na Galeria"</string>
-    <!-- no translation found for screenshot_failed_toast (1990979819772906912) -->
-    <skip />
+    <!-- outdated translation 655180965533683356 -->     <string name="screenshot_failed_toast" msgid="1990979819772906912">"Não foi possível guardar a captura de ecrã"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opções de transm. de fich. USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montar como leitor de multimédia (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Montar como câmara (PTP)"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a6759fd..07fb12b 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Sem SIM."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Vínculo Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Modo de avião."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Bateria em <xliff:g id="NUMBER">%d</xliff:g>%."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Botão Configurações."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Botão de notificações."</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Remover notificação."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 2dd0bd4..70a7c88 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM-карта отсутствует."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Общий Bluetooth-модем."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Режим полета."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Заряд батареи: <xliff:g id="NUMBER">%d</xliff:g>%"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Кнопка вызова настроек."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Кнопка вызова панели уведомлений"</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Удалить уведомление."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index f6ab7e1..b6a774c 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Žiadna karta SIM."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Zdieľanie dátového pripojenia cez Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim V lietadle."</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"Batéria <xliff:g id="NUMBER">%d</xliff:g> %"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"Tlačidlo Nastavenia."</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"Tlačidlo upozornení."</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"Odstrániť upozornenie."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 8aa9c62..62e5a3e 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"无 SIM 卡。"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"蓝牙绑定。"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飞行模式。"</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"电池电量为 <xliff:g id="NUMBER">%d</xliff:g>%。"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"设置按钮。"</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"通知按钮。"</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"删除通知。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 17d0822..54fbefb 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -104,7 +104,9 @@
     <string name="accessibility_no_sim" msgid="8274017118472455155">"沒有 SIM 卡。"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙數據連線"</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"飛行模式。"</string>
-    <string name="accessibility_battery_level" msgid="7451474187113371965">"電池電量為 <xliff:g id="NUMBER">%d</xliff:g>%。"</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+    <skip />
     <string name="accessibility_settings_button" msgid="7913780116850379698">"設定按鈕。"</string>
     <string name="accessibility_notifications_button" msgid="2933903195211483438">"通知按鈕。"</string>
     <string name="accessibility_remove_notification" msgid="4883990503785778699">"移除通知。"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 2818f87..e7ed052 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -30,7 +30,7 @@
 
 public class SwipeHelper {
     static final String TAG = "com.android.systemui.SwipeHelper";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
     private static final boolean DEBUG_INVALIDATE = false;
     private static final boolean SLOW_ANIMATIONS = false; // DEBUG;
 
@@ -142,7 +142,7 @@
     // invalidate a rectangle relative to the view's coordinate system all the way up the view
     // hierarchy
     public static void invalidateGlobalRegion(View view, RectF childBounds) {
-        childBounds.offset(view.getX(), view.getY());
+        //childBounds.offset(view.getTranslationX(), view.getTranslationY());
         if (DEBUG_INVALIDATE)
             Log.v(TAG, "-------------");
         while (view.getParent() != null && view.getParent() instanceof View) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 28a5cc8..8c03ef8 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -41,6 +41,10 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Process;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -51,12 +55,15 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.BaseAdapter;
+import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.PopupMenu;
 import android.widget.RelativeLayout;
+import android.widget.ScrollView;
 import android.widget.TextView;
 
 import com.android.systemui.R;
@@ -68,11 +75,12 @@
 public class RecentsPanelView extends RelativeLayout
         implements OnItemClickListener, RecentsCallback, StatusBarPanel, Animator.AnimatorListener {
     static final String TAG = "RecentsListView";
-    static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG;
+    static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
     private static final int DISPLAY_TASKS = 20;
     private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps
     private StatusBar mBar;
     private ArrayList<ActivityDescription> mActivityDescriptions;
+    private AsyncTask<Void, Integer, Void> mThumbnailLoader;
     private int mIconDpi;
     private View mRecentsScrim;
     private View mRecentsGlowView;
@@ -87,31 +95,47 @@
     private Choreographer mChoreo;
     private View mRecentsDismissButton;
     private ActivityDescriptionAdapter mListAdapter;
+    private final Handler mHandler = new Handler();
 
-    /* package */ final static class ActivityDescription {
+    /* package */ final class ActivityDescription {
+        final ActivityManager.RecentTaskInfo recentTaskInfo;
+        final ResolveInfo resolveInfo;
         int taskId; // application task id for curating apps
-        Bitmap thumbnail; // generated by Activity.onCreateThumbnail()
-        Drawable icon; // application package icon
-        String label; // application package label
-        CharSequence description; // generated by Activity.onCreateDescription()
         Intent intent; // launch intent for application
         Matrix matrix; // arbitrary rotation matrix to correct orientation
         String packageName; // used to override animations (see onClick())
         int position; // position in list
 
-        public ActivityDescription(Bitmap _thumbnail,
-                Drawable _icon, String _label, CharSequence _desc, Intent _intent,
-                int _id, int _pos, String _packageName)
-        {
-            thumbnail = _thumbnail;
-            icon = _icon;
-            label = _label;
-            description = _desc;
+        private Bitmap mThumbnail; // generated by Activity.onCreateThumbnail()
+        private Drawable mIcon; // application package icon
+        private CharSequence mLabel; // application package label
+
+        public ActivityDescription(ActivityManager.RecentTaskInfo _recentInfo,
+                ResolveInfo _resolveInfo, Intent _intent,
+                int _id, int _pos, String _packageName) {
+            recentTaskInfo = _recentInfo;
+            resolveInfo = _resolveInfo;
             intent = _intent;
             taskId = _id;
             position = _pos;
             packageName = _packageName;
         }
+
+        public CharSequence getLabel() {
+            return mLabel;
+        }
+
+        public Drawable getIcon() {
+            return mIcon;
+        }
+
+        public void setThumbnail(Bitmap thumbnail) {
+            mThumbnail = compositeBitmap(mGlowBitmap, thumbnail);
+        }
+
+        public Bitmap getThumbnail() {
+            return mThumbnail;
+        }
     }
 
     private final class OnLongClickDelegate implements View.OnLongClickListener {
@@ -126,6 +150,7 @@
 
     /* package */ final static class ViewHolder {
         View thumbnailView;
+        ImageView thumbnailViewImage;
         ImageView iconView;
         TextView labelView;
         TextView descriptionView;
@@ -157,6 +182,8 @@
                 convertView = mInflater.inflate(R.layout.status_bar_recent_item, null);
                 holder = new ViewHolder();
                 holder.thumbnailView = convertView.findViewById(R.id.app_thumbnail);
+                holder.thumbnailViewImage = (ImageView) convertView.findViewById(
+                        R.id.app_thumbnail_image);
                 holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon);
                 holder.labelView = (TextView) convertView.findViewById(R.id.app_label);
                 holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description);
@@ -169,11 +196,10 @@
             final int activityId = mActivityDescriptions.size() - position - 1;
 
             final ActivityDescription activityDescription = mActivityDescriptions.get(activityId);
-            final Bitmap thumb = activityDescription.thumbnail;
-            updateDrawable(holder.thumbnailView, compositeBitmap(mGlowBitmap, thumb));
-            holder.iconView.setImageDrawable(activityDescription.icon);
-            holder.labelView.setText(activityDescription.label);
-            holder.descriptionView.setText(activityDescription.description);
+            holder.thumbnailViewImage.setImageBitmap(activityDescription.getThumbnail());
+            holder.iconView.setImageDrawable(activityDescription.getIcon());
+            holder.labelView.setText(activityDescription.getLabel());
+            holder.descriptionView.setText(activityDescription.recentTaskInfo.description);
             holder.thumbnailView.setTag(activityDescription);
             holder.thumbnailView.setOnLongClickListener(new OnLongClickDelegate(convertView));
             holder.activityDescription = activityDescription;
@@ -201,20 +227,6 @@
         return x >= l && x < r && y >= t && y < b;
     }
 
-    private void updateDrawable(View thumbnailView, Bitmap bitmap) {
-        Drawable d = thumbnailView.getBackground();
-        if (d instanceof LayerDrawable) {
-            LayerDrawable layerD = (LayerDrawable) d;
-            Drawable thumb = layerD.findDrawableByLayerId(R.id.base_layer);
-            if (thumb != null) {
-                layerD.setDrawableByLayerId(R.id.base_layer,
-                        new BitmapDrawable(getResources(), bitmap));
-                return;
-            }
-        }
-        Log.w(TAG, "Failed to update drawable");
-    }
-
     public void show(boolean show, boolean animate) {
         if (animate) {
             if (mShowing != show) {
@@ -373,12 +385,12 @@
         }
     }
 
-    private Drawable getFullResDefaultActivityIcon() {
+    Drawable getFullResDefaultActivityIcon() {
         return getFullResIcon(Resources.getSystem(),
                 com.android.internal.R.mipmap.sym_def_app_icon);
     }
 
-    private Drawable getFullResIcon(Resources resources, int iconId) {
+    Drawable getFullResIcon(Resources resources, int iconId) {
         try {
             return resources.getDrawableForDensity(iconId, mIconDpi);
         } catch (Resources.NotFoundException e) {
@@ -442,15 +454,13 @@
                 final String title = info.loadLabel(pm).toString();
                 // Drawable icon = info.loadIcon(pm);
                 Drawable icon = getFullResIcon(resolveInfo, pm);
-                int id = recentTasks.get(i).id;
+                int id = recentInfo.id;
                 if (title != null && title.length() > 0 && icon != null) {
                     if (DEBUG) Log.v(TAG, "creating activity desc for id=" + id + ", label=" + title);
                     ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(
                             recentInfo.persistentId);
-                    ActivityDescription item = new ActivityDescription(
-                            thumbs != null ? thumbs.mainThumbnail : null,
-                            icon, title, recentInfo.description, intent, id,
-                            index, info.packageName);
+                    ActivityDescription item = new ActivityDescription(recentInfo,
+                            resolveInfo, intent, id, index, info.packageName);
                     activityDescriptions.add(item);
                     ++index;
                 } else {
@@ -474,12 +484,137 @@
         return desc;
     }
 
+    void loadActivityDescription(ActivityDescription ad, int index) {
+        final ActivityManager am = (ActivityManager)
+                mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        final PackageManager pm = mContext.getPackageManager();
+        ActivityManager.TaskThumbnails thumbs = am.getTaskThumbnails(
+                ad.recentTaskInfo.persistentId);
+        CharSequence label = ad.resolveInfo.activityInfo.loadLabel(pm);
+        Drawable icon = getFullResIcon(ad.resolveInfo, pm);
+        if (DEBUG) Log.v(TAG, "Loaded bitmap for #" + index + " in "
+                + ad + ": " + thumbs.mainThumbnail);
+        synchronized (ad) {
+            ad.mLabel = label;
+            ad.mIcon = icon;
+            ad.setThumbnail(thumbs.mainThumbnail);
+        }
+    }
+
+    void applyActivityDescription(ActivityDescription ad, int index, boolean anim) {
+        synchronized (ad) {
+            if (mRecentsContainer != null) {
+                ViewGroup container = mRecentsContainer;
+                if (container instanceof HorizontalScrollView
+                        || container instanceof ScrollView) {
+                    container = (ViewGroup)container.findViewById(
+                            R.id.recents_linear_layout);
+                }
+                // Look for a view showing this thumbnail, to update.
+                for (int i=0; i<container.getChildCount(); i++) {
+                    View v = container.getChildAt(i);
+                    if (v.getTag() instanceof ViewHolder) {
+                        ViewHolder h = (ViewHolder)v.getTag();
+                        if (h.activityDescription == ad) {
+                            if (DEBUG) Log.v(TAG, "Updatating thumbnail #" + index + " in "
+                                    + h.activityDescription
+                                    + ": " + ad.getThumbnail());
+                            h.iconView.setImageDrawable(ad.getIcon());
+                            if (anim) {
+                                h.iconView.setAnimation(AnimationUtils.loadAnimation(
+                                        mContext, R.anim.recent_appear));
+                            }
+                            h.iconView.setVisibility(View.VISIBLE);
+                            h.labelView.setText(ad.getLabel());
+                            if (anim) {
+                                h.labelView.setAnimation(AnimationUtils.loadAnimation(
+                                        mContext, R.anim.recent_appear));
+                            }
+                            h.labelView.setVisibility(View.VISIBLE);
+                            Bitmap thumbnail = ad.getThumbnail();
+                            if (thumbnail != null) {
+                                // Should remove the default image in the frame
+                                // that this now covers, to improve scrolling speed.
+                                // That can't be done until the anim is complete though.
+                                h.thumbnailViewImage.setImageBitmap(thumbnail);
+                                if (anim) {
+                                    h.thumbnailViewImage.setAnimation(AnimationUtils.loadAnimation(
+                                            mContext, R.anim.recent_appear));
+                                }
+                                h.thumbnailViewImage.setVisibility(View.VISIBLE);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private void refreshApplicationList() {
+        if (mThumbnailLoader != null) {
+            mThumbnailLoader.cancel(false);
+            mThumbnailLoader = null;
+        }
         mActivityDescriptions = getRecentTasks();
         mListAdapter.notifyDataSetInvalidated();
         if (mActivityDescriptions.size() > 0) {
             if (DEBUG) Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
             updateUiElements(getResources().getConfiguration());
+            final ArrayList<ActivityDescription> descriptions = mActivityDescriptions;
+            loadActivityDescription(descriptions.get(0), 0);
+            applyActivityDescription(descriptions.get(0), 0, false);
+            if (descriptions.size() > 1) {
+                mThumbnailLoader = new AsyncTask<Void, Integer, Void>() {
+                    @Override
+                    protected void onProgressUpdate(Integer... values) {
+                        final ActivityDescription ad = descriptions.get(values[0]);
+                        if (!isCancelled()) {
+                            applyActivityDescription(ad, values[0], true);
+                        }
+                        // This is to prevent the loader thread from getting ahead
+                        // of our UI updates.
+                        mHandler.post(new Runnable() {
+                            @Override public void run() {
+                                synchronized (ad) {
+                                    ad.notifyAll();
+                                }
+                            }
+                        });
+                    }
+
+                    @Override
+                    protected Void doInBackground(Void... params) {
+                        final int origPri = Process.getThreadPriority(Process.myTid());
+                        Process.setThreadPriority(Process.THREAD_GROUP_BG_NONINTERACTIVE);
+                        long nextTime = SystemClock.uptimeMillis();
+                        for (int i=1; i<descriptions.size(); i++) {
+                            ActivityDescription ad = descriptions.get(i);
+                            loadActivityDescription(ad, i);
+                            long now = SystemClock.uptimeMillis();
+                            nextTime += 200;
+                            if (nextTime > now) {
+                                try {
+                                    Thread.sleep(nextTime-now);
+                                } catch (InterruptedException e) {
+                                }
+                            }
+                            if (isCancelled()) {
+                                break;
+                            }
+                            synchronized (ad) {
+                                publishProgress(i);
+                                try {
+                                    ad.wait(500);
+                                } catch (InterruptedException e) {
+                                }
+                            }
+                        }
+                        Process.setThreadPriority(origPri);
+                        return null;
+                    }
+                };
+                mThumbnailLoader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+            }
         } else {
             // Immediately hide this panel
             if (DEBUG) Log.v(TAG, "Nothing to show");
@@ -548,7 +683,7 @@
 
     public void handleSwipe(View view) {
         ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
-        if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
+        if (DEBUG) Log.v(TAG, "Jettison " + ad.getLabel());
         mActivityDescriptions.remove(ad);
 
         // Handled by widget containers to enable LayoutTransitions properly
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 89900a1..959328f 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -66,20 +66,34 @@
 
     private void update() {
         mLinearLayout.removeAllViews();
+        // Once we can clear the data associated with individual item views,
+        // we can get rid of the removeAllViews() and the code below will
+        // recycle them.
         for (int i = 0; i < mAdapter.getCount(); i++) {
-            final View view = mAdapter.getView(i, null, mLinearLayout);
-            view.setClickable(true);
-            view.setOnLongClickListener(mOnLongClick);
+            View old = null;
+            if (i < mLinearLayout.getChildCount()) {
+                old = mLinearLayout.getChildAt(i);
+                old.setVisibility(View.VISIBLE);
+            }
+            final View view = mAdapter.getView(i, old, mLinearLayout);
 
-            final View thumbnail = getChildContentView(view);
-            // thumbnail is set to clickable in the layout file
-            thumbnail.setOnClickListener(new OnClickListener() {
-                public void onClick(View v) {
-                    mCallback.handleOnClick(view);
-                }
-            });
+            if (old == null) {
+                view.setClickable(true);
+                view.setOnLongClickListener(mOnLongClick);
 
-            mLinearLayout.addView(view);
+                final View thumbnail = getChildContentView(view);
+                // thumbnail is set to clickable in the layout file
+                thumbnail.setOnClickListener(new OnClickListener() {
+                    public void onClick(View v) {
+                        mCallback.handleOnClick(view);
+                    }
+                });
+
+                mLinearLayout.addView(view);
+            }
+        }
+        for (int i = mAdapter.getCount(); i < mLinearLayout.getChildCount(); i++) {
+            mLinearLayout.getChildAt(i).setVisibility(View.GONE);
         }
         // Scroll to end after layout.
         post(new Runnable() {
@@ -128,8 +142,9 @@
         final float y = ev.getY() + getScrollY();
         for (int i = 0; i < mLinearLayout.getChildCount(); i++) {
             View item = mLinearLayout.getChildAt(i);
-            if (x >= item.getLeft() && x < item.getRight()
-                && y >= item.getTop() && y < item.getBottom()) {
+            if (item.getVisibility() == View.VISIBLE
+                    && x >= item.getLeft() && x < item.getRight()
+                    && y >= item.getTop() && y < item.getBottom()) {
                 return item;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 86dc9a6..fe255cb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -69,6 +69,7 @@
 class SaveImageInBackgroundData {
     Context context;
     Bitmap image;
+    Runnable finisher;
     int result;
 }
 
@@ -141,6 +142,7 @@
             Toast.makeText(params.context, R.string.screenshot_saving_toast,
                     Toast.LENGTH_SHORT).show();
         }
+        params.finisher.run();
     };
 }
 
@@ -231,11 +233,9 @@
                 WindowManager.LayoutParams.FLAG_FULLSCREEN
                     | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                     | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED_SYSTEM
-                    | WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
                     | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                     | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED,
                 PixelFormat.TRANSLUCENT);
-        mWindowLayoutParams.token = new Binder();
         mWindowLayoutParams.setTitle("ScreenshotAnimation");
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
@@ -244,10 +244,11 @@
     /**
      * Creates a new worker thread and saves the screenshot to the media store.
      */
-    private void saveScreenshotInWorkerThread() {
+    private void saveScreenshotInWorkerThread(Runnable finisher) {
         SaveImageInBackgroundData data = new SaveImageInBackgroundData();
         data.context = mContext;
         data.image = mScreenBitmap;
+        data.finisher = finisher;
         new SaveImageInBackgroundTask().execute(data);
     }
 
@@ -269,7 +270,7 @@
     /**
      * Takes a screenshot of the current display and shows an animation.
      */
-    void takeScreenshot() {
+    void takeScreenshot(Runnable finisher) {
         // We need to orient the screenshot correctly (and the Surface api seems to take screenshots
         // only in the natural orientation of the device :!)
         mDisplay.getRealMetrics(mDisplayMetrics);
@@ -302,18 +303,19 @@
         if (mScreenBitmap == null) {
             Toast.makeText(mContext, R.string.screenshot_failed_toast,
                     Toast.LENGTH_SHORT).show();
+            finisher.run();
             return;
         }
 
         // Start the post-screenshot animation
-        startAnimation();
+        startAnimation(finisher);
     }
 
 
     /**
      * Starts the animation after taking the screenshot
      */
-    private void startAnimation() {
+    private void startAnimation(final Runnable finisher) {
         // Add the view for the animation
         mScreenshotView.setImageBitmap(mScreenBitmap);
         mScreenshotLayout.requestFocus();
@@ -332,8 +334,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 // Save the screenshot once we have a bit of time now
-                saveScreenshotInWorkerThread();
-
+                saveScreenshotInWorkerThread(finisher);
                 mWindowManager.removeView(mScreenshotLayout);
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 35eaedf..05ff8be 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -26,7 +26,11 @@
 import android.hardware.usb.UsbAccessory;
 import android.hardware.usb.UsbManager;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.internal.app.AlertActivity;
@@ -39,12 +43,30 @@
 
     private static GlobalScreenshot mScreenshot;
 
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case 1:
+                    final Messenger callback = msg.replyTo;
+                    if (mScreenshot == null) {
+                        mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
+                    }
+                    mScreenshot.takeScreenshot(new Runnable() {
+                        @Override public void run() {
+                            Message reply = Message.obtain(null, 1);
+                            try {
+                                callback.send(reply);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                    });
+            }
+        }
+    };
+
     @Override
     public IBinder onBind(Intent intent) {
-        if (mScreenshot == null) {
-            mScreenshot = new GlobalScreenshot(this);
-        }
-        mScreenshot.takeScreenshot();
-        return null;
+        return new Messenger(mHandler).getBinder();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 1e27233..a90eb3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -59,13 +59,17 @@
         mNotification = notification;
         setContentDescription(notification);
 
-        final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
-        final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
-        final float scale = (float)imageBounds / (float)outerBounds;
-        setScaleX(scale);
-        setScaleY(scale);
-        final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
-        setAlpha(alpha);
+        // We do not resize and scale system icons (on the right), only notification icons (on the
+        // left).
+        if (notification != null) {
+            final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+            final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size);
+            final float scale = (float)imageBounds / (float)outerBounds;
+            setScaleX(scale);
+            setScaleY(scale);
+            final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
+            setAlpha(alpha);
+        }
     }
 
     private static boolean streq(String a, String b) {
@@ -247,4 +251,9 @@
             }
         }
     }
+
+    public String toString() {
+        return "StatusBarIconView(slot=" + mSlot + " icon=" + mIcon 
+            + " notification=" + mNotification + ")";
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index abf505c..5f1ae58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -29,6 +29,7 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.Surface;
 import android.view.WindowManager;
 import android.widget.LinearLayout;
@@ -56,6 +57,7 @@
     boolean mVertical;
 
     boolean mHidden;
+    boolean mEnabled = true;
 
     public View getRecentsButton() {
         return mCurrentView.findViewById(R.id.recent_apps);
@@ -67,6 +69,7 @@
 
     public NavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
+
         mHidden = false;
 
         mDisplay = ((WindowManager)context.getSystemService(
@@ -79,6 +82,11 @@
         mVertical = false;
     }
 
+    public void setEnabled(final boolean enable) {
+        mEnabled = enable;
+        mCurrentView.setVisibility(enable ? View.VISIBLE : View.INVISIBLE);
+    }
+
     public void setHidden(final boolean hide) {
         if (hide == mHidden) return;
 
@@ -129,6 +137,11 @@
                                                 ? findViewById(R.id.rot90)
                                                 : findViewById(R.id.rot270);
 
+        for (View v : mRotatedViews) {
+            // this helps avoid drawing artifacts with glowing navigation keys 
+            ViewGroup group = (ViewGroup) v.findViewById(R.id.nav_buttons);
+            group.setMotionEventSplittingEnabled(false);
+        }
         mCurrentView = mRotatedViews[Surface.ROTATION_0];
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2e14bef..68f6dcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.phone;
 
 import android.animation.ObjectAnimator;
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.Dialog;
 import android.app.Notification;
@@ -90,6 +91,7 @@
     static final String TAG = "PhoneStatusBar";
     public static final boolean DEBUG = false;
     public static final boolean SPEW = false;
+    public static final boolean DUMPTRUCK = true; // extra dumpsys info
 
     // additional instrumentation for testing purposes; intended to be left on during development
     public static final boolean CHATTY = DEBUG || true;
@@ -315,8 +317,8 @@
         mPile = (ViewGroup)expanded.findViewById(R.id.latestItems);
         mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
         mNoNotificationsTitle = (TextView)expanded.findViewById(R.id.noNotificationsTitle);
-        mNoNotificationsTitle.setAlpha(0f);
-        mNoNotificationsTitle.setVisibility(View.VISIBLE);
+        mNoNotificationsTitle.setVisibility(View.GONE); // disabling for now
+
         mClearButton = expanded.findViewById(R.id.clear_all_button);
         mClearButton.setOnClickListener(mClearButtonListener);
         mClearButton.setAlpha(0f);
@@ -371,9 +373,11 @@
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
-                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 (translucent ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
+        if (ActivityManager.isHighEndGfx(mDisplay)) {
+            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        }
         lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
         lp.setTitle("RecentsPanel");
         lp.windowAnimations = R.style.Animation_RecentPanel;
@@ -1023,6 +1027,7 @@
             mClearButton.setAlpha(clearable ? 1.0f : 0.0f);
         }
 
+        /*
         if (mNoNotificationsTitle.isShown()) {
             if (any != (mNoNotificationsTitle.getAlpha() == 0.0f)) {
                 ObjectAnimator a = ObjectAnimator.ofFloat(mNoNotificationsTitle, "alpha",
@@ -1034,6 +1039,7 @@
         } else {
             mNoNotificationsTitle.setAlpha(any ? 0.0f : 0.75f);
         }
+        */
     }
 
 
@@ -1045,12 +1051,30 @@
         final int diff = state ^ old;
         mDisabled = state;
 
+        if (DEBUG) {
+            Slog.d(TAG, String.format("disable: 0x%08x -> 0x%08x (diff: 0x%08x)",
+                old, state, diff));
+        }
+
         if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
             if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
                 Slog.d(TAG, "DISABLE_EXPAND: yes");
                 animateCollapse();
             }
         }
+
+        if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
+            if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
+                Slog.d(TAG, "DISABLE_NAVIGATION: yes");
+
+                // close recents if it's visible
+                mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
+                mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
+            }
+
+            mNavigationBarView.setEnabled((state & StatusBarManager.DISABLE_NAVIGATION) == 0);
+        }
+
         if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
             if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
                 Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
@@ -1676,26 +1700,28 @@
             pw.println("  mScrollView: " + viewInfo(mScrollView)
                     + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
         }
-        /*
-        synchronized (mNotificationData) {
-            int N = mNotificationData.ongoingCount();
-            pw.println("  ongoingCount.size=" + N);
-            for (int i=0; i<N; i++) {
-                StatusBarNotification n = mNotificationData.getOngoing(i);
-                pw.println("    [" + i + "] key=" + n.key + " view=" + n.view);
-                pw.println("           data=" + n.data);
-            }
-            N = mNotificationData.latestCount();
-            pw.println("  ongoingCount.size=" + N);
-            for (int i=0; i<N; i++) {
-                StatusBarNotification n = mNotificationData.getLatest(i);
-                pw.println("    [" + i + "] key=" + n.key + " view=" + n.view);
-                pw.println("           data=" + n.data);
-            }
-        }
-        */
 
-        if (false) {
+        if (DUMPTRUCK) {
+            synchronized (mNotificationData) {
+                int N = mNotificationData.size();
+                pw.println("  notification icons: " + N);
+                for (int i=0; i<N; i++) {
+                    NotificationData.Entry e = mNotificationData.get(i);
+                    pw.println("    [" + i + "] key=" + e.key + " icon=" + e.icon);
+                    StatusBarNotification n = e.notification;
+                    pw.println("         pkg=" + n.pkg + " id=" + n.id + " priority=" + n.priority);
+                    pw.println("         notification=" + n.notification);
+                    pw.println("         tickerText=\"" + n.notification.tickerText + "\"");
+                }
+            }
+
+            int N = mStatusIcons.getChildCount();
+            pw.println("  system icons: " + N);
+            for (int i=0; i<N; i++) {
+                StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
+                pw.println("    [" + i + "] icon=" + ic);
+            }
+            
             pw.println("see the logcat for a dump of the views we have created.");
             // must happen on ui thread
             mHandler.post(new Runnable() {
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 fc18eef..6368d1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -49,6 +49,8 @@
 public class KeyButtonView extends ImageView {
     private static final String TAG = "StatusBar.KeyButtonView";
 
+    final float GLOW_MAX_SCALE_FACTOR = 1.8f;
+
     IWindowManager mWindowManager;
     long mDownTime;
     boolean mSending;
@@ -159,17 +161,22 @@
         mGlowScale = x;
         final float w = getWidth();
         final float h = getHeight();
-        if (x < 1.0f) {
+        if (GLOW_MAX_SCALE_FACTOR <= 1.0f) {
+            // this only works if we know the glow will never leave our bounds
             invalidate();
         } else {
-            final float rx = (w * (x - 1.0f)) / 2.0f;
-            final float ry = (h * (x - 1.0f)) / 2.0f;
+            final float rx = (w * (GLOW_MAX_SCALE_FACTOR - 1.0f)) / 2.0f + 1.0f;
+            final float ry = (h * (GLOW_MAX_SCALE_FACTOR - 1.0f)) / 2.0f + 1.0f;
             com.android.systemui.SwipeHelper.invalidateGlobalRegion(
                     this,
                     new RectF(getLeft() - rx,
                               getTop() - ry,
                               getRight() + rx,
                               getBottom() + ry));
+
+            // also invalidate our immediate parent to help avoid situations where nearby glows
+            // interfere
+            ((View)getParent()).invalidate();
         }
     }
 
@@ -183,7 +190,7 @@
                     setDrawingAlpha(1f);
                     as.playTogether(
                         ObjectAnimator.ofFloat(this, "glowAlpha", 1f),
-                        ObjectAnimator.ofFloat(this, "glowScale", 1.8f)
+                        ObjectAnimator.ofFloat(this, "glowScale", GLOW_MAX_SCALE_FACTOR)
                     );
                     as.setDuration(50);
                 } else {
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 e787113..76dec5e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -497,6 +497,8 @@
         mRecentButton = mNavigationArea.findViewById(R.id.recent_apps);
         mRecentButton.setOnClickListener(mOnClickListener);
         mNavigationArea.setLayoutTransition(mBarContentsLayoutTransition);
+        // no multi-touch on the nav buttons
+        mNavigationArea.setMotionEventSplittingEnabled(false);
 
         // The bar contents buttons
         mFeedbackIconArea = (ViewGroup)sb.findViewById(R.id.feedbackIconArea);
@@ -966,11 +968,11 @@
         if ((diff & StatusBarManager.DISABLE_BACK) != 0) {
             if ((state & StatusBarManager.DISABLE_BACK) != 0) {
                 Slog.i(TAG, "DISABLE_BACK: yes");
-                mBackButton.setVisibility(View.INVISIBLE);
+                mBackButton.setEnabled(false);
                 mInputMethodSwitchButton.setScreenLocked(true);
             } else {
                 Slog.i(TAG, "DISABLE_BACK: no");
-                mBackButton.setVisibility(View.VISIBLE);
+                mBackButton.setEnabled(true);
                 mInputMethodSwitchButton.setScreenLocked(false);
             }
         }
@@ -1218,9 +1220,7 @@
 
     private View.OnClickListener mOnClickListener = new View.OnClickListener() {
         public void onClick(View v) {
-            if (v == mNotificationTrigger) {
-                onClickNotificationTrigger();
-            } else if (v == mRecentButton) {
+            if (v == mRecentButton) {
                 onClickRecentButton();
             } else if (v == mInputMethodSwitchButton) {
                 onClickInputMethodSwitchButton();
@@ -1230,17 +1230,6 @@
         }
     };
 
-    public void onClickNotificationTrigger() {
-        if (DEBUG) Slog.d(TAG, "clicked notification icons; disabled=" + mDisabled);
-        if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
-            int msg = !mNotificationPanel.isShowing()
-                ? MSG_OPEN_NOTIFICATION_PANEL
-                : MSG_CLOSE_NOTIFICATION_PANEL;
-            mHandler.removeMessages(msg);
-            mHandler.sendEmptyMessage(msg);
-        }
-    }
-
     public void onClickRecentButton() {
         if (DEBUG) Slog.d(TAG, "clicked recent apps; disabled=" + mDisabled);
         if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
@@ -1372,6 +1361,11 @@
 //                        event.getY(),
 //                        mInitialTouchX,
 //                        mInitialTouchY));
+
+            if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
+                return true;
+            }
+
             final int action = event.getAction();
             switch (action) {
                 case MotionEvent.ACTION_DOWN:
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 06b7fb9..86de558 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -1142,6 +1142,10 @@
             // insecure and (is covered by another window OR this feature is enabled in general)
             boolean enable = !mShowing
                 || ((ENABLE_STATUS_BAR_IN_KEYGUARD || mHidden) && !isSecure());
+            if (DEBUG) {
+                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+                    + " isSecure=" + isSecure() + " --> enable=" + enable);
+            }
             mStatusBarManager.disable(enable ?
                          StatusBarManager.DISABLE_NONE :
                          ( StatusBarManager.DISABLE_EXPAND
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 0ee6488..c580f08 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -386,6 +386,11 @@
                     // Ditch the menu created above
                     st.menu = null;
 
+                    if (mActionBar != null) {
+                        // Don't show it in the action bar either
+                        mActionBar.setMenu(null, mActionMenuPresenterCallback);
+                    }
+
                     return false;
                 }
                 
@@ -406,6 +411,11 @@
             }
 
             if (!cb.onPreparePanel(st.featureId, st.createdPanelView, st.menu)) {
+                if (mActionBar != null) {
+                    // The app didn't want to show the menu for now but it still exists.
+                    // Clear it out of the action bar.
+                    mActionBar.setMenu(null, mActionMenuPresenterCallback);
+                }
                 st.menu.startDispatchingItemsChanged();
                 return false;
             }
@@ -753,7 +763,7 @@
         if (mPanelChordingKey != 0) {
             mPanelChordingKey = 0;
 
-            if (event.isCanceled()) {
+            if (event.isCanceled() || (mDecor != null && mDecor.mActionMode != null)) {
                 return;
             }
             
@@ -3139,6 +3149,7 @@
 
         public boolean hasPanelItems() {
             if (shownPanelView == null) return false;
+            if (createdPanelView != null) return true;
 
             if (isCompact || isInExpandedMode) {
                 return listMenuPresenter.getAdapter().getCount() > 0;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b60a038..7764e35 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -41,6 +41,8 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.LocalPowerManager;
+import android.os.Message;
+import android.os.Messenger;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -2396,22 +2398,67 @@
         }
     }
 
+    ServiceConnection mScreenshotConnection = null;
+    Runnable mScreenshotTimeout = null;
+
+    void finishScreenshot(ServiceConnection conn) {
+        if (mScreenshotConnection == conn) {
+            mContext.unbindService(conn);
+            mScreenshotConnection = null;
+            if (mScreenshotTimeout != null) {
+                mHandler.removeCallbacks(mScreenshotTimeout);
+                mScreenshotTimeout = null;
+            }
+        }
+    }
+
     private void takeScreenshot() {
         mHandler.post(new Runnable() {
             @Override
             public void run() {
+                if (mScreenshotConnection != null) {
+                    return;
+                }
                 ComponentName cn = new ComponentName("com.android.systemui",
                         "com.android.systemui.screenshot.TakeScreenshotService");
                 Intent intent = new Intent();
                 intent.setComponent(cn);
                 ServiceConnection conn = new ServiceConnection() {
                     @Override
-                    public void onServiceConnected(ComponentName name, IBinder service) {}
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        if (mScreenshotConnection != this) {
+                            return;
+                        }
+                        Messenger messenger = new Messenger(service);
+                        Message msg = Message.obtain(null, 1);
+                        final ServiceConnection myConn = this;
+                        Handler h = new Handler(mHandler.getLooper()) {
+                            @Override
+                            public void handleMessage(Message msg) {
+                                finishScreenshot(myConn);
+                            }
+                        };
+                        msg.replyTo = new Messenger(h);
+                        try {
+                            messenger.send(msg);
+                        } catch (RemoteException e) {
+                        }
+                    }
                     @Override
                     public void onServiceDisconnected(ComponentName name) {}
                 };
-                mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE);
-                mContext.unbindService(conn);
+                if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
+                    mScreenshotConnection = conn;
+                    mScreenshotTimeout = new Runnable() {
+                        @Override public void run() {
+                            if (mScreenshotConnection != null) {
+                                finishScreenshot(mScreenshotConnection);
+                            }
+                        }
+
+                    };
+                    mHandler.postDelayed(mScreenshotTimeout, 10000);
+                }
             }
         });
     }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index fd03201..00aa14c 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -97,6 +97,9 @@
     private static final boolean DEBUG_EVENTS = false;
     private static final boolean DEBUG_OBB = false;
 
+    // Disable this since it messes up long-running cryptfs operations.
+    private static final boolean WATCHDOG_ENABLE = false;
+
     private static final String TAG = "MountService";
 
     private static final String VOLD_TAG = "VoldConnector";
@@ -1182,8 +1185,10 @@
         Thread thread = new Thread(mConnector, VOLD_TAG);
         thread.start();
 
-        // Add ourself to the Watchdog monitors.
-        Watchdog.getInstance().addMonitor(this);
+        // Add ourself to the Watchdog monitors if enabled.
+        if (WATCHDOG_ENABLE) {
+            Watchdog.getInstance().addMonitor(this);
+        }
     }
 
     /**
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index e9c91e6..cba04df 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2699,7 +2699,6 @@
                 }
                 
                 if (!haveBg) {
-                    Slog.i(TAG, "Low Memory: No more background processes.");
                     EventLog.writeEvent(EventLogTags.AM_LOW_MEMORY, mLruProcesses.size());
                     long now = SystemClock.uptimeMillis();
                     for (int i=mLruProcesses.size()-1; i>=0; i--) {
diff --git a/tests/RenderScriptTests/ShadersTest/Android.mk b/tests/RenderScriptTests/ShadersTest/Android.mk
new file mode 100644
index 0000000..109b0a0
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := ShadersTest
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ShadersTest/AndroidManifest.xml b/tests/RenderScriptTests/ShadersTest/AndroidManifest.xml
new file mode 100644
index 0000000..871200d
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.shaderstest">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    
+    <application android:label="_ShadersTest">
+        <activity android:name="ShadersTest"
+                  android:label="_ShadersTest"
+                  android:theme="@android:style/Theme.Black.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/ShadersTest/res/drawable-nodpi/robot.png b/tests/RenderScriptTests/ShadersTest/res/drawable-nodpi/robot.png
new file mode 100644
index 0000000..f7353fd
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/res/drawable-nodpi/robot.png
Binary files differ
diff --git a/tests/RenderScriptTests/ShadersTest/res/raw/depth_fs.glsl b/tests/RenderScriptTests/ShadersTest/res/raw/depth_fs.glsl
new file mode 100644
index 0000000..096843b
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/res/raw/depth_fs.glsl
@@ -0,0 +1,13 @@
+void main() {
+    // Non-linear depth value
+    float z = gl_FragCoord.z;
+    // Near and far planes from the projection
+    // In practice, these values can be used to tweak
+    // the focus range
+    float n = UNI_near;
+    float f = UNI_far;
+    // Linear depth value
+    z = (2.0 * n) / (f + n - z * (f - n));
+
+    gl_FragColor = vec4(z, z, z, 1.0);
+}
diff --git a/tests/RenderScriptTests/ShadersTest/res/raw/robot.a3d b/tests/RenderScriptTests/ShadersTest/res/raw/robot.a3d
new file mode 100644
index 0000000..f48895c
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/res/raw/robot.a3d
Binary files differ
diff --git a/tests/RenderScriptTests/ShadersTest/res/raw/vignette_fs.glsl b/tests/RenderScriptTests/ShadersTest/res/raw/vignette_fs.glsl
new file mode 100644
index 0000000..2dc1ea3
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/res/raw/vignette_fs.glsl
@@ -0,0 +1,31 @@
+#define CRT_MASK
+
+varying vec2 varTex0;
+
+void main() {
+    lowp vec4 color = texture2D(UNI_Tex0, varTex0);
+    
+    vec2 powers = pow(abs((gl_FragCoord.xy / vec2(UNI_width, UNI_height)) - 0.5), vec2(2.0));
+    float gradient = smoothstep(UNI_size - UNI_feather, UNI_size + UNI_feather,
+            powers.x + powers.y);
+
+    color = vec4(mix(color.rgb, vec3(0.0), gradient), 1.0);
+
+#ifdef CRT_MASK
+    float vShift = gl_FragCoord.y;
+    if (mod(gl_FragCoord.x, 6.0) >= 3.0) {
+        vShift += 2.0;
+    }
+
+    lowp vec3 r = vec3(0.95, 0.0, 0.2);
+    lowp vec3 g = vec3(0.2, 0.95, 0.0);
+    lowp vec3 b = vec3(0.0, 0.2, 0.95);
+    int channel = int(floor(mod(gl_FragCoord.x, 3.0)));
+    lowp vec4 crt = vec4(r[channel], g[channel], b[channel], 1.0);
+    crt *= clamp(floor(mod(vShift, 4.0)), 0.0, 1.0);
+    
+    color = (crt * color * 1.25) + 0.05;
+#endif
+
+    gl_FragColor = color;
+}
diff --git a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTest.java b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTest.java
new file mode 100644
index 0000000..6803fbb
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.shaderstest;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class ShadersTest extends Activity {
+
+    private ShadersTestView mView;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mView = new ShadersTestView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        mView.resume();
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        mView.pause();
+    }
+}
diff --git a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTestRS.java b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTestRS.java
new file mode 100644
index 0000000..dad97e2
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTestRS.java
@@ -0,0 +1,202 @@
+/*
+ * 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.shaderstest;
+
+import android.content.res.Resources;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Element.DataKind;
+import android.renderscript.Element.DataType;
+import android.renderscript.FileA3D;
+import android.renderscript.Mesh;
+import android.renderscript.Program;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramFragmentFixedFunction;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramStore.DepthFunc;
+import android.renderscript.ProgramVertex;
+import android.renderscript.ProgramVertexFixedFunction;
+import android.renderscript.RSRuntimeException;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.Sampler;
+import android.renderscript.Type.Builder;
+
+@SuppressWarnings({"FieldCanBeLocal"})
+public class ShadersTestRS {
+    public ShadersTestRS() {
+    }
+
+    public void init(RenderScriptGL rs, Resources res) {
+        mRS = rs;
+        mRes = res;
+        initRS();
+    }
+
+    public void surfaceChanged() {
+        initBuffers(mRS.getWidth(), mRS.getHeight());
+    }
+
+    private Resources mRes;
+    private RenderScriptGL mRS;
+    private Sampler mLinearClamp;
+    private Sampler mNearestClamp;
+    private ProgramStore mPSBackground;
+    private ProgramFragment mPFBackground;
+    private ProgramVertex mPVBackground;
+    private ProgramVertexFixedFunction.Constants mPVA;
+
+    private ProgramFragment mPFVignette;
+    private ScriptField_VignetteConstants_s mFSVignetteConst;
+
+    private Allocation mMeshTexture;
+    private Allocation mScreen;
+    private Allocation mScreenDepth;
+
+    private ScriptField_MeshInfo mMeshes;
+    private ScriptC_shaderstest mScript;
+
+
+    public void onActionDown(float x, float y) {
+        mScript.invoke_onActionDown(x, y);
+    }
+
+    public void onActionScale(float scale) {
+        mScript.invoke_onActionScale(scale);
+    }
+
+    public void onActionMove(float x, float y) {
+        mScript.invoke_onActionMove(x, y);
+    }
+
+    private void initPFS() {
+        ProgramStore.Builder b = new ProgramStore.Builder(mRS);
+
+        b.setDepthFunc(DepthFunc.LESS);
+        b.setDitherEnabled(false);
+        b.setDepthMaskEnabled(true);
+        mPSBackground = b.create();
+
+        mScript.set_gPFSBackground(mPSBackground);
+    }
+
+    private void initPF() {
+        mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
+        mScript.set_gLinear(mLinearClamp);
+
+        mNearestClamp = Sampler.CLAMP_NEAREST(mRS);
+        mScript.set_gNearest(mNearestClamp);
+
+        ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
+        b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                     ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+        mPFBackground = b.create();
+        mPFBackground.bindSampler(mLinearClamp, 0);
+        mScript.set_gPFBackground(mPFBackground);
+
+        mFSVignetteConst = new ScriptField_VignetteConstants_s(mRS, 1);
+        mScript.bind_gFSVignetteConstants(mFSVignetteConst);
+
+        ProgramFragment.Builder fs;
+
+        fs = new ProgramFragment.Builder(mRS);
+        fs.setShader(mRes, R.raw.vignette_fs);
+        fs.addConstant(mFSVignetteConst.getAllocation().getType());
+        fs.addTexture(Program.TextureType.TEXTURE_2D);
+        mPFVignette = fs.create();
+        mPFVignette.bindConstants(mFSVignetteConst.getAllocation(), 0);
+        mScript.set_gPFVignette(mPFVignette);
+    }
+
+    private void initPV() {
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        mPVBackground = pvb.create();
+
+        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
+        ((ProgramVertexFixedFunction) mPVBackground).bindConstants(mPVA);
+
+        mScript.set_gPVBackground(mPVBackground);
+    }
+
+    private void loadImage() {
+        mMeshTexture = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+        mScript.set_gTMesh(mMeshTexture);
+    }
+
+    private void initMeshes(FileA3D model) {
+        int numEntries = model.getIndexEntryCount();
+        int numMeshes = 0;
+        for (int i = 0; i < numEntries; i ++) {
+            FileA3D.IndexEntry entry = model.getIndexEntry(i);
+            if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+                numMeshes ++;
+            }
+        }
+
+        if (numMeshes > 0) {
+            mMeshes = new ScriptField_MeshInfo(mRS, numMeshes);
+
+            for (int i = 0; i < numEntries; i ++) {
+                FileA3D.IndexEntry entry = model.getIndexEntry(i);
+                if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
+                    Mesh mesh = entry.getMesh();
+                    mMeshes.set_mMesh(i, mesh, false);
+                    mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false);
+                }
+            }
+            mMeshes.copyAll();
+        } else {
+            throw new RSRuntimeException("No valid meshes in file");
+        }
+
+        mScript.bind_gMeshes(mMeshes);
+        mScript.invoke_updateMeshInfo();
+    }
+
+    private void initRS() {
+        mScript = new ScriptC_shaderstest(mRS, mRes, R.raw.shaderstest);
+
+        initPFS();
+        initPF();
+        initPV();
+
+        loadImage();
+
+        initBuffers(1, 1);
+
+        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
+        initMeshes(model);
+
+        mRS.bindRootScript(mScript);
+    }
+
+    private void initBuffers(int width, int height) {
+        Builder b;
+        b = new Builder(mRS, Element.RGBA_8888(mRS));
+        b.setX(width).setY(height);
+        mScreen = Allocation.createTyped(mRS, b.create(),
+                Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+        mScript.set_gScreen(mScreen);
+
+        b = new Builder(mRS, Element.createPixel(mRS, DataType.UNSIGNED_16, DataKind.PIXEL_DEPTH));
+        b.setX(width).setY(height);
+        mScreenDepth = Allocation.createTyped(mRS, b.create(),
+                Allocation.USAGE_GRAPHICS_RENDER_TARGET);
+        mScript.set_gScreenDepth(mScreenDepth);
+    }
+}
diff --git a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTestView.java b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTestView.java
new file mode 100644
index 0000000..e0a540f
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/ShadersTestView.java
@@ -0,0 +1,138 @@
+/*
+ * 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.shaderstest;
+
+import android.content.Context;
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScriptGL;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.SurfaceHolder;
+
+public class ShadersTestView extends RSSurfaceView {
+
+    private RenderScriptGL mRS;
+    private ShadersTestRS mRender;
+
+    private ScaleGestureDetector mScaleDetector;
+
+    private static final int INVALID_POINTER_ID = -1;
+    private int mActivePointerId = INVALID_POINTER_ID;
+
+    public ShadersTestView(Context context) {
+        super(context);
+        ensureRenderScript();
+        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
+    }
+
+    private void ensureRenderScript() {
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            sc.setDepth(16, 24);
+            mRS = createRenderScriptGL(sc);
+            mRender = new ShadersTestRS();
+            mRender.init(mRS, getResources());
+        }
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        ensureRenderScript();
+    }
+
+    @Override
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+        mRender.surfaceChanged();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mRender = null;
+        if (mRS != null) {
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        mScaleDetector.onTouchEvent(ev);
+
+        boolean ret = false;
+        float x = ev.getX();
+        float y = ev.getY();
+
+        final int action = ev.getAction();
+
+        switch (action & MotionEvent.ACTION_MASK) {
+        case MotionEvent.ACTION_DOWN: {
+            mRender.onActionDown(x, y);
+            mActivePointerId = ev.getPointerId(0);
+            ret = true;
+            break;
+        }
+        case MotionEvent.ACTION_MOVE: {
+            if (!mScaleDetector.isInProgress()) {
+                mRender.onActionMove(x, y);
+            }
+            mRender.onActionDown(x, y);
+            ret = true;
+            break;
+        }
+
+        case MotionEvent.ACTION_UP: {
+            mActivePointerId = INVALID_POINTER_ID;
+            break;
+        }
+
+        case MotionEvent.ACTION_CANCEL: {
+            mActivePointerId = INVALID_POINTER_ID;
+            break;
+        }
+
+        case MotionEvent.ACTION_POINTER_UP: {
+            final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
+                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+            final int pointerId = ev.getPointerId(pointerIndex);
+            if (pointerId == mActivePointerId) {
+                // This was our active pointer going up. Choose a new
+                // active pointer and adjust accordingly.
+                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+                x = ev.getX(newPointerIndex);
+                y = ev.getY(newPointerIndex);
+                mRender.onActionDown(x, y);
+                mActivePointerId = ev.getPointerId(newPointerIndex);
+            }
+            break;
+        }
+        }
+
+        return ret;
+    }
+
+    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+        @Override
+        public boolean onScale(ScaleGestureDetector detector) {
+            mRender.onActionScale(detector.getScaleFactor());
+            return true;
+        }
+    }
+}
+
+
diff --git a/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
new file mode 100644
index 0000000..53f10f9
--- /dev/null
+++ b/tests/RenderScriptTests/ShadersTest/src/com/android/shaderstest/shaderstest.rs
@@ -0,0 +1,193 @@
+// 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.
+
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.shaderstest)
+
+#include "rs_graphics.rsh"
+
+rs_program_vertex gPVBackground;
+rs_program_fragment gPFBackground;
+
+typedef struct VignetteConstants_s {
+    float size;
+    float feather;
+    float width;
+    float height;
+} VignetteConstants;
+VignetteConstants *gFSVignetteConstants;
+rs_program_fragment gPFVignette;
+
+rs_allocation gTMesh;
+
+rs_sampler gLinear;
+rs_sampler gNearest;
+
+rs_program_store gPFSBackground;
+
+rs_allocation gScreenDepth;
+rs_allocation gScreen;
+
+typedef struct MeshInfo {
+    rs_mesh mMesh;
+    int mNumIndexSets;
+    float3 bBoxMin;
+    float3 bBoxMax;
+} MeshInfo_t;
+MeshInfo_t *gMeshes;
+
+static float3 gLookAt;
+
+static float gRotateX;
+static float gRotateY;
+static float gZoom;
+
+static float gLastX;
+static float gLastY;
+
+void onActionDown(float x, float y) {
+    gLastX = x;
+    gLastY = y;
+}
+
+void onActionScale(float scale) {
+
+    gZoom *= 1.0f / scale;
+    gZoom = max(0.1f, min(gZoom, 500.0f));
+}
+
+void onActionMove(float x, float y) {
+    float dx = gLastX - x;
+    float dy = gLastY - y;
+
+    if (fabs(dy) <= 2.0f) {
+        dy = 0.0f;
+    }
+    if (fabs(dx) <= 2.0f) {
+        dx = 0.0f;
+    }
+
+    gRotateY -= dx;
+    if (gRotateY > 360) {
+        gRotateY -= 360;
+    }
+    if (gRotateY < 0) {
+        gRotateY += 360;
+    }
+
+    gRotateX -= dy;
+    gRotateX = min(gRotateX, 80.0f);
+    gRotateX = max(gRotateX, -80.0f);
+
+    gLastX = x;
+    gLastY = y;
+}
+
+void init() {
+    gRotateX = 0.0f;
+    gRotateY = 0.0f;
+    gZoom = 50.0f;
+    gLookAt = 0.0f;
+}
+
+void updateMeshInfo() {
+    rs_allocation allMeshes = rsGetAllocation(gMeshes);
+    int size = rsAllocationGetDimX(allMeshes);
+    gLookAt = 0.0f;
+    float minX, minY, minZ, maxX, maxY, maxZ;
+    for (int i = 0; i < size; i++) {
+        MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
+        rsgMeshComputeBoundingBox(info->mMesh,
+                                  &minX, &minY, &minZ,
+                                  &maxX, &maxY, &maxZ);
+        info->bBoxMin = (minX, minY, minZ);
+        info->bBoxMax = (maxX, maxY, maxZ);
+        gLookAt += (info->bBoxMin + info->bBoxMax)*0.5f;
+    }
+    gLookAt = gLookAt / (float)size;
+}
+
+static void renderAllMeshes() {
+    rs_allocation allMeshes = rsGetAllocation(gMeshes);
+    int size = rsAllocationGetDimX(allMeshes);
+    gLookAt = 0.0f;
+    float minX, minY, minZ, maxX, maxY, maxZ;
+    for (int i = 0; i < size; i++) {
+        MeshInfo_t *info = (MeshInfo_t*)rsGetElementAt(allMeshes, i);
+        rsgDrawMesh(info->mMesh);
+    }
+}
+
+static void renderOffscreen() {
+    rsgBindProgramVertex(gPVBackground);
+    rs_matrix4x4 proj;
+    float aspect = (float) rsAllocationGetDimX(gScreen) / (float) rsAllocationGetDimY(gScreen);
+    rsMatrixLoadPerspective(&proj, 30.0f, aspect, 1.0f, 1000.0f);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+
+    rsgBindProgramFragment(gPFBackground);
+    rsgBindTexture(gPFBackground, 0, gTMesh);
+
+    rs_matrix4x4 matrix;
+
+    rsMatrixLoadIdentity(&matrix);
+    rsMatrixTranslate(&matrix, gLookAt.x, gLookAt.y, gLookAt.z - gZoom);
+    rsMatrixRotate(&matrix, gRotateX, 1.0f, 0.0f, 0.0f);
+    rsMatrixRotate(&matrix, gRotateY, 0.0f, 1.0f, 0.0f);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+
+    renderAllMeshes();
+}
+
+static void drawOffscreenResult(int posX, int posY, float width, float height) {
+    // display the result d
+    rs_matrix4x4 proj, matrix;
+    rsMatrixLoadOrtho(&proj, 0, width, height, 0, -500, 500);
+    rsgProgramVertexLoadProjectionMatrix(&proj);
+    rsMatrixLoadIdentity(&matrix);
+    rsgProgramVertexLoadModelMatrix(&matrix);
+    float startX = posX, startY = posY;
+    rsgDrawQuadTexCoords(startX, startY, 0, 0, 1,
+                         startX, startY + height, 0, 0, 0,
+                         startX + width, startY + height, 0, 1, 0,
+                         startX + width, startY, 0, 1, 1);
+}
+
+int root(void) {
+    gFSVignetteConstants->size = 0.58f * 0.58f;
+    gFSVignetteConstants->feather = 0.2f;
+    gFSVignetteConstants->width = (float) rsAllocationGetDimX(gScreen);
+    gFSVignetteConstants->height = (float) rsAllocationGetDimY(gScreen);
+
+    rsgBindProgramStore(gPFSBackground);
+
+    // Render scene to fullscreenbuffer
+    rsgBindColorTarget(gScreen, 0);
+    rsgBindDepthTarget(gScreenDepth);
+    rsgClearDepth(1.0f);
+    rsgClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+    renderOffscreen();
+
+    // Render on screen
+    rsgClearAllRenderTargets();
+    rsgClearColor(1.0f, 1.0f, 1.0f, 1.0f);
+    rsgClearDepth(1.0f);
+
+    rsgBindProgramFragment(gPFVignette);
+    rsgBindTexture(gPFVignette, 0, gScreen);
+    drawOffscreenResult(0, 0, rsgGetWidth(), rsgGetHeight());
+
+    return 0;
+}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 3b043b3..bfc4d5e 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -203,70 +203,42 @@
 
     private native static boolean doBooleanCommand(String command);
 
-    //STOPSHIP: remove this after native interface works and replace all
-    //calls to doBooleanTempCommand() with doBooleanCommand()
-    private static boolean doBooleanTempCommand(String command) {
-        try {
-            String str = "/system/bin/wpa_cli " + command;
-            Log.e("WifiNative", "===> " + str);
-            Runtime.getRuntime()
-                .exec(str).waitFor();
-        } catch (Exception e) {
-            Log.e("WifiNative", "exception with doBooleanTempCommand");
-            return false;
-        }
-        return true;
-    }
-
-    private static String doStringTempCommand(String command) {
-        String lines[] = null;
-        try {
-            String str = "/system/bin/wpa_cli " + command;
-            Log.e("WifiNative", "===> " + str);
-            Process p = Runtime.getRuntime()
-                .exec(str);
-            InputStream in = p.getInputStream();
-            p.waitFor();
-            byte[] bytes=new byte[in.available()];
-            in.read(bytes);
-            String s = new String(bytes);
-            Log.e("WifiNative", "====> doString: " + s);
-            lines = s.split("\\r?\\n");
-        } catch (Exception e) {
-            Log.e("WifiNative", "exception with doBooleanTempCommand");
-            return null;
-        }
-        return lines[1];
-    }
-
     private native static int doIntCommand(String command);
 
     private native static String doStringCommand(String command);
 
+    public static boolean wpsPbc() {
+        return doBooleanCommand("WPS_PBC");
+    }
+
+    public static boolean wpsPin(String pin) {
+        return doBooleanCommand("WPS_PIN any " + pin);
+    }
+
     public static boolean p2pFind() {
-        return doBooleanTempCommand("p2p_find");
+        return doBooleanCommand("P2P_FIND");
     }
 
     public static boolean p2pFind(int timeout) {
         if (timeout <= 0) {
             return p2pFind();
         }
-        return doBooleanTempCommand("p2p_find " + timeout);
+        return doBooleanCommand("P2P_FIND " + timeout);
     }
 
     public static boolean p2pListen() {
-        return doBooleanTempCommand("p2p_listen");
+        return doBooleanCommand("P2P_LISTEN");
     }
 
     public static boolean p2pListen(int timeout) {
         if (timeout <= 0) {
             return p2pListen();
         }
-        return doBooleanTempCommand("p2p_listen " + timeout);
+        return doBooleanCommand("P2P_LISTEN " + timeout);
     }
 
     public static boolean p2pFlush() {
-        return doBooleanTempCommand("p2p_flush");
+        return doBooleanCommand("P2P_FLUSH");
     }
 
     /* p2p_connect <peer device address> <pbc|pin|PIN#> [label|display|keypad]
@@ -300,41 +272,36 @@
         if (config.isPersistent) args.add("persistent");
         if (config.joinExistingGroup) args.add("join");
 
-        args.add("go_intent=" + config.groupOwnerIntent);
+        int groupOwnerIntent = config.groupOwnerIntent;
+        if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
+            groupOwnerIntent = 3; //default value
+        }
+        args.add("go_intent=" + groupOwnerIntent);
         if (config.channel > 0) args.add("freq=" + config.channel);
 
-        String command = "p2p_connect ";
+        String command = "P2P_CONNECT ";
         for (String s : args) command += s + " ";
 
-        return doStringTempCommand(command);
+        return doStringCommand(command);
     }
 
     public static boolean p2pGroupAdd() {
-        return doBooleanTempCommand("p2p_group_add");
+        return doBooleanCommand("P2P_GROUP_ADD");
     }
 
     public static boolean p2pGroupRemove(String iface) {
         if (iface == null) return false;
-        return doBooleanTempCommand("p2p_group_remove " + iface);
+        return doBooleanCommand("P2P_GROUP_REMOVE " + iface);
     }
 
     public static boolean p2pReject(String deviceAddress) {
-        return doBooleanTempCommand("p2p_reject " + deviceAddress);
+        return doBooleanCommand("P2P_REJECT " + deviceAddress);
     }
 
     /* Invite a peer to a group */
     public static boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
         if (group == null || deviceAddress == null) return false;
-        return doBooleanTempCommand("p2p_invite group=" + group.getInterface()
+        return doBooleanCommand("P2P_INVITE group=" + group.getInterface()
                 + " peer=" + deviceAddress + " go_dev_addr=" + group.getOwner().deviceAddress);
     }
-
-    public static boolean p2pWpsPbc() {
-        return doBooleanTempCommand("wps_pbc");
-    }
-
-    public static boolean p2pWpsPin(String pin) {
-        return doBooleanTempCommand("wps_pin any " + pin);
-    }
-
 }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
index fff5ee3..b77fd76 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pConfig.java
@@ -46,8 +46,10 @@
      * This is an integer value between 0 and 15 where 0 indicates the least
      * inclination to be a group owner and 15 indicates the highest inclination
      * to be a group owner.
+     *
+     * A value of -1 indicates the system can choose an appropriate value.
      */
-    public int groupOwnerIntent;
+    public int groupOwnerIntent = -1;
 
     public boolean isPersistent;
 
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 176191e..49ce124 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -767,10 +767,10 @@
                     notifyP2pProvDiscPinRequest((WifiP2pDevice) message.obj);
                     break;
                 case WifiP2pManager.WPS_PBC:
-                    WifiNative.p2pWpsPbc();
+                    WifiNative.wpsPbc();
                     break;
                 case WifiP2pManager.WPS_PIN:
-                    WifiNative.p2pWpsPin((String) message.obj);
+                    WifiNative.wpsPin((String) message.obj);
                     break;
                 default:
                     return NOT_HANDLED;