Merge "LayoutLib: parsed resources were always set as platform res."
diff --git a/api/current.xml b/api/current.xml
index fb6b950..e76bd65 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -4211,6 +4211,50 @@
  visibility="public"
 >
 </field>
+<field name="fastScrollOverlayPosition"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843592"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollPreviewBackgroundLeft"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843590"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollThumbDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843589"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fastScrollTrackDrawable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843591"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fillAfter"
  type="int"
  transient="false"
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 6b41ce5..4017242 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -166,7 +166,7 @@
     /**
      * Max distance to overfling for edge effects
      */
-    private static final int OVERFLING_DISTANCE = 12;
+    private static final int OVERFLING_DISTANCE = 20;
 
     private final int mEdgeSlop;
     private final int mFadingEdgeLength;
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 821bcc6..f4ee2384 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -181,6 +181,11 @@
             removeAllCacheFiles();
             mClearCacheOnInit = false;
         }
+        // If we're using the Chrome HTTP stack, disable the cache.
+        // Chrome has its own cache, and we don't provide programmatic access to it.
+        if (JniUtil.useChromiumHttpStack()) {
+            setCacheDisabled(true);
+        }
     }
     
     /**
@@ -233,6 +238,10 @@
         if (mDisabled) {
             removeAllCacheFiles();
         }
+        if (!mDisabled && JniUtil.useChromiumHttpStack()) {
+            Log.w(LOGTAG, "CacheManager enabled, but it will not work as "
+                    + "expected because the Chrome HTTP stack is in use.");
+        }
     }
 
     /**
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 3ba7f81..ff9fe1c 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -99,10 +99,6 @@
 
     private boolean mAcceptCookie = true;
 
-    // TODO: Remove this if/when we permanently switch to the Chromium HTTP stack
-    // http:/b/3118772
-    private static Boolean sUseChromiumHttpStack;
-
     private int pendingCookieOperations = 0;
 
     /**
@@ -264,19 +260,12 @@
         return sRef;
     }
 
-    private static boolean useChromiumHttpStack() {
-        if (sUseChromiumHttpStack == null) {
-            sUseChromiumHttpStack = nativeUseChromiumHttpStack();
-        }
-        return sUseChromiumHttpStack;
-    }
-
     /**
      * Control whether cookie is enabled or disabled
      * @param accept TRUE if accept cookie
      */
     public synchronized void setAcceptCookie(boolean accept) {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             nativeSetAcceptCookie(accept);
             return;
         }
@@ -289,7 +278,7 @@
      * @return TRUE if accept cookie
      */
     public synchronized boolean acceptCookie() {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             return nativeAcceptCookie();
         }
 
@@ -304,7 +293,7 @@
      * @param value The value for set-cookie: in http response header
      */
     public void setCookie(String url, String value) {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             nativeSetCookie(url, value);
             return;
         }
@@ -435,7 +424,7 @@
      * @return The cookies in the format of NAME=VALUE [; NAME=VALUE]
      */
     public String getCookie(String url) {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             return nativeGetCookie(url);
         }
 
@@ -549,7 +538,7 @@
      */
     public void removeSessionCookie() {
         signalCookieOperationsStart();
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             new AsyncTask<Void, Void, Void>() {
                 protected Void doInBackground(Void... none) {
                     nativeRemoveSessionCookie();
@@ -587,7 +576,7 @@
      * Remove all cookies
      */
     public void removeAllCookie() {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             nativeRemoveAllCookie();
             return;
         }
@@ -608,7 +597,7 @@
      *  Return true if there are stored cookies.
      */
     public synchronized boolean hasCookies() {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             return nativeHasCookies();
         }
 
@@ -619,7 +608,7 @@
      * Remove all expired cookies
      */
     public void removeExpiredCookie() {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             nativeRemoveExpiredCookie();
             return;
         }
@@ -655,7 +644,7 @@
      * Flush all cookies managed by the Chrome HTTP stack to flash.
      */
     void flushCookieStore() {
-        if (useChromiumHttpStack()) {
+        if (JniUtil.useChromiumHttpStack()) {
             nativeFlushCookieStore();
         }
     }
@@ -1109,7 +1098,6 @@
     }
 
     // Native functions
-    private static native boolean nativeUseChromiumHttpStack();
     private static native boolean nativeAcceptCookie();
     private static native String nativeGetCookie(String url);
     private static native boolean nativeHasCookies();
diff --git a/core/java/android/webkit/JniUtil.java b/core/java/android/webkit/JniUtil.java
index ef44d3a..8de30c5 100644
--- a/core/java/android/webkit/JniUtil.java
+++ b/core/java/android/webkit/JniUtil.java
@@ -19,9 +19,12 @@
 import android.content.Context;
 
 class JniUtil {
+    private JniUtil() {} // Utility class, do not instantiate.
+
     // Used by the Chromium HTTP stack.
     private static String sDatabaseDirectory;
     private static String sCacheDirectory;
+    private static Boolean sUseChromiumHttpStack;
 
     private static boolean initialized = false;
 
@@ -58,4 +61,19 @@
         checkIntialized();
         return sCacheDirectory;
     }
+
+    /**
+     * Returns true if we're using the Chromium HTTP stack.
+     *
+     * TODO: Remove this if/when we permanently switch to the Chromium HTTP stack
+     * http:/b/3118772
+     */
+    static boolean useChromiumHttpStack() {
+        if (sUseChromiumHttpStack == null) {
+            sUseChromiumHttpStack = nativeUseChromiumHttpStack();
+        }
+        return sUseChromiumHttpStack;
+    }
+
+    private static native boolean nativeUseChromiumHttpStack();
 }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index e1a5c2d..18a0bda 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -921,24 +921,59 @@
      * Private class used for the background of a password textfield.
      */
     private static class OutlineDrawable extends Drawable {
+        private Paint mBackgroundPaint;
+        private Paint mOutlinePaint;
+        private float[] mLines;
+        public OutlineDrawable() {
+            mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mBackgroundPaint.setColor(Color.WHITE);
+
+            mOutlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mOutlinePaint.setColor(Color.BLACK);
+            mOutlinePaint.setStyle(Paint.Style.STROKE);
+
+            mLines = new float[16];
+        }
+        @Override
+        public void setBounds(int left, int top, int right, int bottom) {
+            super.setBounds(left, top, right, bottom);
+            // Top line
+            mLines[0] = left;
+            mLines[1] = top + 1;
+            mLines[2] = right;
+            mLines[3] = top + 1;
+            // Right line
+            mLines[4] = right;
+            mLines[5] = top;
+            mLines[6] = right;
+            mLines[7] = bottom;
+            // Bottom line
+            mLines[8] = left;
+            mLines[9] = bottom;
+            mLines[10] = right;
+            mLines[11] = bottom;
+            // Left line
+            mLines[12] = left + 1;
+            mLines[13] = top;
+            mLines[14] = left + 1;
+            mLines[15] = bottom;
+        }
+        @Override
         public void draw(Canvas canvas) {
-            Rect bounds = getBounds();
-            Paint paint = new Paint();
-            paint.setAntiAlias(true);
             // Draw the background.
-            paint.setColor(Color.WHITE);
-            canvas.drawRect(bounds, paint);
+            canvas.drawRect(getBounds(), mBackgroundPaint);
             // Draw the outline.
-            paint.setStyle(Paint.Style.STROKE);
-            paint.setColor(Color.BLACK);
-            canvas.drawRect(bounds, paint);
+            canvas.drawLines(mLines, mOutlinePaint);
         }
         // Always want it to be opaque.
+        @Override
         public int getOpacity() {
             return PixelFormat.OPAQUE;
         }
         // These are needed because they are abstract in Drawable.
+        @Override
         public void setAlpha(int alpha) { }
+        @Override
         public void setColorFilter(ColorFilter cf) { }
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c6cf918..0959bfa 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1952,21 +1952,6 @@
         }
     }
 
-    /**
-     * Deletes any files that were created as a part of the last private
-     * browsing session and clears any internal state associated with that
-     * session. The consequences of calling this method while a private
-     * browsing session is active are unspecified.
-     * @return True if the private browsing files were successfully deleted,
-     *         false otherwise.
-     * @hide pending API council approval.
-     */
-    public static boolean cleanupPrivateBrowsingFiles() {
-        return nativeCleanupPrivateBrowsingFiles();
-    }
-
-    private static native boolean nativeCleanupPrivateBrowsingFiles();
-
     private boolean extendScroll(int y) {
         int finalY = mScroller.getFinalY();
         int newY = pinLocY(finalY + y);
@@ -6248,7 +6233,12 @@
         // resumes during this effect we will take a performance hit. See computeScroll;
         // we resume webcore there when the animation is finished.
         final int time = mScroller.getDuration();
-        awakenScrollBars(time);
+
+        // Suppress scrollbars for layer scrolling.
+        if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+            awakenScrollBars(time);
+        }
+
         invalidate();
     }
 
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 230cc51..c55d180 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -673,10 +673,9 @@
 
         public boolean onScale(ScaleGestureDetector detector) {
             // Prevent scaling beyond overview scale.
-            float scale = Math.max(
-                Math.round(detector.getScaleFactor() * mActualScale * 100) * 0.01f,
-                getZoomOverviewScale());
-            if (willScaleTriggerZoom(scale)) {
+            float scale = Math.max(detector.getScaleFactor() * mActualScale,
+                    getZoomOverviewScale());
+            if (mPinchToZoomAnimating || willScaleTriggerZoom(scale)) {
                 mPinchToZoomAnimating = true;
                 // limit the scale change per step
                 if (scale > mActualScale) {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 30dd17b..87e4b5a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1779,6 +1779,10 @@
             }
             mRecycler.markChildrenDirty();
         }
+        
+        if (mFastScroller != null && mItemCount != mOldItemCount) {
+            mFastScroller.onItemCountChanged(mOldItemCount, mItemCount);
+        }
 
         layoutChildren();
         mInLayout = false;
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index f824ff4..4e3ef0c 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -307,10 +307,13 @@
         }
 
         if (mTrackDrawable != null) {
-            final int left = mThumbDrawable.getBounds().left;
+            final Rect thumbBounds = mThumbDrawable.getBounds();
+            final int left = thumbBounds.left;
+            final int halfThumbHeight = (thumbBounds.bottom - thumbBounds.top) / 2;
             final int trackWidth = mTrackDrawable.getIntrinsicWidth();
-            final int trackLeft = (left + mThumbW) / 2 - trackWidth / 2;
-            mTrackDrawable.setBounds(trackLeft, 0, trackLeft + trackWidth, mList.getHeight());
+            final int trackLeft = (left + mThumbW / 2) - trackWidth / 2;
+            mTrackDrawable.setBounds(trackLeft, halfThumbHeight,
+                    trackLeft + trackWidth, mList.getHeight() - halfThumbHeight);
             mTrackDrawable.draw(canvas);
         }
 
@@ -393,13 +396,19 @@
             }
         }
     }
