Merge "Tracking jarjar of org.bouncycastle to com.android.org.bouncycastle" into honeycomb
diff --git a/api/current.xml b/api/current.xml
index d17325f..b7d7b3a 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -29889,6 +29889,17 @@
  visibility="public"
 >
 </method>
+<method name="isRemoving"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isResumed"
  return="boolean"
  abstract="false"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 511ddc1..960b943 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2385,7 +2385,9 @@
             performPauseActivity(token, finished, r.isPreHoneycomb());
 
             // Make sure any pending writes are now committed.
-            QueuedWork.waitToFinish();
+            if (r.isPreHoneycomb()) {
+                QueuedWork.waitToFinish();
+            }
             
             // Tell the activity manager we have paused.
             try {
@@ -2583,6 +2585,11 @@
 
         updateVisibility(r, show);
 
+        // Make sure any pending writes are now committed.
+        if (!r.isPreHoneycomb()) {
+            QueuedWork.waitToFinish();
+        }
+
         // Tell activity manager we have been stopped.
         try {
             ActivityManagerNative.getDefault().activityStopped(
@@ -2647,6 +2654,12 @@
                 }
                 r.stopped = true;
             }
+
+            // Make sure any pending writes are now committed.
+            if (!r.isPreHoneycomb()) {
+                QueuedWork.waitToFinish();
+            }
+
             // Tell activity manager we slept.
             try {
                 ActivityManagerNative.getDefault().activitySlept(r.token);
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 3280b22..b3d111a 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -357,6 +357,9 @@
     // True if the fragment is in the list of added fragments.
     boolean mAdded;
     
+    // If set this fragment is being removed from its activity.
+    boolean mRemoving;
+
     // True if the fragment is in the resumed state.
     boolean mResumed;
     
@@ -638,6 +641,9 @@
      * Return <code>getActivity().getResources()</code>.
      */
     final public Resources getResources() {
+        if (mActivity == null) {
+            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+        }
         return mActivity.getResources();
     }
     
@@ -689,7 +695,16 @@
      * Return true if the fragment is currently added to its activity.
      */
     final public boolean isAdded() {
-        return mActivity != null && mActivity.mFragments.mAdded.contains(this);
+        return mActivity != null && mAdded;
+    }
+
+    /**
+     * Return true if this fragment is currently being removed from its
+     * activity.  This is  <em>not</em> whether its activity is finishing, but
+     * rather whether it is in the process of being removed from its activity.
+     */
+    final public boolean isRemoving() {
+        return mRemoving;
     }
     
     /**
@@ -787,6 +802,9 @@
         if (mLoaderManager != null) {
             return mLoaderManager;
         }
+        if (mActivity == null) {
+            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+        }
         mCheckedForLoaderManager = true;
         mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, true);
         return mLoaderManager;
@@ -797,6 +815,9 @@
      * containing Activity.
      */
     public void startActivity(Intent intent) {
+        if (mActivity == null) {
+            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+        }
         mActivity.startActivityFromFragment(this, intent, -1);
     }
     
@@ -805,6 +826,9 @@
      * containing Activity.
      */
     public void startActivityForResult(Intent intent, int requestCode) {
+        if (mActivity == null) {
+            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
+        }
         mActivity.startActivityFromFragment(this, intent, requestCode);
     }
     
@@ -1217,6 +1241,7 @@
                 writer.print(" mWho="); writer.print(mWho);
                 writer.print(" mBackStackNesting="); writer.println(mBackStackNesting);
         writer.print(prefix); writer.print("mAdded="); writer.print(mAdded);
+                writer.print(" mRemoving="); writer.print(mRemoving);
                 writer.print(" mResumed="); writer.print(mResumed);
                 writer.print(" mFromLayout="); writer.print(mFromLayout);
                 writer.print(" mInLayout="); writer.println(mInLayout);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index e729805..2c9c85b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -28,6 +28,8 @@
 import android.os.Parcelable;
 import android.util.DebugUtils;
 import android.util.Log;
+import android.util.LogWriter;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -968,6 +970,7 @@
         makeActive(fragment);
         if (DEBUG) Log.v(TAG, "add: " + fragment);
         fragment.mAdded = true;
+        fragment.mRemoving = false;
         if (fragment.mHasMenu) {
             mNeedMenuInvalidate = true;
         }
@@ -984,6 +987,7 @@
             mNeedMenuInvalidate = true;
         }
         fragment.mAdded = false;
+        fragment.mRemoving = true;
         moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                 transition, transitionStyle);
         if (inactive) {
@@ -1376,6 +1380,14 @@
                     }
 
                     if (f.mTarget != null) {
+                        if (f.mTarget.mIndex < 0) {
+                            String msg = "Failure saving state: " + f
+                                + " has target not in fragment manager: " + f.mTarget;
+                            Slog.e(TAG, msg);
+                            dump("  ", null, new PrintWriter(new LogWriter(
+                                    Log.ERROR, TAG, Log.LOG_ID_SYSTEM)), new String[] { });
+                            throw new IllegalStateException(msg);
+                        }
                         if (fs.mSavedFragmentState == null) {
                             fs.mSavedFragmentState = new Bundle();
                         }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 60213f8..c406524 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -567,6 +567,7 @@
             } else {
                 rd.validate(context, handler);
             }
+            rd.mForgotten = false;
             return rd.getIIntentReceiver();
         }
     }
@@ -596,6 +597,7 @@
                         rd.setUnregisterLocation(ex);
                         holder.put(r, rd);
                     }
+                    rd.mForgotten = true;
                     return rd.getIIntentReceiver();
                 }
             }
@@ -666,6 +668,7 @@
         final boolean mRegistered;
         final IntentReceiverLeaked mLocation;
         RuntimeException mUnregisterLocation;
+        boolean mForgotten;
 
         final class Args extends BroadcastReceiver.PendingResult implements Runnable {
             private Intent mCurIntent;
@@ -696,7 +699,7 @@
                 final Intent intent = mCurIntent;
                 mCurIntent = null;
                 
-                if (receiver == null || !mRegistered) {
+                if (receiver == null || mForgotten) {
                     if (mRegistered && ordered) {
                         if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                 "Finishing null broadcast to " + mReceiver);
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index 3d6182b..a7dd5fb 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -195,7 +195,7 @@
                 }
             }
             if (DEBUG) Slog.v(TAG, "Executing: " + mTask);
-            mTask.execute((Void[]) null);
+            mTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
         }
     }
 
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 5467a30..1764e11 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -899,7 +899,7 @@
                     return null;
                 }
             };
-            task.execute((Object[])null);
+            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[])null);
 
             return fds[0];
         } catch (IOException e) {
diff --git a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
index 01fc010..df8cf9a 100644
--- a/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodSessionWrapper.java
@@ -76,6 +76,8 @@
     }
 
     public void executeMessage(Message msg) {
+        if (mInputMethodSession == null) return;
+
         switch (msg.what) {
             case DO_FINISH_INPUT:
                 mInputMethodSession.finishInput();
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index 6a54846..343242e 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -19,11 +19,16 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
 import android.os.IBinder;
 import android.view.Gravity;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
 import android.view.WindowManager;
 
+import java.lang.Math;
+
 /**
  * A SoftInputWindow is a Dialog that is intended to be used for a top-level input
  * method window.  It will be displayed along the edge of the screen, moving
@@ -32,6 +37,7 @@
  */
 class SoftInputWindow extends Dialog {
     final KeyEvent.DispatcherState mDispatcherState;
+    private final Rect mBounds = new Rect();
     
     public void setToken(IBinder token) {
         WindowManager.LayoutParams lp = getWindow().getAttributes();
@@ -64,6 +70,13 @@
         mDispatcherState.reset();
     }
 
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        getWindow().getDecorView().getHitRect(mBounds);
+        final MotionEvent event = clipMotionEvent(ev, mBounds);
+        return super.dispatchTouchEvent(event);
+    }
+
     /**
      * Get the size of the DockWindow.
      * 
@@ -150,4 +163,48 @@
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                 WindowManager.LayoutParams.FLAG_DIM_BEHIND);
     }
+
+    private static MotionEvent clipMotionEvent(MotionEvent me, Rect bounds) {
+        final int pointerCount = me.getPointerCount();
+        boolean shouldClip = false;
+        for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
+            final int x = (int)me.getX(pointerIndex);
+            final int y = (int)me.getY(pointerIndex);
+            if (!bounds.contains(x, y)) {
+                shouldClip = true;
+                break;
+            }
+        }
+        if (!shouldClip)
+            return me;
+
+        if (pointerCount == 1) {
+            final int x = (int)me.getX();
+            final int y = (int)me.getY();
+            me.setLocation(
+                    Math.max(bounds.left, Math.min(x, bounds.right - 1)),
+                    Math.max(bounds.top, Math.min(y, bounds.bottom - 1)));
+            return me;
+        }
+
+        final int[] pointerIds = new int[pointerCount];
+        final MotionEvent.PointerCoords[] pointerCoords =
+            new MotionEvent.PointerCoords[pointerCount];
+        for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
+            pointerIds[pointerIndex] = me.getPointerId(pointerIndex);
+            final MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords();
+            me.getPointerCoords(pointerIndex, coords);
+            pointerCoords[pointerIndex] = coords;
+            final int x = (int)coords.x;
+            final int y = (int)coords.y;
+            if (!bounds.contains(x, y)) {
+                coords.x = Math.max(bounds.left, Math.min(x, bounds.right - 1));
+                coords.y = Math.max(bounds.top, Math.min(y, bounds.bottom - 1));
+            }
+        }
+        return MotionEvent.obtain(
+                me.getDownTime(), me.getEventTime(), me.getAction(), pointerCount, pointerIds,
+                pointerCoords, me.getMetaState(), me.getXPrecision(), me.getYPrecision(),
+                me.getDeviceId(), me.getEdgeFlags(), me.getSource(), me.getFlags());
+    }
 }
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index a6fd2f1..90279d1 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -90,13 +90,11 @@
         tl.mText = null;
         tl.mPaint = null;
         tl.mDirections = null;
-        if (tl.mLen < 250) {
-            synchronized(cached) {
-                for (int i = 0; i < cached.length; ++i) {
-                    if (cached[i] == null) {
-                        cached[i] = tl;
-                        break;
-                    }
+        synchronized(cached) {
+            for (int i = 0; i < cached.length; ++i) {
+                if (cached[i] == null) {
+                    cached[i] = tl;
+                    break;
                 }
             }
         }
diff --git a/core/java/android/util/LogWriter.java b/core/java/android/util/LogWriter.java
new file mode 100644
index 0000000..ce30631
--- /dev/null
+++ b/core/java/android/util/LogWriter.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import java.io.Writer;
+
+/** @hide */
+public class LogWriter extends Writer {
+    private final int mPriority;
+    private final String mTag;
+    private final int mBuffer;
+    private StringBuilder mBuilder = new StringBuilder(128);
+
+    /**
+     * Create a new Writer that sends to the log with the given priority
+     * and tag.
+     *
+     * @param priority The desired log priority:
+     * {@link android.util.Log#VERBOSE Log.VERBOSE},
+     * {@link android.util.Log#DEBUG Log.DEBUG},
+     * {@link android.util.Log#INFO Log.INFO},
+     * {@link android.util.Log#WARN Log.WARN}, or
+     * {@link android.util.Log#ERROR Log.ERROR}.
+     * @param tag A string tag to associate with each printed log statement.
+     */
+    public LogWriter(int priority, String tag) {
+        mPriority = priority;
+        mTag = tag;
+        mBuffer = Log.LOG_ID_MAIN;
+    }
+
+    /**
+     * @hide
+     * Same as above, but buffer is one of the LOG_ID_ constants from android.util.Log.
+     */
+    public LogWriter(int priority, String tag, int buffer) {
+        mPriority = priority;
+        mTag = tag;
+        mBuffer = buffer;
+    }
+
+    @Override public void close() {
+        flushBuilder();
+    }
+
+    @Override public void flush() {
+        flushBuilder();
+    }
+
+    @Override public void write(char[] buf, int offset, int count) {
+        for(int i = 0; i < count; i++) {
+            char c = buf[offset + i];
+            if ( c == '\n') {
+                flushBuilder();
+            }
+            else {
+                mBuilder.append(c);
+            }
+        }
+    }
+
+    private void flushBuilder() {
+        if (mBuilder.length() > 0) {
+            Log.println_native(mBuffer, mPriority, mTag, mBuilder.toString());
+            mBuilder.delete(0, mBuilder.length());
+        }
+    }
+}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index dce1a6c..dac3135 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -192,21 +192,36 @@
         nSetViewport(mRenderer, width, height);
     }
     
-    private native void nSetViewport(int renderer, int width, int height);
+    private static native void nSetViewport(int renderer, int width, int height);
 
-    @Override
-    void onPreDraw() {
-        nPrepare(mRenderer, mOpaque);
+    /**
+     * @hide
+     */
+    public static boolean preserveBackBuffer() {
+        return nPreserveBackBuffer();
     }
 
-    private native void nPrepare(int renderer, boolean opaque);
+    private static native boolean nPreserveBackBuffer();    
+    
+    @Override
+    void onPreDraw(Rect dirty) {
+        if (dirty != null) {
+            nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom, mOpaque);
+        } else {
+            nPrepare(mRenderer, mOpaque);
+        }
+    }
+
+    private static native void nPrepare(int renderer, boolean opaque);
+    private static native void nPrepareDirty(int renderer, int left, int top, int right, int bottom,
+            boolean opaque);
 
     @Override
     void onPostDraw() {
         nFinish(mRenderer);
     }
     
-    private native void nFinish(int renderer);
+    private static native void nFinish(int renderer);
 
     @Override
     public boolean acquireContext() {
@@ -217,14 +232,14 @@
         return mContextLocked;
     }
 
-    private native void nAcquireContext(int renderer);
+    private static native void nAcquireContext(int renderer);
 
     @Override
     public boolean callDrawGLFunction(int drawGLFunction) {
         return nCallDrawGLFunction(mRenderer, drawGLFunction);
     }
 
-    private native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
+    private static native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
 
     @Override
     public void releaseContext() {
@@ -234,7 +249,7 @@
         }
     }
 