-    
+
+    void onItemCountChanged(int oldCount, int newCount) {
+        if (mAlwaysShow) {
+            mLongList = true;
+        }
+    }
+
     void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 
             int totalItemCount) {
         // Are there enough pages to require fast scroll? Recompute only if total count changes
         if (mItemCount != totalItemCount && visibleItemCount > 0) {
             mItemCount = totalItemCount;
-            mLongList = mItemCount / visibleItemCount >= MIN_PAGES;
+            mLongList = mAlwaysShow || mItemCount / visibleItemCount >= MIN_PAGES;
         }
         if (!mLongList) {
             if (mState != STATE_NONE) {
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index b9e59d6..407d7a7 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -44,7 +44,7 @@
     private static final int FLING_MODE = 1;
 
     /**
-     * Creates an OverScroller with a viscous fluid scroll interpolator.
+     * Creates an OverScroller with a viscous fluid scroll interpolator and flywheel.
      * @param context
      */
     public OverScroller(Context context) {
@@ -52,14 +52,30 @@
     }
 
     /**
-     * Creates an OverScroller with default edge bounce coefficients and flywheel enabled.
+     * Creates an OverScroller with flywheel enabled.
      * @param context The context of this application.
      * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will
      * be used.
      */
     public OverScroller(Context context, Interpolator interpolator) {
-        this(context, interpolator, SplineOverScroller.DEFAULT_BOUNCE_COEFFICIENT,
-                SplineOverScroller.DEFAULT_BOUNCE_COEFFICIENT);
+        this(context, interpolator, true);
+    }
+
+    /**
+     * Creates an OverScroller.
+     * @param context The context of this application.
+     * @param interpolator The scroll interpolator. If null, a default (viscous) interpolator will
+     * be used.
+     * @param flywheel If true, successive fling motions will keep on increasing scroll speed.
+     * @hide
+     */
+    public OverScroller(Context context, Interpolator interpolator, boolean flywheel) {
+        mInterpolator = interpolator;
+        mFlywheel = flywheel;
+        mScrollerX = new SplineOverScroller();
+        mScrollerY = new SplineOverScroller();
+
+        SplineOverScroller.initFromContext(context);
     }
 
     /**
@@ -69,12 +85,14 @@
      * be used.
      * @param bounceCoefficientX A value between 0 and 1 that will determine the proportion of the
      * velocity which is preserved in the bounce when the horizontal edge is reached. A null value
-     * means no bounce.
-     * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction.
+     * means no bounce. This behavior is no longer supported and this coefficient has no effect.
+     * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction. This
+     * behavior is no longer supported and this coefficient has no effect.
+     * !deprecated Use {!link #OverScroller(Context, Interpolator, boolean)} instead.
      */
     public OverScroller(Context context, Interpolator interpolator,
             float bounceCoefficientX, float bounceCoefficientY) {
-        this(context, interpolator, bounceCoefficientX, bounceCoefficientY, true);
+        this(context, interpolator, true);
     }
 
     /**
@@ -84,21 +102,15 @@
      * be used.
      * @param bounceCoefficientX A value between 0 and 1 that will determine the proportion of the
      * velocity which is preserved in the bounce when the horizontal edge is reached. A null value
-     * means no bounce.
-     * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction.
+     * means no bounce. This behavior is no longer supported and this coefficient has no effect.
+     * @param bounceCoefficientY Same as bounceCoefficientX but for the vertical direction. This
+     * behavior is no longer supported and this coefficient has no effect.
      * @param flywheel If true, successive fling motions will keep on increasing scroll speed.
+     * !deprecated Use {!link OverScroller(Context, Interpolator, boolean)} instead.
      */
     public OverScroller(Context context, Interpolator interpolator,
             float bounceCoefficientX, float bounceCoefficientY, boolean flywheel) {
-        mInterpolator = interpolator;
-        mFlywheel = flywheel;
-        mScrollerX = new SplineOverScroller();
-        mScrollerY = new SplineOverScroller();
-
-        SplineOverScroller.initFromContext(context);
-
-        mScrollerX.setBounceCoefficient(bounceCoefficientX);
-        mScrollerY.setBounceCoefficient(bounceCoefficientY);
+        this(context, interpolator, flywheel);
     }
 
     /**
@@ -155,7 +167,7 @@
 
     /**
      * @hide
-     * Returns the current velocity.
+     * Returns the absolute value of the current velocity.
      *
      * @return The original velocity less the deceleration, norm of the X and Y velocity vector.
      */
@@ -484,9 +496,9 @@
      */
     public boolean isOverScrolled() {
         return ((!mScrollerX.mFinished &&
-                mScrollerX.mState != SplineOverScroller.TO_EDGE) ||
+                mScrollerX.mState != SplineOverScroller.SPLINE) ||
                 (!mScrollerY.mFinished &&
-                        mScrollerY.mState != SplineOverScroller.TO_EDGE));
+                        mScrollerY.mState != SplineOverScroller.SPLINE));
     }
 
     /**
@@ -564,11 +576,8 @@
         // Fling friction
         private float mFlingFriction = ViewConfiguration.getScrollFriction();
 
-        // Proportion of velocity preserved at the end of a bounce animation.
-        private float mBounceCoefficient = DEFAULT_BOUNCE_COEFFICIENT;
-
         // Current state of the animation.
-        private int mState = TO_EDGE;
+        private int mState = SPLINE;
 
         // Constant gravity value, used in the deceleration phase.
         private static final float GRAVITY = 2000.0f;
@@ -577,9 +586,9 @@
         private static float PHYSICAL_COEF;
 
         private static float DECELERATION_RATE = (float) (Math.log(0.75) / Math.log(0.9));
-        private static final float INFLEXION = 0.3f; // Tension lines cross at (INFLEXION, 1)
-        private static final float START_TENSION = 0.7f;
-        private static final float END_TENSION = 0.8f;
+        private static final float INFLEXION = 0.4f; // Tension lines cross at (INFLEXION, 1)
+        private static final float START_TENSION = 1.0f;
+        private static final float END_TENSION = 0.6666f;
         private static final float P1 = START_TENSION * INFLEXION;
         private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
 
@@ -587,16 +596,9 @@
         private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
         private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
 
-        private static final int TO_EDGE = 0;
-        private static final int TO_BOUNDARY = 1;
-        private static final int TO_BOUNCE = 2;
-
-        // If the velocity is smaller than this value, no bounce is triggered
-        // when the edge limits are reached.
-        private static final float MINIMUM_VELOCITY_FOR_BOUNCE = Float.MAX_VALUE;//140.0f;
-
-        // Proportion of the velocity that is preserved when the edge is reached.
-        private static final float DEFAULT_BOUNCE_COEFFICIENT = 0.16f;
+        private static final int SPLINE = 0;
+        private static final int CUBIC = 1;
+        private static final int BALLISTIC = 2;
 
         static {
             float x_min = 0.0f;
@@ -711,10 +713,6 @@
             mFinished = false;
         }
 
-        void setBounceCoefficient(float coefficient) {
-            mBounceCoefficient = coefficient;
-        }
-
         boolean springback(int start, int min, int max) {
             mFinished = true;
 
@@ -734,13 +732,17 @@
         }
 
         private void startSpringback(int start, int end, int velocity) {
+            // mStartTime has been set
             mFinished = false;
-            mState = TO_BOUNCE;
-            mStart = mFinal = end;
-            final float velocitySign = Math.signum(start - end);
-            mDeceleration = getDeceleration((int) velocitySign);
-            fitOnBounceCurve(start, end, velocity);
-            mDuration = - (int) (2000.0f * mVelocity / mDeceleration);
+            mState = CUBIC;
+            mStart = start;
+            mFinal = end;
+            final int delta = start - end;
+            mDeceleration = getDeceleration(delta);
+            // TODO take velocity into account
+            mVelocity = -delta; // only sign is used
+            mOver = Math.abs(delta);
+            mDuration = (int) (1000.0 * Math.sqrt(-2.0 * delta / mDeceleration));
         }
 
         void fling(int start, int velocity, int min, int max, int over) {
@@ -756,7 +758,7 @@
                 return;
             }
 
-            mState = TO_EDGE;
+            mState = SPLINE;
             double totalDistance = 0.0;
 
             if (velocity != 0) {
@@ -838,41 +840,41 @@
         }
 
         void notifyEdgeReached(int start, int end, int over) {
-            if (mState == TO_EDGE) {
+            // mState is used to detect successive notifications 
+            if (mState == SPLINE) {
                 mOver = over;
                 mStartTime = AnimationUtils.currentAnimationTimeMillis();
                 // We were in fling/scroll mode before: current velocity is such that distance to
-                // edge is increasing. Ensures that startAfterEdge will not start a new fling.
+                // edge is increasing. This ensures that startAfterEdge will not start a new fling.
                 startAfterEdge(start, end, end, (int) mCurrVelocity);
             }
         }
 
         private void onEdgeReached() {
             // mStart, mVelocity and mStartTime were adjusted to their values when edge was reached.
-            final float distance = - mVelocity * mVelocity / (2.0f * mDeceleration);
+            float distance = mVelocity * mVelocity / (2.0f * Math.abs(mDeceleration));
+            final float sign = Math.signum(mVelocity);
 
-            if (Math.abs(distance) < mOver) {
-                // Spring force will bring us back to final position
-                mState = TO_BOUNCE;
-                mFinal = mStart;
-                mDuration = - (int) (2000.0f * mVelocity / mDeceleration);
-            } else {
-                // Velocity is too high, we will hit the boundary limit
-                mState = TO_BOUNDARY;
-                int over = mVelocity > 0 ? mOver : -mOver;
-                mFinal = mStart + over;
-                mDuration = (int) (1000.0 * Math.PI * over / 2.0 / mVelocity);
+            if (distance > mOver) {
+                // Default deceleration is not sufficient to slow us down before boundary
+                 mDeceleration = - sign * mVelocity * mVelocity / (2.0f * mOver);
+                 distance = mOver;
             }
+
+            mOver = (int) distance;
+            mState = BALLISTIC;
+            mFinal = mStart + (int) (mVelocity > 0 ? distance : -distance);
+            mDuration = - (int) (1000.0f * mVelocity / mDeceleration);
         }
 
         boolean continueWhenFinished() {
             switch (mState) {
-                case TO_EDGE:
+                case SPLINE:
                     // Duration from start to null velocity
                     if (mDuration < mSplineDuration) {
                         // If the animation was clamped, we reached the edge
                         mStart = mFinal;
-                        // Speed when edge was reached
+                        // TODO Better compute speed when edge was reached
                         mVelocity = (int) mCurrVelocity;
                         mDeceleration = getDeceleration(mVelocity);
                         mStartTime += mDuration;
@@ -882,18 +884,12 @@
                         return false;
                     }
                     break;
-                case TO_BOUNDARY:
+                case BALLISTIC:
                     mStartTime += mDuration;
-                    startSpringback(mFinal, mFinal - (mVelocity > 0 ? mOver:-mOver), 0);
+                    startSpringback(mFinal, mStart, 0);
                     break;
-                case TO_BOUNCE:
-                    mVelocity = (int) (mVelocity * mBounceCoefficient);
-                    if (Math.abs(mVelocity) < MINIMUM_VELOCITY_FOR_BOUNCE) {
-                        return false;
-                    }
-                    mStartTime += mDuration;
-                    mDuration = - (int) (mVelocity / mDeceleration);
-                    break;
+                case CUBIC:
+                    return false;
             }
 
             update();
@@ -915,7 +911,7 @@
 
             double distance = 0.0;
             switch (mState) {
-                case TO_EDGE: {
+                case SPLINE: {
                     final float t = (float) currentTime / mSplineDuration;
                     final int index = (int) (NB_SAMPLES * t);
                     float distanceCoef = 1.f;
@@ -930,22 +926,23 @@
                     }
 
                     distance = distanceCoef * mSplineDistance;
-                    mCurrVelocity = velocityCoef * mSplineDistance / mSplineDuration * 1000;
+                    mCurrVelocity = velocityCoef * mSplineDistance / mSplineDuration * 1000.0f;
                     break;
                 }
 
-                case TO_BOUNCE: {
+                case BALLISTIC: {
                     final float t = currentTime / 1000.0f;
                     mCurrVelocity = mVelocity + mDeceleration * t;
                     distance = mVelocity * t + mDeceleration * t * t / 2.0f;
                     break;
                 }
 
-                case TO_BOUNDARY: {
-                    final float t = currentTime / 1000.0f;
-                    final float d = t * Math.abs(mVelocity) / mOver;
-                    mCurrVelocity = mVelocity * (float) Math.cos(d);
-                    distance = (mVelocity > 0 ? mOver : -mOver) * Math.sin(d);
+                case CUBIC: {
+                    final float t = (float) (currentTime) / mDuration;
+                    final float t2 = t * t;
+                    final float sign = Math.signum(mVelocity);
+                    distance = sign * mOver * (3.0f * t2 - 2.0f * t * t2); 
+                    mCurrVelocity = sign * mOver * 6.0f * (- t + t2); 
                     break;
                 }
             }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d6e5974..1dbb03d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3944,6 +3944,15 @@
         if (mBlink != null) {
             mBlink.cancel();
         }
+
+        if (mInsertionPointCursorController != null) {
+            mInsertionPointCursorController.onDetached();
+        }
+
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.onDetached();
+        }
+
         hideControllers();
     }
 
@@ -8291,6 +8300,13 @@
          * @param event The touch event
          */
         public boolean onTouchEvent(MotionEvent event);
+
+        /**
+         * Called when the view is detached from window. Perform house keeping task, such as
+         * stopping Runnable thread that would otherwise keep a reference on the context, thus
+         * preventing the activity to be recycled.
+         */
+        public void onDetached();
     }
 
     private class PastePopupMenu implements OnClickListener {
@@ -8413,7 +8429,7 @@
         private long mTouchTimer;
         private boolean mIsInsertionHandle = false;
         private PastePopupMenu mPastePopupWindow;
-        private LongPressCallback mLongPressCallback;
+        private Runnable mLongPressCallback;
 
         public static final int LEFT = 0;
         public static final int CENTER = 1;
@@ -8643,7 +8659,12 @@
                 if (mIsInsertionHandle) {
                     mTouchTimer = SystemClock.uptimeMillis();
                     if (mLongPressCallback == null) {
-                        mLongPressCallback = new LongPressCallback();
+                        mLongPressCallback = new Runnable() {
+                            public void run() {
+                                mController.hide();
+                                startSelectionActionMode();
+                            }
+                        };
                     }
                     postDelayed(mLongPressCallback, ViewConfiguration.getLongPressTimeout());
                 }
@@ -8663,7 +8684,7 @@
                     final float dy = rawY - mDownPositionY;
                     final float distanceSquared = dx * dx + dy * dy;
                     if (distanceSquared >= mSquaredTouchSlopDistance) {
-                        removeCallbacks(mLongPressCallback);
+                        removeLongPressCallback();
                     }
                 }
                 break;
@@ -8671,7 +8692,7 @@
 
             case MotionEvent.ACTION_UP:
                 if (mIsInsertionHandle) {
-                    removeCallbacks(mLongPressCallback);
+                    removeLongPressCallback();
                     long delay = SystemClock.uptimeMillis() - mTouchTimer;
                     if (delay < ViewConfiguration.getTapTimeout()) {
                         if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) {
@@ -8687,7 +8708,7 @@
 
             case MotionEvent.ACTION_CANCEL:
                 if (mIsInsertionHandle) {
-                    removeCallbacks(mLongPressCallback);
+                    removeLongPressCallback();
                 }
                 mIsDragging = false;
             }
@@ -8726,6 +8747,16 @@
                 mPastePopupWindow.show();
             }
         }
+
+        private void removeLongPressCallback() {
+            if (mLongPressCallback != null) {
+                removeCallbacks(mLongPressCallback);
+            }
+        }
+
+        void onDetached() {
+            removeLongPressCallback();
+        }
     }
 
     private class InsertionPointCursorController implements CursorController {
@@ -8735,18 +8766,8 @@
 
         // The cursor controller image. Lazily created.
         private HandleView mHandle;
-
-        private final Runnable mHider = new Runnable() {
-            public void run() {
-                hide();
-            }
-        };
-
-        private final Runnable mPastePopupShower = new Runnable() {
-            public void run() {
-                getHandle().showPastePopupWindow();
-            }
-        };
+        private Runnable mHider;
+        private Runnable mPastePopupShower;
 
         public void show() {
             show(DELAY_BEFORE_PASTE);
@@ -8756,25 +8777,52 @@
             updatePosition();
             hideDelayed();
             getHandle().show();
-            removeCallbacks(mPastePopupShower);
+            removePastePopupCallback();
             if (canPaste()) {
                 final long durationSinceCutOrCopy = SystemClock.uptimeMillis() - sLastCutOrCopyTime;
-                if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION)
+                if (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION) {
                     delayBeforePaste = 0;
+                }
+                if (mPastePopupShower == null) {
+                    mPastePopupShower = new Runnable() {
+                        public void run() {
+                            getHandle().showPastePopupWindow();
+                        }
+                    };
+                }
                 postDelayed(mPastePopupShower, delayBeforePaste);
             }
         }
 
+        private void removePastePopupCallback() {
+            if (mPastePopupShower != null) {
+                removeCallbacks(mPastePopupShower);
+            }
+        }
+
+        private void removeHiderCallback() {
+            if (mHider != null) {
+                removeCallbacks(mHider);
+            }
+        }
+
         public void hide() {
             if (mHandle != null) {
                 mHandle.hide();
             }
-            removeCallbacks(mHider);
-            removeCallbacks(mPastePopupShower);
+            removeHiderCallback();
+            removePastePopupCallback();
         }
 
         private void hideDelayed() {
-            removeCallbacks(mHider);
+            removeHiderCallback();
+            if (mHider == null) {
+                mHider = new Runnable() {
+                    public void run() {
+                        hide();
+                    }
+                };
+            }
             postDelayed(mHider, DELAY_BEFORE_FADE_OUT);
         }
 
@@ -8822,6 +8870,15 @@
             }
             return mHandle;
         }
+
+        @Override
+        public void onDetached() {
+            removeHiderCallback();
+            removePastePopupCallback();
+            if (mHandle != null) {
+                mHandle.onDetached();
+            }
+        }
     }
 
     private class SelectionModifierCursorController implements CursorController {
@@ -9013,6 +9070,9 @@
                 hide();
             }
         }
+
+        @Override
+        public void onDetached() {}
     }
 
     private void hideInsertionPointCursorController() {
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 3e19811..3a58867 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -26,6 +26,7 @@
 import android.animation.Animator.AnimatorListener;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
@@ -41,6 +42,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.Window;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import android.widget.SpinnerAdapter;
@@ -91,6 +93,8 @@
 
     private Animator mCurrentAnim;
 
+    private static final TimeInterpolator sFadeOutInterpolator = new DecelerateInterpolator();
+
     final AnimatorListener[] mAfterAnimation = new AnimatorListener[] {
             new AnimatorListener() { // NORMAL_VIEW
                 @Override
@@ -166,6 +170,7 @@
         @Override
         public void onAnimationEnd(Animator animation) {
             mCurrentAnim = null;
+            mContainerView.requestLayout();
         }
 
         @Override
@@ -321,7 +326,7 @@
     }
 
     public void setBackgroundDrawable(Drawable d) {
-        mActionView.setBackgroundDrawable(d);
+        mContainerView.setBackgroundDrawable(d);
     }
 
     public View getCustomNavigationView() {
@@ -492,12 +497,12 @@
 
     @Override
     public void show() {
-        if (mCurrentAnim != null) {
-            mCurrentAnim.end();
-        }
         if (mContainerView.getVisibility() == View.VISIBLE) {
             return;
         }
+        if (mCurrentAnim != null) {
+            mCurrentAnim.end();
+        }
         mContainerView.setVisibility(View.VISIBLE);
         mContainerView.setAlpha(0);
         mContainerView.setTranslationY(-mContainerView.getHeight());
@@ -545,10 +550,6 @@
         final View targetChild = mContainerView.getChildAt(viewIndex);
         targetChild.setVisibility(View.VISIBLE);
         AnimatorSet.Builder b = set.play(ObjectAnimator.ofFloat(targetChild, "alpha", 1));
-        if (viewIndex == NORMAL_VIEW) {
-            targetChild.setScaleY(0);
-            b.with(ObjectAnimator.ofFloat(targetChild, "scaleY", 1));
-        }
 
         final int count = mContainerView.getChildCount();
         for (int i = 0; i < count; i++) {
@@ -558,11 +559,9 @@
             }
 
             if (child.getVisibility() != View.GONE) {
-                ObjectAnimator a = ObjectAnimator.ofFloat(child, "alpha", 0);
+                Animator a = ObjectAnimator.ofFloat(child, "alpha", 0);
+                a.setInterpolator(sFadeOutInterpolator);
                 b.with(a);
-                if (viewIndex == CONTEXT_VIEW) {
-                    b.with(ObjectAnimator.ofFloat(child, "scaleY", 0));
-                }
             }
         }
 
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
new file mode 100644
index 0000000..e520e69
--- /dev/null
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * This class acts as a container for the action bar view and action mode context views.
+ * It applies special styles as needed to help handle animated transitions between them.
+ * @hide
+ */
+public class ActionBarContainer extends FrameLayout {
+    public ActionBarContainer(Context context) {
+        this(context, null);
+    }
+
+    public ActionBarContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.ActionBar);
+        setBackgroundDrawable(a.getDrawable(com.android.internal.R.styleable.ActionBar_background));
+        a.recycle();
+    }
+}
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 6d4c6bd..60c3487 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -159,15 +159,13 @@
     }
 
     public void initForMode(final ActionMode mode) {
-        if (mCurrentAnimation != null && mCurrentAnimation.isRunning()) {
-            mCurrentAnimation.end();
-            killMode();
-        }
+        finishAnimation();
+
         if (mClose == null) {
             LayoutInflater inflater = LayoutInflater.from(mContext);
             mClose = inflater.inflate(R.layout.action_mode_close_item, this, false);
             addView(mClose);
-        } else {
+        } else if (mClose.getParent() == null) {
             addView(mClose);
         }
 
@@ -188,6 +186,10 @@
     }
 
     public void closeMode() {
+        if (mAnimationMode == ANIMATE_OUT) {
+            // Called again during close; just finish what we were doing.
+            return;
+        }
         if (mClose == null) {
             killMode();
             return;
@@ -200,8 +202,10 @@
     }
 
     private void finishAnimation() {
-        if (mCurrentAnimation != null && mCurrentAnimation.isRunning()) {
-            mCurrentAnimation.end();
+        final Animator a = mCurrentAnimation;
+        if (a != null && a.isRunning()) {
+            mCurrentAnimation = null;
+            a.end();
         }
     }
 
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 931bea9..ccec32a 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -183,11 +183,6 @@
         mHomeAsUpView = mHomeLayout.findViewById(com.android.internal.R.id.up);
         mIconView = (ImageView) mHomeLayout.findViewById(com.android.internal.R.id.home);
         
-        Drawable background = a.getDrawable(R.styleable.ActionBar_background);
-        if (background != null) {
-            setBackgroundDrawable(background);
-        }
-        
         mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
         mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
         mProgressStyle = a.getResourceId(R.styleable.ActionBar_progressBarStyle, 0);
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index ee07d4b..164b357 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -225,6 +225,9 @@
     if (javaBitmap == NULL) {
         bitmap = new SkBitmap;
     } else {
+        if (sampleSize != 1) {
+            return nullObjectReturn("SkImageDecoder: Cannot reuse bitmap with sampleSize != 1");
+        }
         bitmap = (SkBitmap *) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID);
         // config of supplied bitmap overrules config set in options
         prefConfig = bitmap->getConfig();
@@ -232,7 +235,7 @@
     Res_png_9patch      dummy9Patch;
 
     SkAutoTDelete<SkImageDecoder>   add(decoder);
-    SkAutoTDelete<SkBitmap>         adb(bitmap);
+    SkAutoTDelete<SkBitmap>         adb(bitmap, (javaBitmap == NULL));
 
     decoder->setPeeker(&peeker);
     if (!isPurgeable) {
diff --git a/core/res/res/layout-xlarge/screen_action_bar.xml b/core/res/res/layout-xlarge/screen_action_bar.xml
index 5aae733..751d322 100644
--- a/core/res/res/layout-xlarge/screen_action_bar.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar.xml
@@ -21,9 +21,10 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:fitsSystemWindows="true">
-    <FrameLayout android:id="@+id/action_bar_container"
+    <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        style="?android:attr/actionBarStyle">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
             android:layout_width="match_parent"
@@ -35,7 +36,7 @@
             android:layout_height="wrap_content"
             android:visibility="gone"
             style="?android:attr/actionModeStyle" />
-    </FrameLayout>
+    </com.android.internal.widget.ActionBarContainer>
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="0dip"
diff --git a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
index 11e0eac..89f0d89 100644
--- a/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
+++ b/core/res/res/layout-xlarge/screen_action_bar_overlay.xml
@@ -24,9 +24,10 @@
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
-    <FrameLayout android:id="@+id/action_bar_container"
+    <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        style="?android:attr/actionBarStyle"
         android:gravity="top">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
@@ -39,7 +40,7 @@
             android:layout_height="wrap_content"
             android:visibility="gone"
             style="?android:attr/actionModeStyle" />
-    </FrameLayout>
+    </com.android.internal.widget.ActionBarContainer>
     <ImageView android:src="?android:attr/windowContentOverlay"
                android:scaleType="fitXY"
                android:layout_width="match_parent"
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index e60a7e3..70af265 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -21,9 +21,10 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:fitsSystemWindows="true">
-    <FrameLayout android:id="@+id/action_bar_container"
+    <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        style="?android:attr/actionBarStyle">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
             android:layout_width="match_parent"
@@ -35,7 +36,7 @@
             android:layout_height="wrap_content"
             android:visibility="gone"
             style="?android:attr/actionModeStyle" />
-    </FrameLayout>
+    </com.android.internal.widget.ActionBarContainer>
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent" 
         android:layout_height="0dip"
diff --git a/core/res/res/layout/screen_action_bar_overlay.xml b/core/res/res/layout/screen_action_bar_overlay.xml
index 47d87a9..b486ee7 100644
--- a/core/res/res/layout/screen_action_bar_overlay.xml
+++ b/core/res/res/layout/screen_action_bar_overlay.xml
@@ -24,9 +24,10 @@
     <FrameLayout android:id="@android:id/content"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
-    <FrameLayout android:id="@+id/action_bar_container"
+    <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        style="?android:attr/actionBarStyle"
         android:gravity="top">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
@@ -39,7 +40,7 @@
             android:layout_height="wrap_content"
             android:visibility="gone"
             style="?android:attr/actionModeStyle" />
-    </FrameLayout>
+    </com.android.internal.widget.ActionBarContainer>
     <ImageView android:src="?android:attr/windowContentOverlay"
                android:scaleType="fitXY"
                android:layout_width="match_parent"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index f399578..181bbcc 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -520,15 +520,20 @@
         <attr name="dayPickerWeekDayViewStyle" format="reference" />
 
         <!-- Fast scroller styles -->
-        <!-- @hide -->
+        <eat-comment />
+
+        <!-- Drawable to use as the fast scroll thumb. -->
         <attr name="fastScrollThumbDrawable" format="reference" />
-        <!-- @hide -->
+        <!-- Drawable to use as the fast scroll index preview window background
+             when shown on the right. -->
         <attr name="fastScrollPreviewBackgroundRight" format="reference" />
-        <!-- @hide -->
+        <!-- Drawable to use as the fast scroll index preview window background
+             when shown on the left. -->
         <attr name="fastScrollPreviewBackgroundLeft" format="reference" />
-        <!-- @hide -->
+        <!-- Drawable to use as the track for the fast scroll thumb.
+             This may be null. -->
         <attr name="fastScrollTrackDrawable" format="reference" />
-        <!-- @hide -->
+        <!-- Position of the fast scroll index overlay window. -->
         <attr name="fastScrollOverlayPosition">
             <enum name="floating" value="0" />
             <enum name="atThumb" value="1" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index af0e866..5d03638 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -105,6 +105,16 @@
          removable. -->
     <bool name="config_externalStorageRemovable" product="default">true</bool>
 
+    <!-- Number of megabytes of space to leave unallocated by MTP.
+         MTP will subtract this value from the free space it reports back
+         to the host via GetStorageInfo, and will not allow new files to
+         be added via MTP if there is less than this amount left free in the storage.
+         If MTP has dedicated storage this value should be zero, but if MTP is
+         sharing storage with the rest of the system, set this to a positive value
+         to ensure that MTP activity does not result in the storage being
+         too close to full. -->
+    <integer name="config_mtpReserveSpaceMegabytes">0</integer>
+
     <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
          Please don't copy them, copy anything else. -->
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1f9cb6d..6c76f57 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1403,6 +1403,10 @@
   <public type="attr" name="isAlwaysSyncable" />
   <public type="attr" name="verticalScrollbarPosition" />
   <public type="attr" name="fastScrollAlwaysVisible" />
+  <public type="attr" name="fastScrollThumbDrawable" />
+  <public type="attr" name="fastScrollPreviewBackgroundLeft" />
+  <public type="attr" name="fastScrollTrackDrawable" />
+  <public type="attr" name="fastScrollOverlayPosition" />
 
   <public type="anim" name="animator_fade_in" />
   <public type="anim" name="animator_fade_out" />
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index f6a9c63..fe723f2 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -44,10 +44,11 @@
 
         /**
          * If set, decode methods that take the Options object will attempt to
-         * reuse this bitmap when loading content. This is a hint to the decoder
-         * only, and the decoder may choose to create a new Bitmap instead. The
+         * reuse this bitmap when loading content. If the decode operation cannot
+         * use this bitmap, the decode method will return <code>null</code> and
+         * will throw an IllegalArgumentException. The
          * current implementation necessitates that the reused bitmap be of the
-         * same size as the source content and in jpeg format (whether as a
+         * same size as the source content and in jpeg or png format (whether as a
          * resource or as a stream). The {@link android.graphics.Bitmap.Config
          * configuration} of the reused bitmap will override the setting of
          * {@link #inPreferredConfig}, if set.
@@ -389,6 +390,10 @@
             }
         }
 
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
+
         return bm;
     }
 
@@ -421,7 +426,11 @@
         if ((offset | length) < 0 || data.length < offset + length) {
             throw new ArrayIndexOutOfBoundsException();
         }
-        return nativeDecodeByteArray(data, offset, length, opts);
+        Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
+        return bm;
     }
 
     /**
@@ -488,6 +497,9 @@
             if (tempStorage == null) tempStorage = new byte[16 * 1024];
             bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
         }
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
 
         return finishDecode(bm, outPadding, opts);
     }
@@ -558,6 +570,9 @@
      */
     public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
         Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
+        if (bm == null && opts != null && opts.inBitmap != null) {
+            throw new IllegalArgumentException("Problem decoding into existing bitmap");
+        }
         return finishDecode(bm, outPadding, opts);
     }
 
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 97d513a..b937721 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -55,13 +55,13 @@
         }
     }
 