-    private native void nReleaseContext(int renderer);
+    private static native void nReleaseContext(int renderer);
     
     ///////////////////////////////////////////////////////////////////////////
     // Display list
@@ -244,7 +259,7 @@
         return nGetDisplayList(mRenderer);
     }
 
-    private native int nGetDisplayList(int renderer);
+    private static native int nGetDisplayList(int renderer);
     
     static void destroyDisplayList(int displayList) {
         nDestroyDisplayList(displayList);
@@ -257,7 +272,7 @@
         return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
     }
 
-    private native boolean nDrawDisplayList(int renderer, int displayList);
+    private static native boolean nDrawDisplayList(int renderer, int displayList);
 
     ///////////////////////////////////////////////////////////////////////////
     // Hardware layer
@@ -271,7 +286,7 @@
         if (hasColorFilter) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
+    private static native void nDrawLayer(int renderer, int layer, float x, float y, int paint);
     
     void interrupt() {
         nInterrupt(mRenderer);
@@ -281,8 +296,8 @@
         nResume(mRenderer);
     }
 
-    private native void nInterrupt(int renderer);
-    private native void nResume(int renderer);
+    private static native void nInterrupt(int renderer);
+    private static native void nResume(int renderer);
 
     ///////////////////////////////////////////////////////////////////////////
     // Clipping
@@ -303,7 +318,7 @@
         return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
     }
     
-    private native boolean nClipRect(int renderer, float left, float top,
+    private static native boolean nClipRect(int renderer, float left, float top,
             float right, float bottom, int op);
 
     @Override
@@ -316,7 +331,8 @@
         return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
     }
     
-    private native boolean nClipRect(int renderer, int left, int top, int right, int bottom, int op);
+    private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom,
+            int op);
 
     @Override
     public boolean clipRect(Rect rect) {
@@ -355,14 +371,14 @@
         return nGetClipBounds(mRenderer, bounds);
     }
 
-    private native boolean nGetClipBounds(int renderer, Rect bounds);
+    private static native boolean nGetClipBounds(int renderer, Rect bounds);
 
     @Override
     public boolean quickReject(float left, float top, float right, float bottom, EdgeType type) {
         return nQuickReject(mRenderer, left, top, right, bottom, type.nativeInt);
     }
     
-    private native boolean nQuickReject(int renderer, float left, float top,
+    private static native boolean nQuickReject(int renderer, float left, float top,
             float right, float bottom, int edge);
 
     @Override
@@ -384,56 +400,56 @@
         if (dx != 0.0f || dy != 0.0f) nTranslate(mRenderer, dx, dy);
     }
     
-    private native void nTranslate(int renderer, float dx, float dy);
+    private static native void nTranslate(int renderer, float dx, float dy);
 
     @Override
     public void skew(float sx, float sy) {
         nSkew(mRenderer, sx, sy);
     }
 
-    private native void nSkew(int renderer, float sx, float sy);
+    private static native void nSkew(int renderer, float sx, float sy);
 
     @Override
     public void rotate(float degrees) {
         nRotate(mRenderer, degrees);
     }
     
-    private native void nRotate(int renderer, float degrees);
+    private static native void nRotate(int renderer, float degrees);
 
     @Override
     public void scale(float sx, float sy) {
         nScale(mRenderer, sx, sy);
     }
     
-    private native void nScale(int renderer, float sx, float sy);
+    private static native void nScale(int renderer, float sx, float sy);
 
     @Override
     public void setMatrix(Matrix matrix) {
         nSetMatrix(mRenderer, matrix.native_instance);
     }
     
-    private native void nSetMatrix(int renderer, int matrix);
+    private static native void nSetMatrix(int renderer, int matrix);
 
     @Override
     public int getNativeMatrix() {
         return nGetMatrix(mRenderer);
     }
 
-    private native int nGetMatrix(int renderer);    
+    private static native int nGetMatrix(int renderer);    
 
     @Override
     public void getMatrix(Matrix matrix) {
         nGetMatrix(mRenderer, matrix.native_instance);
     }
     
-    private native void nGetMatrix(int renderer, int matrix);
+    private static native void nGetMatrix(int renderer, int matrix);
 
     @Override
     public void concat(Matrix matrix) {
         nConcatMatrix(mRenderer, matrix.native_instance);
     }
     
-    private native void nConcatMatrix(int renderer, int matrix);
+    private static native void nConcatMatrix(int renderer, int matrix);
     
     ///////////////////////////////////////////////////////////////////////////
     // State management
@@ -449,7 +465,7 @@
         return nSave(mRenderer, saveFlags);
     }
 
-    private native int nSave(int renderer, int flags);
+    private static native int nSave(int renderer, int flags);
     
     @Override
     public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
@@ -469,8 +485,8 @@
         return save(saveFlags);
     }
 
-    private native int nSaveLayer(int renderer, float left, float top, float right, float bottom,
-            int paint, int saveFlags);
+    private static native int nSaveLayer(int renderer, float left, float top,
+            float right, float bottom, int paint, int saveFlags);
 
     @Override
     public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
@@ -487,7 +503,7 @@
         return save(saveFlags);
     }
 
-    private native int nSaveLayerAlpha(int renderer, float left, float top, float right,
+    private static native int nSaveLayerAlpha(int renderer, float left, float top, float right,
             float bottom, int alpha, int saveFlags);
     
     @Override
@@ -495,21 +511,21 @@
         nRestore(mRenderer);
     }
     
-    private native void nRestore(int renderer);
+    private static native void nRestore(int renderer);
 
     @Override
     public void restoreToCount(int saveCount) {
         nRestoreToCount(mRenderer, saveCount);
     }
 
-    private native void nRestoreToCount(int renderer, int saveCount);
+    private static native void nRestoreToCount(int renderer, int saveCount);
     
     @Override
     public int getSaveCount() {
         return nGetSaveCount(mRenderer);
     }
     
-    private native int nGetSaveCount(int renderer);
+    private static native int nGetSaveCount(int renderer);
 
     ///////////////////////////////////////////////////////////////////////////
     // Filtering
@@ -538,8 +554,9 @@
         if (hasModifier) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawArc(int renderer, float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, boolean useCenter, int paint);