-    public enum MipmapGenerationControl {
+    public enum MipmapControl {
         MIPMAP_NONE(0),
         MIPMAP_FULL(1),
         MIPMAP_ON_SYNC_TO_TEXTURE(2);
 
         int mID;
-        MipmapGenerationControl(int id) {
+        MipmapControl(int id) {
             mID = id;
         }
     }
@@ -131,6 +131,14 @@
         subData1D(0, mType.getCount(), i);
     }
 
+    private void validateBitmap(Bitmap b) {
+        mRS.validate();
+        if(mType.getX() != b.getWidth() ||
+           mType.getY() != b.getHeight()) {
+            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
+        }
+    }
+
     public void copyFrom(int[] d) {
         mRS.validate();
         subData1D(0, mType.getCount(), d);
@@ -147,18 +155,17 @@
         mRS.validate();
         subData1D(0, mType.getCount(), d);
     }
-
     public void copyFrom(Bitmap b) {
-
-        mRS.validate();
-        if(mType.getX() != b.getWidth() ||
-           mType.getY() != b.getHeight()) {
-            throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch");
-        }
-
-        mRS.nAllocationUpdateFromBitmap(getID(), b);
+        validateBitmap(b);
+        mRS.nAllocationCopyFromBitmap(getID(), b);
     }
 
+    public void copyTo(Bitmap b) {
+        validateBitmap(b);
+        mRS.nAllocationCopyToBitmap(getID(), b);
+    }
+
+
     public void subData(int xoff, FieldPacker fp) {
         int eSize = mType.mElement.getSizeBytes();
         final byte[] data = fp.getData();
@@ -423,17 +430,17 @@
     }
 
     static private Type typeFromBitmap(RenderScript rs, Bitmap b,
-                                       MipmapGenerationControl mip) {
+                                       MipmapControl mip) {
         Element e = elementFromBitmap(rs, b);
         Type.Builder tb = new Type.Builder(rs, e);
         tb.setX(b.getWidth());
         tb.setY(b.getHeight());
-        tb.setMipmaps(mip == MipmapGenerationControl.MIPMAP_FULL);
+        tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL);
         return tb.create();
     }
 
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
-                                              MipmapGenerationControl mips,
+                                              MipmapControl mips,
                                               int usage) {
         rs.validate();
         Type t = typeFromBitmap(rs, b, mips);
@@ -447,15 +454,15 @@
 
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
                                               Element dstFmt, boolean genMips) {
-        MipmapGenerationControl mc = MipmapGenerationControl.MIPMAP_NONE;
+        MipmapControl mc = MipmapControl.MIPMAP_NONE;
         if (genMips) {
-            mc = MipmapGenerationControl.MIPMAP_ON_SYNC_TO_TEXTURE;
+            mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE;
         }
         return createFromBitmap(rs, b, mc, USAGE_ALL);
     }
 
     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
-                                                     MipmapGenerationControl mips,
+                                                     MipmapControl mips,
                                                      CubemapLayout layout,
                                                      int usage) {
         rs.validate();
@@ -482,7 +489,7 @@
         tb.setX(width);
         tb.setY(width);
         tb.setFaces(true);
-        tb.setMipmaps(mips == MipmapGenerationControl.MIPMAP_FULL);
+        tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
         Type t = tb.create();
 
         int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage);
@@ -496,33 +503,17 @@
                                                      Element dstFmt,
                                                      boolean genMips,
                                                      CubemapLayout layout) {
-        MipmapGenerationControl mc = MipmapGenerationControl.MIPMAP_NONE;
+        MipmapControl mc = MipmapControl.MIPMAP_NONE;
         if (genMips) {
-            mc = MipmapGenerationControl.MIPMAP_ON_SYNC_TO_TEXTURE;
+            mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE;
         }
         return createCubemapFromBitmap(rs, b, mc, layout, USAGE_ALL);
     }
 
-
-    static public Allocation createBitmapRef(RenderScript rs, Bitmap b) {
-
-        rs.validate();
-        Type t = typeFromBitmap(rs, b, MipmapGenerationControl.MIPMAP_NONE);
-
-        int id = rs.nAllocationCreateBitmapRef(t.getID(), b);
-        if(id == 0) {
-            throw new RSRuntimeException("Load failed.");
-        }
-
-        Allocation a = new Allocation(id, rs, t, USAGE_SCRIPT);
-        a.mBitmap = b;
-        return a;
-    }
-
     static public Allocation createFromBitmapResource(RenderScript rs,
                                                       Resources res,
                                                       int id,
-                                                      MipmapGenerationControl mips,
+                                                      MipmapControl mips,
                                                       int usage) {
 
         rs.validate();
@@ -537,9 +528,9 @@
                                                       int id,
                                                       Element dstFmt,
                                                       boolean genMips) {
-        MipmapGenerationControl mc = MipmapGenerationControl.MIPMAP_NONE;
+        MipmapControl mc = MipmapControl.MIPMAP_NONE;
         if (genMips) {
-            mc = MipmapGenerationControl.MIPMAP_ON_SYNC_TO_TEXTURE;
+            mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE;
         }
         return createFromBitmapResource(rs, res, id, mc, USAGE_ALL);
     }
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 7e89a56..7616316 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -654,17 +654,5 @@
             return new Element(id, mRS, ein, sin, asin);
         }
     }
-
-    static void initPredefined(RenderScript rs) {
-        int a8 = rs.nElementCreate(DataType.UNSIGNED_8.mID,
-                                   DataKind.PIXEL_A.mID, true, 1);
-        int rgba4444 = rs.nElementCreate(DataType.UNSIGNED_4_4_4_4.mID,
-                                         DataKind.PIXEL_RGBA.mID, true, 4);
-        int rgba8888 = rs.nElementCreate(DataType.UNSIGNED_8.mID,
-                                         DataKind.PIXEL_RGBA.mID, true, 4);
-        int rgb565 = rs.nElementCreate(DataType.UNSIGNED_5_6_5.mID,
-                                       DataKind.PIXEL_RGB.mID, true, 3);
-        rs.nInitElements(a8, rgba4444, rgba8888, rgb565);
-    }
 }
 
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index e3a9a67..3fa9965 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -65,7 +65,6 @@
     }
 
     // Non-threadsafe functions.
-    native void nInitElements(int a8, int rgba4444, int rgba8888, int rgb565);
     native int  nDeviceCreate();
     native void nDeviceDestroy(int dev);
     native void nDeviceSetConfig(int dev, int param, int value);
@@ -213,13 +212,19 @@
         return rsnAllocationCreateFromAssetStream(mContext, mips, assetStream, usage);
     }
 
+    native void  rsnAllocationCopyToBitmap(int con, int alloc, Bitmap bmp);
+    synchronized void nAllocationCopyToBitmap(int alloc, Bitmap bmp) {
+        rsnAllocationCopyToBitmap(mContext, alloc, bmp);
+    }
+
+
     native void rsnAllocationSyncAll(int con, int alloc, int src);
     synchronized void nAllocationSyncAll(int alloc, int src) {
         rsnAllocationSyncAll(mContext, alloc, src);
     }
-    native void  rsnAllocationUpdateFromBitmap(int con, int alloc, Bitmap bmp);
-    synchronized void nAllocationUpdateFromBitmap(int alloc, Bitmap bmp) {
-        rsnAllocationUpdateFromBitmap(mContext, alloc, bmp);
+    native void  rsnAllocationCopyFromBitmap(int con, int alloc, Bitmap bmp);
+    synchronized void nAllocationCopyFromBitmap(int alloc, Bitmap bmp) {
+        rsnAllocationCopyFromBitmap(mContext, alloc, bmp);
     }
 
     native void rsnAllocationUploadToTexture(int con, int alloc, boolean genMips, int baseMioLevel);
@@ -787,7 +792,6 @@
         rs.mContext = rs.nContextCreate(rs.mDev, 0);
         rs.mMessageThread = new MessageThread(rs);
         rs.mMessageThread.start();
-        Element.initPredefined(rs);
         return rs;
     }
 
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
index 4a1c40a..0886db4 100644
--- a/graphics/java/android/renderscript/RenderScriptGL.java
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -190,7 +190,6 @@
         }
         mMessageThread = new MessageThread(this);
         mMessageThread.start();