+    private static native void nDrawArc(int renderer, float left, float top,
+            float right, float bottom, float startAngle, float sweepAngle,
+            boolean useCenter, int paint);
 
     @Override
     public void drawARGB(int a, int r, int g, int b) {
@@ -556,7 +573,7 @@
         if (hasColorFilter) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks,
+    private static native void nDrawPatch(int renderer, int bitmap, byte[] buffer, byte[] chunks,
             float left, float top, float right, float bottom, int paint);
 
     @Override
@@ -568,7 +585,7 @@
         if (hasColorFilter) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawBitmap(
+    private static native void nDrawBitmap(
             int renderer, int bitmap, byte[] buffer, float left, float top, int paint);
 
     @Override
@@ -581,7 +598,8 @@
         if (hasColorFilter) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawBitmap(int renderer, int bitmap, byte[] buff, int matrix, int paint);
+    private static native void nDrawBitmap(int renderer, int bitmap, byte[] buff,
+            int matrix, int paint);
 
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
@@ -616,7 +634,7 @@
         if (hasColorFilter) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
+    private static native void nDrawBitmap(int renderer, int bitmap, byte[] buffer,
             float srcLeft, float srcTop, float srcRight, float srcBottom,
             float left, float top, float right, float bottom, int paint);
 
@@ -665,7 +683,7 @@
         if (hasColorFilter) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
+    private static native void nDrawBitmapMesh(int renderer, int bitmap, byte[] buffer,
             int meshWidth, int meshHeight, float[] verts, int vertOffset,
             int[] colors, int colorOffset, int paint);
 
@@ -676,7 +694,8 @@
         if (hasModifier) nResetModifiers(mRenderer);        
     }
 
-    private native void nDrawCircle(int renderer, float cx, float cy, float radius, int paint);
+    private static native void nDrawCircle(int renderer, float cx, float cy,
+            float radius, int paint);
 
     @Override
     public void drawColor(int color) {
@@ -688,7 +707,7 @@
         nDrawColor(mRenderer, color, mode.nativeInt);
     }
     
-    private native void nDrawColor(int renderer, int color, int mode);
+    private static native void nDrawColor(int renderer, int color, int mode);
 
     @Override
     public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
@@ -709,7 +728,8 @@
         if (hasModifier) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawLines(int renderer, float[] points, int offset, int count, int paint);
+    private static native void nDrawLines(int renderer, float[] points,
+            int offset, int count, int paint);
 
     @Override
     public void drawLines(float[] pts, Paint paint) {
@@ -723,8 +743,8 @@
         if (hasModifier) nResetModifiers(mRenderer); 
     }
 
-    private native void nDrawOval(int renderer, float left, float top, float right, float bottom,
-            int paint);
+    private static native void nDrawOval(int renderer, float left, float top,
+            float right, float bottom, int paint);
 
     @Override
     public void drawPaint(Paint paint) {
@@ -746,8 +766,8 @@
         if (hasModifier) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawPath(int renderer, int path, int paint);
-    private native void nDrawRects(int renderer, int region, int paint);
+    private static native void nDrawPath(int renderer, int path, int paint);
+    private static native void nDrawRects(int renderer, int region, int paint);
 
     @Override
     public void drawPicture(Picture picture) {
@@ -798,8 +818,8 @@
         if (hasModifier) nResetModifiers(mRenderer);
     }
 
-    private native void nDrawRect(int renderer, float left, float top, float right, float bottom,
-            int paint);
+    private static native void nDrawRect(int renderer, float left, float top,
+            float right, float bottom, int paint);
 
     @Override
     public void drawRect(Rect r, Paint paint) {
@@ -824,7 +844,7 @@
         if (hasModifier) nResetModifiers(mRenderer);        
     }
 
-    private native void nDrawRoundRect(int renderer, float left, float top,
+    private static native void nDrawRoundRect(int renderer, float left, float top,
             float right, float bottom, float rx, float y, int paint);
 
     @Override
@@ -841,8 +861,8 @@
         }
     }
     
-    private native void nDrawText(int renderer, char[] text, int index, int count, float x, float y,
-            int bidiFlags, int paint);
+    private static native void nDrawText(int renderer, char[] text, int index, int count,
+            float x, float y, int bidiFlags, int paint);
 
     @Override
     public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
@@ -858,7 +878,8 @@
             } else {
                 char[] buf = TemporaryBuffer.obtain(end - start);
                 TextUtils.getChars(text, start, end, buf, 0);
-                nDrawText(mRenderer, buf, 0, end - start, x, y, paint.mBidiFlags, paint.mNativePaint);
+                nDrawText(mRenderer, buf, 0, end - start, x, y,
+                        paint.mBidiFlags, paint.mNativePaint);
                 TemporaryBuffer.recycle(buf);
             }
         } finally {
@@ -880,8 +901,8 @@
         }
     }
 
-    private native void nDrawText(int renderer, String text, int start, int end, float x, float y,
-            int bidiFlags, int paint);
+    private static native void nDrawText(int renderer, String text, int start, int end,
+            float x, float y, int bidiFlags, int paint);
 
     @Override
     public void drawText(String text, float x, float y, Paint paint) {
@@ -924,7 +945,7 @@
         }
     }
 
-    private native void nDrawTextRun(int renderer, char[] text, int index, int count,
+    private static native void nDrawTextRun(int renderer, char[] text, int index, int count,
             int contextIndex, int contextCount, float x, float y, int dir, int nativePaint);
 
     @Override
@@ -958,7 +979,7 @@
         }
     }
 
-    private native void nDrawTextRun(int renderer, String text, int start, int end,
+    private static native void nDrawTextRun(int renderer, String text, int start, int end,
             int contextStart, int contextEnd, float x, float y, int flags, int nativePaint);
 
     @Override
@@ -1001,9 +1022,10 @@
         return false;        
     }
     
-    private native void nSetupShader(int renderer, int shader);
-    private native void nSetupColorFilter(int renderer, int colorFilter);
-    private native void nSetupShadow(int renderer, float radius, float dx, float dy, int color);
+    private static native void nSetupShader(int renderer, int shader);
+    private static native void nSetupColorFilter(int renderer, int colorFilter);
+    private static native void nSetupShadow(int renderer, float radius,
+            float dx, float dy, int color);
 
-    private native void nResetModifiers(int renderer);
+    private static native void nResetModifiers(int renderer);
 }
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index a4d36b7..e6fecc8 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -19,6 +19,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Rect;
 
 /**
  * Hardware accelerated canvas.
@@ -38,8 +39,10 @@
     
     /**
      * Invoked before any drawing operation is performed in this canvas.
+     * 
+     * @param dirty The dirty rectangle to update, can be null.
      */
-    abstract void onPreDraw();
+    abstract void onPreDraw(Rect dirty);
 
     /**
      * Invoked after all drawing operation have been performed.
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c82184a..48f40c3 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -18,6 +18,8 @@
 package android.view;
 
 import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
 import android.os.SystemClock;
 import android.util.EventLog;
 import android.util.Log;
@@ -39,6 +41,16 @@
     static final String LOG_TAG = "HardwareRenderer";
 
     /**
+     * Turn on to only refresh the parts of the screen that need updating.
+     */
+    public static final boolean RENDER_DIRTY_REGIONS = true;
+
+    /**
+     * Turn on to draw dirty regions every other frame.
+     */
+    private static final boolean DEBUG_DIRTY_REGION = false;
+    
+    /**
      * A process can set this flag to false to prevent the use of hardware
      * rendering.
      * 
@@ -108,11 +120,14 @@
 
     /**
      * Draws the specified view.
-     * 
+     *
      * @param view The view to draw.
      * @param attachInfo AttachInfo tied to the specified view.
+     * @param callbacks Callbacks invoked when drawing happens.
+     * @param dirty The dirty rectangle to update, can be null.
      */
-    abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
+    abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+            Rect dirty);
 
     /**
      * Creates a new display list that can be used to record batches of
@@ -214,7 +229,13 @@
     @SuppressWarnings({"deprecation"})
     static abstract class GlRenderer extends HardwareRenderer {
         private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+        private static final int EGL_SURFACE_TYPE = 0x3033;
+        private static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
 
+        private static final int SURFACE_STATE_ERROR = 0;
+        private static final int SURFACE_STATE_SUCCESS = 1;
+        private static final int SURFACE_STATE_UPDATED = 2;
+        
         static EGLContext sEglContext;
         static EGL10 sEgl;
         static EGLDisplay sEglDisplay;
@@ -226,6 +247,9 @@
         
         GL mGl;
         HardwareCanvas mCanvas;
+        int mFrameCount;
+        Paint mDebugPaint;
+
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -412,7 +436,7 @@
             if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
                 int error = sEgl.eglGetError();
                 if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
-                    Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+                    Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
                     return null;
                 }
                 throw new RuntimeException("createWindowSurface failed "
@@ -427,6 +451,12 @@
                 throw new RuntimeException("eglMakeCurrent failed "
                         + getEGLErrorString(sEgl.eglGetError()));
             }
+            
+            if (RENDER_DIRTY_REGIONS) {
+                if (!GLES20Canvas.preserveBackBuffer()) {
+                    Log.w(LOG_TAG, "Backbuffer cannot be preserved");
+                }
+            }
 
             return sEglContext.getGL();
         }
@@ -471,12 +501,12 @@
         void setup(int width, int height) {
             mCanvas.setViewport(width, height);
         }
-        
+
         boolean canDraw() {
             return mGl != null && mCanvas != null;
         }        
         
-        void onPreDraw() {
+        void onPreDraw(Rect dirty) {
         }
 
         void onPostDraw() {
@@ -492,8 +522,14 @@
         }
 
         @Override
-        void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
+        void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
+                Rect dirty) {
             if (canDraw()) {
+                //noinspection PointlessBooleanExpression,ConstantConditions
+                if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+                    dirty = null;
+                }
+
                 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
                 attachInfo.mIgnoreDirtyState = true;
                 view.mPrivateFlags |= View.DRAWN;
@@ -503,11 +539,18 @@
                     startTime = SystemClock.elapsedRealtime();
                 }
 
-                if (checkCurrent()) {
-                    onPreDraw();
+                final int surfaceState = checkCurrent();
+                if (surfaceState != SURFACE_STATE_ERROR) {
+                    // We had to change the current surface and/or context, redraw everything
+                    if (surfaceState == SURFACE_STATE_UPDATED) {
+                        dirty = null;
+                    }
+
+                    onPreDraw(dirty);
     
                     HardwareCanvas canvas = mCanvas;
                     attachInfo.mHardwareCanvas = canvas;
+
                     int saveCount = canvas.save();
                     callbacks.onHardwarePreDraw(canvas);
 
@@ -515,6 +558,7 @@
                         view.mRecreateDisplayList =
                                 (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
                         view.mPrivateFlags &= ~View.INVALIDATED;
+
                         DisplayList displayList = view.getDisplayList();
                         if (displayList != null) {
                             if (canvas.drawDisplayList(displayList)) {
@@ -524,6 +568,16 @@
                             // Shouldn't reach here
                             view.draw(canvas);
                         }
+
+                        if (DEBUG_DIRTY_REGION) {
+                            if (mDebugPaint == null) {
+                                mDebugPaint = new Paint();
+                                mDebugPaint.setColor(0x7fff0000);
+                            }
+                            if (dirty != null && (mFrameCount++ & 1) == 0) {
+                                canvas.drawRect(dirty, mDebugPaint);
+                            }
+                        }
                     } finally {
                         callbacks.onHardwarePostDraw(canvas);
                         canvas.restoreToCount(saveCount);
@@ -543,8 +597,8 @@
                 }
             }
         }
-
-        private boolean checkCurrent() {
+        
+        private int checkCurrent() {
             // TODO: Don't check the current context when we have one per UI thread
             // TODO: Use a threadlocal flag to know whether the surface has changed
             if (sEgl.eglGetCurrentContext() != sEglContext ||
@@ -553,10 +607,12 @@
                     fallback(true);
                     Log.e(LOG_TAG, "eglMakeCurrent failed " +
                             getEGLErrorString(sEgl.eglGetError()));
-                    return false;
+                    return SURFACE_STATE_ERROR;
+                } else {
+                    return SURFACE_STATE_UPDATED;
                 }
             }
-            return true;
+            return SURFACE_STATE_SUCCESS;
         }
 
         static abstract class EglConfigChooser {
@@ -629,6 +685,7 @@
 
             ComponentSizeChooser(int glVersion, int redSize, int greenSize, int blueSize,
                     int alphaSize, int depthSize, int stencilSize) {
+                //noinspection PointlessBitwiseExpression
                 super(glVersion, new int[] {
                         EGL10.EGL_RED_SIZE, redSize,
                         EGL10.EGL_GREEN_SIZE, greenSize,
@@ -636,6 +693,8 @@
                         EGL10.EGL_ALPHA_SIZE, alphaSize,
                         EGL10.EGL_DEPTH_SIZE, depthSize,
                         EGL10.EGL_STENCIL_SIZE, stencilSize,
+                        EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT |
+                                (RENDER_DIRTY_REGIONS ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
                         EGL10.EGL_NONE });
                 mValue = new int[1];
                 mRedSize = redSize;
@@ -656,7 +715,16 @@
                         int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
                         int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
                         int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
-                        if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize) {
+                        boolean backBuffer;
+                        if (RENDER_DIRTY_REGIONS) {
+                            int surfaceType = findConfigAttrib(egl, display, config,
+                                    EGL_SURFACE_TYPE, 0);
+                            backBuffer = (surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) != 0;
+                        } else {
+                            backBuffer = true;
+                        }
+                        if (r >= mRedSize && g >= mGreenSize && b >= mBlueSize && a >= mAlphaSize
+                                && backBuffer) {
                             return config;
                         }
                     }
@@ -696,8 +764,8 @@
         }                
 
         @Override
-        void onPreDraw() {
-            mGlCanvas.onPreDraw();
+        void onPreDraw(Rect dirty) {
+            mGlCanvas.onPreDraw(dirty);
         }
 
         @Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index aa69aea..65d2e11 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6730,11 +6730,14 @@
             mPrivateFlags |= INVALIDATED;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
-            if (p != null && ai != null && ai.mHardwareAccelerated) {
-                // fast-track for GL-enabled applications; just invalidate the whole hierarchy
-                // with a null dirty rect, which tells the ViewRoot to redraw everything
-                p.invalidateChild(this, null);
-                return;
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+                if (p != null && ai != null && ai.mHardwareAccelerated) {
+                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+                    // with a null dirty rect, which tells the ViewRoot to redraw everything
+                    p.invalidateChild(this, null);
+                    return;
+                }
             }
             if (p != null && ai != null) {
                 final int scrollX = mScrollX;
@@ -6770,11 +6773,14 @@
             mPrivateFlags |= INVALIDATED;
             final ViewParent p = mParent;
             final AttachInfo ai = mAttachInfo;
-            if (p != null && ai != null && ai.mHardwareAccelerated) {
-                // fast-track for GL-enabled applications; just invalidate the whole hierarchy
-                // with a null dirty rect, which tells the ViewRoot to redraw everything
-                p.invalidateChild(this, null);
-                return;
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+                if (p != null && ai != null && ai.mHardwareAccelerated) {
+                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+                    // with a null dirty rect, which tells the ViewRoot to redraw everything
+                    p.invalidateChild(this, null);
+                    return;
+                }
             }
             if (p != null && ai != null && l < r && t < b) {
                 final int scrollX = mScrollX;
@@ -6823,11 +6829,14 @@
             }
             final AttachInfo ai = mAttachInfo;
             final ViewParent p = mParent;
-            if (p != null && ai != null && ai.mHardwareAccelerated) {
-                // fast-track for GL-enabled applications; just invalidate the whole hierarchy
-                // with a null dirty rect, which tells the ViewRoot to redraw everything
-                p.invalidateChild(this, null);
-                return;
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
+                if (p != null && ai != null && ai.mHardwareAccelerated) {
+                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
+                    // with a null dirty rect, which tells the ViewRoot to redraw everything
+                    p.invalidateChild(this, null);
+                    return;
+                }
             }
 
             if (p != null && ai != null) {
@@ -8078,7 +8087,7 @@
      *
      * @return A HardwareLayer ready to render, or null if an error occurred.
      */