-        Element.initPredefined(this);
     }
 
     /**
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 65acf93..8344842 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -59,11 +59,6 @@
 static jfieldID gNativeBitmapID = 0;
 static jfieldID gTypeNativeCache = 0;
 
-static RsElement g_A_8 = NULL;
-static RsElement g_RGBA_4444 = NULL;
-static RsElement g_RGBA_8888 = NULL;
-static RsElement g_RGB_565 = NULL;
-
 static void _nInit(JNIEnv *_env, jclass _this)
 {
     gContextId             = _env->GetFieldID(_this, "mContext", "I");
@@ -72,14 +67,6 @@
     gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "I");
 }
 
-static void nInitElements(JNIEnv *_env, jobject _this, jint a8, jint rgba4444, jint rgba8888, jint rgb565)
-{
-    g_A_8 = reinterpret_cast<RsElement>(a8);
-    g_RGBA_4444 = reinterpret_cast<RsElement>(rgba4444);
-    g_RGBA_8888 = reinterpret_cast<RsElement>(rgba8888);
-    g_RGB_565 = reinterpret_cast<RsElement>(rgb565);
-}
-
 // ---------------------------------------------------------------------------
 
 static void
@@ -415,26 +402,6 @@
     rsAllocationSyncAll(con, (RsAllocation)a, (RsAllocationUsageType)bits);
 }
 
-static RsElement SkBitmapToPredefined(SkBitmap::Config cfg)
-{
-    switch (cfg) {
-    case SkBitmap::kA8_Config:
-        return g_A_8;
-    case SkBitmap::kARGB_4444_Config:
-        return g_RGBA_4444;
-    case SkBitmap::kARGB_8888_Config:
-        return g_RGBA_8888;
-    case SkBitmap::kRGB_565_Config:
-        return g_RGB_565;
-
-    default:
-        break;
-    }
-    // If we don't have a conversion mark it as a user type.
-    LOGE("Unsupported bitmap type");
-    return NULL;
-}
-
 static int
 nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint type, jint mip, jobject jbitmap, jint usage)
 {
@@ -464,20 +431,29 @@
 }
 
 static void
-nAllocationUpdateFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject jbitmap)
+nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject jbitmap)
 {
     SkBitmap const * nativeBitmap =
             (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
     const SkBitmap& bitmap(*nativeBitmap);
-    SkBitmap::Config config = bitmap.getConfig();
 
-    RsElement e = SkBitmapToPredefined(config);
-    if (e) {
-        bitmap.lockPixels();
-        const void* ptr = bitmap.getPixels();
-        rsAllocationUpdateFromBitmap(con, (RsAllocation)alloc, e, ptr);
-        bitmap.unlockPixels();
-    }
+    bitmap.lockPixels();
+    const void* ptr = bitmap.getPixels();
+    rsAllocationCopyFromBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize());
+    bitmap.unlockPixels();
+}
+
+static void
+nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jobject jbitmap)
+{
+    SkBitmap const * nativeBitmap =
+            (SkBitmap const *)_env->GetIntField(jbitmap, gNativeBitmapID);
+    const SkBitmap& bitmap(*nativeBitmap);
+
+    bitmap.lockPixels();
+    void* ptr = bitmap.getPixels();
+    rsAllocationCopyToBitmap(con, (RsAllocation)alloc, ptr, bitmap.getSize());
+    bitmap.unlockPixels();
 }
 
 static void ReleaseBitmapCallback(void *bmp)
@@ -486,44 +462,6 @@
     nativeBitmap->unlockPixels();
 }
 
-static int
-nAllocationCreateBitmapRef(JNIEnv *_env, jobject _this, RsContext con, jint type, jobject jbitmap)
-{
-    SkBitmap * nativeBitmap =
-            (SkBitmap *)_env->GetIntField(jbitmap, gNativeBitmapID);
-
-
-    nativeBitmap->lockPixels();
-    void* ptr = nativeBitmap->getPixels();
-    jint id = (jint)rsAllocationCreateBitmapRef(con, (RsType)type, ptr, nativeBitmap, ReleaseBitmapCallback);
-    return id;
-}
-
-static int
-nAllocationCreateFromAssetStream(JNIEnv *_env, jobject _this, RsContext con, jint dstFmt, jboolean genMips, jint native_asset, jint usage)
-{
-    /*
-    Asset* asset = reinterpret_cast<Asset*>(native_asset);
-    SkBitmap bitmap;
-    SkImageDecoder::DecodeMemory(asset->getBuffer(false), asset->getLength(),
-            &bitmap, SkBitmap::kNo_Config, SkImageDecoder::kDecodePixels_Mode);
-
-    SkBitmap::Config config = bitmap.getConfig();
-
-    RsElement e = SkBitmapToPredefined(config);
-
-    if (e) {
-        bitmap.lockPixels();
-        const int w = bitmap.width();
-        const int h = bitmap.height();
-        const void* ptr = bitmap.getPixels();
-        jint id = (jint)rsaAllocationCreateFromBitmap(con, w, h, (RsElement)dstFmt, e, genMips, ptr, usage);
-        bitmap.unlockPixels();
-        return id;
-    }
-    */
-    return 0;
-}
 
 static void
 nAllocationSubData1D_i(JNIEnv *_env, jobject _this, RsContext con, jint alloc, jint offset, jint count, jintArray data, int sizeBytes)
@@ -1266,7 +1204,6 @@
 
 static JNINativeMethod methods[] = {
 {"_nInit",                         "()V",                                     (void*)_nInit },
-{"nInitElements",                  "(IIII)V",                                 (void*)nInitElements },
 
 {"nDeviceCreate",                  "()I",                                     (void*)nDeviceCreate },
 {"nDeviceDestroy",                 "(I)V",                                    (void*)nDeviceDestroy },
@@ -1311,10 +1248,10 @@
 {"rsnAllocationCreateTyped",         "(III)I",                                (void*)nAllocationCreateTyped },
 {"rsnAllocationCreateFromBitmap",    "(IIILandroid/graphics/Bitmap;I)I",      (void*)nAllocationCreateFromBitmap },
 {"rsnAllocationCubeCreateFromBitmap","(IIILandroid/graphics/Bitmap;I)I",      (void*)nAllocationCubeCreateFromBitmap },
-{"rsnAllocationCreateBitmapRef",     "(IILandroid/graphics/Bitmap;)I",        (void*)nAllocationCreateBitmapRef },
-{"rsnAllocationCreateFromAssetStream","(IIII)I",                              (void*)nAllocationCreateFromAssetStream },
 
-{"rsnAllocationUpdateFromBitmap",    "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationUpdateFromBitmap },
+{"rsnAllocationCopyFromBitmap",      "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyFromBitmap },
+{"rsnAllocationCopyToBitmap",        "(IILandroid/graphics/Bitmap;)V",        (void*)nAllocationCopyToBitmap },
+
 {"rsnAllocationUploadToTexture",     "(IIZI)V",                               (void*)nAllocationUploadToTexture },
 {"rsnAllocationUploadToBufferObject","(II)V",                                 (void*)nAllocationUploadToBufferObject },
 {"rsnAllocationSyncAll",             "(III)V",                                (void*)nAllocationSyncAll },
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index dafc621..a31395e 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -78,31 +78,18 @@
         void clearSeekTo();
         bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
 
-        // Option allows encoder to skip some frames until the specified
-        // time stamp.
-        // To prevent from being abused, when the skipFrame timestamp is
-        // found to be more than 1 second later than the current timestamp,
-        // an error will be returned from read().
-        void clearSkipFrame();
-        bool getSkipFrame(int64_t *timeUs) const;
-        void setSkipFrame(int64_t timeUs);
-
         void setLateBy(int64_t lateness_us);
         int64_t getLateBy() const;
 
     private:
         enum Options {
-            // Bit map
             kSeekTo_Option      = 1,
-            kSkipFrame_Option   = 2,
         };
 
         uint32_t mOptions;
         int64_t mSeekTimeUs;
         SeekMode mSeekMode;
         int64_t mLatenessUs;
-
-        int64_t mSkipFrameUntilTimeUs;
     };
 
     // Causes this source to suspend pulling data from its upstream source
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index d37c22d..bba5b53 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -167,7 +167,6 @@
     int64_t mSeekTimeUs;
     ReadOptions::SeekMode mSeekMode;
     int64_t mTargetTimeUs;
-    int64_t mSkipTimeUs;
 
     MediaBuffer *mLeftOverBuffer;
 
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index 382cbda..693fbfb 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -121,7 +121,8 @@
     virtual status_t captureScreen(DisplayID dpy,
             sp<IMemoryHeap>* heap,
             uint32_t* width, uint32_t* height, PixelFormat* format,
-            uint32_t reqWidth, uint32_t reqHeight) = 0;
+            uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ) = 0;
 
     virtual status_t turnElectronBeamOff(int32_t mode) = 0;
     virtual status_t turnElectronBeamOn(int32_t mode) = 0;
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index a80832d..25b2ebf 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -183,6 +183,8 @@
     // frees the previous screenshot and capture a new one
     status_t update();
     status_t update(uint32_t reqWidth, uint32_t reqHeight);
+    status_t update(uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ);
 
     // release memory occupied by the screenshot
     void release();
diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
index 897b231..4338f33 100644
--- a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java
@@ -129,9 +129,7 @@
     }
 
     public void newTouchPosition(float x, float y, float pressure, int id) {
-        mPhysicsScript.set_touchX(x);
-        mPhysicsScript.set_touchY(y);
-        mPhysicsScript.set_touchPressure(pressure);
+        mPhysicsScript.invoke_touch(x, y, pressure, id);
     }
 
     public void setAccel(float x, float y) {
diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsView.java b/libs/rs/java/Balls/src/com/android/balls/BallsView.java
index 12f017b..4442eec 100644
--- a/libs/rs/java/Balls/src/com/android/balls/BallsView.java
+++ b/libs/rs/java/Balls/src/com/android/balls/BallsView.java
@@ -82,6 +82,7 @@
             int pointerIndex = ev.getActionIndex();
             int pointerId = ev.getPointerId(pointerIndex);
             mRender.newTouchPosition(0, 0, 0, pointerId);
+            return false;
         }
         int count = ev.getHistorySize();
         int pcount = ev.getPointerCount();
diff --git a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs
index 7c86c67..ff38be5 100644
--- a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs
+++ b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs
@@ -8,18 +8,22 @@
 float2 gMinPos = {0.f, 0.f};
 float2 gMaxPos = {1280.f, 700.f};
 
-float touchX;
-float touchY;
-float touchPressure = 0.f;
+static float2 touchPos[10];
+static float touchPressure[10];
 
-void setGamma(float g) {
+void touch(float x, float y, float pressure, int id) {
+    if (id >= 10) {
+        return;
+    }
+
+    touchPos[id].x = x;
+    touchPos[id].y = y;
+    touchPressure[id] = pressure;
 }
 
-
 void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) {
     float2 fv = {0, 0};
     float2 pos = ballIn->position;
-    //rsDebug("physics pos in", pos);
 
     int arcID = -1;
     float arcInvStr = 100000;
@@ -38,10 +42,6 @@
             if (len2 > 16 /* (minDist*minDist)*/)  {
                 // Repulsion
                 float len = sqrt(len2);
-                //if (len < arcInvStr) {
-                    //arcInvStr = len;
-                    //arcID = xin;
-                //}
                 fv -= (vec / (len * len * len)) * 20000.f * forceScale;
             } else {
                 if (len2 < 1) {
@@ -78,12 +78,13 @@
     fv -= gGravityVector * 4.f;
     fv *= ctl->dt;
 
-    if (touchPressure > 0.1f) {
-        float2 tp = {touchX, touchY};
-        float2 vec = tp - ballIn->position;
-        float2 vec2 = vec * vec;
-        float len2 = max(2.f, vec2.x + vec2.y);
-        fv -= (vec / len2) * touchPressure * 400.f;
+    for (int i=0; i < 10; i++) {
+        if (touchPressure[i] > 0.1f) {
+            float2 vec = touchPos[i] - ballIn->position;
+            float2 vec2 = vec * vec;
+            float len2 = max(2.f, vec2.x + vec2.y);
+            fv -= (vec / len2) * touchPressure[i] * 300.f;
+        }
     }
 
     ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv;
@@ -138,11 +139,6 @@
         }
     }
 
-    //ballOut->color.b = 1.f;
-    //ballOut->color.r = min(sqrt(length(ballOut->delta)) * 0.1f, 1.f);
-    //ballOut->color.g = min(sqrt(length(fv) * 0.1f), 1.f);
-    //ballOut->arcID = arcID;
-    //ballOut->arcStr = 8 / arcInvStr;
     ballOut->size = ballIn->size;
 
     //rsDebug("physics pos out", ballOut->position);
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index e935fa9..09654ab 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -283,7 +283,7 @@
             long t = java.lang.System.currentTimeMillis();
             if (true) {
                 mScript.invoke_filter();
-                mRS.finish();
+                mOutPixelsAllocation.copyTo(mBitmapOut);
             } else {
                 javaFilter();
                 mDisplayView.invalidate();
@@ -352,7 +352,7 @@
     public void surfaceCreated(SurfaceHolder holder) {
         createScript();
         mScript.invoke_filter();
-        mRS.finish();
+        mOutPixelsAllocation.copyTo(mBitmapOut);
     }
 
     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
@@ -365,8 +365,12 @@
         mRS = RenderScript.create();
         mRS.setMessageHandler(new FilterCallback());
 
-        mInPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapIn);
-        mOutPixelsAllocation = Allocation.createBitmapRef(mRS, mBitmapOut);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
+                                                           Allocation.MipmapControl.MIPMAP_NONE,
+                                                           Allocation.USAGE_SCRIPT);
 
         Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
         tb.setX(mBitmapIn.getWidth());
@@ -419,7 +423,7 @@
         long t = java.lang.System.currentTimeMillis();
 
         mScript.invoke_filter();
-        mRS.finish();
+        mOutPixelsAllocation.copyTo(mBitmapOut);
 
         t = java.lang.System.currentTimeMillis() - t;
         android.util.Log.v("Img", "Renderscript frame time core ms " + t);
@@ -432,6 +436,6 @@
         mScript.set_radius(mRadius);
 
         mScript.invoke_filter();
-        mRS.finish();
+        mOutPixelsAllocation.copyTo(mBitmapOut);
     }
 }
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 97ecca0..14094c4 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -77,10 +77,16 @@
 	ret RsElement
 	}
 
-AllocationUpdateFromBitmap {
+AllocationCopyFromBitmap {
 	param RsAllocation alloc
-	param RsElement srcFmt
 	param const void * data
+	param size_t dataLen
+	}
+
+AllocationCopyToBitmap {
+	param RsAllocation alloc
+	param void * data
+	param size_t dataLen
 	}
 
 AllocationCreateBitmapRef {
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index f42be0e..10a5caf 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -763,30 +763,42 @@
     return alloc;
 }
 
-void rsi_AllocationUpdateFromBitmap(Context *rsc, RsAllocation va,
-                                    RsElement _src, const void *data) {
+void rsi_AllocationCopyFromBitmap(Context *rsc, RsAllocation va, const void *data, size_t dataLen) {
     Allocation *texAlloc = static_cast<Allocation *>(va);
-    const Element *src = static_cast<const Element *>(_src);
-    const Element *dst = texAlloc->getType()->getElement();
-    uint32_t w = texAlloc->getType()->getDimX();
-    uint32_t h = texAlloc->getType()->getDimY();
-    bool genMips = texAlloc->getType()->getDimLOD();
+    const Type * t = texAlloc->getType();
 
-    ElementConverter_t cvt = pickConverter(dst, src);
-    if (cvt) {
-        cvt(texAlloc->getPtr(), data, w * h);
-        if (genMips) {
-            Adapter2D adapt(rsc, texAlloc);
-            Adapter2D adapt2(rsc, texAlloc);
-            for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
-                adapt.setLOD(lod);
-                adapt2.setLOD(lod + 1);
-                mip(adapt2, adapt);
-            }
-        }
-    } else {
-        rsc->setError(RS_ERROR_BAD_VALUE, "Unsupported bitmap format");
+    uint32_t w = t->getDimX();
+    uint32_t h = t->getDimY();
+    bool genMips = t->getDimLOD();
+    size_t s = w * h * t->getElementSizeBytes();
+    if (s != dataLen) {
+        rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
+        return;
     }
+
+    memcpy(texAlloc->getPtr(), data, s);
+    if (genMips) {
+        Adapter2D adapt(rsc, texAlloc);
+        Adapter2D adapt2(rsc, texAlloc);
+        for (uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+            adapt.setLOD(lod);
+            adapt2.setLOD(lod + 1);
+            mip(adapt2, adapt);
+        }
+    }
+}
+
+void rsi_AllocationCopyToBitmap(Context *rsc, RsAllocation va, void *data, size_t dataLen) {
+    Allocation *texAlloc = static_cast<Allocation *>(va);
+    const Type * t = texAlloc->getType();
+
+    size_t s = t->getDimX() * t->getDimY() * t->getElementSizeBytes();
+    if (s != dataLen) {
+        rsc->setError(RS_ERROR_BAD_VALUE, "Bitmap size didn't match allocation size");
+        return;
+    }
+
+    memcpy(data, texAlloc->getPtr(), s);
 }
 
 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes) {
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index d4edafd..b3dbf11 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -47,7 +47,6 @@
 }
 
 void ScriptC::setupScript(Context *rsc) {
-    setupGLState(rsc);
     mEnviroment.mStartTimeMillis
                 = nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
 
@@ -123,6 +122,7 @@
         return 0;
     }
 
+    setupGLState(rsc);
     setupScript(rsc);
 
     uint32_t ret = 0;
@@ -278,6 +278,7 @@
 
     rsAssert(ain->getType()->getDimZ() == 0);
 
+    setupGLState(rsc);
     setupScript(rsc);
     Script * oldTLS = setTLS(this);
 
@@ -336,7 +337,6 @@
 }
 
 void ScriptC::Invoke(Context *rsc, uint32_t slot, const void *data, uint32_t len) {
-    //LOGE("rsi_ScriptInvoke %i", slot);
     if ((slot >= mEnviroment.mInvokeFunctionCount) ||
         (mEnviroment.mInvokeFunctions[slot] == NULL)) {
         rsc->setError(RS_ERROR_BAD_SCRIPT, "Calling invoke on bad script");
diff --git a/libs/surfaceflinger_client/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
index 969ee79..b8a7a79 100644
--- a/libs/surfaceflinger_client/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -127,13 +127,16 @@
     virtual status_t captureScreen(DisplayID dpy,
             sp<IMemoryHeap>* heap,
             uint32_t* width, uint32_t* height, PixelFormat* format,
-            uint32_t reqWidth, uint32_t reqHeight)
+            uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeInt32(dpy);
         data.writeInt32(reqWidth);
         data.writeInt32(reqHeight);
+        data.writeInt32(minLayerZ);
+        data.writeInt32(maxLayerZ);
         remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
         *heap = interface_cast<IMemoryHeap>(reply.readStrongBinder());
         *width = reply.readInt32();
@@ -231,11 +234,13 @@
             DisplayID dpy = data.readInt32();
             uint32_t reqWidth = data.readInt32();
             uint32_t reqHeight = data.readInt32();
+            uint32_t minLayerZ = data.readInt32();
+            uint32_t maxLayerZ = data.readInt32();
             sp<IMemoryHeap> heap;
             uint32_t w, h;
             PixelFormat f;
             status_t res = captureScreen(dpy, &heap, &w, &h, &f,
-                    reqWidth, reqHeight);
+                    reqWidth, reqHeight, minLayerZ, maxLayerZ);
             reply->writeStrongBinder(heap->asBinder());
             reply->writeInt32(w);
             reply->writeInt32(h);
diff --git a/libs/surfaceflinger_client/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
index f270461..d336724 100644
--- a/libs/surfaceflinger_client/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -555,7 +555,8 @@
     if (s == NULL) return NO_INIT;
     mHeap = 0;
     return s->captureScreen(0, &mHeap,
-            &mWidth, &mHeight, &mFormat, 0, 0);
+            &mWidth, &mHeight, &mFormat, 0, 0,
+            0, -1UL);
 }
 
 status_t ScreenshotClient::update(uint32_t reqWidth, uint32_t reqHeight) {
@@ -563,7 +564,18 @@
     if (s == NULL) return NO_INIT;
     mHeap = 0;
     return s->captureScreen(0, &mHeap,
-            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight);
+            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
+            0, -1UL);
+}
+
+status_t ScreenshotClient::update(uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    if (s == NULL) return NO_INIT;
+    mHeap = 0;
+    return s->captureScreen(0, &mHeap,
+            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
+            minLayerZ, maxLayerZ);
 }
 
 void ScreenshotClient::release() {
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2836005..6d47c44 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -752,6 +752,10 @@
                 mode = mMode;
             }
             if (mode != mMode) {
+
+                // automatically handle audio focus for mode changes
+                handleFocusForCalls(mMode, mode);
+
                 if (AudioSystem.setPhoneState(mode) == AudioSystem.AUDIO_STATUS_OK) {
                     mMode = mode;
 
@@ -807,6 +811,38 @@
         }
     }
 
+    /** pre-condition: oldMode != newMode */
+    private void handleFocusForCalls(int oldMode, int newMode) {
+        // if ringing
+        if (newMode == AudioSystem.MODE_RINGTONE) {
+            // if not ringing silently
+            int ringVolume = AudioService.this.getStreamVolume(AudioManager.STREAM_RING);
+            if (ringVolume > 0) {
+                // request audio focus for the communication focus entry
+                requestAudioFocus(AudioManager.STREAM_RING,
+                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
+                        null, null /* both allowed to be null only for this clientId */,
+                        IN_VOICE_COMM_FOCUS_ID /*clientId*/);
+
+            }
+        }
+        // if entering call
+        else if ((newMode == AudioSystem.MODE_IN_CALL)
+                || (newMode == AudioSystem.MODE_IN_COMMUNICATION)) {
+            // request audio focus for the communication focus entry
+            // (it's ok if focus was already requested during ringing)
+            requestAudioFocus(AudioManager.STREAM_RING,
+                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
+                    null, null /* both allowed to be null only for this clientId */,
+                    IN_VOICE_COMM_FOCUS_ID /*clientId*/);
+        }
+        // if exiting call
+        else if (newMode == AudioSystem.MODE_NORMAL) {
+            // abandon audio focus for communication focus entry
+            abandonAudioFocus(null, IN_VOICE_COMM_FOCUS_ID);
+        }
+    }
+
     /** @see AudioManager#getMode() */
     public int getMode() {
         return mMode;
@@ -2093,28 +2129,11 @@
                 synchronized(mRingingLock) {
                     mIsRinging = true;
                 }
-                int ringVolume = AudioService.this.getStreamVolume(AudioManager.STREAM_RING);
-                if (ringVolume > 0) {
-                    requestAudioFocus(AudioManager.STREAM_RING,
-                                AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
-                                null, null /* both allowed to be null only for this clientId */,
-                                IN_VOICE_COMM_FOCUS_ID /*clientId*/);
-                }
-            } else if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
-                //Log.v(TAG, " CALL_STATE_OFFHOOK");
+            } else if ((state == TelephonyManager.CALL_STATE_OFFHOOK)
+                    || (state == TelephonyManager.CALL_STATE_IDLE)) {
                 synchronized(mRingingLock) {
                     mIsRinging = false;
                 }
-                requestAudioFocus(AudioManager.STREAM_RING,
-                        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
-                        null, null /* both allowed to be null only for this clientId */,
-                        IN_VOICE_COMM_FOCUS_ID /*clientId*/);
-            } else if (state == TelephonyManager.CALL_STATE_IDLE) {
-                //Log.v(TAG, " CALL_STATE_IDLE");
-                synchronized(mRingingLock) {
-                    mIsRinging = false;
-                }
-                abandonAudioFocus(null, IN_VOICE_COMM_FOCUS_ID);
             }
         }
     };
diff --git a/media/java/android/media/MtpServer.java b/media/java/android/media/MtpServer.java
index 7f15276..76e6f3f 100644
--- a/media/java/android/media/MtpServer.java
+++ b/media/java/android/media/MtpServer.java
@@ -30,8 +30,8 @@
         System.loadLibrary("media_jni");
     }
 