-    HardwareLayer getHardwareLayer(Canvas currentCanvas) {
+    HardwareLayer getHardwareLayer() {
         if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
             return null;
         }
@@ -8098,10 +8107,13 @@
                 mHardwareLayer.resize(width, height);
             }
 
-            final HardwareCanvas canvas = mHardwareLayer.start(mAttachInfo.mHardwareCanvas);
+            Canvas currentCanvas = mAttachInfo.mHardwareCanvas;
+            final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
+            mAttachInfo.mHardwareCanvas = canvas;
             try {
                 canvas.setViewport(width, height);
-                canvas.onPreDraw();
+                // TODO: We should pass the dirty rect
+                canvas.onPreDraw(null);
 
                 computeScroll();
                 canvas.translate(-mScrollX, -mScrollY);
@@ -8121,7 +8133,8 @@
                 canvas.restoreToCount(restoreCount);
             } finally {
                 canvas.onPostDraw();
-                mHardwareLayer.end(mAttachInfo.mHardwareCanvas);
+                mHardwareLayer.end(currentCanvas);
+                mAttachInfo.mHardwareCanvas = currentCanvas;
             }
         }
 
@@ -8190,7 +8203,7 @@
             ViewGroup parent = (ViewGroup) this;
             final int count = parent.getChildCount();
             for (int i = 0; i < count; i++) {
-                final View child = (View) parent.getChildAt(i);
+                final View child = parent.getChildAt(i);
                 child.outputDirtyFlags(indent + "  ", clear, clearMask);
             }
         }
@@ -8251,7 +8264,8 @@
                 int height = mBottom - mTop;
 
                 canvas.setViewport(width, height);
-                canvas.onPreDraw();
+                // The dirty rect should always be null for a display list
+                canvas.onPreDraw(null);
 
                 final int restoreCount = canvas.save();
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index ccf2453..f198c46 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2395,8 +2395,6 @@
                 canvas.scale(scale, scale);
             }
         }
-        
-        boolean layerSaved = false;
 
         if (transformToApply != null || alpha < 1.0f || !child.hasIdentityMatrix()) {
             if (transformToApply != null || !childHasIdentityMatrix) {
@@ -2477,7 +2475,7 @@
         if (hasNoCache) {
             boolean layerRendered = false;
             if (layerType == LAYER_TYPE_HARDWARE) {
-                final HardwareLayer layer = child.getHardwareLayer(canvas);
+                final HardwareLayer layer = child.getHardwareLayer();
                 if (layer != null && layer.isValid()) {
                     ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, child.mLayerPaint);
                     layerRendered = true;
@@ -3529,10 +3527,20 @@
                             (int) (boundingRect.bottom + 0.5f));
                 }
 
+                if (child.mLayerType != LAYER_TYPE_NONE) {
+                    mPrivateFlags |= INVALIDATED;
+                    mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                }                
                 do {
                     View view = null;
                     if (parent instanceof View) {
                         view = (View) parent;
+                        if (view.mLayerType != LAYER_TYPE_NONE &&
+                                view.getParent() instanceof View) {
+                            final View grandParent = (View) view.getParent();
+                            grandParent.mPrivateFlags |= INVALIDATED;
+                            grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+                        }
                     }
 
                     if (drawAnimation) {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ba671c0..19d7811 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -160,7 +160,9 @@
 
     int mWidth;
     int mHeight;
-    Rect mDirty; // will be a graphics.Region soon
+    Rect mDirty;
+    final Rect mCurrentDirty = new Rect();
+    final Rect mPreviousDirty = new Rect();
     boolean mIsAnimating;
 
     CompatibilityInfo.Translator mTranslator;
@@ -1055,6 +1057,7 @@
                     disposeResizeBitmap();
                 } else if (surfaceGenerationId != mSurface.getGenerationId() &&
                         mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
+                    fullRedrawNeeded = true;
                     mAttachInfo.mHardwareRenderer.updateSurface(mHolder);
                 }
             } catch (RemoteException e) {
@@ -1488,10 +1491,15 @@
         if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
             if (!dirty.isEmpty() || mIsAnimating) {
                 mIsAnimating = false;
-                dirty.setEmpty();
                 mHardwareYOffset = yoff;
                 mResizeAlpha = resizeAlpha;
-                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
+
+                mCurrentDirty.set(dirty);
+                mCurrentDirty.union(mPreviousDirty);
+                mPreviousDirty.set(dirty);
+                dirty.setEmpty();
+
+                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this, mCurrentDirty);
             }
 
             if (animating) {
@@ -1986,6 +1994,7 @@
 
                     if (mAttachInfo.mHardwareRenderer != null &&
                             mSurface != null && mSurface.isValid()) {
+                        mFullRedrawNeeded = true;
                         mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
                                 mAttachInfo, mHolder);
                     }
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index 257ed2a..8eb1524 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -75,6 +75,9 @@
     private Handler mHandler = null;
     private Handler mUIHandler = null;
 
+    /**
+     * Class containing the HTML5 database quota and usage for an origin.
+     */
     public static class Origin {
         private String mOrigin = null;
         private long mQuota = 0;
@@ -95,14 +98,30 @@
             mOrigin = origin;
         }
 
+        /**
+         * An origin string is created using WebCore::SecurityOrigin::toString().
+         * Note that WebCore::SecurityOrigin uses 0 (which is not printed) for
+         * the port if the port is the default for the protocol. Eg
+         * http://www.google.com and http://www.google.com:80 both record a port
+         * of 0 and hence toString() == 'http://www.google.com' for both.
+         * @return The origin string.
+         */
         public String getOrigin() {
             return mOrigin;
         }
 
+        /**
+         * Returns the quota for this origin's HTML5 database.
+         * @return The quota in bytes.
+         */
         public long getQuota() {
             return mQuota;
         }
 
+        /**
+         * Returns the usage for this origin's HTML5 database.
+         * @return The usage in bytes.
+         */
         public long getUsage() {
             return mUsage;
         }
@@ -229,7 +248,8 @@
      */
 
     /**
-     * Returns a list of origins having a database
+     * Returns a list of origins having a database. The Map is of type
+     * Map<String, Origin>.
      */
     public void getOrigins(ValueCallback<Map> callback) {
         if (callback != null) {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index bb4441f..0992079 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -130,6 +130,7 @@
 
     private int mLowMemoryUsageThresholdMb;
     private int mHighMemoryUsageThresholdMb;
+    private int mHighUsageDeltaMb;
 
     // The thread name used to identify the WebCore thread and for use in
     // debugging other classes that require operation within the WebCore thread.
@@ -186,12 +187,15 @@
 
         // Allow us to use up to our memory class value before V8's GC kicks in.
         // These values have been determined by experimentation.
-        mLowMemoryUsageThresholdMb = manager.getMemoryClass();
+        mLowMemoryUsageThresholdMb = manager.getLargeMemoryClass();
         // If things get crazy, allow V8 to use up to 3 times our memory class, or a third of the
-        // device's total available memory, whichever is smaller. At that point V8 will start
-        // attempting more aggressive garbage collection.
-        mHighMemoryUsageThresholdMb = Math.min(mLowMemoryUsageThresholdMb * 3,
-                (int) (memInfo.availMem / 3) >> 20);
+        // device's total available memory, whichever is smaller.  This value must be no less
+        // than the low memory threshold.
+        // At that point V8 will start attempting more aggressive garbage collection.
+        mHighMemoryUsageThresholdMb = Math.max(Math.min(mLowMemoryUsageThresholdMb * 3,
+                (int) (memInfo.availMem / 3) >> 20), mLowMemoryUsageThresholdMb);
+        // Avoid constant V8 GC when memory usage equals to working set estimate.
+        mHighUsageDeltaMb = 1;
 
         // Send a message to initialize the WebViewCore.
         Message init = sWebCoreHandler.obtainMessage(
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 796af55..a107c60 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2706,7 +2706,7 @@
             int startPos = (mSelectedPosition != INVALID_POSITION) ?
                     mSelectedPosition - 1 :
                     firstPosition + getChildCount() - 1;
-            if (startPos < 0) {
+            if (startPos < 0 || startPos >= mAdapter.getCount()) {
                 return INVALID_POSITION;
             }
             if (startPos > last) {
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index ff59950..14d0ac5 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -215,6 +215,11 @@
 
     private ViewGroup mMeasureActionButtonParent;
 
+    private final WeakReference<MenuAdapter>[] mAdapterCache =
+            new WeakReference[NUM_TYPES];
+    private final WeakReference<OverflowMenuAdapter>[] mOverflowAdapterCache =
+            new WeakReference[NUM_TYPES];
+
     // Group IDs that have been added as actions - used temporarily, allocated here for reuse.
     private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
 
@@ -1004,6 +1009,12 @@
                     MenuView menuView = menuTypes[i].mMenuView.get();
                     menuView.updateChildren(cleared);
                 }
+
+                MenuAdapter adapter = mAdapterCache[i] == null ? null : mAdapterCache[i].get();
+                if (adapter != null) adapter.notifyDataSetChanged();
+
+                adapter = mOverflowAdapterCache[i] == null ? null : mOverflowAdapterCache[i].get();
+                if (adapter != null) adapter.notifyDataSetChanged();
             }
         }
     }
@@ -1358,7 +1369,13 @@
      * @return A {@link MenuAdapter} for this menu with the given menu type.
      */
     public MenuAdapter getMenuAdapter(int menuType) {
-        return new MenuAdapter(menuType);
+        MenuAdapter adapter = mAdapterCache[menuType] == null ?
+                null : mAdapterCache[menuType].get();
+        if (adapter != null) return adapter;
+
+        adapter = new MenuAdapter(menuType);
+        mAdapterCache[menuType] = new WeakReference<MenuAdapter>(adapter);
+        return adapter;
     }
 
     /**
@@ -1368,7 +1385,13 @@
      * @return A {@link MenuAdapter} for this menu with the given menu type.
      */
     public MenuAdapter getOverflowMenuAdapter(int menuType) {
-        return new OverflowMenuAdapter(menuType);
+        OverflowMenuAdapter adapter = mOverflowAdapterCache[menuType] == null ?
+                null : mOverflowAdapterCache[menuType].get();
+        if (adapter != null) return adapter;
+
+        adapter = new OverflowMenuAdapter(menuType);
+        mOverflowAdapterCache[menuType] = new WeakReference<OverflowMenuAdapter>(adapter);
+        return adapter;
     }
 
     void setOptionalIconsVisible(boolean visible) {
@@ -1469,21 +1492,18 @@
      * source for overflow menu items that do not fit in the list of action items.
      */
     private class OverflowMenuAdapter extends MenuAdapter {
-        private ArrayList<MenuItemImpl> mOverflowItems;
-
         public OverflowMenuAdapter(int menuType) {
             super(menuType);
-            mOverflowItems = getNonActionItems(true);
         }
 
         @Override
         public MenuItemImpl getItem(int position) {
-            return mOverflowItems.get(position);
+            return getNonActionItems(true).get(position);
         }
 
         @Override
         public int getCount() {
-            return mOverflowItems.size();
+            return getNonActionItems(true).size();
         }
     }
 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index e4a89d7..9de270d 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "OpenGLRenderer"
 
+#include <EGL/egl.h>
+
 #include "jni.h"
 #include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
@@ -75,6 +77,23 @@
 } gRectClassInfo;
 
 // ----------------------------------------------------------------------------
+// Misc
+// ----------------------------------------------------------------------------
+
+static jboolean android_view_GLES20Canvas_preserveBackBuffer(JNIEnv* env, jobject clazz) {
+    EGLDisplay display = eglGetCurrentDisplay();
+    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
+
+    eglGetError();
+    eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
+
+    EGLint error = eglGetError();
+    RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
+
+    return error == EGL_SUCCESS;
+}
+
+// ----------------------------------------------------------------------------
 // Constructors
 // ----------------------------------------------------------------------------
 
@@ -97,32 +116,38 @@
 // Setup
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jint width, jint height) {
     renderer->setViewport(width, height);
 }
 
-static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jboolean opaque) {
     renderer->prepare(opaque);
 }
 
-static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
+        OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom,
+        jboolean opaque) {
+    renderer->prepareDirty(left, top, right, bottom, opaque);
+}
+
+static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->finish();
 }
 