-    public MtpServer(MtpDatabase database, String storagePath) {
-        native_setup(database, storagePath);
+    public MtpServer(MtpDatabase database, String storagePath, long reserveSpace) {
+        native_setup(database, storagePath, reserveSpace);
     }
 
     @Override
@@ -66,7 +66,8 @@
     // used by the JNI code
     private int mNativeContext;
 
-    private native final void native_setup(MtpDatabase database, String storagePath);
+    private native final void native_setup(MtpDatabase database, String storagePath,
+            long reserveSpace);
     private native final void native_finalize();
     private native final void native_start();
     private native final void native_stop();
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index bce1241..c08e51b 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -710,7 +710,7 @@
                     break;
                 case MTP_TYPE_STR: {
                     jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
-                    const char *valueStr = env->GetStringUTFChars(value, NULL);
+                    const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
                     if (valueStr) {
                         packet.putString(valueStr);
                         env->ReleaseStringUTFChars(value, valueStr);
diff --git a/media/jni/android_media_MtpServer.cpp b/media/jni/android_media_MtpServer.cpp
index f16cdd9..28a80cb 100644
--- a/media/jni/android_media_MtpServer.cpp
+++ b/media/jni/android_media_MtpServer.cpp
@@ -60,14 +60,17 @@
     MtpDatabase*    mDatabase;
     MtpServer*      mServer;
     String8         mStoragePath;
+    uint64_t        mReserveSpace;
     jobject         mJavaServer;
     int             mFd;
 
 public:
-    MtpThread(MtpDatabase* database, const char* storagePath, jobject javaServer)
+    MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace,
+                jobject javaServer)
         :   mDatabase(database),
             mServer(NULL),
             mStoragePath(storagePath),
+            mReserveSpace(reserveSpace),
             mJavaServer(javaServer),
             mFd(-1)
     {
@@ -100,7 +103,7 @@
         }
 
         mServer = new MtpServer(mFd, mDatabase, AID_SDCARD_RW, 0664, 0775);
-        mServer->addStorage(mStoragePath);
+        mServer->addStorage(mStoragePath, mReserveSpace);
         sMutex.unlock();
 
         LOGD("MtpThread mServer->run");
@@ -139,7 +142,8 @@
 #endif // HAVE_ANDROID_OS
 
 static void
-android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase, jstring storagePath)
+android_media_MtpServer_setup(JNIEnv *env, jobject thiz, jobject javaDatabase,
+        jstring storagePath, jlong reserveSpace)
 {
 #ifdef HAVE_ANDROID_OS
     LOGD("setup\n");
@@ -147,7 +151,8 @@
     MtpDatabase* database = getMtpDatabase(env, javaDatabase);
     const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
 
-    MtpThread* thread = new MtpThread(database, storagePathStr, env->NewGlobalRef(thiz));
+    MtpThread* thread = new MtpThread(database, storagePathStr,
+            reserveSpace, env->NewGlobalRef(thiz));
     env->SetIntField(thiz, field_context, (int)thread);
 
     env->ReleaseStringUTFChars(storagePath, storagePathStr);
@@ -213,7 +218,7 @@
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"native_setup",                "(Landroid/media/MtpDatabase;Ljava/lang/String;)V",
+    {"native_setup",                "(Landroid/media/MtpDatabase;Ljava/lang/String;J)V",
                                             (void *)android_media_MtpServer_setup},
     {"native_finalize",             "()V",  (void *)android_media_MtpServer_finalize},
     {"native_start",                "()V",  (void *)android_media_MtpServer_start},
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 29f16d8..235d752 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -140,38 +140,6 @@
     return meta;
 }
 
-/*
- * Returns -1 if frame skipping request is too long.
- * Returns  0 if there is no need to skip frames.
- * Returns  1 if we need to skip frames.
- */
-static int skipFrame(int64_t timestampUs,
-        const MediaSource::ReadOptions *options) {
-
-    int64_t skipFrameUs;
-    if (!options || !options->getSkipFrame(&skipFrameUs)) {
-        return 0;
-    }
-
-    if (skipFrameUs <= timestampUs) {
-        return 0;
-    }
-
-    // Safe guard against the abuse of the kSkipFrame_Option.
-    if (skipFrameUs - timestampUs >= 1E6) {
-        LOGE("Frame skipping requested is way too long: %lld us",
-            skipFrameUs - timestampUs);
-
-        return -1;
-    }
-
-    LOGV("skipFrame: %lld us > timestamp: %lld us",
-        skipFrameUs, timestampUs);
-
-    return 1;
-
-}
-
 void AudioSource::rampVolume(
         int32_t startFrame, int32_t rampDurationFrames,
         uint8_t *data,   size_t bytes) {
@@ -218,7 +186,7 @@
     CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
 
     int err = 0;
-    while (mStarted) {
+    if (mStarted) {
 
         uint32_t numFramesRecorded;
         mRecord->getPosition(&numFramesRecorded);
@@ -268,12 +236,6 @@
             if (mCollectStats) {
                 mTotalLostFrames += (numLostBytes >> 1);
             }
-            if ((err = skipFrame(timestampUs, options)) == -1) {
-                buffer->release();
-                return UNKNOWN_ERROR;
-            } else if (err != 0) {
-                continue;
-            }
             memset(buffer->data(), 0, numLostBytes);
             buffer->set_range(0, numLostBytes);
             if (numFramesRecorded == 0) {
@@ -294,12 +256,6 @@
 
         int64_t recordDurationUs = (1000000LL * n >> 1) / sampleRate;
         timestampUs += recordDurationUs;
-        if ((err = skipFrame(timestampUs, options)) == -1) {
-            buffer->release();
-            return UNKNOWN_ERROR;
-        } else if (err != 0) {
-            continue;
-        }
 
         if (mPrevSampleTimeUs - mStartTimeUs < kAutoRampStartUs) {
             // Mute the initial video recording signal
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 8c686b9..2f3353b 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -485,10 +485,13 @@
     // check earlier by calling mCamera->setParameters().
     CHECK_EQ(OK, mCamera->setPreviewDisplay(mSurface));
 
+    // By default, do not store metadata in video buffers
     mIsMetaDataStoredInVideoBuffers = false;
-    if (storeMetaDataInVideoBuffers &&
-        OK == mCamera->storeMetaDataInBuffers(true)) {
-        mIsMetaDataStoredInVideoBuffers = true;
+    mCamera->storeMetaDataInBuffers(false);
+    if (storeMetaDataInVideoBuffers) {
+        if (OK == mCamera->storeMetaDataInBuffers(true)) {
+            mIsMetaDataStoredInVideoBuffers = true;
+        }
     }
 
     IPCThreadState::self()->restoreCallingIdentity(token);
@@ -662,45 +665,22 @@
 
     {
         Mutex::Autolock autoLock(mLock);
-        while (mStarted) {
-            while(mFramesReceived.empty()) {
-                mFrameAvailableCondition.wait(mLock);
-            }
-
-            if (!mStarted) {
-                return OK;
-            }
-
-            frame = *mFramesReceived.begin();
-            mFramesReceived.erase(mFramesReceived.begin());
-
-            frameTime = *mFrameTimes.begin();
-            mFrameTimes.erase(mFrameTimes.begin());
-            int64_t skipTimeUs;
-            if (!options || !options->getSkipFrame(&skipTimeUs)) {
-                skipTimeUs = frameTime;
-            }
-            if (skipTimeUs > frameTime) {
-                LOGV("skipTimeUs: %lld us > frameTime: %lld us",
-                    skipTimeUs, frameTime);
-                releaseOneRecordingFrame(frame);
-                ++mNumFramesDropped;
-                // Safeguard against the abuse of the kSkipFrame_Option.
-                if (skipTimeUs - frameTime >= 1E6) {
-                    LOGE("Frame skipping requested is way too long: %lld us",
-                        skipTimeUs - frameTime);
-                    return UNKNOWN_ERROR;
-                }
-            } else {
-                mFramesBeingEncoded.push_back(frame);
-                *buffer = new MediaBuffer(frame->pointer(), frame->size());
-                (*buffer)->setObserver(this);
-                (*buffer)->add_ref();
-                (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
-
-                return OK;
-            }
+        while (mStarted && mFramesReceived.empty()) {
+            mFrameAvailableCondition.wait(mLock);
         }
+        if (!mStarted) {
+            return OK;
+        }
+        frame = *mFramesReceived.begin();
+        mFramesReceived.erase(mFramesReceived.begin());
+
+        frameTime = *mFrameTimes.begin();
+        mFrameTimes.erase(mFrameTimes.begin());
+        mFramesBeingEncoded.push_back(frame);
+        *buffer = new MediaBuffer(frame->pointer(), frame->size());
+        (*buffer)->setObserver(this);
+        (*buffer)->add_ref();
+        (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
     }
     return OK;
 }
@@ -726,7 +706,7 @@
 
     // May need to skip frame or modify timestamp. Currently implemented
     // by the subclass CameraSourceTimeLapse.
-    if(skipCurrentFrame(timestampUs)) {
+    if (skipCurrentFrame(timestampUs)) {
         releaseOneRecordingFrame(data);
         return;
     }
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 602aa9f..06c4c98 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1734,6 +1734,8 @@
     } else {
         prctl(PR_SET_NAME, (unsigned long)"VideoTrackEncoding", 0, 0, 0);
     }
+    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
+
     sp<MetaData> meta_data;
 
     mNumSamples = 0;
diff --git a/media/libstagefright/MediaSource.cpp b/media/libstagefright/MediaSource.cpp
index b4ef338..fd0e79c3 100644
--- a/media/libstagefright/MediaSource.cpp
+++ b/media/libstagefright/MediaSource.cpp
@@ -32,7 +32,6 @@
     mOptions = 0;
     mSeekTimeUs = 0;
     mLatenessUs = 0;
-    mSkipFrameUntilTimeUs = 0;
 }
 
 void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
@@ -54,21 +53,6 @@
     return (mOptions & kSeekTo_Option) != 0;
 }
 
-void MediaSource::ReadOptions::clearSkipFrame() {
-    mOptions &= ~kSkipFrame_Option;
-    mSkipFrameUntilTimeUs = 0;
-}
-
-void MediaSource::ReadOptions::setSkipFrame(int64_t timeUs) {
-    mOptions |= kSkipFrame_Option;
-    mSkipFrameUntilTimeUs = timeUs;
-}
-
-bool MediaSource::ReadOptions::getSkipFrame(int64_t *timeUs) const {
-    *timeUs = mSkipFrameUntilTimeUs;
-    return (mOptions & kSkipFrame_Option) != 0;
-}
-
 void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
     mLatenessUs = lateness_us;
 }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4bf922f..43e4e97 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1426,7 +1426,6 @@
       mSeekTimeUs(-1),
       mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
       mTargetTimeUs(-1),
-      mSkipTimeUs(-1),
       mLeftOverBuffer(NULL),
       mPaused(false),
       mNativeWindow(nativeWindow) {
@@ -2030,6 +2029,9 @@
 
                 mFilledBuffers.push_back(i);
                 mBufferFilled.signal();
+                if (mIsEncoder) {
+                    sched_yield();
+                }
             }
 
             break;
@@ -2635,15 +2637,13 @@
 
     for (;;) {
         MediaBuffer *srcBuffer;
-        MediaSource::ReadOptions options;
-        if (mSkipTimeUs >= 0) {
-            options.setSkipFrame(mSkipTimeUs);
-        }
         if (mSeekTimeUs >= 0) {
             if (mLeftOverBuffer) {
                 mLeftOverBuffer->release();
                 mLeftOverBuffer = NULL;
             }
+
+            MediaSource::ReadOptions options;
             options.setSeekTo(mSeekTimeUs, mSeekMode);
 
             mSeekTimeUs = -1;
@@ -2668,7 +2668,7 @@
 
             err = OK;
         } else {
-            err = mSource->read(&srcBuffer, &options);
+            err = mSource->read(&srcBuffer);
         }
 
         if (err != OK) {
@@ -3304,12 +3304,6 @@
     if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
         seeking = true;
     }
-    int64_t skipTimeUs;
-    if (options && options->getSkipFrame(&skipTimeUs)) {
-        mSkipTimeUs = skipTimeUs;
-    } else {
-        mSkipTimeUs = -1;
-    }
 
     if (mInitialBufferSubmit) {
         mInitialBufferSubmit = false;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index d65845d..b371e41 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -104,10 +104,10 @@
 MtpServer::~MtpServer() {
 }
 
-void MtpServer::addStorage(const char* filePath) {
+void MtpServer::addStorage(const char* filePath, uint64_t reserveSpace) {
     int index = mStorages.size() + 1;
     index |= index << 16;   // set high and low part to our index
-    MtpStorage* storage = new MtpStorage(index, filePath, mDatabase);
+    MtpStorage* storage = new MtpStorage(index, filePath, reserveSpace);
     addStorage(storage);
 }
 
@@ -687,6 +687,10 @@
     if (access(path, R_OK) == 0)
         return MTP_RESPONSE_GENERAL_ERROR;
 
+    // check space first
+    if (mSendObjectFileSize > storage->getFreeSpace())
+        return MTP_RESPONSE_STORAGE_FULL;
+
     MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
             format, parent, storageID, mSendObjectFileSize, modifiedTime);
     if (handle == kInvalidObjectHandle) {
diff --git a/media/mtp/MtpServer.h b/media/mtp/MtpServer.h
index 5aee4ea..605d5a2 100644
--- a/media/mtp/MtpServer.h
+++ b/media/mtp/MtpServer.h
@@ -67,7 +67,7 @@
                                     int fileGroup, int filePerm, int directoryPerm);
     virtual             ~MtpServer();
 
-    void                addStorage(const char* filePath);
+    void                addStorage(const char* filePath, uint64_t reserveSpace);
     inline void         addStorage(MtpStorage* storage) { mStorages.push(storage); }
     MtpStorage*         getStorage(MtpStorageID id);
     void                run();
diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp
index eccf186..abc23de 100644
--- a/media/mtp/MtpStorage.cpp
+++ b/media/mtp/MtpStorage.cpp
@@ -32,11 +32,11 @@
 
 namespace android {
 
-MtpStorage::MtpStorage(MtpStorageID id, const char* filePath, MtpDatabase* db)
+MtpStorage::MtpStorage(MtpStorageID id, const char* filePath, uint64_t reserveSpace)
     :   mStorageID(id),
         mFilePath(filePath),
-        mDatabase(db),
-        mMaxCapacity(0)
+        mMaxCapacity(0),
+        mReserveSpace(reserveSpace)
 {
     LOGD("MtpStorage id: %d path: %s\n", id, filePath);
 }
@@ -70,7 +70,8 @@
     struct statfs   stat;
     if (statfs(mFilePath, &stat))
         return -1;
-    return (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
+    uint64_t freeSpace = (uint64_t)stat.f_bavail * (uint64_t)stat.f_bsize;
+    return (freeSpace > mReserveSpace ? freeSpace - mReserveSpace : 0);
 }
 
 const char* MtpStorage::getDescription() const {
diff --git a/media/mtp/MtpStorage.h b/media/mtp/MtpStorage.h
index b13b926..ace720b 100644
--- a/media/mtp/MtpStorage.h
+++ b/media/mtp/MtpStorage.h
@@ -28,11 +28,13 @@
 private:
     MtpStorageID            mStorageID;
     const char*             mFilePath;
-    MtpDatabase*            mDatabase;
     uint64_t                mMaxCapacity;
+    // amount of free space to leave unallocated
+    uint64_t                mReserveSpace;
 
 public:
-                            MtpStorage(MtpStorageID id, const char* filePath, MtpDatabase* db);
+                            MtpStorage(MtpStorageID id, const char* filePath,
+                                    uint64_t reserveSpace);
     virtual                 ~MtpStorage();
 
     inline MtpStorageID     getStorageID() const { return mStorageID; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7980dfa..61d08aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2078,7 +2078,8 @@
 status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
         sp<IMemoryHeap>* heap,
         uint32_t* w, uint32_t* h, PixelFormat* f,
-        uint32_t sw, uint32_t sh)
+        uint32_t sw, uint32_t sh,
+        uint32_t minLayerZ, uint32_t maxLayerZ)
 {
     status_t result = PERMISSION_DENIED;
 
@@ -2132,7 +2133,10 @@
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; ++i) {
             const sp<LayerBase>& layer(layers[i]);
-            layer->drawForSreenShot();
+            const uint32_t z = layer->drawingState().z;
+            if (z >= minLayerZ && z <= maxLayerZ) {
+                layer->drawForSreenShot();
+            }
         }
 
         // XXX: this is needed on tegra
@@ -2185,7 +2189,8 @@
 status_t SurfaceFlinger::captureScreen(DisplayID dpy,
         sp<IMemoryHeap>* heap,
         uint32_t* width, uint32_t* height, PixelFormat* format,
-        uint32_t sw, uint32_t sh)
+        uint32_t sw, uint32_t sh,
+        uint32_t minLayerZ, uint32_t maxLayerZ)
 {
     // only one display supported for now
     if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
@@ -2203,13 +2208,18 @@
         PixelFormat* f;
         uint32_t sw;
         uint32_t sh;
+        uint32_t minLayerZ;
+        uint32_t maxLayerZ;
         status_t result;
     public:
         MessageCaptureScreen(SurfaceFlinger* flinger, DisplayID dpy,
                 sp<IMemoryHeap>* heap, uint32_t* w, uint32_t* h, PixelFormat* f,
-                uint32_t sw, uint32_t sh)
+                uint32_t sw, uint32_t sh,
+                uint32_t minLayerZ, uint32_t maxLayerZ)
             : flinger(flinger), dpy(dpy),
-              heap(heap), w(w), h(h), f(f), sw(sw), sh(sh), result(PERMISSION_DENIED)
+              heap(heap), w(w), h(h), f(f), sw(sw), sh(sh),
+              minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
+              result(PERMISSION_DENIED)
         {
         }
         status_t getResult() const {
@@ -2223,14 +2233,14 @@
                 return true;
 
             result = flinger->captureScreenImplLocked(dpy,
-                    heap, w, h, f, sw, sh);
+                    heap, w, h, f, sw, sh, minLayerZ, maxLayerZ);
 
             return true;
         }
     };
 
     sp<MessageBase> msg = new MessageCaptureScreen(this,
-            dpy, heap, width, height, format, sw, sh);
+            dpy, heap, width, height, format, sw, sh, minLayerZ, maxLayerZ);
     status_t res = postMessageSync(msg);
     if (res == NO_ERROR) {
         res = static_cast<MessageCaptureScreen*>( msg.get() )->getResult();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c0e5acd..ca7d27d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -192,13 +192,13 @@
     virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);
     virtual void                        signal() const;
-    virtual status_t                    captureScreen(DisplayID dpy,
-                                                      sp<IMemoryHeap>* heap,
-                                                      uint32_t* width,
-                                                      uint32_t* height,
-                                                      PixelFormat* format,
-                                                      uint32_t reqWidth,
-                                                      uint32_t reqHeight);
+
+    virtual status_t captureScreen(DisplayID dpy,
+            sp<IMemoryHeap>* heap,
+            uint32_t* width, uint32_t* height,
+            PixelFormat* format, uint32_t reqWidth, uint32_t reqHeight,
+            uint32_t minLayerZ, uint32_t maxLayerZ);
+
     virtual status_t                    turnElectronBeamOff(int32_t mode);
     virtual status_t                    turnElectronBeamOn(int32_t mode);
 
@@ -313,7 +313,8 @@
             status_t captureScreenImplLocked(DisplayID dpy,
                     sp<IMemoryHeap>* heap,
                     uint32_t* width, uint32_t* height, PixelFormat* format,
-                    uint32_t reqWidth = 0, uint32_t reqHeight = 0);
+                    uint32_t reqWidth, uint32_t reqHeight,
+                    uint32_t minLayerZ, uint32_t maxLayerZ);
 
             status_t turnElectronBeamOffImplLocked(int32_t mode);
             status_t turnElectronBeamOnImplLocked(int32_t mode);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 38f57c9..4424e5b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -954,4 +954,20 @@
         return mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_voice_capable);
     }
+
+    /**
+     * @return true if the current device supports sms service.
+     * <p>
+     * If true, this means that the device supports both sending and
+     * receiving sms via the telephony network.
+     * <p>
+     * Note: Voicemail waiting sms, cell broadcasting sms, and MMS are
+     *       disabled when device doesn't support sms.
+     *
+     * @hide pending API review
+     */
+    public boolean isSmsCapable() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_sms_capable);
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index b64b45d..5887130 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -742,6 +742,10 @@
     }
 
     public void notifyMessageWaitingIndicator() {
+        // Do not notify voice mail waiting if device doesn't support voice
+        if (!mIsVoiceCapable)
+            return;
+
         // This function is added to send the notification to DefaultPhoneNotifier.
         mNotifier.notifyMessageWaitingChanged(this);
     }