-static void android_view_GLES20Canvas_acquireContext(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_acquireContext(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->acquireContext();
 }
 
-static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, Functor *functor) {
     return renderer->callDrawGLFunction(functor);
 }
 
-static void android_view_GLES20Canvas_releaseContext(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_releaseContext(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->releaseContext();
 }
@@ -131,22 +156,22 @@
 // State
 // ----------------------------------------------------------------------------
 
-static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject canvas, OpenGLRenderer* renderer,
+static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer,
         jint flags) {
     return renderer->save(flags);
 }
 
-static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject canvas,
+static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     return renderer->getSaveCount();
 }
 
-static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->restore();
 }
 
-static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jint saveCount) {
     renderer->restoreToCount(saveCount);
 }
@@ -155,13 +180,13 @@
 // Layers
 // ----------------------------------------------------------------------------
 
-static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject canvas,
+static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         SkPaint* paint, jint saveFlags) {
     return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
 }
 
-static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject canvas,
+static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jint alpha, jint saveFlags) {
     return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
@@ -171,25 +196,25 @@
 // Clipping
 // ----------------------------------------------------------------------------
 
-static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         SkCanvas::EdgeType edge) {
     return renderer->quickReject(left, top, right, bottom);
 }
 
-static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         SkRegion::Op op) {
     return renderer->clipRect(left, top, right, bottom, op);
 }
 
-static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jint left, jint top, jint right, jint bottom,
         SkRegion::Op op) {
     return renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
 }
 
-static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject canvas,
+static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jobject rect) {
     const android::uirenderer::Rect& bounds(renderer->getClipBounds());
 
@@ -203,42 +228,42 @@
 // Transforms
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat dx, jfloat dy) {
     renderer->translate(dx, dy);
 }
 
-static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat degrees) {
     renderer->rotate(degrees);
 }
 
-static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
     renderer->scale(sx, sy);
 }
 
-static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat sx, jfloat sy) {
     renderer->skew(sx, sy);
 }
 
-static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkMatrix* matrix) {
     renderer->setMatrix(matrix);
 }
 
 static const float* android_view_GLES20Canvas_getNativeMatrix(JNIEnv* env,
-        jobject canvas, OpenGLRenderer* renderer) {
+        jobject clazz, OpenGLRenderer* renderer) {
     return renderer->getMatrix();
 }
 
-static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkMatrix* matrix) {
     renderer->getMatrix(matrix);
 }
 
-static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkMatrix* matrix) {
     renderer->concatMatrix(matrix);
 }
@@ -247,7 +272,7 @@
 // Drawing
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, float left,
         float top, SkPaint* paint) {
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
@@ -256,7 +281,7 @@
     renderer->drawBitmap(bitmap, left, top, paint);
 }
 
-static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
         float srcLeft, float srcTop, float srcRight, float srcBottom,
         float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) {
@@ -267,7 +292,7 @@
             dstLeft, dstTop, dstRight, dstBottom, paint);
 }
 
-static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, SkMatrix* matrix,
         SkPaint* paint) {
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
@@ -276,7 +301,7 @@
     renderer->drawBitmap(bitmap, matrix, paint);
 }
 
-static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer,
         jint meshWidth, jint meshHeight, jfloatArray vertices, jint offset,
         jintArray colors, jint colorOffset, SkPaint* paint) {
@@ -292,7 +317,7 @@
     if (colors) env->ReleaseIntArrayElements(colors, colorsArray, 0);
 }
 
-static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray buffer, jbyteArray chunks,
         float left, float top, float right, float bottom, SkPaint* paint) {
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
@@ -309,41 +334,41 @@
     env->ReleaseByteArrayElements(chunks, storage, 0);
 }
 
-static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jint color, SkXfermode::Mode mode) {
     renderer->drawColor(color, mode);
 }
 
-static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         SkPaint* paint) {
     renderer->drawRect(left, top, right, bottom, paint);
 }
 
-static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jfloat rx, jfloat ry, SkPaint* paint) {
     renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
 }
 
-static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat x, jfloat y, jfloat radius, SkPaint* paint) {
     renderer->drawCircle(x, y, radius, paint);
 }
 
-static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         SkPaint* paint) {
     renderer->drawOval(left, top, right, bottom, paint);
 }
 
-static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jfloat startAngle, jfloat sweepAngle, jboolean useCenter, SkPaint* paint) {
     renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
 }
 
-static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkRegion* region, SkPaint* paint) {
     SkRegion::Iterator it(*region);
     while (!it.done()) {
@@ -353,12 +378,12 @@
     }
 }
 
-static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkPath* path, SkPaint* paint) {
     renderer->drawPath(path, paint);
 }
 
-static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) {
     jfloat* storage = env->GetFloatArrayElements(points, NULL);
 
@@ -371,24 +396,24 @@
 // Shaders and color filters
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->resetShader();
     renderer->resetColorFilter();
     renderer->resetShadow();
 }
 
-static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkiaShader* shader) {
     renderer->setupShader(shader);
 }
 
-static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setupColorFilter(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, SkiaColorFilter* filter) {
     renderer->setupColorFilter(filter);
 }
 
-static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_setupShadow(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jfloat radius, jfloat dx, jfloat dy, jint color) {
     renderer->setupShadow(radius, dx, dy, color);
 }
@@ -425,7 +450,7 @@
     }
 }
 
-static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
         jfloat x, jfloat y, jint flags, SkPaint* paint) {
     jchar* textArray = env->GetCharArrayElements(text, NULL);
@@ -433,7 +458,7 @@
     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
 }
 
-static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jstring text, jint start, jint end,
         jfloat x, jfloat y, jint flags, SkPaint* paint) {
     const jchar* textArray = env->GetStringChars(text, NULL);
@@ -441,7 +466,7 @@
     env->ReleaseStringChars(text, textArray);
 }
 
-static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jcharArray text, jint index, jint count,
         jint contextIndex, jint contextCount, jfloat x, jfloat y, jint dirFlags,
         SkPaint* paint) {
@@ -451,7 +476,7 @@
     env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
  }
 
-static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, jstring text, jint start, jint end,
         jint contextStart, int contextEnd, jfloat x, jfloat y, jint dirFlags,
         SkPaint* paint) {
@@ -468,7 +493,7 @@
 // ----------------------------------------------------------------------------
 
 static DisplayList* android_view_GLES20Canvas_getDisplayList(JNIEnv* env,
-        jobject canvas, DisplayListRenderer* renderer) {
+        jobject clazz, DisplayListRenderer* renderer) {
     return renderer->getDisplayList();
 }
 
@@ -488,7 +513,7 @@
 }
 
 static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
-        jobject canvas, OpenGLRenderer* renderer, DisplayList* displayList) {
+        jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) {
     return renderer->drawDisplayList(displayList);
 }
 
@@ -496,12 +521,12 @@
 // Layers
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->interrupt();
 }
 
-static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer) {
     renderer->resume();
 }
@@ -547,7 +572,7 @@
     LayerRenderer::destroyLayerDeferred(layer);
 }
 
-static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject canvas,
+static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
         OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
     renderer->drawLayer(layer, x, y, paint);
 }