diff --git a/telephony/java/com/android/internal/telephony/SMSDispatcher.java b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
index ec49a19..e7cfe75 100644
--- a/telephony/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/SMSDispatcher.java
@@ -156,6 +156,9 @@
     protected boolean mStorageAvailable = true;
     protected boolean mReportMemoryStatusPending = false;
 
+    /* Flag indicating whether the current device allows sms service */
+    protected boolean mSmsCapable = true;
+
     protected static int getNextConcatenatedRef() {
         sConcatenatedRef += 1;
         return sConcatenatedRef;
@@ -249,6 +252,9 @@
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_FULL);
         filter.addAction(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
         mContext.registerReceiver(mResultReceiver, filter);
+
+        mSmsCapable = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_sms_capable);
     }
 
     public void dispose() {
@@ -682,6 +688,7 @@
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
      *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  <code>RESULT_ERROR_NO_SERVICE</code><br>.
      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
      *  the extra "errorCode" containing a radio technology specific value,
      *  generally only useful for troubleshooting.<br>
@@ -709,6 +716,7 @@
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
      *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  <code>RESULT_ERROR_NO_SERVICE</code><br>.
      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
      *  the extra "errorCode" containing a radio technology specific value,
      *  generally only useful for troubleshooting.<br>
@@ -737,7 +745,8 @@
      *   or one of these errors:
      *   <code>RESULT_ERROR_GENERIC_FAILURE</code>
      *   <code>RESULT_ERROR_RADIO_OFF</code>
-     *   <code>RESULT_ERROR_NULL_PDU</code>.
+     *   <code>RESULT_ERROR_NULL_PDU</code>
+     *   <code>RESULT_ERROR_NO_SERVICE</code>.
      *  The per-application based SMS control checks sentIntent. If sentIntent
      *  is NULL the caller will be checked against all unknown applications,
      *  which cause smaller number of SMS to be sent in checking period.
@@ -763,7 +772,8 @@
      *  or one of these errors:
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code>
      *  <code>RESULT_ERROR_RADIO_OFF</code>
-     *  <code>RESULT_ERROR_NULL_PDU</code>.
+     *  <code>RESULT_ERROR_NULL_PDU</code>
+     *  <code>RESULT_ERROR_NO_SERVICE</code>.
      *  The per-application based SMS control checks sentIntent. If sentIntent
      *  is NULL the caller will be checked against all unknown applications,
      *  which cause smaller number of SMS to be sent in checking period.
@@ -773,6 +783,16 @@
      */
     protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
             PendingIntent deliveryIntent) {
+        if (!mSmsCapable) {
+            if (sentIntent != null) {
+                try {
+                    sentIntent.send(RESULT_ERROR_NO_SERVICE);
+                } catch (CanceledException ex) {}
+            }
+            Log.d(TAG, "Device does not support sms service.");
+            return;
+        }
+
         if (pdu == null) {
             if (sentIntent != null) {
                 try {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 53555d8..01234b0 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -107,6 +107,13 @@
             return Activity.RESULT_OK;
         }
 
+        if (!mSmsCapable) {
+            // Device doesn't support SMS service,
+            Log.d(TAG, "Received short message on device which doesn't support "
+                    + "SMS service. Ignored.");
+            return Intents.RESULT_SMS_HANDLED;
+        }
+
         // See if we have a network duplicate SMS.
         SmsMessage sms = (SmsMessage) smsb;
         mLastDispatchedSmsFingerprint = sms.getIncomingSmsFingerprint();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 70f8f86..497c552 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -110,6 +110,13 @@
             return Intents.RESULT_SMS_HANDLED;
         }
 
+        if (!mSmsCapable) {
+            // Device doesn't support SMS service,
+            Log.d(TAG, "Received short message on device which doesn't support "
+                    + "SMS service. Ignored.");
+            return Intents.RESULT_SMS_HANDLED;
+        }
+
         // Special case the message waiting indicator messages
         if (sms.isMWISetMessage()) {
             mGsmPhone.updateMessageWaitingIndicator(true);