@@ -576,16 +601,20 @@
     { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
 
 #ifdef USE_OPENGL_RENDERER
+    { "nPreserveBackBuffer", "()Z",            (void*) android_view_GLES20Canvas_preserveBackBuffer },
+
     { "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
     { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
     { "nSetViewport",       "(III)V",          (void*) android_view_GLES20Canvas_setViewport },
     { "nPrepare",           "(IZ)V",           (void*) android_view_GLES20Canvas_prepare },
+    { "nPrepareDirty",      "(IIIIIZ)V",       (void*) android_view_GLES20Canvas_prepareDirty },
     { "nFinish",            "(I)V",            (void*) android_view_GLES20Canvas_finish },
     { "nAcquireContext",    "(I)V",            (void*) android_view_GLES20Canvas_acquireContext },
-    { "nCallDrawGLFunction",    "(II)Z",
-            (void*) android_view_GLES20Canvas_callDrawGLFunction },
     { "nReleaseContext",    "(I)V",            (void*) android_view_GLES20Canvas_releaseContext },
 
+    { "nCallDrawGLFunction", "(II)Z",
+            (void*) android_view_GLES20Canvas_callDrawGLFunction },
+
     { "nSave",              "(II)I",           (void*) android_view_GLES20Canvas_save },
     { "nRestore",           "(I)V",            (void*) android_view_GLES20Canvas_restore },
     { "nRestoreToCount",    "(II)V",           (void*) android_view_GLES20Canvas_restoreToCount },
diff --git a/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png
index bd353ae..00e8f06 100644
--- a/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png
index d127b3c..997ccb2 100644
--- a/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_holo_dark.9.png
deleted file mode 100644
index b86c65a..0000000
--- a/core/res/res/drawable-hdpi/btn_group_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_holo_light.9.png
deleted file mode 100644
index 1248e88..0000000
--- a/core/res/res/drawable-hdpi/btn_group_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png
new file mode 100644
index 0000000..b2120f4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png
new file mode 100644
index 0000000..782d36b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png
index aa04cc9..5894afe 100644
--- a/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png
index 25aefd2..1dfc7d3 100644
--- a/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_group_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_holo_dark.9.png
deleted file mode 100644
index 9541252..0000000
--- a/core/res/res/drawable-mdpi/btn_group_holo_dark.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_holo_light.9.png
deleted file mode 100644
index bf4f9b2..0000000
--- a/core/res/res/drawable-mdpi/btn_group_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png
new file mode 100644
index 0000000..c6257bb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_group_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png
new file mode 100644
index 0000000..7e25ad3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_group_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_group_holo_dark.xml b/core/res/res/drawable/btn_group_holo_dark.xml
new file mode 100644
index 0000000..553f023
--- /dev/null
+++ b/core/res/res/drawable/btn_group_holo_dark.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_group_normal_holo_dark" />
+    <item
+        android:drawable="@drawable/btn_group_disabled_holo_dark" />
+</selector>
diff --git a/core/res/res/drawable/btn_group_holo_light.xml b/core/res/res/drawable/btn_group_holo_light.xml
new file mode 100644
index 0000000..9c89eef
--- /dev/null
+++ b/core/res/res/drawable/btn_group_holo_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="true"
+        android:drawable="@drawable/btn_group_normal_holo_light" />
+    <item
+        android:drawable="@drawable/btn_group_disabled_holo_light" />
+</selector>
diff --git a/core/res/res/drawable/group_button_background_holo_dark.xml b/core/res/res/drawable/group_button_background_holo_dark.xml
deleted file mode 100644
index fa00785..0000000
--- a/core/res/res/drawable/group_button_background_holo_dark.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_window_focused="false" android:drawable="@color/transparent" />
-
-    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
-    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/btn_group_disabled_holo_dark" />
-    <item android:state_focused="true"  android:state_enabled="false"                              android:drawable="@drawable/btn_group_disabled_holo_dark" />
-    <item android:state_focused="true"                                android:state_pressed="true" android:drawable="@drawable/btn_group_pressed_holo_dark" />
-    <item android:state_focused="false"                               android:state_pressed="true" android:drawable="@drawable/btn_group_pressed_holo_dark" />
-    <item android:state_focused="true"                                                             android:drawable="@drawable/btn_group_focused_holo_dark" />
-    <item                                                                                          android:drawable="@color/transparent" />
-</selector>
diff --git a/core/res/res/drawable/group_button_background_holo_light.xml b/core/res/res/drawable/group_button_background_holo_light.xml
deleted file mode 100644
index 1e74ec7..0000000
--- a/core/res/res/drawable/group_button_background_holo_light.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <item android:state_window_focused="false" android:drawable="@color/transparent" />
-
-    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
-    <item android:state_focused="true"  android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/btn_group_disabled_holo_light" />
-    <item android:state_focused="true"  android:state_enabled="false"                              android:drawable="@drawable/btn_group_disabled_holo_light" />
-    <item android:state_focused="true"                                android:state_pressed="true" android:drawable="@drawable/btn_group_pressed_holo_light" />
-    <item android:state_focused="false"                               android:state_pressed="true" android:drawable="@drawable/btn_group_pressed_holo_light" />
-    <item android:state_focused="true"                                                             android:drawable="@drawable/btn_group_focused_holo_light" />
-    <item                                                                                          android:drawable="@color/transparent" />
-</selector>
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
index fab69d8..e4a1b81 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
@@ -74,6 +74,7 @@
             android:layout_height="230dip"
             android:background="#00000000"
             android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+            android:visibility="gone"
         />
 
         <!-- emergency call button -->
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index a768efe..c2106d4 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -629,7 +629,8 @@
     mHeight = height;
 }
 
-void DisplayListRenderer::prepare(bool opaque) {
+void DisplayListRenderer::prepareDirty(float left, float top,
+        float right, float bottom, bool opaque) {
     mSnapshot = new Snapshot(mFirstSnapshot,
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     mSaveCount = 1;
@@ -848,7 +849,7 @@
 
 void DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
         float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
-    addOp(DisplayList::DrawOval);
+    addOp(DisplayList::DrawArc);
     addBounds(left, top, right, bottom);
     addPoint(startAngle, sweepAngle);
     addInt(useCenter ? 1 : 0);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 6c8e8f5..bab5149 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -28,7 +28,7 @@
 #include <SkTSearch.h>
 
 #include "OpenGLRenderer.h"
-#include "Functor.h"
+#include "utils/Functor.h"
 
 namespace android {
 namespace uirenderer {
@@ -241,7 +241,7 @@
     DisplayList* getDisplayList();
 
     void setViewport(int width, int height);
-    void prepare(bool opaque);
+    void prepareDirty(float left, float top, float right, float bottom, bool opaque);
     void finish();
 
     bool callDrawGLFunction(Functor *functor);
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 1c89577..36709dc 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -26,7 +26,7 @@
 // Rendering
 ///////////////////////////////////////////////////////////////////////////////
 
-void LayerRenderer::prepare(bool opaque) {
+void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
 
 #if RENDER_LAYERS_AS_REGIONS
@@ -35,7 +35,7 @@
 
     glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
 
-    OpenGLRenderer::prepare(opaque);
+    OpenGLRenderer::prepareDirty(0.0f, 0.0f, mLayer->width, mLayer->height, opaque);
 }
 
 void LayerRenderer::finish() {
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 1e39847..d2f565e 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -46,7 +46,7 @@
     ~LayerRenderer() {
     }
 
-    void prepare(bool opaque);
+    void prepareDirty(float left, float top, float right, float bottom, bool opaque);
     void finish();
 
     bool hasLayer();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 98f8fc5..4813e93 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -136,6 +136,10 @@
 }
 
 void OpenGLRenderer::prepare(bool opaque) {
+    prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
+}
+
+void OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
     mCaches.clearGarbage();
 
     mSnapshot = new Snapshot(mFirstSnapshot,
@@ -146,15 +150,14 @@
 
     glDisable(GL_DITHER);
 
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
+    mSnapshot->setClip(left, top, right, bottom);
+
     if (!opaque) {
-        glDisable(GL_SCISSOR_TEST);
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT);
     }
-
-    glEnable(GL_SCISSOR_TEST);
-    glScissor(0, 0, mWidth, mHeight);
-    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
 }
 
 void OpenGLRenderer::finish() {
@@ -1210,8 +1213,7 @@
         const bool pureTranslate = mSnapshot->transform->isPureTranslate();
 #if RENDER_LAYERS_AS_REGIONS
         // Mark the current layer dirty where we are going to draw the patch
-        if ((mSnapshot->flags & Snapshot::kFlagFboTarget) &&
-                mSnapshot->region && mesh->hasEmptyQuads) {
+        if (hasLayer() && mesh->hasEmptyQuads) {
             const size_t count = mesh->quads.size();
             for (size_t i = 0; i < count; i++) {
                 const Rect& bounds = mesh->quads.itemAt(i);
@@ -1607,6 +1609,7 @@
     layer->alpha = alpha;
     layer->mode = mode;
 
+    LOGD("Drawing layer with alpha = %d", alpha);
 
 #if RENDER_LAYERS_AS_REGIONS
     if (!layer->region.isEmpty()) {
@@ -1614,11 +1617,12 @@
             const Rect r(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight());
             composeLayerRect(layer, r);
         } else if (layer->mesh) {
+            const float a = alpha / 255.0f;
             const Rect& rect = layer->layer;
 
             setupDraw();
             setupDrawWithTexture();
-            setupDrawColor(alpha, alpha, alpha, alpha);
+            setupDrawColor(a, a, a, a);
             setupDrawColorFilter();
             setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
             setupDrawProgram();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index bd29609..77de1d2 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -62,7 +62,8 @@
 
     virtual void setViewport(int width, int height);
 
-    virtual void prepare(bool opaque);
+    void prepare(bool opaque);
+    virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
 
     // These two calls must not be recorded in display lists
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 11d0bdc..40cb5c7 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -735,6 +735,8 @@
     mWorkers.mRunningCount = (int)mWorkers.mCount;
     for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) {
         mWorkers.mLaunchSignals[ct].set();
+    }
+    for (uint32_t ct = 0; ct < mWorkers.mCount; ct++) {
         int status = pthread_join(mWorkers.mThreadId[ct], &res);
     }
     rsAssert(!mWorkers.mRunningCount);
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index eb2af1c..3f88543 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -76,7 +76,8 @@
 }
 
 bool LocklessCommandFifo::isEmpty() const {
-    return mPut == mGet;
+    uint32_t p = android_atomic_acquire_load((int32_t *)&mPut);
+    return ((uint8_t *)p) == mGet;
 }
 
 
@@ -155,7 +156,9 @@
 
 void LocklessCommandFifo::next() {
     uint32_t bytes = reinterpret_cast<const uint16_t *>(mGet)[1];
-    mGet += ((bytes + 3) & ~3) + 4;
+
+    android_atomic_add(((bytes + 3) & ~3) + 4, (int32_t *)&mGet);
+    //mGet += ((bytes + 3) & ~3) + 4;
     if (isEmpty()) {
         mSignalToControl.set();
     }
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 11e27a9..925f965 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -299,12 +299,16 @@
         String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
 
         if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
-            output[0] = convertRationalLatLonToFloat(latValue, latRef);
-            output[1] = convertRationalLatLonToFloat(lngValue, lngRef);
-            return true;
-        } else {
-            return false;
+            try {
+                output[0] = convertRationalLatLonToFloat(latValue, latRef);
+                output[1] = convertRationalLatLonToFloat(lngValue, lngRef);
+                return true;
+            } catch (IllegalArgumentException e) {
+                // if values are not parseable
+            }
         }
+
+        return false;
     }
 
     /**
@@ -373,12 +377,12 @@
 
             String [] pair;
             pair = parts[0].split("/");
-            int degrees = (int) (Float.parseFloat(pair[0].trim())
-                    / Float.parseFloat(pair[1].trim()));
+            double degrees = Double.parseDouble(pair[0].trim())
+                    / Double.parseDouble(pair[1].trim());
 
             pair = parts[1].split("/");
-            int minutes = (int) ((Float.parseFloat(pair[0].trim())
-                    / Float.parseFloat(pair[1].trim())));
+            double minutes = Double.parseDouble(pair[0].trim())
+                    / Double.parseDouble(pair[1].trim());
 
             pair = parts[2].split("/");
             double seconds = Double.parseDouble(pair[0].trim())
@@ -389,10 +393,12 @@
                 return (float) -result;
             }
             return (float) result;
-        } catch (RuntimeException ex) {
-            // if for whatever reason we can't parse the lat long then return
-            // null
-            return 0f;
+        } catch (NumberFormatException e) {
+            // Some of the nubmers are not valid
+            throw new IllegalArgumentException();
+        } catch (ArrayIndexOutOfBoundsException e) {
+            // Some of the rational does not follow the correct format
+            throw new IllegalArgumentException();
         }
     }
 
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 77b7dc8..8156439 100755
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -30,6 +30,9 @@
 import android.util.Log;
 import android.util.Pair;
 import android.view.Surface;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
 
 /**
  *This class provide Native methods to be used by MediaArtist {@hide}
@@ -67,7 +70,10 @@
     private boolean mExportDone = false;
 
     private int mProgressToApp;
-
+    /**
+     *  The resize paint
+     */
+    private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
 
     public static final int TASK_LOADING_SETTINGS = 1;
 
@@ -3838,11 +3844,39 @@
             throw new IllegalArgumentException();
         }
 
-        IntBuffer rgb888 = IntBuffer.allocate(width * height * 4);
-        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        nativeGetPixels(inputFile, rgb888.array(), width, height, timeMS);
-        bitmap.copyPixelsFromBuffer(rgb888);
+        int newWidth = 0;
+        int newHeight = 0;
+        Bitmap tempBitmap = null;
 
+        /* Make width and height as even */
+        newWidth = (width + 1) & 0xFFFFFFFE;
+        newHeight = (height + 1) & 0xFFFFFFFE;
+
+        /* Create a temp bitmap for resized thumbnails */
+        if ((newWidth != width) || (newHeight != height)) {
+             tempBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
+        }
+
+        IntBuffer rgb888 = IntBuffer.allocate(newWidth * newHeight * 4);
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        nativeGetPixels(inputFile, rgb888.array(), newWidth, newHeight, timeMS);
+
+        if ((newWidth == width) && (newHeight == height)) {
+            bitmap.copyPixelsFromBuffer(rgb888);
+        } else {
+            /* Create a temp bitmap to be used for resize */
+            tempBitmap.copyPixelsFromBuffer(rgb888);
+
+            /* Create a canvas to resize */
+            final Canvas canvas = new Canvas(bitmap);
+            canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
+                                          new Rect(0, 0, width, height),
+                                          sResizePaint);
+        }
+
+        if (tempBitmap != null) {
+            tempBitmap.recycle();
+        }
         return bitmap;
     }
 
@@ -3863,11 +3897,24 @@
     public Bitmap[] getPixelsList(String filename, int width, int height, long startMs, long endMs,
             int thumbnailCount) {
         int[] rgb888 = null;
-        int thumbnailSize = width * height * 4;
+        int thumbnailSize = 0;
+        int newWidth = 0;
+        int newHeight = 0;
+        Bitmap tempBitmap = null;
 
+        /* Make width and height as even */
+        newWidth = (width + 1) & 0xFFFFFFFE;
+        newHeight = (height + 1) & 0xFFFFFFFE;
+        thumbnailSize = newWidth * newHeight * 4;
+
+        /* Create a temp bitmap for resized thumbnails */
+        if ((newWidth != width) || (newHeight != height)) {
+            tempBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
+        }
         int i = 0;
         int deltaTime = (int)(endMs - startMs) / thumbnailCount;
         Bitmap[] bitmap = null;
+
         try {
             // This may result in out of Memory Error
             rgb888 = new int[thumbnailSize * thumbnailCount];
@@ -3880,19 +3927,35 @@
                 bitmap = new Bitmap[MAX_THUMBNAIL_PERMITTED];
                 thumbnailCount = MAX_THUMBNAIL_PERMITTED;
             } catch (Throwable ex) {
-                throw new RuntimeException("Memory allocation fails,reduce nos of thumbanail count");
+                throw new RuntimeException("Memory allocation fails, thumbnail count too large: "+thumbnailCount);
             }
         }
         IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize);
-        nativeGetPixelsList(filename, rgb888, width, height, deltaTime, thumbnailCount, startMs,
+        nativeGetPixelsList(filename, rgb888, newWidth, newHeight, deltaTime, thumbnailCount, startMs,
                 endMs);
+
         for (; i < thumbnailCount; i++) {
             bitmap[i] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
             tmpBuffer.put(rgb888, (i * thumbnailSize), thumbnailSize);
             tmpBuffer.rewind();
-            bitmap[i].copyPixelsFromBuffer(tmpBuffer);
+
+            if ((newWidth == width) && (newHeight == height)) {
+                bitmap[i].copyPixelsFromBuffer(tmpBuffer);
+            } else {
+                /* Copy the out rgb buffer to temp bitmap */
+                tempBitmap.copyPixelsFromBuffer(tmpBuffer);
+
+                /* Create a canvas to resize */
+                final Canvas canvas = new Canvas(bitmap[i]);
+                canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight),
+                                              new Rect(0, 0, width, height),
+                                              sResizePaint);
+            }
         }
 
+        if (tempBitmap != null) {
+            tempBitmap.recycle();
+        }
         return bitmap;
     }
 
@@ -3942,8 +4005,8 @@
         }
     }
 
-    public void clearPreviewSurface(Surface surface, int width, int height) {
-       nativeClearSurface(surface,width,height);
+    public void clearPreviewSurface(Surface surface) {
+       nativeClearSurface(surface);
     }
     /**     Native Methods        */
     native Properties getMediaProperties(String file) throws IllegalArgumentException,
@@ -3990,7 +4053,7 @@
     /*
      * Clear the preview surface
      */
-    public native void nativeClearSurface(Surface surface, int width, int height);
+    private native void nativeClearSurface(Surface surface);
 
 
     /**
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index 1c02878..a977b8e 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -1013,9 +1013,20 @@
 
             if (dx > dy) {
                 bitmapWidth = width;
-                bitmapHeight = Math.round(nativeHeight / dx);
+
+                if (((float)nativeHeight / dx) < (float)height) {
+                    bitmapHeight = (float)Math.ceil(nativeHeight / dx);
+                } else { // value equals the requested height
+                    bitmapHeight = (float)Math.floor(nativeHeight / dx);
+                }
+
             } else {
-                bitmapWidth = Math.round(nativeWidth / dy);
+                if (((float)nativeWidth / dy) > (float)width) {
+                    bitmapWidth = (float)Math.floor(nativeWidth / dy);
+                } else { // value equals the requested width
+                    bitmapWidth = (float)Math.ceil(nativeWidth / dy);
+                }
+
                 bitmapHeight = height;
             }
 
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index 5b87d16..c19725c 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -1828,9 +1828,6 @@
       if (surfaceHolder == null) {
          throw new IllegalArgumentException();
        }
-      Rect frame;
-      int surfaceWidth;
-      int surfaceHeight;
       Surface surface = surfaceHolder.getSurface();
 
       if (surface == null) {
@@ -1838,10 +1835,7 @@
         "Surface could not be retrieved from surface holder");
         throw new RuntimeException();
       }
-      frame = surfaceHolder.getSurfaceFrame();
-      surfaceWidth = frame.width();
-      surfaceHeight = frame.height();
-      mMANativeHelper.clearPreviewSurface(surface,surfaceWidth,surfaceHeight);
+      mMANativeHelper.clearPreviewSurface(surface);
     }
 
 }
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 1751396..8ce788b 100755
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -261,9 +261,7 @@
 
 static void videoEditor_clearSurface(JNIEnv* pEnv,
                                     jobject thiz,
-                                    jobject surface,
-                                    jint width,
-                                    jint height);
+                                    jobject surface);
 
 static JNINativeMethod gManualEditMethods[] = {
     {"getVersion",               "()L"VERSION_CLASS_NAME";",
@@ -300,7 +298,7 @@
                                 (int *)videoEditor_generateAudioRawFile      },
     {"nativeGenerateClip",      "(L"EDIT_SETTINGS_CLASS_NAME";)I",
                                 (void *)videoEditor_generateClip  },
-    {"nativeClearSurface",       "(Landroid/view/Surface;II)V",
+    {"nativeClearSurface",       "(Landroid/view/Surface;)V",
                                 (void *)videoEditor_clearSurface  },
 };
 
@@ -428,16 +426,15 @@
 
 static void videoEditor_clearSurface(JNIEnv* pEnv,
                                     jobject thiz,
-                                    jobject surface,
-                                    jint width,
-                                    jint height)
+                                    jobject surface)
 {
     bool needToBeLoaded = true;
-    M4OSA_UInt32 framesizeYuv =0;
     M4OSA_ERR result = M4NO_ERROR;
     VideoEditor_renderPreviewFrameStr frameStr;
     const char* pMessage = NULL;
-    M4VIFI_ImagePlane *yuvPlane;
+    // Let the size be QVGA
+    int width = 320;
+    int height = 240;
     ManualEditContext* pContext = M4OSA_NULL;
 
     // Get the context.
@@ -474,62 +471,7 @@
     Surface* const p = (Surface*)pEnv->GetIntField(surface, surface_native);
     sp<Surface> previewSurface = sp<Surface>(p);
 
-    /**
-    * Allocate output YUV planes
-    */
-    yuvPlane = (M4VIFI_ImagePlane*)M4OSA_malloc(3*sizeof(M4VIFI_ImagePlane), M4VS,
-        (M4OSA_Char*)"videoEditor_clearSurface Output plane YUV");
-    if (yuvPlane == M4OSA_NULL) {
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "videoEditor_clearSurface() malloc error for yuv plane");
-        pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
-        jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-        return ;
-    }
-
-    framesizeYuv = width * height * 1.5;
-    yuvPlane[0].u_width = width;
-    yuvPlane[0].u_height = height;
-    yuvPlane[0].u_topleft = 0;
-    yuvPlane[0].u_stride = width;
-    yuvPlane[0].pac_data = (M4VIFI_UInt8 *)M4OSA_malloc(framesizeYuv, M4VS,
-            (M4OSA_Char*)"videoEditor pixelArray");
-    if (yuvPlane[0].pac_data == M4OSA_NULL) {
-       VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-       "videoEditor_renderPreviewFrame() malloc error");
-       pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
-       jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-       return;
-    }
-
-    /* memset yuvPlane[0].pac_data with 0 for black frame */
-    M4OSA_memset((M4OSA_MemAddr8)yuvPlane[0].pac_data,framesizeYuv,0x00);
-    FILE *p1 = fopen("/mnt/sdcard/black.raw","wb");
-    fwrite(yuvPlane[0].pac_data,1,framesizeYuv,p1);
-    fclose(p1);
-
-    yuvPlane[1].u_width = width>>1;
-    yuvPlane[1].u_height = height>>1;
-    yuvPlane[1].u_topleft = 0;
-    yuvPlane[1].u_stride = width>>1;
-    yuvPlane[1].pac_data = yuvPlane[0].pac_data
-                + yuvPlane[0].u_width * yuvPlane[0].u_height;
-
-    M4OSA_memset((M4OSA_MemAddr8)yuvPlane[1].pac_data,yuvPlane[1].u_width *
-                                yuvPlane[1].u_height,128);
-    yuvPlane[2].u_width = (width)>>1;
-    yuvPlane[2].u_height = (height)>>1;
-    yuvPlane[2].u_topleft = 0;
-    yuvPlane[2].u_stride = (width)>>1;
-    yuvPlane[2].pac_data = yuvPlane[1].pac_data
-                + yuvPlane[1].u_width * yuvPlane[1].u_height;
-
-    M4OSA_memset((M4OSA_MemAddr8)yuvPlane[2].pac_data,yuvPlane[2].u_width *
-                                 yuvPlane[2].u_height,128);
-
-    /* Fill up the render structure*/
-    frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data;
-
+    frameStr.pBuffer = M4OSA_NULL;
     frameStr.timeMs = 0;
     frameStr.uiSurfaceWidth = width;
     frameStr.uiSurfaceHeight = height;
@@ -539,19 +481,11 @@
     frameStr.clipBeginCutTime = 0;
     frameStr.clipEndCutTime = 0;
 
-    /*pContext->mPreviewController->setPreviewFrameRenderingMode(
-        pContext->pEditSettings->\
-        pClipList[iCurrentClipIndex]->xVSS.MediaRendering,
-        pContext->pEditSettings->xVSS.outputVideoSize);
-     */
-
-    result = pContext->mPreviewController->renderPreviewFrame(previewSurface,
+    result = pContext->mPreviewController->clearSurface(previewSurface,
                                                               &frameStr);
     videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
             (M4NO_ERROR != result), result);
 
-    M4OSA_free((M4OSA_MemAddr32)yuvPlane[0].pac_data);
-    M4OSA_free((M4OSA_MemAddr32)yuvPlane);
   }
 
 static int videoEditor_renderPreviewFrame(JNIEnv* pEnv,
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
index 3028a42..3fef7e0 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
@@ -47,12 +47,11 @@
                 android:id="@+id/item_radio"
                 android:layout_width="30dip"
                 android:layout_height="wrap_content"
-                android:layout_marginRight="11dip"
                 android:focusable="false"
                 android:clickable="false" />
             <ImageView
                 android:id="@+id/item_icon"
-                android:layout_width="wrap_content"
+                android:layout_width="@android:dimen/app_icon_size"
                 android:layout_height="wrap_content"
                 android:scaleType="fitCenter" />
             <LinearLayout
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index a3ccef9..06c789c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -36,9 +36,12 @@
 import android.widget.RadioButton;
 import android.widget.TextView;
 
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import com.android.systemui.R;
 
@@ -47,9 +50,10 @@
     private static final String TAG = "InputMethodsPanel";
 
     private final InputMethodManager mImm;
-    private final HashMap<InputMethodInfo, List<InputMethodSubtype>>
+    private final TreeMap<InputMethodInfo, List<InputMethodSubtype>>
             mEnabledInputMethodAndSubtypesCache =
-                    new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
+                    new TreeMap<InputMethodInfo, List<InputMethodSubtype>>(
+                            new InputMethodComparator());
     private final HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>> mRadioViewAndImiMap =
             new HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>>();
 
@@ -61,6 +65,21 @@
     private String mEnabledInputMethodAndSubtypesCacheStr;
     private View mConfigureImeShortcut;
 
+    private class InputMethodComparator implements Comparator<InputMethodInfo> {
+        public int compare(InputMethodInfo imi1, InputMethodInfo imi2) {
+            if (imi2 == null) return 0;
+            if (imi1 == null) return 1;
+            if (mPackageManager != null) {
+                CharSequence imiId1 = imi1.loadLabel(mPackageManager);
+                CharSequence imiId2 = imi2.loadLabel(mPackageManager);
+                if (imiId1 != null && imiId2 != null) {
+                    return imiId1.toString().compareTo(imiId2.toString());
+                }
+            }
+            return imi1.getId().compareTo(imi2.getId());
+        }
+    }
+
     public InputMethodsPanel(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
@@ -190,8 +209,8 @@
         mRadioViewAndImiMap.clear();
         mPackageManager = mContext.getPackageManager();
 
-        HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs
-                = getEnabledInputMethodAndSubtypeList();
+        Map<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs =
+                getEnabledInputMethodAndSubtypeList();
         // TODO: Sort by alphabet and mode.
         Set<InputMethodInfo> cachedImiSet = enabledIMIs.keySet();
         for (InputMethodInfo imi: cachedImiSet) {
@@ -278,7 +297,7 @@
         }
     }
 
-    private HashMap<InputMethodInfo, List<InputMethodSubtype>>
+    private TreeMap<InputMethodInfo, List<InputMethodSubtype>>
             getEnabledInputMethodAndSubtypeList() {
         String newEnabledIMIs = Settings.Secure.getString(
                 mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index e26b8ea..9549930 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -81,7 +81,7 @@
 
     public static final int MAX_NOTIFICATION_ICONS = 5;
     // IME switcher icon is big and occupy width of two icons
-    public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 2;
+    public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 1;
 
     public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
     public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
@@ -860,11 +860,8 @@
         if (DEBUG) {
             Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
         }
-        int oldVisibility = mInputMethodSwitchButton.getVisibility();
         mInputMethodSwitchButton.setIMEButtonVisible(token, visible);
-        if (oldVisibility != mInputMethodSwitchButton.getVisibility()) {
-            updateNotificationIcons();
-        }
+        updateNotificationIcons();
         mInputMethodsPanel.setImeToken(token);
         mBackButton.setImageResource(
                 visible ? R.drawable.ic_sysbar_back_ime : R.drawable.ic_sysbar_back);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 21c1e81..0147b1a 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1356,14 +1356,27 @@
 
     public boolean switchToLastInputMethod(IBinder token) {
         synchronized (mMethodMap) {
-            Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
-            if (lastIme != null) {
-                InputMethodInfo imi = mMethodMap.get(lastIme.first);
-                if (imi != null) {
-                    setInputMethodWithSubtypeId(token, lastIme.first, getSubtypeIdFromHashCode(
-                            imi, Integer.valueOf(lastIme.second)));
-                    return true;
+            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
+            if (lastIme == null) return false;
+            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
+            if (lastImi == null) return false;
+
+            final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
+            final int lastSubtypeHash = Integer.valueOf(lastIme.second);
+            // If the last IME is the same as the current IME and the last subtype is not defined,
+            // there is no need to switch to the last IME.
+            if (imiIdIsSame && lastSubtypeHash == NOT_A_SUBTYPE_ID) return false;
+
+            int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
+                    : mCurrentSubtype.hashCode();
+            if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second + ", from: "
+                            + mCurMethodId + ", " + currentSubtypeHash);
                 }
+                setInputMethodWithSubtypeId(token, lastIme.first, getSubtypeIdFromHashCode(
+                        lastImi, lastSubtypeHash));
+                return true;
             }
             return false;
         }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 059c0b8..5806de2 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2087,7 +2087,7 @@
                 return (List<ResolveInfo>) mActivities.queryIntentForPackage(intent,
                         resolvedType, flags, pkg.activities);
             }
-            return null;
+            return new ArrayList<ResolveInfo>();
         }
     }
 
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index dd9db9a..26c7e71 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -31,6 +31,7 @@
 import android.net.InterfaceConfiguration;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
+import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.os.Binder;
 import android.os.Environment;
@@ -1219,7 +1220,20 @@
             }
             protected String findActiveUpstreamIface() {
                 // check for what iface we can use - if none found switch to error.
-                IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
+                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
+
+                try {
+                    LinkProperties defaultProp = cm.getActiveLinkProperties();
+                    if (defaultProp != null) {
+                        String iface = defaultProp.getInterfaceName();
+                        for(String regex : mUpstreamIfaceRegexs) {
+                            if (iface.matches(regex)) return iface;
+                        }
+                    }
+                } catch (RemoteException e) { }
+
+                b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
                 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
 
                 String[] ifaces = new String[0];
@@ -1390,7 +1404,8 @@
                         }
                         break;
                     case CMD_UPSTREAM_CHANGED:
-                        mTryCell = WAIT_FOR_NETWORK_TO_SETTLE;
+                        // need to try DUN immediately if Wifi goes down
+                        mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
                         chooseUpstreamType(mTryCell);
                         mTryCell = !mTryCell;
                         break;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 694af70..291ebc5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2170,8 +2170,6 @@
 
     GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
 
-    LOGD("screenshot: FBO created, status=0x%x", status);
-
     if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
 
         // invert everything, b/c glReadPixel() below will invert the FB
@@ -2187,8 +2185,6 @@
         glClearColor(0,0,0,1);
         glClear(GL_COLOR_BUFFER_BIT);
 
-        LOGD("screenshot: glClear() issued");
-
         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
         const size_t count = layers.size();
         for (size_t i=0 ; i<count ; ++i) {
@@ -2199,8 +2195,6 @@
             }
         }
 
-        LOGD("screenshot: All layers rendered");
-
         // XXX: this is needed on tegra
         glScissor(0, 0, sw, sh);
 
@@ -2215,10 +2209,6 @@
                     new MemoryHeapBase(size, 0, "screen-capture") );
             void* const ptr = base->getBase();
             if (ptr) {
-
-                LOGD("screenshot: about to call glReadPixels(0,0,%d,%d,...,%p)",
-                        sw, sh, ptr);
-
                 // capture the screen with glReadPixels()
                 glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
                 if (glGetError() == GL_NO_ERROR) {
@@ -2231,9 +2221,6 @@
             } else {
                 result = NO_MEMORY;
             }
-
-            LOGD("screenshot: glReadPixels() returned %s", strerror(result));
-
         }
         glEnable(GL_SCISSOR_TEST);
         glViewport(0, 0, hw_w, hw_h);
@@ -2244,18 +2231,14 @@
         result = BAD_VALUE;
     }
 
-    LOGD("screenshot: about to release FBO resources");
-
     // release FBO resources
     glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
     glDeleteRenderbuffersOES(1, &tname);
     glDeleteFramebuffersOES(1, &name);
 
-    LOGD("screenshot: about to call compositionComplete()");
-
     hw.compositionComplete();
 
-    LOGD("screenshot: result = %s", strerror(result));
+    LOGD("screenshot: result = %s", result<0 ? strerror(result) : "OK");
 
     return result;
 }
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 61f8e1a..2895b69 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -18,7 +18,7 @@
     package="com.android.test.hwui">
 
     <uses-permission android:name="android.permission.INTERNET" />
-    <uses-sdk android:minSdkVersion="Honeycomb" />
+    <uses-sdk android:minSdkVersion="11" />
     
     <application
         android:label="HwUi"
diff --git a/tests/HwAccelerationTest/default.properties b/tests/HwAccelerationTest/default.properties
index 5a8ea50..da2dcdd 100644
--- a/tests/HwAccelerationTest/default.properties
+++ b/tests/HwAccelerationTest/default.properties
@@ -8,4 +8,4 @@
 # project structure.
 
 # Project target.
-target=android-Froyo
+target=android-Honeycomb