Merge "Add support for specifying Drawable color filter in XML"
diff --git a/api/current.txt b/api/current.txt
index 27db398..76c30fa 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11064,7 +11064,6 @@
     method public abstract int setRepeatingBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract int setRepeatingRequest(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void stopRepeating() throws android.hardware.camera2.CameraAccessException;
-    method public abstract void waitUntilIdle() throws android.hardware.camera2.CameraAccessException;
     field public static final int TEMPLATE_PREVIEW = 1; // 0x1
     field public static final int TEMPLATE_RECORD = 3; // 0x3
     field public static final int TEMPLATE_STILL_CAPTURE = 2; // 0x2
@@ -13190,6 +13189,7 @@
     ctor public MediaRecorder();
     method public static final int getAudioSourceMax();
     method public int getMaxAmplitude() throws java.lang.IllegalStateException;
+    method public android.view.Surface getSurface();
     method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
     method public void release();
     method public void reset();
@@ -13274,6 +13274,7 @@
   public final class MediaRecorder.VideoSource {
     field public static final int CAMERA = 1; // 0x1
     field public static final int DEFAULT = 0; // 0x0
+    field public static final int SURFACE = 2; // 0x2
   }
 
   public class MediaRouter {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 40899c0..3725cd4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -100,6 +100,8 @@
 import com.android.org.conscrypt.OpenSSLSocketImpl;
 import com.google.android.collect.Lists;
 
+import dalvik.system.VMRuntime;
+
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
@@ -748,6 +750,9 @@
 
             setCoreSettings(coreSettings);
 
+            // Tell the VMRuntime about the application.
+            VMRuntime.registerAppInfo(appInfo.dataDir, appInfo.processName);
+
             AppBindData data = new AppBindData();
             data.processName = processName;
             data.appInfo = appInfo;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index ddefc70..22322e3 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -412,27 +412,28 @@
      *             if an i/o error occurs.
      */
     /*package*/ void flush() throws IOException {
+        if (mSocketOS == null) throw new IOException("flush is called on null OutputStream");
         if (VDBG) Log.d(TAG, "flush: " + mSocketOS);
         mSocketOS.flush();
     }
 
     /*package*/ int read(byte[] b, int offset, int length) throws IOException {
-
-            if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
-            int ret = mSocketIS.read(b, offset, length);
-            if(ret < 0)
-                throw new IOException("bt socket closed, read return: " + ret);
-            if (VDBG) Log.d(TAG, "read out:  " + mSocketIS + " ret: " + ret);
-            return ret;
+        if (mSocketIS == null) throw new IOException("read is called on null InputStream");
+        if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
+        int ret = mSocketIS.read(b, offset, length);
+        if(ret < 0)
+            throw new IOException("bt socket closed, read return: " + ret);
+        if (VDBG) Log.d(TAG, "read out:  " + mSocketIS + " ret: " + ret);
+        return ret;
     }
 
     /*package*/ int write(byte[] b, int offset, int length) throws IOException {
-
-            if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
-            mSocketOS.write(b, offset, length);
-            // There is no good way to confirm since the entire process is asynchronous anyway
-            if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
-            return length;
+        if (mSocketOS == null) throw new IOException("write is called on null OutputStream");
+        if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
+        mSocketOS.write(b, offset, length);
+        // There is no good way to confirm since the entire process is asynchronous anyway
+        if (VDBG) Log.d(TAG, "write out: " + mSocketOS + " length: " + length);
+        return length;
     }
 
     @Override
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 9e8d7d1..42880af 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -501,31 +501,6 @@
     public void stopRepeating() throws CameraAccessException;
 
     /**
-     * <p>Wait until all the submitted requests have finished processing</p>
-     *
-     * <p>This method blocks until all the requests that have been submitted to
-     * the camera device, either through {@link #capture capture},
-     * {@link #captureBurst captureBurst},
-     * {@link #setRepeatingRequest setRepeatingRequest}, or
-     * {@link #setRepeatingBurst setRepeatingBurst}, have completed their
-     * processing.</p>
-     *
-     * <p>Once this call returns successfully, the device is in an idle state,
-     * and can be reconfigured with {@link #configureOutputs configureOutputs}.</p>
-     *
-     * <p>This method cannot be used if there is an active repeating request or
-     * burst, set with {@link #setRepeatingRequest setRepeatingRequest} or
-     * {@link #setRepeatingBurst setRepeatingBurst}. Call
-     * {@link #stopRepeating stopRepeating} before calling this method.</p>
-     *
-     * @throws CameraAccessException if the camera device is no longer connected
-     * @throws IllegalStateException if the camera device has been closed, the
-     * device has encountered a fatal error, or if there is an active repeating
-     * request or burst.
-     */
-    public void waitUntilIdle() throws CameraAccessException;
-
-    /**
      * Flush all captures currently pending and in-progress as fast as
      * possible.
      *
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 40586f0..2c8a5c2 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -106,9 +106,7 @@
 
     private final Runnable mCallOnClosed = new Runnable() {
         public void run() {
-            if (!CameraDevice.this.isClosed()) {
-                mDeviceListener.onClosed(CameraDevice.this);
-            }
+            mDeviceListener.onClosed(CameraDevice.this);
         }
     };
 
@@ -351,8 +349,7 @@
         }
     }
 
-    @Override
-    public void waitUntilIdle() throws CameraAccessException {
+    private void waitUntilIdle() throws CameraAccessException {
 
         synchronized (mLock) {
             checkIfCameraClosed();
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index 4dade20..de46a4a 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -36,16 +36,16 @@
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
-    private int mReceiverPtr;
+    private long mReceiverPtr;
 
     // We keep a reference message queue object here so that it is not
     // GC'd while the native peer of the receiver is using them.
     private MessageQueue mMessageQueue;
 
-    private static native int nativeInit(DisplayEventReceiver receiver,
+    private static native long nativeInit(DisplayEventReceiver receiver,
             MessageQueue messageQueue);
-    private static native void nativeDispose(int receiverPtr);
-    private static native void nativeScheduleVsync(int receiverPtr);
+    private static native void nativeDispose(long receiverPtr);
+    private static native void nativeScheduleVsync(long receiverPtr);
 
     /**
      * Creates a display event receiver.
diff --git a/core/java/android/view/RemoteGLRenderer.java b/core/java/android/view/RemoteGLRenderer.java
index 6195fcb..0862458 100644
--- a/core/java/android/view/RemoteGLRenderer.java
+++ b/core/java/android/view/RemoteGLRenderer.java
@@ -16,40 +16,11 @@
 
 package android.view;
 
-import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_BAD_NATIVE_WINDOW;
-import static javax.microedition.khronos.egl.EGL10.EGL_BLUE_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_CONFIG_CAVEAT;
-import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_DEPTH_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_DRAW;
-import static javax.microedition.khronos.egl.EGL10.EGL_GREEN_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_HEIGHT;
-import static javax.microedition.khronos.egl.EGL10.EGL_NONE;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_CONTEXT;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_SURFACE;
-import static javax.microedition.khronos.egl.EGL10.EGL_RED_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_RENDERABLE_TYPE;
-import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLES;
-import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLE_BUFFERS;
-import static javax.microedition.khronos.egl.EGL10.EGL_STENCIL_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_SUCCESS;
-import static javax.microedition.khronos.egl.EGL10.EGL_SURFACE_TYPE;
-import static javax.microedition.khronos.egl.EGL10.EGL_WIDTH;
-import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT;
-
-import android.content.ComponentCallbacks2;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
-import android.opengl.EGL14;
-import android.opengl.GLUtils;
-import android.opengl.ManagedEGLContext;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
@@ -58,19 +29,9 @@
 import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
 
-import com.google.android.gles_jni.EGLImpl;
-
 import java.io.PrintWriter;
 import java.util.concurrent.locks.ReentrantLock;
 
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
-
 /**
  * Hardware renderer using OpenGL that's used as the remote endpoint
  * of ThreadedRenderer
@@ -119,21 +80,8 @@
     private static final int OVERDRAW_TYPE_COUNT = 1;
     private static final int GL_VERSION = 2;
 
-    static EGL10 sEgl;
-    static EGLDisplay sEglDisplay;
-    static EGLConfig sEglConfig;
-    static final Object[] sEglLock = new Object[0];
     int mWidth = -1, mHeight = -1;
 
-    static final ThreadLocal<ManagedEGLContext> sEglContextStorage
-            = new ThreadLocal<ManagedEGLContext>();
-
-    EGLContext mEglContext;
-    Thread mEglThread;
-
-    EGLSurface mEglSurface;
-
-    GL mGl;
     HardwareCanvas mCanvas;
 
     String mName;
@@ -141,17 +89,8 @@
     long mFrameCount;
     Paint mDebugPaint;
 
-    static boolean sDirtyRegions;
-    static final boolean sDirtyRegionsRequested;
-    static {
-        String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        sDirtyRegions = "true".equalsIgnoreCase(dirtyProperty);
-        sDirtyRegionsRequested = sDirtyRegions;
-    }
-
     boolean mDirtyRegionsEnabled;
-    boolean mUpdateDirtyRegions;
+    boolean mSurfaceUpdated;
 
     boolean mProfileEnabled;
     int mProfileVisualizerType = -1;
@@ -170,8 +109,6 @@
 
     final boolean mTranslucent;
 
-    private boolean mDestroyed;
-
     private final Rect mRedrawClip = new Rect();
 
     private final int[] mSurfaceSize = new int[2];
@@ -183,84 +120,12 @@
 
     private DisplayMetrics mDisplayMetrics;
     private ThreadedRenderer mOwningRenderer;
-
-    private static EGLSurface sPbuffer;
-    private static final Object[] sPbufferLock = new Object[0];
-
-    private static class GLRendererEglContext extends ManagedEGLContext {
-        final Handler mHandler = new Handler();
-
-        public GLRendererEglContext(EGLContext context) {
-            super(context);
-        }
-
-        @Override
-        public void onTerminate(final EGLContext eglContext) {
-            // Make sure we do this on the correct thread.
-            if (mHandler.getLooper() != Looper.myLooper()) {
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        onTerminate(eglContext);
-                    }
-                });
-                return;
-            }
-
-            synchronized (sEglLock) {
-                if (sEgl == null) return;
-
-                if (EGLImpl.getInitCount(sEglDisplay) == 1) {
-                    usePbufferSurface(eglContext);
-                    GLES20Canvas.terminateCaches();
-
-                    sEgl.eglDestroyContext(sEglDisplay, eglContext);
-                    sEglContextStorage.set(null);
-                    sEglContextStorage.remove();
-
-                    sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
-                    sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
-                            EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-                    sEgl.eglReleaseThread();
-                    sEgl.eglTerminate(sEglDisplay);
-
-                    sEgl = null;
-                    sEglDisplay = null;
-                    sEglConfig = null;
-                    sPbuffer = null;
-                }
-            }
-        }
-    }
+    private long mNativeCanvasContext;
 
     HardwareCanvas createCanvas() {
         return mGlCanvas = new GLES20Canvas(mTranslucent);
     }
 
-    ManagedEGLContext createManagedContext(EGLContext eglContext) {
-        return new GLRendererEglContext(mEglContext);
-    }
-
-    int[] getConfig(boolean dirtyRegions) {
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        final int stencilSize = GLES20Canvas.getStencilSize();
-        final int swapBehavior = dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
-
-        return new int[] {
-                EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
-                EGL_RED_SIZE, 8,
-                EGL_GREEN_SIZE, 8,
-                EGL_BLUE_SIZE, 8,
-                EGL_ALPHA_SIZE, 8,
-                EGL_DEPTH_SIZE, 0,
-                EGL_CONFIG_CAVEAT, EGL_NONE,
-                EGL_STENCIL_SIZE, stencilSize,
-                EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
-                EGL_NONE
-        };
-    }
-
     void initCaches() {
         if (GLES20Canvas.initCaches()) {
             // Caches were (re)initialized, rebind atlas
@@ -295,7 +160,7 @@
     }
 
     boolean canDraw() {
-        return mGl != null && mCanvas != null && mGlCanvas != null;
+        return mCanvas != null && mGlCanvas != null;
     }
 
     int onPreDraw(Rect dirty) {
@@ -458,17 +323,11 @@
             if (full && mCanvas != null) {
                 mCanvas = null;
             }
-
-            if (!isEnabled() || mDestroyed) {
-                setEnabled(false);
-                return;
+            if (mNativeCanvasContext != 0) {
+                destroyContext(mNativeCanvasContext);
+                mNativeCanvasContext = 0;
             }
-
-            destroySurface();
             setEnabled(false);
-
-            mDestroyed = true;
-            mGl = null;
         } finally {
             if (full && mGlCanvas != null) {
                 mGlCanvas = null;
@@ -524,21 +383,13 @@
         boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
 
         if (needsContext) {
-            GLRendererEglContext managedContext =
-                    (GLRendererEglContext) sEglContextStorage.get();
-            if (managedContext == null) return false;
-            usePbufferSurface(managedContext.getContext());
-        }
-
-        try {
-            action.run();
-        } finally {
-            if (needsContext) {
-                sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
-                        EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            if (!usePBufferSurface()) {
+                return false;
             }
         }
 
+        action.run();
+
         return true;
     }
 
@@ -600,44 +451,6 @@
         }
     }
 
-    static void startTrimMemory(int level) {
-        if (sEgl == null || sEglConfig == null) return;
-
-        GLRendererEglContext managedContext =
-                (GLRendererEglContext) sEglContextStorage.get();
-        // We do not have OpenGL objects
-        if (managedContext == null) {
-            return;
-        } else {
-            usePbufferSurface(managedContext.getContext());
-        }
-
-        if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
-            GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
-        } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
-            GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
-        }
-    }
-
-    static void endTrimMemory() {
-        if (sEgl != null && sEglDisplay != null) {
-            sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-        }
-    }
-
-    private static void usePbufferSurface(EGLContext eglContext) {
-        synchronized (sPbufferLock) {
-            // Create a temporary 1x1 pbuffer so we have a context
-            // to clear our OpenGL objects
-            if (sPbuffer == null) {
-                sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] {
-                        EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
-                });
-            }
-        }
-        sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
-    }
-
     RemoteGLRenderer(ThreadedRenderer owningRenderer, boolean translucent) {
         mOwningRenderer = owningRenderer;
         mTranslucent = translucent;
@@ -771,62 +584,31 @@
         return mDirtyRegionsEnabled;
     }
 
-    /**
-     * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
-     * is invoked and the requested flag is turned off. The error code is
-     * also logged as a warning.
-     */
-    void checkEglErrors() {
-        if (isEnabled()) {
-            checkEglErrorsForced();
-        }
-    }
-
-    private void checkEglErrorsForced() {
-        int error = sEgl.eglGetError();
-        if (error != EGL_SUCCESS) {
-            // something bad has happened revert to
-            // normal rendering.
-            Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
-            fallback(error != EGL11.EGL_CONTEXT_LOST);
-        }
-    }
-
-    private void fallback(boolean fallback) {
+    private void triggerSoftwareFallback() {
         destroy(true);
-        if (fallback) {
-            // we'll try again if it was context lost
-            setRequested(false);
-            Log.w(LOG_TAG, "Mountain View, we've had a problem here. "
-                    + "Switching back to software rendering.");
-        }
+        // we'll try again if it was context lost
+        setRequested(false);
+        Log.w(LOG_TAG, "Mountain View, we've had a problem here. "
+                + "Switching back to software rendering.");
     }
 
     @Override
     boolean initialize(Surface surface) throws OutOfResourcesException {
         if (isRequested() && !isEnabled()) {
-            boolean contextCreated = initializeEgl();
-            mGl = createEglSurface(surface);
-            mDestroyed = false;
+            mNativeCanvasContext = createContext();
+            boolean surfaceCreated = createEglSurface(surface);
 
-            if (mGl != null) {
-                int err = sEgl.eglGetError();
-                if (err != EGL_SUCCESS) {
-                    destroy(true);
-                    setRequested(false);
-                } else {
-                    if (mCanvas == null) {
-                        mCanvas = createCanvas();
-                        mCanvas.setName(mName);
-                    }
-                    setEnabled(true);
-
-                    if (contextCreated) {
-                        initAtlas();
-                    }
+            if (surfaceCreated) {
+                if (mCanvas == null) {
+                    mCanvas = createCanvas();
+                    mCanvas.setName(mName);
                 }
-
-                return mCanvas != null;
+                setEnabled(true);
+                initAtlas();
+                return true;
+            } else {
+                destroy(true);
+                setRequested(false);
             }
         }
         return false;
@@ -839,251 +621,30 @@
         }
     }
 
-    boolean initializeEgl() {
-        synchronized (sEglLock) {
-            if (sEgl == null && sEglConfig == null) {
-                sEgl = (EGL10) EGLContext.getEGL();
-
-                // Get to the default display.
-                sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
-                if (sEglDisplay == EGL_NO_DISPLAY) {
-                    throw new RuntimeException("eglGetDisplay failed "
-                            + GLUtils.getEGLErrorString(sEgl.eglGetError()));
-                }
-
-                // We can now initialize EGL for that display
-                int[] version = new int[2];
-                if (!sEgl.eglInitialize(sEglDisplay, version)) {
-                    throw new RuntimeException("eglInitialize failed " +
-                            GLUtils.getEGLErrorString(sEgl.eglGetError()));
-                }
-
-                checkEglErrorsForced();
-
-                sEglConfig = loadEglConfig();
-            }
-        }
-
-        ManagedEGLContext managedContext = sEglContextStorage.get();
-        mEglContext = managedContext != null ? managedContext.getContext() : null;
-        mEglThread = Thread.currentThread();
-
-        if (mEglContext == null) {
-            mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
-            sEglContextStorage.set(createManagedContext(mEglContext));
-            return true;
-        }
-
-        return false;
-    }
-
-    private EGLConfig loadEglConfig() {
-        EGLConfig eglConfig = chooseEglConfig();
-        if (eglConfig == null) {
-            // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
-            if (sDirtyRegions) {
-                sDirtyRegions = false;
-                eglConfig = chooseEglConfig();
-                if (eglConfig == null) {
-                    throw new RuntimeException("eglConfig not initialized");
-                }
-            } else {
-                throw new RuntimeException("eglConfig not initialized");
-            }
-        }
-        return eglConfig;
-    }
-
-    private EGLConfig chooseEglConfig() {
-        EGLConfig[] configs = new EGLConfig[1];
-        int[] configsCount = new int[1];
-        int[] configSpec = getConfig(sDirtyRegions);
-
-        // Debug
-        final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, "");
-        if ("all".equalsIgnoreCase(debug)) {
-            sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount);
-
-            EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]];
-            sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs,
-                    configsCount[0], configsCount);
-
-            for (EGLConfig config : debugConfigs) {
-                printConfig(config);
-            }
-        }
-
-        if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
-            throw new IllegalArgumentException("eglChooseConfig failed " +
-                    GLUtils.getEGLErrorString(sEgl.eglGetError()));
-        } else if (configsCount[0] > 0) {
-            if ("choice".equalsIgnoreCase(debug)) {
-                printConfig(configs[0]);
-            }
-            return configs[0];
-        }
-
-        return null;
-    }
-
-    private static void printConfig(EGLConfig config) {
-        int[] value = new int[1];
-
-        Log.d(LOG_TAG, "EGL configuration " + config + ":");
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value);
-        Log.d(LOG_TAG, "  RED_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value);
-        Log.d(LOG_TAG, "  GREEN_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value);
-        Log.d(LOG_TAG, "  BLUE_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value);
-        Log.d(LOG_TAG, "  ALPHA_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value);
-        Log.d(LOG_TAG, "  DEPTH_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
-        Log.d(LOG_TAG, "  STENCIL_SIZE = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLE_BUFFERS, value);
-        Log.d(LOG_TAG, "  SAMPLE_BUFFERS = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLES, value);
-        Log.d(LOG_TAG, "  SAMPLES = " + value[0]);
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
-        Log.d(LOG_TAG, "  SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
-
-        sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_CONFIG_CAVEAT, value);
-        Log.d(LOG_TAG, "  CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0]));
-    }
-
-    GL createEglSurface(Surface surface) throws OutOfResourcesException {
-        // Check preconditions.
-        if (sEgl == null) {
-            throw new RuntimeException("egl not initialized");
-        }
-        if (sEglDisplay == null) {
-            throw new RuntimeException("eglDisplay not initialized");
-        }
-        if (sEglConfig == null) {
-            throw new RuntimeException("eglConfig not initialized");
-        }
-        if (Thread.currentThread() != mEglThread) {
-            throw new IllegalStateException("HardwareRenderer cannot be used "
-                    + "from multiple threads");
-        }
-
-        // In case we need to destroy an existing surface
-        destroySurface();
-
+    boolean createEglSurface(Surface surface) throws OutOfResourcesException {
         // Create an EGL surface we can render into.
-        if (!createSurface(surface)) {
-            return null;
+        if (!setSurface(mNativeCanvasContext, surface)) {
+            return false;
         }
+        makeCurrent(mNativeCanvasContext);
+        mSurfaceUpdated = true;
 
         initCaches();
-
-        return mEglContext.getGL();
-    }
-
-    private void enableDirtyRegions() {
-        // If mDirtyRegions is set, this means we have an EGL configuration
-        // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
-        if (sDirtyRegions) {
-            if (!(mDirtyRegionsEnabled = GLRenderer.preserveBackBuffer())) {
-                Log.w(LOG_TAG, "Backbuffer cannot be preserved");
-            }
-        } else if (sDirtyRegionsRequested) {
-            // If mDirtyRegions is not set, our EGL configuration does not
-            // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
-            // swap behavior might be EGL_BUFFER_PRESERVED, which means we
-            // want to set mDirtyRegions. We try to do this only if dirty
-            // regions were initially requested as part of the device
-            // configuration (see RENDER_DIRTY_REGIONS)
-            mDirtyRegionsEnabled = GLRenderer.isBackBufferPreserved();
-        }
-    }
-
-    EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-        final int[] attribs = { EGL14.EGL_CONTEXT_CLIENT_VERSION, GL_VERSION, EGL_NONE };
-
-        EGLContext context = egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
-                attribs);
-        if (context == null || context == EGL_NO_CONTEXT) {
-            //noinspection ConstantConditions
-            throw new IllegalStateException(
-                    "Could not create an EGL context. eglCreateContext failed with error: " +
-                    GLUtils.getEGLErrorString(sEgl.eglGetError()));
-        }
-
-        return context;
-    }
-
-    void destroySurface() {
-        if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
-            if (mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
-                sEgl.eglMakeCurrent(sEglDisplay,
-                        EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            }
-            sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
-            mEglSurface = null;
-        }
+        return true;
     }
 
     @Override
     void invalidate(Surface surface) {
-        // Cancels any existing buffer to ensure we'll get a buffer
-        // of the right size before we call eglSwapBuffers
-        sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-        if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
-            sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
-            mEglSurface = null;
-            setEnabled(false);
-        }
+        setSurface(mNativeCanvasContext, null);
+        setEnabled(false);
 
         if (surface.isValid()) {
-            if (!createSurface(surface)) {
-                return;
-            }
-
-            mUpdateDirtyRegions = true;
-
-            if (mCanvas != null) {
+            if (createEglSurface(surface) && mCanvas != null) {
                 setEnabled(true);
             }
         }
     }
 
-    private boolean createSurface(Surface surface) {
-        mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, surface, null);
-
-        if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
-            int error = sEgl.eglGetError();
-            if (error == EGL_BAD_NATIVE_WINDOW) {
-                Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
-                return false;
-            }
-            throw new RuntimeException("createWindowSurface failed "
-                    + GLUtils.getEGLErrorString(error));
-        }
-
-        if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-            throw new IllegalStateException("eglMakeCurrent failed " +
-                    GLUtils.getEGLErrorString(sEgl.eglGetError()));
-        }
-
-        enableDirtyRegions();
-
-        return true;
-    }
-
     @Override
     boolean validate() {
         return checkRenderContext() != SURFACE_STATE_ERROR;
@@ -1153,8 +714,7 @@
                 dirty = null;
             }
 
-            // We are already on the correct thread
-            final int surfaceState = checkRenderContextUnsafe();
+            final int surfaceState = checkRenderContext();
             if (surfaceState != SURFACE_STATE_ERROR) {
                 HardwareCanvas canvas = mCanvas;
 
@@ -1328,15 +888,16 @@
                 eglSwapBuffersStartTime = System.nanoTime();
             }
 
-            sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
+            if (!swapBuffers(mNativeCanvasContext)) {
+                triggerSoftwareFallback();
+            }
+            mSurfaceUpdated = false;
 
             if (mProfileEnabled) {
                 long now = System.nanoTime();
                 float total = (now - eglSwapBuffersStartTime) * 0.000001f;
                 mProfileData[mProfileCurrentFrame + 2] = total;
             }
-
-            checkEglErrors();
         }
     }
 
@@ -1408,42 +969,11 @@
      * @see #checkRenderContextUnsafe()
      */
     int checkRenderContext() {
-        if (mEglThread != Thread.currentThread()) {
-            throw new IllegalStateException("Hardware acceleration can only be used with a " +
-                    "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
-                    "Current thread: " + Thread.currentThread());
+        if (!makeCurrent(mNativeCanvasContext)) {
+            triggerSoftwareFallback();
+            return SURFACE_STATE_ERROR;
         }
-
-        return checkRenderContextUnsafe();
-    }
-
-    /**
-     * Ensures the current EGL context and surface are the ones we expect.
-     * This method does not check the current thread.
-     *
-     * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
-     *         {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
-     *         {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
-     *
-     * @see #checkRenderContext()
-     */
-    private int checkRenderContextUnsafe() {
-        if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) ||
-                !mEglContext.equals(sEgl.eglGetCurrentContext())) {
-            if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                Log.e(LOG_TAG, "eglMakeCurrent failed " +
-                        GLUtils.getEGLErrorString(sEgl.eglGetError()));
-                fallback(true);
-                return SURFACE_STATE_ERROR;
-            } else {
-                if (mUpdateDirtyRegions) {
-                    enableDirtyRegions();
-                    mUpdateDirtyRegions = false;
-                }
-                return SURFACE_STATE_UPDATED;
-            }
-        }
-        return SURFACE_STATE_SUCCESS;
+        return mSurfaceUpdated ? SURFACE_STATE_UPDATED : SURFACE_STATE_SUCCESS;
     }
 
     private static int dpToPx(int dp, float density) {
@@ -1535,4 +1065,11 @@
             if (mGraphType == GRAPH_TYPE_LINES) paint.setStrokeWidth(mThresholdStroke);
         }
     }
+
+    static native long createContext();
+    static native boolean usePBufferSurface();
+    static native boolean setSurface(long nativeCanvasContext, Surface surface);
+    static native boolean swapBuffers(long nativeCanvasContext);
+    static native boolean makeCurrent(long nativeCanvasContext);
+    static native void destroyContext(long nativeCanvasContext);
 }
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index bdb5046..b22088c 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -366,8 +366,6 @@
 
     @Override
     public Parcelable onSaveInstanceState() {
-        // Force our ancestor class to save its state
-        setFreezesText(true);
         Parcelable superState = super.onSaveInstanceState();
 
         SavedState ss = new SavedState(superState);
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8ea35ff..11dbce8 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -315,7 +315,7 @@
 
                 mErrorPopup = null;
             }
-
+            mShowErrorAfterAttach = false;
         } else {
             setErrorIcon(icon);
             if (mTextView.isFocused()) {
diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java
index 0b74cf3..b35de93 100644
--- a/core/java/com/android/internal/util/XmlUtils.java
+++ b/core/java/com/android/internal/util/XmlUtils.java
@@ -482,12 +482,13 @@
      * @see #readThisMapXml
      * #see #writeMapXml
      */
-    public static final HashMap readMapXml(InputStream in)
+    @SuppressWarnings("unchecked")
+    public static final HashMap<String, ?> readMapXml(InputStream in)
     throws XmlPullParserException, java.io.IOException
     {
         XmlPullParser   parser = Xml.newPullParser();
         parser.setInput(in, null);
-        return (HashMap)readValueXml(parser, new String[1]);
+        return (HashMap<String, ?>) readValueXml(parser, new String[1]);
     }
 
     /**
@@ -548,22 +549,16 @@
      *
      * @see #readMapXml
      */
-    public static final HashMap readThisMapXml(XmlPullParser parser, String endTag, String[] name)
-    throws XmlPullParserException, java.io.IOException
+    public static final HashMap<String, ?> readThisMapXml(XmlPullParser parser, String endTag,
+            String[] name) throws XmlPullParserException, java.io.IOException
     {
-        HashMap map = new HashMap();
+        HashMap<String, Object> map = new HashMap<String, Object>();
 
         int eventType = parser.getEventType();
         do {
             if (eventType == parser.START_TAG) {
                 Object val = readThisValueXml(parser, name);
-                if (name[0] != null) {
-                    //System.out.println("Adding to map: " + name + " -> " + val);
-                    map.put(name[0], val);
-                } else {
-                    throw new XmlPullParserException(
-                        "Map value without name attribute: " + parser.getName());
-                }
+                map.put(name[0], val);
             } else if (eventType == parser.END_TAG) {
                 if (parser.getName().equals(endTag)) {
                     return map;
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index df4e1a6..9fefd00 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.database.ContentObserver;
+import android.graphics.Point;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
@@ -26,15 +28,20 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
+import android.view.Display;
 import android.view.IWindowManager;
 import android.view.Surface;
 import android.view.WindowManagerGlobal;
 
+import com.android.internal.R;
+
 /**
  * Provides helper functions for configuring the display rotation policy.
  */
 public final class RotationPolicy {
     private static final String TAG = "RotationPolicy";
+    private static final int CURRENT_ROTATION = -1;
+    private static final int NATURAL_ROTATION = Surface.ROTATION_0;
 
     private RotationPolicy() {
     }
@@ -55,23 +62,33 @@
     }
 
     /**
-     * Returns true if the device supports the rotation-lock toggle feature
-     * in the system UI or system bar.
+     * Returns the orientation that will be used when locking the orientation from system UI
+     * with {@link #setRotationLock}.
      *
-     * When the rotation-lock toggle is supported, the "auto-rotate screen" option in
-     * Display settings should be hidden, but it should remain available in Accessibility
-     * settings.
+     * If the device only supports locking to its natural orientation, this will be either
+     * Configuration.ORIENTATION_PORTRAIT or Configuration.ORIENTATION_LANDSCAPE,
+     * otherwise Configuration.ORIENTATION_UNDEFINED if any orientation is lockable.
      */
-    public static boolean isRotationLockToggleSupported(Context context) {
-        return isRotationSupported(context)
-                && context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+    public static int getRotationLockOrientation(Context context) {
+        if (!areAllRotationsAllowed(context)) {
+            final Point size = new Point();
+            final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+            try {
+                wm.getInitialDisplaySize(Display.DEFAULT_DISPLAY, size);
+                return size.x < size.y ?
+                        Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
+            } catch (RemoteException e) {
+                Log.w(TAG, "Unable to get the display size");
+            }
+        }
+        return Configuration.ORIENTATION_UNDEFINED;
     }
 
     /**
-     * Returns true if the rotation-lock toggle should be shown in the UI.
+     * Returns true if the rotation-lock toggle should be shown in system UI.
      */
     public static boolean isRotationLockToggleVisible(Context context) {
-        return isRotationLockToggleSupported(context) &&
+        return isRotationSupported(context) &&
                 Settings.System.getIntForUser(context.getContentResolver(),
                         Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
                         UserHandle.USER_CURRENT) == 0;
@@ -86,50 +103,42 @@
     }
 
     /**
-     * Enables or disables rotation lock.
-     *
-     * Should be used by the rotation lock toggle.
+     * Enables or disables rotation lock from the system UI toggle.
      */
     public static void setRotationLock(Context context, final boolean enabled) {
         Settings.System.putIntForUser(context.getContentResolver(),
                 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0,
                 UserHandle.USER_CURRENT);
 
-        AsyncTask.execute(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
-                    if (enabled) {
-                        wm.freezeRotation(-1);
-                    } else {
-                        wm.thawRotation();
-                    }
-                } catch (RemoteException exc) {
-                    Log.w(TAG, "Unable to save auto-rotate setting");
-                }
-            }
-        });
+        final int rotation = areAllRotationsAllowed(context) ? CURRENT_ROTATION : NATURAL_ROTATION;
+        setRotationLock(enabled, rotation);
     }
 
     /**
-     * Enables or disables rotation lock and adjusts whether the rotation lock toggle
-     * should be hidden for accessibility purposes.
+     * Enables or disables natural rotation lock from Accessibility settings.
      *
-     * Should be used by Display settings and Accessibility settings.
+     * If rotation is locked for accessibility, the system UI toggle is hidden to avoid confusion.
      */
     public static void setRotationLockForAccessibility(Context context, final boolean enabled) {
         Settings.System.putIntForUser(context.getContentResolver(),
                 Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, enabled ? 1 : 0,
                         UserHandle.USER_CURRENT);
 
+        setRotationLock(enabled, NATURAL_ROTATION);
+    }
+
+    private static boolean areAllRotationsAllowed(Context context) {
+        return context.getResources().getBoolean(R.bool.config_allowAllRotations);
+    }
+
+    private static void setRotationLock(final boolean enabled, final int rotation) {
         AsyncTask.execute(new Runnable() {
             @Override
             public void run() {
                 try {
                     IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
                     if (enabled) {
-                        wm.freezeRotation(Surface.ROTATION_0);
+                        wm.freezeRotation(rotation);
                     } else {
                         wm.thawRotation();
                     }
diff --git a/services/core/java/com/android/server/LocalServices.java b/core/java/com/android/server/LocalServices.java
similarity index 98%
rename from services/core/java/com/android/server/LocalServices.java
rename to core/java/com/android/server/LocalServices.java
index deff79dc..25dcb30 100644
--- a/services/core/java/com/android/server/LocalServices.java
+++ b/core/java/com/android/server/LocalServices.java
@@ -24,6 +24,8 @@
  *
  * Once all services are converted to the SystemService interface, this class can be absorbed
  * into SystemServiceManager.
+ *
+ * {@hide}
  */
 public final class LocalServices {
     private LocalServices() {}
diff --git a/services/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java
similarity index 83%
rename from services/core/java/com/android/server/SystemService.java
rename to core/java/com/android/server/SystemService.java
index b9d30ce..0356753 100644
--- a/services/core/java/com/android/server/SystemService.java
+++ b/core/java/com/android/server/SystemService.java
@@ -21,7 +21,28 @@
 import android.os.ServiceManager;
 
 /**
- * System services respond to lifecycle events that help the services know what
+ * The base class for services running in the system process. Override and implement
+ * the lifecycle event callback methods as needed.
+ *
+ * The lifecycle of a SystemService:
+ *
+ * {@link #onCreate(android.content.Context)} is called to initialize the
+ * service.
+ *
+ * {@link #onStart()} is called to get the service running. It is common
+ * for services to publish their Binder interface at this point. All required
+ * dependencies are also assumed to be ready to use.
+ *
+ * Then {@link #onBootPhase(int)} is called as many times as there are boot phases
+ * until {@link #PHASE_BOOT_COMPLETE} is sent, which is the last boot phase. Each phase
+ * is an opportunity to do special work, like acquiring optional service dependencies,
+ * waiting to see if SafeMode is enabled, or registering with a service that gets
+ * started after this one.
+ *
+ * NOTE: All lifecycle methods are called from the same thread that created the
+ * SystemService.
+ *
+ * {@hide}
  */
 public abstract class SystemService {
     /*
diff --git a/services/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java
similarity index 97%
rename from services/core/java/com/android/server/SystemServiceManager.java
rename to core/java/com/android/server/SystemServiceManager.java
index 59f7e92..e2a6063 100644
--- a/services/core/java/com/android/server/SystemServiceManager.java
+++ b/core/java/com/android/server/SystemServiceManager.java
@@ -23,7 +23,10 @@
 import java.util.ArrayList;
 
 /**
- * Manages creating, starting, and other lifecycle events of system services.
+ * Manages creating, starting, and other lifecycle events of
+ * {@link com.android.server.SystemService}s.
+ *
+ * {@hide}
  */
 public class SystemServiceManager {
     private static final String TAG = "SystemServiceManager";
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f26374a..e88db54 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -58,6 +58,7 @@
 	android_view_GLRenderer.cpp \
 	android_view_GLES20Canvas.cpp \
 	android_view_ThreadedRenderer.cpp \
+	android_view_RemoteGLRenderer.cpp \
 	android_view_MotionEvent.cpp \
 	android_view_PointerIcon.cpp \
 	android_view_VelocityTracker.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 89d75dc..011db5e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -124,6 +124,7 @@
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
 extern int register_android_view_GLRenderer(JNIEnv* env);
 extern int register_android_view_ThreadedRenderer(JNIEnv* env);
+extern int register_android_view_RemoteGLRenderer(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
 extern int register_android_view_SurfaceControl(JNIEnv* env);
 extern int register_android_view_SurfaceSession(JNIEnv* env);
@@ -1129,6 +1130,7 @@
     REG_JNI(register_android_view_GLES20Canvas),
     REG_JNI(register_android_view_GLRenderer),
     REG_JNI(register_android_view_ThreadedRenderer),
+    REG_JNI(register_android_view_RemoteGLRenderer),
     REG_JNI(register_android_view_Surface),
     REG_JNI(register_android_view_SurfaceControl),
     REG_JNI(register_android_view_SurfaceSession),
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index 83d8aa2..b7d4423 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * Copyright (C) 2007-2014 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.
@@ -142,18 +142,21 @@
  * In class android.util.EventLog:
  *  static native void readEvents(int[] tags, Collection<Event> output)
  *
- *  Reads events from the event log, typically /dev/log/events
+ *  Reads events from the event log
  */
 static void android_util_EventLog_readEvents(JNIEnv* env, jobject clazz,
                                              jintArray tags,
                                              jobject out) {
+
     if (tags == NULL || out == NULL) {
         jniThrowNullPointerException(env, NULL);
         return;
     }
 
-    int fd = open("/dev/" LOGGER_LOG_EVENTS, O_RDONLY | O_NONBLOCK);
-    if (fd < 0) {
+    struct logger_list *logger_list = android_logger_list_open(
+        LOG_ID_EVENTS, O_RDONLY | O_NONBLOCK, 0, 0);
+
+    if (!logger_list) {
         jniThrowIOException(env, errno);
         return;
     }
@@ -161,41 +164,26 @@
     jsize tagLength = env->GetArrayLength(tags);
     jint *tagValues = env->GetIntArrayElements(tags, NULL);
 
-    uint8_t buf[LOGGER_ENTRY_MAX_LEN];
-    struct timeval timeout = {0, 0};
-    fd_set readset;
-    FD_ZERO(&readset);
+    while (1) {
+        log_msg log_msg;
+        int ret = android_logger_list_read(logger_list, &log_msg);
 
-    for (;;) {
-        // Use a short select() to try to avoid problems hanging on read().
-        // This means we block for 5ms at the end of the log -- oh well.
-        timeout.tv_usec = 5000;
-        FD_SET(fd, &readset);
-        int r = select(fd + 1, &readset, NULL, NULL, &timeout);
-        if (r == 0) {
-            break;  // no more events
-        } else if (r < 0 && errno == EINTR) {
-            continue;  // interrupted by signal, try again
-        } else if (r < 0) {
-            jniThrowIOException(env, errno);  // Will throw on return
+        if (ret == 0) {
+            break;
+        }
+        if (ret < 0) {
+            if (errno == EINTR) {
+                continue;
+            }
+            if (errno == EINVAL) {
+                jniThrowException(env, "java/io/IOException", "Event too short");
+            } else if (errno != EAGAIN) {
+                jniThrowIOException(env, errno);  // Will throw on return
+            }
             break;
         }
 
-        int len = read(fd, buf, sizeof(buf));
-        if (len == 0 || (len < 0 && errno == EAGAIN)) {
-            break;  // no more events
-        } else if (len < 0 && errno == EINTR) {
-            continue;  // interrupted by signal, try again
-        } else if (len < 0) {
-            jniThrowIOException(env, errno);  // Will throw on return
-            break;
-        } else if ((size_t) len < sizeof(logger_entry) + sizeof(int32_t)) {
-            jniThrowException(env, "java/io/IOException", "Event too short");
-            break;
-        }
-
-        logger_entry* entry = (logger_entry*) buf;
-        int32_t tag = * (int32_t*) (buf + sizeof(*entry));
+        int32_t tag = * (int32_t *) log_msg.msg();
 
         int found = 0;
         for (int i = 0; !found && i < tagLength; ++i) {
@@ -203,16 +191,20 @@
         }
 
         if (found) {
-            jsize len = sizeof(*entry) + entry->len;
+            jsize len = ret;
             jbyteArray array = env->NewByteArray(len);
-            if (array == NULL) break;
+            if (array == NULL) {
+                break;
+            }
 
             jbyte *bytes = env->GetByteArrayElements(array, NULL);
-            memcpy(bytes, buf, len);
+            memcpy(bytes, log_msg.buf, len);
             env->ReleaseByteArrayElements(array, bytes, 0);
 
             jobject event = env->NewObject(gEventClass, gEventInitID, array);
-            if (event == NULL) break;
+            if (event == NULL) {
+                break;
+            }
 
             env->CallBooleanMethod(out, gCollectionAddID, event);
             env->DeleteLocalRef(event);
@@ -220,7 +212,8 @@
         }
     }
 
-    close(fd);
+    android_logger_list_close(logger_list);
+
     env->ReleaseIntArrayElements(tags, tagValues, 0);
 }
 
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 01ab2ff..d4cc159 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -207,7 +207,7 @@
 }
 
 
-static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
+static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
         jobject messageQueueObj) {
     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
     if (messageQueue == NULL) {
@@ -226,17 +226,17 @@
     }
 
     receiver->incStrong(gDisplayEventReceiverClassInfo.clazz); // retain a reference for the object
-    return reinterpret_cast<jint>(receiver.get());
+    return reinterpret_cast<jlong>(receiver.get());
 }
 
-static void nativeDispose(JNIEnv* env, jclass clazz, jint receiverPtr) {
+static void nativeDispose(JNIEnv* env, jclass clazz, jlong receiverPtr) {
     sp<NativeDisplayEventReceiver> receiver =
             reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
     receiver->dispose();
     receiver->decStrong(gDisplayEventReceiverClassInfo.clazz); // drop reference held by the object
 }
 
-static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jint receiverPtr) {
+static void nativeScheduleVsync(JNIEnv* env, jclass clazz, jlong receiverPtr) {
     sp<NativeDisplayEventReceiver> receiver =
             reinterpret_cast<NativeDisplayEventReceiver*>(receiverPtr);
     status_t status = receiver->scheduleVsync();
@@ -251,12 +251,12 @@
 static JNINativeMethod gMethods[] = {
     /* name, signature, funcPtr */
     { "nativeInit",
-            "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)I",
+            "(Landroid/view/DisplayEventReceiver;Landroid/os/MessageQueue;)J",
             (void*)nativeInit },
     { "nativeDispose",
-            "(I)V",
+            "(J)V",
             (void*)nativeDispose },
-    { "nativeScheduleVsync", "(I)V",
+    { "nativeScheduleVsync", "(J)V",
             (void*)nativeScheduleVsync }
 };
 
diff --git a/core/jni/android_view_RemoteGLRenderer.cpp b/core/jni/android_view_RemoteGLRenderer.cpp
new file mode 100644
index 0000000..96a203b
--- /dev/null
+++ b/core/jni/android_view_RemoteGLRenderer.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#define LOG_TAG "RemoteGLRenderer"
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+
+#include <utils/StrongPointer.h>
+#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <renderthread/CanvasContext.h>
+#include <system/window.h>
+
+namespace android {
+
+#ifdef USE_OPENGL_RENDERER
+
+#define CHECK_CONTEXT(c) if (!c) ALOGE("Null context passed to %s!", __func__ )
+
+namespace RT = android::uirenderer::renderthread;
+
+static jlong android_view_RemoteGLRenderer_createContext(JNIEnv* env, jobject clazz) {
+    RT::CanvasContext* context = new RT::CanvasContext();
+    return reinterpret_cast<jlong>(context);
+}
+
+static jboolean android_view_RemoteGLRenderer_usePBufferSurface(JNIEnv* env, jobject clazz) {
+    return RT::CanvasContext::useGlobalPBufferSurface();
+}
+
+static jboolean android_view_RemoteGLRenderer_setSurface(JNIEnv* env, jobject clazz,
+        jlong jcontextptr, jobject jsurface) {
+    RT::CanvasContext* context = reinterpret_cast<RT::CanvasContext*>(jcontextptr);
+    CHECK_CONTEXT(context);
+    sp<ANativeWindow> window;
+    if (jsurface) {
+        window = android_view_Surface_getNativeWindow(env, jsurface);
+    }
+    return context->setSurface(window.get());
+}
+
+static jboolean android_view_RemoteGLRenderer_swapBuffers(JNIEnv* env, jobject clazz,
+        jlong jcontextptr) {
+    RT::CanvasContext* context = reinterpret_cast<RT::CanvasContext*>(jcontextptr);
+    CHECK_CONTEXT(context);
+    return context->swapBuffers();
+}
+
+static jboolean android_view_RemoteGLRenderer_makeCurrent(JNIEnv* env, jobject clazz,
+        jlong jcontextptr) {
+    RT::CanvasContext* context = reinterpret_cast<RT::CanvasContext*>(jcontextptr);
+    CHECK_CONTEXT(context);
+    return context->makeCurrent();
+}
+
+static void android_view_RemoteGLRenderer_destroyContext(JNIEnv* env, jobject clazz,
+        jlong jcontextptr) {
+    RT::CanvasContext* context = reinterpret_cast<RT::CanvasContext*>(jcontextptr);
+    CHECK_CONTEXT(context);
+    delete context;
+}
+#endif
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/view/RemoteGLRenderer";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+    { "createContext", "()J",   (void*) android_view_RemoteGLRenderer_createContext },
+    { "usePBufferSurface", "()Z",   (void*) android_view_RemoteGLRenderer_usePBufferSurface },
+    { "setSurface", "(JLandroid/view/Surface;)Z",   (void*) android_view_RemoteGLRenderer_setSurface },
+    { "swapBuffers", "(J)Z",   (void*) android_view_RemoteGLRenderer_swapBuffers },
+    { "makeCurrent", "(J)Z",   (void*) android_view_RemoteGLRenderer_makeCurrent },
+    { "destroyContext", "(J)V",   (void*) android_view_RemoteGLRenderer_destroyContext },
+#endif
+};
+
+int register_android_view_RemoteGLRenderer(JNIEnv* env) {
+    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 8bb6cb4..8d77e36 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "GLRenderer"
+#define LOG_TAG "ThreadedRenderer"
 
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index ceafa3b..7319994 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -551,8 +551,8 @@
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"start CDMA-opsætning af tabletcomputeren direkte"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"start CDMA-telefonopsætning direkte"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Tillader, at appen kan starte CDMA-levering. Ondsindede apps kan starte unødvendig CDMA-levering."</string>
-    <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontroller meddelelser om placeringsopdatering"</string>
-    <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Tillader, at appen kan aktivere/deaktivere meddelelser om placeringsopdatering fra senderen. Anvendes ikke i almindelige apps."</string>
+    <string name="permlab_locationUpdates" msgid="7785408253364335740">"kontroller underretninger om placeringsopdatering"</string>
+    <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Tillader, at appen kan aktivere/deaktivere underretninger om placeringsopdatering fra senderen. Anvendes ikke i almindelige apps."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"egenskaber for adgangskontrol"</string>
     <string name="permdesc_checkinProperties" msgid="4024526968630194128">"Tillader, at appen kan få læse/skrive-adgang til egenskaber, der er uploadet af kontroltjenesten. Anvendes ikke af almindelige apps."</string>
     <string name="permlab_bindGadget" msgid="776905339015863471">"vælg widgets"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index b846e6d..d4b7cc6 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1129,7 +1129,7 @@
     <string name="whichApplication" msgid="4533185947064773386">"Dokončiť akciu pomocou aplikácie"</string>
     <string name="whichHomeApplication" msgid="4616420172727326782">"Vyberte domovskú aplikáciu"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Použiť ako predvolené nastavenie pre túto akciu."</string>
-    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Vymazať predvolené nastavenia v sekcii Nastavenia systému &gt; Aplikácie &gt; Prevzaté položky."</string>
+    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Vymazať predvolené nastavenia v sekcii Nastavenia systému &gt; Aplikácie &gt; Stiahnuté položky."</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Zvoľte akciu"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Zvoľte aplikáciu pre zariadenie USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Túto akciu nemôžu vykonávať žiadne aplikácie."</string>
@@ -1150,7 +1150,7 @@
     <string name="launch_warning_original" msgid="188102023021668683">"Pôvodne bola spustená aplikácia <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Prispôsobiť veľkosť"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"Vždy zobraziť"</string>
-    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Povoľte to znova v sekcii Nastavenia systému &gt; Aplikácie &gt; Prevzaté súbory."</string>
+    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Povoľte to znova v sekcii Nastavenia systému &gt; Aplikácie &gt; Stiahnuté súbory."</string>
     <string name="smv_application" msgid="3307209192155442829">"Aplikácia <xliff:g id="APPLICATION">%1$s</xliff:g> (proces <xliff:g id="PROCESS">%2$s</xliff:g>) porušila svoje vlastné vynútené pravidlá StrictMode."</string>
     <string name="smv_process" msgid="5120397012047462446">"Proces <xliff:g id="PROCESS">%1$s</xliff:g> porušil svoje vlastné vynútené pravidlá StrictMode."</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Prebieha inovácia systému Android..."</string>
diff --git a/core/tests/coretests/src/com/android/internal/util/XmlUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/XmlUtilsTest.java
new file mode 100644
index 0000000..2596ece
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/util/XmlUtilsTest.java
@@ -0,0 +1,41 @@
+/**
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.TestCase;
+
+public class XmlUtilsTest extends TestCase {
+
+    // https://code.google.com/p/android/issues/detail?id=63717
+    public void testMapWithNullKeys() throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put(null, "nullValue");
+        map.put("foo", "fooValue");
+        XmlUtils.writeMapXml(map, baos);
+
+        InputStream mapInput = new ByteArrayInputStream(baos.toByteArray());
+        HashMap<String, ?> deserialized = XmlUtils.readMapXml(mapInput);
+        assertEquals("nullValue", deserialized.get(null));
+        assertEquals("fooValue", deserialized.get("foo"));
+    }
+}
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index 3f02907..d2e65d4 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -36,7 +36,7 @@
 <h2 id="create-proj">Creating a Google API project</h2>
 <p>To create a Google API project:</p>
 <ol>
-  <li>Open the <a href="https://cloud.google.com/console">Google Cloud Console</a>.
+  <li>Open the <a href="https://cloud.google.com/console">Google Developers Console</a>.
   </li>
   <li>If you haven't created an API project yet, click <strong>Create Project</strong>.</li>
 
@@ -60,25 +60,27 @@
 <h2 id="access-key">Obtaining an API Key</h2>
 <p>To obtain an API  key:</p>
 <ol>
- <li>In the sidebar on the left, select <strong>APIs &amp; auth > Registered apps</strong>.</li>
-<li>Click <strong>Register app</strong>. </li>
+ <li>In the sidebar on the left, select <strong>APIs &amp; auth > Credentials</strong>.</li>
 
-<li>In the <strong>Name</strong> field, type your app's name.</li>
-<li>Click <strong>Android > Accessing APIs directly from Android</strong>.</li>
-<li>Under <strong>Android identification</strong>, type the package name for your app.</li>
-<li>Enter an SHA1 fingerprint. To get this value, follow the instructions in the
+ <li>Under <strong>Public API access</strong>, click <strong>Create new key</strong>.</li>
+
+<li>In the <strong>Create a new key</strong> dialog, click <strong>Android key</strong>.</li>
+
+<li>In the resulting configuration dialog, supply one SHA1 fingerprint and
+the package name for your app, separated by a semicolon. For example,
+{@code 45:B5:E4:6F:36:AD:0A:98:94:B4:02:66:2B:12:17:F2:56:26:A0:E0;com.myexample}.
+<p>To get the value for the SHA1 fingerprint, follow the instructions in the
 <a href="http://developers.google.com/console/help/new/#installedapplications">console
-help</a>.</li>
-<li>Click <strong>Register</strong>.</li>
+help</a>.</p></li>
+<li>Click <strong>Create</strong>.</li>
 
-<li>In the new page, open the <strong>Android Key</strong> section and copy the
+<li>In the refreshed page, copy the
 <a href="{@docRoot}google/gcm/gcm.html#apikey">API key</a>.
 You will need the API key later on to perform authentication in your application server.</li>
 
 <p class="note"><strong>Note:</strong> If you need to rotate the key, click
-the "recycle key" icon. A new key  will be created. If you think the key has been compromised
-and you want to delete it immediately, you can accomplish this by deleting the app from
-the console. Then create a new entry for the app with the same SHA1 and package name.</p>
+<strong>Regenerate key</strong>. A new key  will be created. If you think the key has been
+compromised and you want to delete it immediately, click <strong>Delete</strong>.</p>
 </ol>
 
 <h2 id="next">Next Steps</h2>
diff --git a/docs/html/google/play/billing/billing_admin.jd b/docs/html/google/play/billing/billing_admin.jd
index f1e4ec4..dd29b82 100644
--- a/docs/html/google/play/billing/billing_admin.jd
+++ b/docs/html/google/play/billing/billing_admin.jd
@@ -97,8 +97,8 @@
 
 <ol>
   <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
-  <li>In the <strong>All Google Play listings</strong> panel, under the application name, click
-  <strong>In-app Products</strong>.</li>
+  <li>In the <strong>All Applications</strong> panel, click on the
+  app name, then select <strong>In-app Products</strong>.</li>
   <li>Click <strong>Add new product</strong> (see figure 2) and provide details about the item you are
   selling and then click <strong>Save</strong> or <strong>Publish</strong>.</li>
 </ol>
@@ -363,10 +363,11 @@
 
 <ol>
   <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
-  <li>In the <strong>All Google Play listings</strong> panel, under the application name, click
-  <strong>In-app Products</strong>.</li>
-  <li>On the In-app Products List page, click <strong>Choose File</strong> and select your CSV
-file.
+  <li>In the <strong>All Applications</strong> panel, click on the app
+  name, then select <strong>In-app Products</strong>.</li>
+  <li>On the In-app Products List page, click <strong>Import/Export</strong>
+  &gt; <strong>Import in-app products from CSV file</strong>, then select your
+  CSV file.
     <p>The CSV file must be on your local computer or on a local disk that is connected to your
     computer.</p>
   </li>
@@ -377,7 +378,6 @@
     Overwriting does not delete items that are on a product list but not present in the CSV
     file.</p>
   </li>
-  <li>On the In-app Products List page, click <strong>Import from CSV</strong>.</li>
 </ol>
 
 <p>You can also export an existing product list to a CSV file by clicking <strong>Export to CSV
@@ -471,9 +471,8 @@
 
 <ol>
   <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
-  <li>Click the <strong>Settings</strong> icon. (If you are using the old Developer Console UI, click
-  <strong>Edit profile</strong> in the upper left part of the page, under your name,)</li>
-  <li>Locate the License Testing panel. (In the old UI, scroll down to the Licensing &amp; In-app Billing panel.)</li>
+  <li>Click the <strong>Settings</strong> icon.</li>
+  <li>Locate the License Testing panel.</li>
   <li>Add the email addresses for the test accounts you want to register,
   separating each account with a comma.</li>
   <li>Click <strong>Save</strong> to save your profile changes.</li>
@@ -481,18 +480,24 @@
 
 <h3 id="license_key">Getting an app's license key</h3>
 
-<p>The Google Play Developer Console provides a public licensing key for each app. To get the key for an app,
-load the app's publishing details in the Developer Console and click the <strong>Settings</strong> icon. The key
-for the app is available for copy/paste in License Key for this Application field, as shown in the figure below.</p>
-
-<p>Previously, the Developer Console provided a single public key per developer account. To transition apps to the
-new per-app public key, the Developer Console set the app-specific key as the former developer key. This ensures
-compatibility for apps that depend on the (former) developer key. </p>
+<p>The Google Play Developer Console provides a public licensing key for each
+app. To get the key for an app, follow these steps:</p>
+<ol>
+  <li>Open the <strong>All Applications</strong> panel.</li>
+  <li>Click on the app name, then select <strong>Services &amp; APIs</strong>.</li>
+  <li>Scroll down to the <strong>Your License Key for this Application</strong>
+field to locate the key for the app, as shown in the figure below.</li>
+</ol>
+<p>Previously, the Developer Console provided a single public key per developer
+account. To transition apps to the new per-app public key, the Developer Console
+set the app-specific key as the former developer key. This ensures compatibility
+for apps that depend on the (former) developer key. </p>
 
 <div style="margin:1em;">
 <img style="border:1px solid #ddd;padding-bottom:.5em" src="{@docRoot}images/in-app-billing/billing_app_key.png" xheight="510" id="figure4" />
 <p class="img-caption" style="padding-left:.5em;">
-  <strong>Figure 4.</strong> You can find the license key for each app in the <strong>Services &amp; APIs</strong> panel.
+  <strong>Figure 4.</strong> You can find the license key for each app in the
+  <strong>Services &amp; APIs</strong> panel.
 </p>
 </div>
 
diff --git a/docs/html/google/play/billing/billing_testing.jd b/docs/html/google/play/billing/billing_testing.jd
index 42b6d65..9d1964a 100644
--- a/docs/html/google/play/billing/billing_testing.jd
+++ b/docs/html/google/play/billing/billing_testing.jd
@@ -82,10 +82,10 @@
 APK itself. For example, you can publish your in-app items while your APK is
 still a draft. </p>
 
-<p>Next, create license test accounts for authorized users.  In the Developer
+<p>Next, create license test accounts for authorized users. In the Developer
 Console, go to <strong>Settings</strong> &gt; <strong>Account details</strong>,
 then in the License Testing section, add the addresses to <strong>Gmail accounts
-with testing status</strong>. For more information, see <a
+with testing access</strong> field. For more information, see <a
 href="#billing-testing-test">Setting Up for Test Purchases</a>.</p>
 
 <p>Once you’ve added the users as license tester accounts and saved the change,
diff --git a/docs/html/google/play/billing/gp-purchase-status-api.jd b/docs/html/google/play/billing/gp-purchase-status-api.jd
index 8db7133..d272301 100644
--- a/docs/html/google/play/billing/gp-purchase-status-api.jd
+++ b/docs/html/google/play/billing/gp-purchase-status-api.jd
@@ -58,7 +58,7 @@
 
 <p>The Purchase Status API is part of the <a
 href="https://developers.google.com/android-publisher/v1_1/">Google Play Android
-Developer API v1.1</a>, available through the Google Cloud Console. The new version
+Developer API v1.1</a>, available through the Google Developers Console. The new version
 of the API supersedes the v1 API, which is deprecated. If you are using the v1
 API, please migrate your operations to the v1.1 API as soon as possible.</p>
 
@@ -66,7 +66,7 @@
 <h2 id="using">Using the API</h2>
 
 <p>To use the API, you must first register a project at the <a
-href="https://cloud.google.com/console">Google Cloud Console</a> and receive
+href="https://cloud.google.com/console">Google Developers Console</a> and receive
 a Client ID and shared secret that  your app will present when calling the
 API. All calls are authenticated with OAuth 2.0.</p>
 
@@ -95,7 +95,8 @@
 
 <p>If you need to request a higher limit for your application, see the
 instructions in the <a
-href="https://developers.google.com/console/help/new/#trafficcontrols">Google Cloud Console Help</a>.
+href="https://developers.google.com/console/help/new/#trafficcontrols">Google Developers
+Console Help</a>.
 Also, please read the section below on design best practices for minimizing your
 use of the API.</p>
 
diff --git a/graphics/java/android/graphics/drawable/RevealDrawable.java b/graphics/java/android/graphics/drawable/RevealDrawable.java
index ca3543a..c357ae1 100644
--- a/graphics/java/android/graphics/drawable/RevealDrawable.java
+++ b/graphics/java/android/graphics/drawable/RevealDrawable.java
@@ -17,14 +17,11 @@
 package android.graphics.drawable;
 
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
-import android.graphics.Shader.TileMode;
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -70,15 +67,11 @@
     /** Target density, used to scale density-independent pixels. */
     private float mDensity = 1.0f;
 
-    // Masking layer.
-    private Bitmap mMaskBitmap;
-    private Canvas mMaskCanvas;
-    private Paint mMaskPaint;
+    /** Paint used to control appearance of ripples. */
+    private Paint mRipplePaint;
 
-    // Reveal layer.
-    private Bitmap mRevealBitmap;
-    private Canvas mRevealCanvas;
-    private Paint mRevealPaint;
+    /** Paint used to control reveal layer masking. */
+    private Paint mMaskingPaint;
 
     /**
      * Create a new reveal drawable with the specified list of layers. At least
@@ -232,61 +225,61 @@
 
     @Override
     public void draw(Canvas canvas) {
-        final Drawable lower = getDrawable(0);
-        lower.draw(canvas);
-
-        // No ripples? No problem.
-        if (mActiveRipples == null || mActiveRipples.isEmpty()) {
+        final int layerCount = getNumberOfLayers();
+        if (layerCount == 0) {
             return;
         }
 
-        // Ensure we have a mask buffer.
+        getDrawable(0).draw(canvas);
+
+        final ArrayList<Ripple> activeRipples = mActiveRipples;
+        if (layerCount == 1 || activeRipples == null || activeRipples.isEmpty()) {
+            // Nothing to reveal, we're done here.
+            return;
+        }
+
         final Rect bounds = getBounds();
         final int width = bounds.width();
         final int height = bounds.height();
-        if (mMaskBitmap == null) {
-            mMaskBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
-            mMaskCanvas = new Canvas(mMaskBitmap);
-            mMaskPaint = new Paint();
-            mMaskPaint.setAntiAlias(true);
-        } else if (mMaskBitmap.getHeight() < height || mMaskBitmap.getWidth() < width) {
-            mMaskBitmap.recycle();
-            mMaskBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
+
+        if (mRipplePaint == null) {
+            mRipplePaint = new Paint();
+            mRipplePaint.setAntiAlias(true);
         }
 
-        // Ensure we have a reveal buffer.
-        if (mRevealBitmap == null) {
-            mRevealBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            mRevealCanvas = new Canvas(mRevealBitmap);
-            mRevealPaint = new Paint();
-            mRevealPaint.setAntiAlias(true);
-            mRevealPaint.setShader(new BitmapShader(mRevealBitmap, TileMode.CLAMP, TileMode.CLAMP));
-        } else if (mRevealBitmap.getHeight() < height || mRevealBitmap.getWidth() < width) {
-            mRevealBitmap.recycle();
-            mRevealBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        }
-
-        // Draw ripples into the mask buffer.
-        mMaskCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
-        int n = mActiveRipples.size();
+        // Draw ripple mask into a buffer that merges using SRC_OVER.
+        int layerSaveCount = -1;
+        int n = activeRipples.size();
         for (int i = 0; i < n; i++) {
-            final Ripple ripple = mActiveRipples.get(i);
+            final Ripple ripple = activeRipples.get(i);
             if (!ripple.active()) {
-                mActiveRipples.remove(i);
+                activeRipples.remove(i);
                 i--;
                 n--;
             } else {
-                ripple.draw(mMaskCanvas, mMaskPaint);
+                if (layerSaveCount < 0) {
+                    layerSaveCount = canvas.saveLayer(0, 0, width, height, null, 0);
+                }
+
+                ripple.draw(canvas, mRipplePaint);
             }
         }
 
-        // Draw upper layer into the reveal buffer.
-        mRevealCanvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
-        final Drawable upper = getDrawable(1);
-        upper.draw(mRevealCanvas);
+        // If a layer was saved, it contains the ripple mask. Draw the reveal
+        // into another layer and composite using SRC_IN, then composite onto
+        // the original canvas.
+        if (layerSaveCount >= 0) {
+            if (mMaskingPaint == null) {
+                mMaskingPaint = new Paint();
+                mMaskingPaint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
+            }
 
-        // Draw mask buffer onto the canvas using the reveal shader.
-        canvas.drawBitmap(mMaskBitmap, 0, 0, mRevealPaint);
+            // TODO: When Drawable.setXfermode() is supported by all drawables,
+            // we won't need an extra layer.
+            canvas.saveLayer(0, 0, width, height, mMaskingPaint, 0);
+            getDrawable(1).draw(canvas);
+            canvas.restoreToCount(layerSaveCount);
+        }
     }
 
     private static class RevealState extends LayerState {
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 923571e..1f5d26c 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -18,6 +18,7 @@
 
 #include <math.h>
 #include <utils/Log.h>
+#include <utils/Vector.h>
 
 #include "AmbientShadow.h"
 #include "Vertex.h"
@@ -60,10 +61,11 @@
     Vector2 centroid;
     calculatePolygonCentroid(vertices, vertexCount, centroid);
 
-    Vector2 dir[rays];
+    Vector<Vector2> dir; // TODO: use C++11 unique_ptr
+    dir.setCapacity(rays);
     float rayDist[rays];
     float rayHeight[rays];
-    calculateRayDirections(rays, dir);
+    calculateRayDirections(rays, dir.editArray());
 
     // Calculate the length and height of the points along the edge.
     //
@@ -105,7 +107,7 @@
         for (int i = 0; i < rays; i++) {
 
             Vector2 normal(1.0f, 0.0f);
-            calculateNormal(rays, i, dir, rayDist, normal);
+            calculateNormal(rays, i, dir.array(), rayDist, normal);
 
             float opacity = strength * (0.5f) / (1 + rayHeight[i] / heightFactor);
 
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 9d31232..05163c8 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -4,7 +4,7 @@
 # Only build libhwui when USE_OPENGL_RENDERER is
 # defined in the current device/board configuration
 ifeq ($(USE_OPENGL_RENDERER),true)
-	LOCAL_SRC_FILES:= \
+	LOCAL_SRC_FILES := \
 		utils/Blur.cpp \
 		utils/SortedListImpl.cpp \
 		thread/TaskManager.cpp \
@@ -50,6 +50,7 @@
 
 	# RenderThread stuff
 	LOCAL_SRC_FILES += \
+		renderthread/CanvasContext.cpp \
 		renderthread/RenderTask.cpp \
 		renderthread/RenderThread.cpp
 
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index eb8bb9f..fddfe90 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -74,12 +74,12 @@
 // Entries
 ///////////////////////////////////////////////////////////////////////////////
 
-AssetAtlas::Entry* AssetAtlas::getEntry(SkBitmap* const bitmap) const {
+AssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const {
     ssize_t index = mEntries.indexOfKey(bitmap);
     return index >= 0 ? mEntries.valueAt(index) : NULL;
 }
 
-Texture* AssetAtlas::getEntryTexture(SkBitmap* const bitmap) const {
+Texture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const {
     ssize_t index = mEntries.indexOfKey(bitmap);
     return index >= 0 ? mEntries.valueAt(index)->texture : NULL;
 }
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index a28efc6..57c8a60 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -160,13 +160,13 @@
      * Returns the entry in the atlas associated with the specified
      * bitmap. If the bitmap is not in the atlas, return NULL.
      */
-    Entry* getEntry(SkBitmap* const bitmap) const;
+    Entry* getEntry(const SkBitmap* bitmap) const;
 
     /**
      * Returns the texture for the atlas entry associated with the
      * specified bitmap. If the bitmap is not in the atlas, return NULL.
      */
-    Texture* getEntryTexture(SkBitmap* const bitmap) const;
+    Texture* getEntryTexture(const SkBitmap* bitmap) const;
 
     /**
      * Returns the current generation id of the atlas.
@@ -186,7 +186,7 @@
     const bool mBlendKey;
     const bool mOpaqueKey;
 
-    KeyedVector<SkBitmap*, Entry*> mEntries;
+    KeyedVector<const SkBitmap*, Entry*> mEntries;
 }; // class AssetAtlas
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index caed2b1..8da425d 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -90,7 +90,7 @@
     }
 
     for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
-        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
+        const SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
         caches.resourceCache.decrementRefcountLocked(bitmap);
         caches.resourceCache.destructorLocked(bitmap);
     }
@@ -173,16 +173,16 @@
     caches.registerFunctors(mFunctorCount);
     caches.resourceCache.lock();
 
-    const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
+    const Vector<const SkBitmap*>& bitmapResources = recorder.getBitmapResources();
     for (size_t i = 0; i < bitmapResources.size(); i++) {
-        SkBitmap* resource = bitmapResources.itemAt(i);
+        const SkBitmap* resource = bitmapResources.itemAt(i);
         mBitmapResources.add(resource);
         caches.resourceCache.incrementRefcountLocked(resource);
     }
 
-    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
+    const Vector<const SkBitmap*>& ownedBitmapResources = recorder.getOwnedBitmapResources();
     for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
-        SkBitmap* resource = ownedBitmapResources.itemAt(i);
+        const SkBitmap* resource = ownedBitmapResources.itemAt(i);
         mOwnedBitmapResources.add(resource);
         caches.resourceCache.incrementRefcountLocked(resource);
     }
@@ -194,9 +194,9 @@
         caches.resourceCache.incrementRefcountLocked(resource);
     }
 
-    const Vector<Res_png_9patch*>& patchResources = recorder.getPatchResources();
+    const Vector<const Res_png_9patch*>& patchResources = recorder.getPatchResources();
     for (size_t i = 0; i < patchResources.size(); i++) {
-        Res_png_9patch* resource = patchResources.itemAt(i);
+        const Res_png_9patch* resource = patchResources.itemAt(i);
         mPatchResources.add(resource);
         caches.resourceCache.incrementRefcountLocked(resource);
     }
@@ -208,7 +208,7 @@
         caches.resourceCache.incrementRefcountLocked(resource);
     }
 
-    const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
+    const SortedVector<const SkPath*>& sourcePaths = recorder.getSourcePaths();
     for (size_t i = 0; i < sourcePaths.size(); i++) {
         mSourcePaths.add(sourcePaths.itemAt(i));
         caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
@@ -610,14 +610,14 @@
     handler(op, PROPERTY_SAVECOUNT, mClipToBounds);
     int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
 
-    for (int i = 0; i < m3dNodes.size(); i++) {
+    for (size_t i = 0; i < m3dNodes.size(); i++) {
         const float zValue = m3dNodes.keyAt(i);
 
         if (mode == kPositiveZChildren && zValue < 0.0f) continue;
         if (mode == kNegativeZChildren && zValue > 0.0f) break;
 
         const Vector<DrawDisplayListOp*>& nodesAtZ = m3dNodes[i];
-        for (int j = 0; j < nodesAtZ.size(); j++) {
+        for (size_t j = 0; j < nodesAtZ.size(); j++) {
             DrawDisplayListOp* op = nodesAtZ[j];
             if (mode == kPositiveZChildren) {
                 /* draw shadow on renderer with parent matrix applied, passing in the child's total matrix
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 9933d9d..3f9ad9b 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -549,16 +549,16 @@
         const char* mText;
     };
 
-    Vector<SkBitmap*> mBitmapResources;
-    Vector<SkBitmap*> mOwnedBitmapResources;
+    Vector<const SkBitmap*> mBitmapResources;
+    Vector<const SkBitmap*> mOwnedBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
-    Vector<Res_png_9patch*> mPatchResources;
+    Vector<const Res_png_9patch*> mPatchResources;
 
-    Vector<SkPaint*> mPaints;
-    Vector<SkPath*> mPaths;
-    SortedVector<SkPath*> mSourcePaths;
-    Vector<SkRegion*> mRegions;
-    Vector<SkMatrix*> mMatrices;
+    Vector<const SkPaint*> mPaints;
+    Vector<const SkPath*> mPaths;
+    SortedVector<const SkPath*> mSourcePaths;
+    Vector<const SkRegion*> mRegions;
+    Vector<const SkMatrix*> mMatrices;
     Vector<SkiaShader*> mShaders;
     Vector<Layer*> mLayers;
 
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 1980b03..c375bfa 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -111,7 +111,7 @@
 class DrawOp : public DisplayListOp {
 friend class MergingDrawBatch;
 public:
-    DrawOp(SkPaint* paint)
+    DrawOp(const SkPaint* paint)
             : mPaint(paint), mQuickRejected(false) {}
 
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
@@ -191,7 +191,7 @@
     }
 
 protected:
-    SkPaint* getPaint(OpenGLRenderer& renderer) {
+    const SkPaint* getPaint(OpenGLRenderer& renderer) {
         return renderer.filterPaint(mPaint);
     }
 
@@ -212,22 +212,22 @@
 
     }
 
-    SkPaint* mPaint; // should be accessed via getPaint() when applying
+    const SkPaint* mPaint; // should be accessed via getPaint() when applying
     bool mQuickRejected;
 };
 
 class DrawBoundedOp : public DrawOp {
 public:
-    DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
+    DrawBoundedOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
 
-    DrawBoundedOp(const Rect& localBounds, SkPaint* paint)
+    DrawBoundedOp(const Rect& localBounds, const SkPaint* paint)
             : DrawOp(paint), mLocalBounds(localBounds) {}
 
     // Calculates bounds as smallest rect encompassing all points
     // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
     // subclass' constructor)
-    DrawBoundedOp(const float* points, int count, SkPaint* paint)
+    DrawBoundedOp(const float* points, int count, const SkPaint* paint)
             : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
         for (int i = 2; i < count; i += 2) {
             mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
@@ -238,7 +238,7 @@
     }
 
     // default empty constructor for bounds, to be overridden in child constructor body
-    DrawBoundedOp(SkPaint* paint): DrawOp(paint) { }
+    DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
 
     bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
         localBounds.set(mLocalBounds);
@@ -456,7 +456,7 @@
 
 class SetMatrixOp : public StateOp {
 public:
-    SetMatrixOp(SkMatrix* matrix)
+    SetMatrixOp(const SkMatrix* matrix)
             : mMatrix(matrix) {}
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
@@ -474,12 +474,12 @@
     virtual const char* name() { return "SetMatrix"; }
 
 private:
-    SkMatrix* mMatrix;
+    const SkMatrix* mMatrix;
 };
 
 class ConcatMatrixOp : public StateOp {
 public:
-    ConcatMatrixOp(SkMatrix* matrix)
+    ConcatMatrixOp(const SkMatrix* matrix)
             : mMatrix(matrix) {}
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
@@ -493,7 +493,7 @@
     virtual const char* name() { return "ConcatMatrix"; }
 
 private:
-    SkMatrix* mMatrix;
+    const SkMatrix* mMatrix;
 };
 
 class ClipOp : public StateOp {
@@ -551,7 +551,7 @@
 
 class ClipPathOp : public ClipOp {
 public:
-    ClipPathOp(SkPath* path, SkRegion::Op op)
+    ClipPathOp(const SkPath* path, SkRegion::Op op)
             : ClipOp(op), mPath(path) {}
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
@@ -567,12 +567,12 @@
     virtual const char* name() { return "ClipPath"; }
 
 private:
-    SkPath* mPath;
+    const SkPath* mPath;
 };
 
 class ClipRegionOp : public ClipOp {
 public:
-    ClipRegionOp(SkRegion* region, SkRegion::Op op)
+    ClipRegionOp(const SkRegion* region, SkRegion::Op op)
             : ClipOp(op), mRegion(region) {}
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
@@ -588,7 +588,7 @@
     virtual const char* name() { return "ClipRegion"; }
 
 private:
-    SkRegion* mRegion;
+    const SkRegion* mRegion;
 };
 
 class ResetShaderOp : public StateOp {
@@ -728,7 +728,7 @@
 
 class DrawBitmapOp : public DrawBoundedOp {
 public:
-    DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
+    DrawBitmapOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
             : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
             mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) {
         mEntry = mAtlas.getEntry(bitmap);
@@ -827,7 +827,7 @@
 
     const SkBitmap* bitmap() { return mBitmap; }
 protected:
-    SkBitmap* mBitmap;
+    const SkBitmap* mBitmap;
     const AssetAtlas& mAtlas;
     uint32_t mEntryGenerationId;
     AssetAtlas::Entry* mEntry;
@@ -836,7 +836,7 @@
 
 class DrawBitmapMatrixOp : public DrawBoundedOp {
 public:
-    DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
+    DrawBitmapMatrixOp(const SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint)
             : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
         mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
         const mat4 transform(*matrix);
@@ -859,14 +859,15 @@
     }
 
 private:
-    SkBitmap* mBitmap;
-    SkMatrix* mMatrix;
+    const SkBitmap* mBitmap;
+    const SkMatrix* mMatrix;
 };
 
 class DrawBitmapRectOp : public DrawBoundedOp {
 public:
-    DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
-            float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
+    DrawBitmapRectOp(const SkBitmap* bitmap,
+            float srcLeft, float srcTop, float srcRight, float srcBottom,
+            float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint)
             : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
             mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
 
@@ -889,13 +890,13 @@
     }
 
 private:
-    SkBitmap* mBitmap;
+    const SkBitmap* mBitmap;
     Rect mSrc;
 };
 
 class DrawBitmapDataOp : public DrawBitmapOp {
 public:
-    DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
+    DrawBitmapDataOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint)
             : DrawBitmapOp(bitmap, left, top, paint) {}
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
@@ -917,8 +918,8 @@
 
 class DrawBitmapMeshOp : public DrawBoundedOp {
 public:
-    DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
-            float* vertices, int* colors, SkPaint* paint)
+    DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint)
             : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
             mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
             mVertices(vertices), mColors(colors) {}
@@ -940,17 +941,17 @@
     }
 
 private:
-    SkBitmap* mBitmap;
+    const SkBitmap* mBitmap;
     int mMeshWidth;
     int mMeshHeight;
-    float* mVertices;
-    int* mColors;
+    const float* mVertices;
+    const int* mColors;
 };
 
 class DrawPatchOp : public DrawBoundedOp {
 public:
-    DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
-            float left, float top, float right, float bottom, SkPaint* paint)
+    DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch,
+            float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawBoundedOp(left, top, right, bottom, paint),
             mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL),
             mAtlas(Caches::getInstance().assetAtlas) {
@@ -1082,8 +1083,8 @@
     }
 
 private:
-    SkBitmap* mBitmap;
-    Res_png_9patch* mPatch;
+    const SkBitmap* mBitmap;
+    const Res_png_9patch* mPatch;
 
     uint32_t mGenerationId;
     const Patch* mMesh;
@@ -1115,7 +1116,7 @@
 
 class DrawStrokableOp : public DrawBoundedOp {
 public:
-    DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
+    DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawBoundedOp(left, top, right, bottom, paint) {};
 
     bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
@@ -1140,7 +1141,7 @@
 
 class DrawRectOp : public DrawStrokableOp {
 public:
-    DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
+    DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint) {}
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
@@ -1164,7 +1165,7 @@
 
 class DrawRectsOp : public DrawBoundedOp {
 public:
-    DrawRectsOp(const float* rects, int count, SkPaint* paint)
+    DrawRectsOp(const float* rects, int count, const SkPaint* paint)
             : DrawBoundedOp(rects, count, paint),
             mRects(rects), mCount(count) {}
 
@@ -1191,7 +1192,7 @@
 class DrawRoundRectOp : public DrawStrokableOp {
 public:
     DrawRoundRectOp(float left, float top, float right, float bottom,
-            float rx, float ry, SkPaint* paint)
+            float rx, float ry, const SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
@@ -1212,7 +1213,7 @@
 
 class DrawCircleOp : public DrawStrokableOp {
 public:
-    DrawCircleOp(float x, float y, float radius, SkPaint* paint)
+    DrawCircleOp(float x, float y, float radius, const SkPaint* paint)
             : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
             mX(x), mY(y), mRadius(radius) {}
 
@@ -1234,7 +1235,7 @@
 
 class DrawOvalOp : public DrawStrokableOp {
 public:
-    DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
+    DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint) {}
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
@@ -1252,7 +1253,7 @@
 class DrawArcOp : public DrawStrokableOp {
 public:
     DrawArcOp(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint)
             : DrawStrokableOp(left, top, right, bottom, paint),
             mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
 
@@ -1277,7 +1278,7 @@
 
 class DrawPathOp : public DrawBoundedOp {
 public:
-    DrawPathOp(SkPath* path, SkPaint* paint)
+    DrawPathOp(const SkPath* path, const SkPaint* paint)
             : DrawBoundedOp(paint), mPath(path) {
         float left, top, offset;
         uint32_t width, height;
@@ -1293,7 +1294,7 @@
 
     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
             const DeferredDisplayState& state) {
-        SkPaint* paint = getPaint(renderer);
+        const SkPaint* paint = getPaint(renderer);
         renderer.getCaches().pathCache.precache(mPath, paint);
 
         deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
@@ -1306,12 +1307,12 @@
     virtual const char* name() { return "DrawPath"; }
 
 private:
-    SkPath* mPath;
+    const SkPath* mPath;
 };
 
 class DrawLinesOp : public DrawBoundedOp {
 public:
-    DrawLinesOp(float* points, int count, SkPaint* paint)
+    DrawLinesOp(const float* points, int count, const SkPaint* paint)
             : DrawBoundedOp(points, count, paint),
             mPoints(points), mCount(count) {
         mLocalBounds.outset(strokeWidthOutset());
@@ -1335,13 +1336,13 @@
     }
 
 protected:
-    float* mPoints;
+    const float* mPoints;
     int mCount;
 };
 
 class DrawPointsOp : public DrawLinesOp {
 public:
-    DrawPointsOp(float* points, int count, SkPaint* paint)
+    DrawPointsOp(const float* points, int count, const SkPaint* paint)
             : DrawLinesOp(points, count, paint) {}
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
@@ -1357,7 +1358,7 @@
 
 class DrawSomeTextOp : public DrawOp {
 public:
-    DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
+    DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint)
             : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
 
     virtual void output(int level, uint32_t logFlags) const {
@@ -1366,7 +1367,7 @@
 
     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
             const DeferredDisplayState& state) {
-        SkPaint* paint = getPaint(renderer);
+        const SkPaint* paint = getPaint(renderer);
         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
         fontRenderer.precache(paint, mText, mCount, mat4::identity());
 
@@ -1384,7 +1385,7 @@
 class DrawTextOnPathOp : public DrawSomeTextOp {
 public:
     DrawTextOnPathOp(const char* text, int bytesCount, int count,
-            SkPath* path, float hOffset, float vOffset, SkPaint* paint)
+            const SkPath* path, float hOffset, float vOffset, const SkPaint* paint)
             : DrawSomeTextOp(text, bytesCount, count, paint),
             mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
         /* TODO: inherit from DrawBounded and init mLocalBounds */
@@ -1398,7 +1399,7 @@
     virtual const char* name() { return "DrawTextOnPath"; }
 
 private:
-    SkPath* mPath;
+    const SkPath* mPath;
     float mHOffset;
     float mVOffset;
 };
@@ -1406,7 +1407,7 @@
 class DrawPosTextOp : public DrawSomeTextOp {
 public:
     DrawPosTextOp(const char* text, int bytesCount, int count,
-            const float* positions, SkPaint* paint)
+            const float* positions, const SkPaint* paint)
             : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
         /* TODO: inherit from DrawBounded and init mLocalBounds */
     }
@@ -1424,7 +1425,7 @@
 class DrawTextOp : public DrawBoundedOp {
 public:
     DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
-            const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds)
+            const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds)
             : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
             mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
         memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
@@ -1432,7 +1433,7 @@
 
     virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
             const DeferredDisplayState& state) {
-        SkPaint* paint = getPaint(renderer);
+        const SkPaint* paint = getPaint(renderer);
         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
         const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
         if (mPrecacheTransform != transform) {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 9c5db6e..051ccfe 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -203,13 +203,13 @@
     StatefulBaseRenderer::skew(sx, sy);
 }
 
-void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
+void DisplayListRenderer::setMatrix(const SkMatrix* matrix) {
     matrix = refMatrix(matrix);
     addStateOp(new (alloc()) SetMatrixOp(matrix));
     StatefulBaseRenderer::setMatrix(matrix);
 }
 
-void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
+void DisplayListRenderer::concatMatrix(const SkMatrix* matrix) {
     matrix = refMatrix(matrix);
     addStateOp(new (alloc()) ConcatMatrixOp(matrix));
     StatefulBaseRenderer::concatMatrix(matrix);
@@ -218,19 +218,19 @@
 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
         SkRegion::Op op) {
     addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op));
-    return OpenGLRenderer::clipRect(left, top, right, bottom, op);
+    return StatefulBaseRenderer::clipRect(left, top, right, bottom, op);
 }
 
-bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
+bool DisplayListRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
     path = refPath(path);
     addStateOp(new (alloc()) ClipPathOp(path, op));
-    return OpenGLRenderer::clipPath(path, op);
+    return StatefulBaseRenderer::clipPath(path, op);
 }
 
-bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
+bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
     region = refRegion(region);
     addStateOp(new (alloc()) ClipRegionOp(region, op));
-    return OpenGLRenderer::clipRegion(region, op);
+    return StatefulBaseRenderer::clipRegion(region, op);
 }
 
 status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
@@ -242,7 +242,8 @@
     //       resources cache, but we rely on the caller (UI toolkit) to
     //       do the right thing for now
 
-    DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList, flags, currentTransform());
+    DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
+            flags, *currentTransform());
     addDrawOp(op);
     mDisplayListData->children.push(op);
 
@@ -255,7 +256,8 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
+status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, float left, float top,
+        const SkPaint* paint) {
     bitmap = refBitmap(bitmap);
     paint = refPaint(paint);
 
@@ -263,7 +265,8 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
+status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, const SkMatrix* matrix,
+        const SkPaint* paint) {
     bitmap = refBitmap(bitmap);
     matrix = refMatrix(matrix);
     paint = refPaint(paint);
@@ -272,9 +275,9 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
+status_t DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop,
-        float dstRight, float dstBottom, SkPaint* paint) {
+        float dstRight, float dstBottom, const SkPaint* paint) {
     bitmap = refBitmap(bitmap);
     paint = refPaint(paint);
 
@@ -293,8 +296,8 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
-        SkPaint* paint) {
+status_t DisplayListRenderer::drawBitmapData(const SkBitmap* bitmap, float left, float top,
+        const SkPaint* paint) {
     bitmap = refBitmapData(bitmap);
     paint = refPaint(paint);
 
@@ -302,8 +305,8 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
-        float* vertices, int* colors, SkPaint* paint) {
+status_t DisplayListRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+        const float* vertices, const int* colors, const SkPaint* paint) {
     int count = (meshWidth + 1) * (meshHeight + 1) * 2;
     bitmap = refBitmap(bitmap);
     vertices = refBuffer<float>(vertices, count);
@@ -315,8 +318,8 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-        float left, float top, float right, float bottom, SkPaint* paint) {
+status_t DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
+        float left, float top, float right, float bottom, const SkPaint* paint) {
     bitmap = refBitmap(bitmap);
     patch = refPatch(patch);
     paint = refPaint(paint);
@@ -331,41 +334,41 @@
 }
 
 status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
-        SkPaint* paint) {
+        const SkPaint* paint) {
     paint = refPaint(paint);
     addDrawOp(new (alloc()) DrawRectOp(left, top, right, bottom, paint));
     return DrawGlInfo::kStatusDone;
 }
 
 status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
-        float rx, float ry, SkPaint* paint) {
+        float rx, float ry, const SkPaint* paint) {
     paint = refPaint(paint);
     addDrawOp(new (alloc()) DrawRoundRectOp(left, top, right, bottom, rx, ry, paint));
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
+status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const SkPaint* paint) {
     paint = refPaint(paint);
     addDrawOp(new (alloc()) DrawCircleOp(x, y, radius, paint));
     return DrawGlInfo::kStatusDone;
 }
 
 status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
-        SkPaint* paint) {
+        const SkPaint* paint) {
     paint = refPaint(paint);
     addDrawOp(new (alloc()) DrawOvalOp(left, top, right, bottom, paint));
     return DrawGlInfo::kStatusDone;
 }
 
 status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
+        float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
     paint = refPaint(paint);
     addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
                     startAngle, sweepAngle, useCenter, paint));
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
+status_t DisplayListRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
     path = refPath(path);
     paint = refPaint(paint);
 
@@ -373,7 +376,7 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
+status_t DisplayListRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
     points = refBuffer<float>(points, count);
     paint = refPaint(paint);
 
@@ -381,7 +384,7 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
+status_t DisplayListRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
     points = refBuffer<float>(points, count);
     paint = refPaint(paint);
 
@@ -390,7 +393,7 @@
 }
 
 status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
-        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
+        const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
 
     text = refText(text, bytesCount);
@@ -404,7 +407,7 @@
 }
 
 status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
-        const float* positions, SkPaint* paint) {
+        const float* positions, const SkPaint* paint) {
     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
 
     text = refText(text, bytesCount);
@@ -417,7 +420,7 @@
 }
 
 status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
-        float x, float y, const float* positions, SkPaint* paint,
+        float x, float y, const float* positions, const SkPaint* paint,
         float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) {
 
     if (!text || count <= 0) return DrawGlInfo::kStatusDone;
@@ -432,7 +435,7 @@
     return DrawGlInfo::kStatusDone;
 }
 
-status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
+status_t DisplayListRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
     if (count <= 0) return DrawGlInfo::kStatusDone;
 
     rects = refBuffer<float>(rects, count);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b5d9924..f129c10 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -54,7 +54,7 @@
 class StateOp;
 
 /**
- * Records drawing commands in a display list for latter playback.
+ * Records drawing commands in a display list for later playback into an OpenGLRenderer.
  */
 class DisplayListRenderer: public OpenGLRenderer {
 public:
@@ -63,7 +63,7 @@
 
     ANDROID_API DisplayList* getDisplayList(DisplayList* displayList);
 
-    virtual bool isRecording() { return true; }
+    virtual bool isRecording() const { return true; }
 
 // ----------------------------------------------------------------------------
 // Frame state operations
@@ -90,13 +90,13 @@
     virtual void scale(float sx, float sy);
     virtual void skew(float sx, float sy);
 
-    virtual void setMatrix(SkMatrix* matrix);
-    virtual void concatMatrix(SkMatrix* matrix);
+    virtual void setMatrix(const SkMatrix* matrix);
+    virtual void concatMatrix(const SkMatrix* matrix);
 
     // Clip
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
-    virtual bool clipPath(SkPath* path, SkRegion::Op op);
-    virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
+    virtual bool clipPath(const SkPath* path, SkRegion::Op op);
+    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
 
     // Misc - should be implemented with SkPaint inspection
     virtual void resetShader();
@@ -117,38 +117,43 @@
     virtual status_t drawColor(int color, SkXfermode::Mode mode);
 
     // Bitmap-based
-    virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
-    virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
-    virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
+    virtual status_t drawBitmap(const SkBitmap* bitmap, float left, float top,
+            const SkPaint* paint);
+    virtual status_t drawBitmap(const SkBitmap* bitmap, const SkMatrix* matrix,
+            const SkPaint* paint);
+    virtual status_t drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, SkPaint* paint);
-    virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint);
-    virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
-            float* vertices, int* colors, SkPaint* paint);
-    virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-            float left, float top, float right, float bottom, SkPaint* paint);
+            float dstRight, float dstBottom, const SkPaint* paint);
+    virtual status_t drawBitmapData(const SkBitmap* bitmap, float left, float top,
+            const SkPaint* paint);
+    virtual status_t drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint);
+    virtual status_t drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
+            float left, float top, float right, float bottom, const SkPaint* paint);
 
     // Shapes
-    virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint);
-    virtual status_t drawRects(const float* rects, int count, SkPaint* paint);
+    virtual status_t drawRect(float left, float top, float right, float bottom,
+            const SkPaint* paint);
+    virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, SkPaint* paint);
-    virtual status_t drawCircle(float x, float y, float radius, SkPaint* paint);
-    virtual status_t drawOval(float left, float top, float right, float bottom, SkPaint* paint);
+            float rx, float ry, const SkPaint* paint);
+    virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawOval(float left, float top, float right, float bottom,
+            const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
-    virtual status_t drawPath(SkPath* path, SkPaint* paint);
-    virtual status_t drawLines(float* points, int count, SkPaint* paint);
-    virtual status_t drawPoints(float* points, int count, SkPaint* paint);
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint);
+    virtual status_t drawPath(const SkPath* path, const SkPaint* paint);
+    virtual status_t drawLines(const float* points, int count, const SkPaint* paint);
+    virtual status_t drawPoints(const float* points, int count, const SkPaint* paint);
 
     // Text
     virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds,
+            const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
             DrawOpMode drawOpMode = kDrawOpMode_Immediate);
-    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
-            float hOffset, float vOffset, SkPaint* paint);
+    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path,
+            float hOffset, float vOffset, const SkPaint* paint);
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
-            const float* positions, SkPaint* paint);
+            const float* positions, const SkPaint* paint);
 
 // ----------------------------------------------------------------------------
 // Canvas draw operations - special
@@ -169,11 +174,11 @@
         return mDisplayListData;
     }
 
-    const Vector<SkBitmap*>& getBitmapResources() const {
+    const Vector<const SkBitmap*>& getBitmapResources() const {
         return mBitmapResources;
     }
 
-    const Vector<SkBitmap*>& getOwnedBitmapResources() const {
+    const Vector<const SkBitmap*>& getOwnedBitmapResources() const {
         return mOwnedBitmapResources;
     }
 
@@ -181,7 +186,7 @@
         return mFilterResources;
     }
 
-    const Vector<Res_png_9patch*>& getPatchResources() const {
+    const Vector<const Res_png_9patch*>& getPatchResources() const {
         return mPatchResources;
     }
 
@@ -189,19 +194,19 @@
         return mShaders;
     }
 
-    const Vector<SkPaint*>& getPaints() const {
+    const Vector<const SkPaint*>& getPaints() const {
         return mPaints;
     }
 
-    const Vector<SkPath*>& getPaths() const {
+    const Vector<const SkPath*>& getPaths() const {
         return mPaths;
     }
 
-    const SortedVector<SkPath*>& getSourcePaths() const {
+    const SortedVector<const SkPath*>& getSourcePaths() const {
         return mSourcePaths;
     }
 
-    const Vector<SkRegion*>& getRegions() const {
+    const Vector<const SkRegion*>& getRegions() const {
         return mRegions;
     }
 
@@ -209,7 +214,7 @@
         return mLayers;
     }
 
-    const Vector<SkMatrix*>& getMatrices() const {
+    const Vector<const SkMatrix*>& getMatrices() const {
         return mMatrices;
     }
 
@@ -231,8 +236,9 @@
     }
 
     template<class T>
-    inline T* refBuffer(const T* srcBuffer, int32_t count) {
-        if (srcBuffer == NULL) return NULL;
+    inline const T* refBuffer(const T* srcBuffer, int32_t count) {
+        if (!srcBuffer) return NULL;
+
         T* dstBuffer = (T*) mDisplayListData->allocator.alloc(count * sizeof(T));
         memcpy(dstBuffer, srcBuffer, count * sizeof(T));
         return dstBuffer;
@@ -242,13 +248,15 @@
         return (char*) refBuffer<uint8_t>((uint8_t*)text, byteLength);
     }
 
-    inline SkPath* refPath(SkPath* path) {
+    inline const SkPath* refPath(const SkPath* path) {
         if (!path) return NULL;
 
-        SkPath* pathCopy = mPathMap.valueFor(path);
+        const SkPath* pathCopy = mPathMap.valueFor(path);
         if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
-            pathCopy = new SkPath(*path);
-            pathCopy->setSourcePath(path);
+            SkPath* newPathCopy = new SkPath(*path);
+            newPathCopy->setSourcePath(path);
+
+            pathCopy = newPathCopy;
             // replaceValueFor() performs an add if the entry doesn't exist
             mPathMap.replaceValueFor(path, pathCopy);
             mPaths.add(pathCopy);
@@ -260,12 +268,12 @@
         return pathCopy;
     }
 
-    inline SkPaint* refPaint(SkPaint* paint) {
+    inline const SkPaint* refPaint(const SkPaint* paint) {
         if (!paint) {
             return paint;
         }
 
-        SkPaint* paintCopy = mPaintMap.valueFor(paint);
+        const SkPaint* paintCopy = mPaintMap.valueFor(paint);
         if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
             paintCopy = new SkPaint(*paint);
             // replaceValueFor() performs an add if the entry doesn't exist
@@ -276,12 +284,12 @@
         return paintCopy;
     }
 
-    inline SkRegion* refRegion(SkRegion* region) {
+    inline const SkRegion* refRegion(const SkRegion* region) {
         if (!region) {
             return region;
         }
 
-        SkRegion* regionCopy = mRegionMap.valueFor(region);
+        const SkRegion* regionCopy = mRegionMap.valueFor(region);
         // TODO: Add generation ID to SkRegion
         if (regionCopy == NULL) {
             regionCopy = new SkRegion(*region);
@@ -293,11 +301,11 @@
         return regionCopy;
     }
 
-    inline SkMatrix* refMatrix(SkMatrix* matrix) {
+    inline const SkMatrix* refMatrix(const SkMatrix* matrix) {
         if (matrix) {
             // Copying the matrix is cheap and prevents against the user changing
             // the original matrix before the operation that uses it
-            SkMatrix* copy = new SkMatrix(*matrix);
+            const SkMatrix* copy = new SkMatrix(*matrix);
             mMatrices.add(copy);
             return copy;
         }
@@ -310,7 +318,7 @@
         return layer;
     }
 
-    inline SkBitmap* refBitmap(SkBitmap* bitmap) {
+    inline const SkBitmap* refBitmap(const SkBitmap* bitmap) {
         // Note that this assumes the bitmap is immutable. There are cases this won't handle
         // correctly, such as creating the bitmap from scratch, drawing with it, changing its
         // contents, and drawing again. The only fix would be to always copy it the first time,
@@ -320,7 +328,7 @@
         return bitmap;
     }
 
-    inline SkBitmap* refBitmapData(SkBitmap* bitmap) {
+    inline const SkBitmap* refBitmapData(const SkBitmap* bitmap) {
         mOwnedBitmapResources.add(bitmap);
         mCaches.resourceCache.incrementRefcount(bitmap);
         return bitmap;
@@ -347,33 +355,33 @@
         return colorFilter;
     }
 
-    inline Res_png_9patch* refPatch(Res_png_9patch* patch) {
+    inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
         mPatchResources.add(patch);
         mCaches.resourceCache.incrementRefcount(patch);
         return patch;
     }
 
     // TODO: move these to DisplayListData
-    Vector<SkBitmap*> mBitmapResources;
-    Vector<SkBitmap*> mOwnedBitmapResources;
+    Vector<const SkBitmap*> mBitmapResources;
+    Vector<const SkBitmap*> mOwnedBitmapResources;
     Vector<SkiaColorFilter*> mFilterResources;
-    Vector<Res_png_9patch*> mPatchResources;
+    Vector<const Res_png_9patch*> mPatchResources;
 
-    Vector<SkPaint*> mPaints;
-    DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
+    Vector<const SkPaint*> mPaints;
+    DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
 
-    Vector<SkPath*> mPaths;
-    DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
+    Vector<const SkPath*> mPaths;
+    DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
 
-    SortedVector<SkPath*> mSourcePaths;
+    SortedVector<const SkPath*> mSourcePaths;
 
-    Vector<SkRegion*> mRegions;
-    DefaultKeyedVector<SkRegion*, SkRegion*> mRegionMap;
+    Vector<const SkRegion*> mRegions;
+    DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
 
     Vector<SkiaShader*> mShaders;
     DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
 
-    Vector<SkMatrix*> mMatrices;
+    Vector<const SkMatrix*> mMatrices;
 
     Vector<Layer*> mLayers;
 
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index f7493a3..f907d64 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -587,11 +587,11 @@
     }
 }
 
-void FontRenderer::setFont(SkPaint* paint, const mat4& matrix) {
+void FontRenderer::setFont(const SkPaint* paint, const mat4& matrix) {
     mCurrentFont = Font::create(this, paint, matrix);
 }
 
-FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
+FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) {
     checkInit();
 
@@ -676,7 +676,8 @@
     issueDrawCommand();
 }
 
-void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix) {
+void FontRenderer::precache(const SkPaint* paint, const char* text, int numGlyphs,
+        const mat4& matrix) {
     Font* font = Font::create(this, paint, matrix);
     font->precache(paint, text, numGlyphs);
 }
@@ -685,7 +686,7 @@
     checkTextureUpdate();
 }
 
-bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text,
+bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
         uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y,
         const float* positions, Rect* bounds, Functor* functor, bool forceFinish) {
     if (!mCurrentFont) {
@@ -703,8 +704,8 @@
     return mDrawn;
 }
 
-bool FontRenderer::renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text,
-        uint32_t startIndex, uint32_t len, int numGlyphs, SkPath* path,
+bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
+        uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
         float hOffset, float vOffset, Rect* bounds, Functor* functor) {
     if (!mCurrentFont) {
         ALOGE("No font set");
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index db4e020..9259028 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -62,7 +62,7 @@
     };
 
     TextSetupFunctor(OpenGLRenderer* renderer, float x, float y, bool pureTranslate,
-            int alpha, SkXfermode::Mode mode, SkPaint* paint): Functor(),
+            int alpha, SkXfermode::Mode mode, const SkPaint* paint): Functor(),
             renderer(renderer), x(x), y(y), pureTranslate(pureTranslate),
             alpha(alpha), mode(mode), paint(paint) {
     }
@@ -76,7 +76,7 @@
     bool pureTranslate;
     int alpha;
     SkXfermode::Mode mode;
-    SkPaint* paint;
+    const SkPaint* paint;
 };
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -95,20 +95,20 @@
         mGammaTable = gammaTable;
     }
 
-    void setFont(SkPaint* paint, const mat4& matrix);
+    void setFont(const SkPaint* paint, const mat4& matrix);
 
-    void precache(SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix);
+    void precache(const SkPaint* paint, const char* text, int numGlyphs, const mat4& matrix);
     void endPrecaching();
 
     // bounds is an out parameter
-    bool renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
-            uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds,
-            Functor* functor, bool forceFinish = true);
+    bool renderPosText(const SkPaint* paint, const Rect* clip, const char *text,
+            uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions,
+            Rect* bounds, Functor* functor, bool forceFinish = true);
 
     // bounds is an out parameter
-    bool renderTextOnPath(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
-            uint32_t len, int numGlyphs, SkPath* path, float hOffset, float vOffset, Rect* bounds,
-            Functor* functor);
+    bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text,
+            uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path,
+            float hOffset, float vOffset, Rect* bounds, Functor* functor);
 
     struct DropShadow {
         DropShadow() { };
@@ -128,7 +128,7 @@
 
     // After renderDropShadow returns, the called owns the memory in DropShadow.image
     // and is responsible for releasing it when it's done with it
-    DropShadow renderDropShadow(SkPaint* paint, const char *text, uint32_t startIndex,
+    DropShadow renderDropShadow(const SkPaint* paint, const char *text, uint32_t startIndex,
             uint32_t len, int numGlyphs, uint32_t radius, const float* positions);
 
     void setTextureFiltering(bool linearFiltering) {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index b70042f..471a4a6 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -49,7 +49,8 @@
 /**
  * A layer has dimensions and is backed by an OpenGL texture or FBO.
  */
-struct Layer {
+class Layer {
+public:
     Layer(const uint32_t layerWidth, const uint32_t layerHeight);
     ~Layer();
 
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 35fd46e..0b38c4d 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -117,7 +117,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Region* LayerRenderer::getRegion() const {
-    if (getSnapshot()->flags & Snapshot::kFlagFboTarget) {
+    if (currentSnapshot()->flags & Snapshot::kFlagFboTarget) {
         return OpenGLRenderer::getRegion();
     }
     return &mLayer->region;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a3a4432..22cd2d4 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -208,7 +208,7 @@
     // invoked during the frame
     mSuppressTiling = mCaches.hasRegisteredFunctors();
 
-    startTiling(*mSnapshot, true);
+    startTilingCurrentClip(true);
 
     debugOverdraw(true, true);
 
@@ -225,7 +225,7 @@
     // The framebuffer renderer will first defer the display list
     // for each layer and wait until the first drawing command
     // to start the frame
-    if (currentSnapshot().fbo == 0) {
+    if (currentSnapshot()->fbo == 0) {
         syncState();
         updateLayers();
     } else {
@@ -252,7 +252,7 @@
 status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
     if (!opaque || mCountOverdraw) {
         mCaches.enableScissor();
-        mCaches.setScissor(left, currentSnapshot().height - bottom, right - left, bottom - top);
+        mCaches.setScissor(left, currentSnapshot()->height - bottom, right - left, bottom - top);
         glClear(GL_COLOR_BUFFER_BIT);
         return DrawGlInfo::kStatusDrew;
     }
@@ -269,14 +269,16 @@
     }
 }
 
-void OpenGLRenderer::startTiling(const Snapshot& s, bool opaque) {
+void OpenGLRenderer::startTilingCurrentClip(bool opaque) {
     if (!mSuppressTiling) {
+        const Snapshot* snapshot = currentSnapshot();
+
         const Rect* clip = &mTilingClip;
-        if (s.flags & Snapshot::kFlagFboTarget) {
-            clip = &(s.layer->clipRect);
+        if (snapshot->flags & Snapshot::kFlagFboTarget) {
+            clip = &(snapshot->layer->clipRect);
         }
 
-        startTiling(*clip, s.height, opaque);
+        startTiling(*clip, snapshot->height, opaque);
     }
 }
 
@@ -355,9 +357,9 @@
 }
 
 void OpenGLRenderer::resume() {
-    const Snapshot& snapshot = currentSnapshot();
-    glViewport(0, 0, snapshot.viewport.getWidth(), snapshot.viewport.getHeight());
-    glBindFramebuffer(GL_FRAMEBUFFER, snapshot.fbo);
+    const Snapshot* snapshot = currentSnapshot();
+    glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
     debugOverdraw(true, false);
 
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -377,9 +379,9 @@
 }
 
 void OpenGLRenderer::resumeAfterLayer() {
-    const Snapshot& snapshot = currentSnapshot();
-    glViewport(0, 0, snapshot.viewport.getWidth(), snapshot.viewport.getHeight());
-    glBindFramebuffer(GL_FRAMEBUFFER, snapshot.fbo);
+    const Snapshot* snapshot = currentSnapshot();
+    glViewport(0, 0, snapshot->viewport.getWidth(), snapshot->viewport.getHeight());
+    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
     debugOverdraw(true, false);
 
     mCaches.resetScissor();
@@ -433,16 +435,16 @@
 }
 
 status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
-    if (currentSnapshot().isIgnored()) return DrawGlInfo::kStatusDone;
+    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
 
     detachFunctor(functor);
 
 
-    Rect clip(currentClipRect());
+    Rect clip(*currentClipRect());
     clip.snapToPixelBoundaries();
 
     // Since we don't know what the functor will draw, let's dirty
-    // tne entire clip region
+    // the entire clip region
     if (hasLayer()) {
         dirtyLayerUnchecked(clip, getRegion());
     }
@@ -453,9 +455,9 @@
     info.clipRight = clip.right;
     info.clipBottom = clip.bottom;
     info.isLayer = hasLayer();
-    info.width = getSnapshot()->viewport.getWidth();
-    info.height = getSnapshot()->height;
-    getSnapshot()->transform->copyTo(&info.transform[0]);
+    info.width = currentSnapshot()->viewport.getWidth();
+    info.height = currentSnapshot()->height;
+    currentTransform()->copyTo(&info.transform[0]);
 
     bool dirtyClip = mDirtyClip;
     // setup GL state for functor
@@ -518,7 +520,7 @@
         const Rect* clip = &mTilingClip;
 
         mCaches.enableScissor();
-        mCaches.setScissor(clip->left, mFirstSnapshot->height - clip->bottom,
+        mCaches.setScissor(clip->left, firstSnapshot()->height - clip->bottom,
                 clip->right - clip->left, clip->bottom - clip->top);
 
         // 1x overdraw
@@ -580,7 +582,7 @@
 
         if (inFrame) {
             resumeAfterLayer();
-            startTiling(*mSnapshot);
+            startTilingCurrentClip();
         }
 
         layer->debugDrawUpdate = mCaches.debugLayersUpdates;
@@ -709,7 +711,7 @@
     if (restoreOrtho) {
         const Rect& r = restored.viewport;
         glViewport(r.left, r.top, r.right, r.bottom);
-        mViewProjMatrix.load(removed.orthoMatrix); // todo: should ortho be stored in 'restored'?
+        mViewProjMatrix.load(removed.orthoMatrix); // TODO: should ortho be stored in 'restored'?
     }
 
     if (restoreClip) {
@@ -732,7 +734,7 @@
         int alpha, SkXfermode::Mode mode, int flags) {
     const int count = saveSnapshot(flags);
 
-    if (!currentSnapshot().isIgnored()) {
+    if (!currentSnapshot()->isIgnored()) {
         createLayer(left, top, right, bottom, alpha, mode, flags);
     }
 
@@ -742,22 +744,22 @@
 void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool fboLayer) {
     const Rect untransformedBounds(bounds);
 
-    currentTransform().mapRect(bounds);
+    currentTransform()->mapRect(bounds);
 
     // Layers only make sense if they are in the framebuffer's bounds
-    if (bounds.intersect(currentClipRect())) {
+    if (bounds.intersect(*currentClipRect())) {
         // We cannot work with sub-pixels in this case
         bounds.snapToPixelBoundaries();
 
         // When the layer is not an FBO, we may use glCopyTexImage so we
         // need to make sure the layer does not extend outside the bounds
         // of the framebuffer
-        if (!bounds.intersect(currentSnapshot().previous->viewport)) {
+        if (!bounds.intersect(currentSnapshot()->previous->viewport)) {
             bounds.setEmpty();
         } else if (fboLayer) {
             clip.set(bounds);
             mat4 inverse;
-            inverse.loadInverse(currentTransform());
+            inverse.loadInverse(*currentTransform());
             inverse.mapRect(clip);
             clip.snapToPixelBoundaries();
             if (clip.intersect(untransformedBounds)) {
@@ -787,7 +789,7 @@
         int alpha, SkXfermode::Mode mode, int flags) {
     const int count = saveSnapshot(flags);
 
-    if (!currentSnapshot().isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
+    if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) {
         // initialize the snapshot as though it almost represents an FBO layer so deferred draw
         // operations will be able to store and restore the current clip and transform info, and
         // quick rejection will be correct (for display lists)
@@ -797,7 +799,7 @@
         calculateLayerBoundsAndClip(bounds, clip, true);
         updateSnapshotIgnoreForLayer(bounds, clip, true, alpha);
 
-        if (!currentSnapshot().isIgnored()) {
+        if (!currentSnapshot()->isIgnored()) {
             mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
             mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
             mSnapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
@@ -873,7 +875,7 @@
     updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, alpha);
 
     // Bail out if we won't draw in this snapshot
-    if (currentSnapshot().isIgnored()) {
+    if (currentSnapshot()->isIgnored()) {
         return false;
     }
 
@@ -952,7 +954,7 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-    startTiling(*mSnapshot, true);
+    startTilingCurrentClip(true);
 
     // Clear the FBO, expand the clear region by 1 to get nice bilinear filtering
     mCaches.enableScissor();
@@ -1001,7 +1003,7 @@
         glBindFramebuffer(GL_FRAMEBUFFER, restored.fbo);
         debugOverdraw(true, false);
 
-        startTiling(restored);
+        startTilingCurrentClip();
     }
 
     if (!fboLayer && layer->getAlpha() < 255) {
@@ -1067,11 +1069,11 @@
     } else {
         setupDrawExternalTexture(layer->getTexture());
     }
-    if (currentTransform().isPureTranslate() &&
+    if (currentTransform()->isPureTranslate() &&
             layer->getWidth() == (uint32_t) rect.getWidth() &&
             layer->getHeight() == (uint32_t) rect.getHeight()) {
-        const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
-        const float y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f);
+        const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
+        const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
 
         layer->setFilter(GL_NEAREST);
         setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -1095,15 +1097,15 @@
 
         float x = rect.left;
         float y = rect.top;
-        bool simpleTransform = currentTransform().isPureTranslate() &&
+        bool simpleTransform = currentTransform()->isPureTranslate() &&
                 layer->getWidth() == (uint32_t) rect.getWidth() &&
                 layer->getHeight() == (uint32_t) rect.getHeight();
 
         if (simpleTransform) {
             // When we're swapping, the layer is already in screen coordinates
             if (!swap) {
-                x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
-                y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f);
+                x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
+                y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
             }
 
             layer->setFilter(GL_NEAREST, true);
@@ -1186,9 +1188,9 @@
         setupDrawPureColorUniforms();
         setupDrawColorFilterUniforms();
         setupDrawTexture(layer->getTexture());
-        if (currentTransform().isPureTranslate()) {
-            const float x = (int) floorf(rect.left + currentTransform().getTranslateX() + 0.5f);
-            const float y = (int) floorf(rect.top + currentTransform().getTranslateY() + 0.5f);
+        if (currentTransform()->isPureTranslate()) {
+            const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
+            const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
 
             layer->setFilter(GL_NEAREST);
             setupDrawModelView(kModelViewMode_Translate, false,
@@ -1298,7 +1300,7 @@
 }
 
 void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) {
-    if (bounds.intersect(currentClipRect())) {
+    if (bounds.intersect(*currentClipRect())) {
         bounds.snapToPixelBoundaries();
         android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
         if (!dirty.isEmpty()) {
@@ -1326,7 +1328,7 @@
     const size_t count = mLayers.size();
     if (count == 0) return;
 
-    if (!currentSnapshot().isIgnored()) {
+    if (!currentSnapshot()->isIgnored()) {
         // Doing several glScissor/glClear here can negatively impact
         // GPUs with a tiler architecture, instead we draw quads with
         // the Clear blending mode
@@ -1378,51 +1380,51 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) {
-    const Rect& currentClip = currentClipRect();
-    const mat4& currentMatrix = currentTransform();
+    const Rect* currentClip = currentClipRect();
+    const mat4* currentMatrix = currentTransform();
 
     if (stateDeferFlags & kStateDeferFlag_Draw) {
         // state has bounds initialized in local coordinates
         if (!state.mBounds.isEmpty()) {
-            currentMatrix.mapRect(state.mBounds);
+            currentMatrix->mapRect(state.mBounds);
             Rect clippedBounds(state.mBounds);
             // NOTE: if we ever want to use this clipping info to drive whether the scissor
             // is used, it should more closely duplicate the quickReject logic (in how it uses
             // snapToPixelBoundaries)
 
-            if(!clippedBounds.intersect(currentClip)) {
+            if(!clippedBounds.intersect(*currentClip)) {
                 // quick rejected
                 return true;
             }
 
             state.mClipSideFlags = kClipSide_None;
-            if (!currentClip.contains(state.mBounds)) {
+            if (!currentClip->contains(state.mBounds)) {
                 int& flags = state.mClipSideFlags;
                 // op partially clipped, so record which sides are clipped for clip-aware merging
-                if (currentClip.left > state.mBounds.left) flags |= kClipSide_Left;
-                if (currentClip.top > state.mBounds.top) flags |= kClipSide_Top;
-                if (currentClip.right < state.mBounds.right) flags |= kClipSide_Right;
-                if (currentClip.bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
+                if (currentClip->left > state.mBounds.left) flags |= kClipSide_Left;
+                if (currentClip->top > state.mBounds.top) flags |= kClipSide_Top;
+                if (currentClip->right < state.mBounds.right) flags |= kClipSide_Right;
+                if (currentClip->bottom < state.mBounds.bottom) flags |= kClipSide_Bottom;
             }
             state.mBounds.set(clippedBounds);
         } else {
             // Empty bounds implies size unknown. Label op as conservatively clipped to disable
             // overdraw avoidance (since we don't know what it overlaps)
             state.mClipSideFlags = kClipSide_ConservativeFull;
-            state.mBounds.set(currentClip);
+            state.mBounds.set(*currentClip);
         }
     }
 
     state.mClipValid = (stateDeferFlags & kStateDeferFlag_Clip);
     if (state.mClipValid) {
-        state.mClip.set(currentClip);
+        state.mClip.set(*currentClip);
     }
 
     // Transform, drawModifiers, and alpha always deferred, since they are used by state operations
     // (Note: saveLayer/restore use colorFilter and alpha, so we just save restore everything)
-    state.mMatrix.load(currentMatrix);
+    state.mMatrix.load(*currentMatrix);
     state.mDrawModifiers = mDrawModifiers;
-    state.mAlpha = currentSnapshot().alpha;
+    state.mAlpha = currentSnapshot()->alpha;
     return false;
 }
 
@@ -1460,10 +1462,10 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void OpenGLRenderer::setScissorFromClip() {
-    Rect clip(currentClipRect());
+    Rect clip(*currentClipRect());
     clip.snapToPixelBoundaries();
 
-    if (mCaches.setScissor(clip.left, currentSnapshot().height - clip.bottom,
+    if (mCaches.setScissor(clip.left, currentSnapshot()->height - clip.bottom,
             clip.getWidth(), clip.getHeight())) {
         mDirtyClip = false;
     }
@@ -1474,7 +1476,7 @@
     // cannot attach a stencil buffer to fbo0 dynamically. Let's
     // just hope we have one when hasLayer() returns false.
     if (hasLayer()) {
-        attachStencilBufferToLayer(currentSnapshot().layer);
+        attachStencilBufferToLayer(currentSnapshot()->layer);
     }
 }
 
@@ -1496,7 +1498,7 @@
 
 void OpenGLRenderer::setStencilFromClip() {
     if (!mCaches.debugOverdraw) {
-        if (!currentSnapshot().clipRegion->isEmpty()) {
+        if (!currentSnapshot()->clipRegion->isEmpty()) {
             // NOTE: The order here is important, we must set dirtyClip to false
             //       before any draw call to avoid calling back into this method
             mDirtyClip = false;
@@ -1521,7 +1523,7 @@
 
             // The last parameter is important: we are not drawing in the color buffer
             // so we don't want to dirty the current layer, if any
-            drawRegionRects(*(currentSnapshot().clipRegion),
+            drawRegionRects(*(currentSnapshot()->clipRegion),
                     0xff000000, SkXfermode::kSrc_Mode, false);
 
             mCaches.stencil.enableTest();
@@ -1529,7 +1531,7 @@
             // Draw the region used to generate the stencil if the appropriate debug
             // mode is enabled
             if (mCaches.debugStencilClip == Caches::kStencilShowRegion) {
-                drawRegionRects(*(currentSnapshot().clipRegion),
+                drawRegionRects(*(currentSnapshot()->clipRegion),
                         0x7f0000ff, SkXfermode::kSrcOver_Mode);
             }
         } else {
@@ -1545,7 +1547,7 @@
  *         style, and tessellated AA ramp
  */
 bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, float bottom,
-        SkPaint* paint) {
+        const SkPaint* paint) {
     bool clipRequired = false;
     bool snapOut = paint && paint->isAntiAlias();
 
@@ -1570,64 +1572,12 @@
 
 void OpenGLRenderer::debugClip() {
 #if DEBUG_CLIP_REGIONS
-    if (!isRecording() && !currentSnapshot().clipRegion->isEmpty()) {
-        drawRegionRects(*(currentSnapshot().clipRegion), 0x7f00ff00, SkXfermode::kSrcOver_Mode);
+    if (!isRecording() && !currentSnapshot()->clipRegion->isEmpty()) {
+        drawRegionRects(*(currentSnapshot()->clipRegion), 0x7f00ff00, SkXfermode::kSrcOver_Mode);
     }
 #endif
 }
 
-bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
-    if (CC_LIKELY(currentTransform().rectToRect())) {
-        bool clipped = mSnapshot->clip(left, top, right, bottom, op);
-        if (clipped) {
-            dirtyClip();
-        }
-        return !mSnapshot->clipRect->isEmpty();
-    }
-
-    SkPath path;
-    path.addRect(left, top, right, bottom);
-
-    return OpenGLRenderer::clipPath(&path, op);
-}
-
-bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
-    SkMatrix transform;
-    currentTransform().copyTo(transform);
-
-    SkPath transformed;
-    path->transform(transform, &transformed);
-
-    SkRegion clip;
-    if (!mSnapshot->previous->clipRegion->isEmpty()) {
-        clip.setRegion(*mSnapshot->previous->clipRegion);
-    } else {
-        if (mSnapshot->previous == mFirstSnapshot) {
-            clip.setRect(0, 0, getWidth(), getHeight());
-        } else {
-            Rect* bounds = mSnapshot->previous->clipRect;
-            clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom);
-        }
-    }
-
-    SkRegion region;
-    region.setPath(transformed, clip);
-
-    bool clipped = mSnapshot->clipRegionTransformed(region, op);
-    if (clipped) {
-        dirtyClip();
-    }
-    return !mSnapshot->clipRect->isEmpty();
-}
-
-bool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
-    bool clipped = mSnapshot->clipRegionTransformed(*region, op);
-    if (clipped) {
-        dirtyClip();
-    }
-    return !mSnapshot->clipRect->isEmpty();
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 // Drawing commands
 ///////////////////////////////////////////////////////////////////////////////
@@ -1772,8 +1722,8 @@
 
     bool dirty = right - left > 0.0f && bottom - top > 0.0f;
     if (!ignoreTransform) {
-        mCaches.currentProgram->set(mViewProjMatrix, mModelView, currentTransform(), offset);
-        if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, currentTransform());
+        mCaches.currentProgram->set(mViewProjMatrix, mModelView, *currentTransform(), offset);
+        if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *currentTransform());
     } else {
         mCaches.currentProgram->set(mViewProjMatrix, mModelView, mat4::identity(), offset);
         if (dirty && mTrackDirtyRegions) dirtyLayer(left, top, right, bottom);
@@ -1799,7 +1749,7 @@
             // because it was built into modelView / the geometry, and the SkiaShader needs to
             // compensate.
             mat4 modelViewWithoutTransform;
-            modelViewWithoutTransform.loadInverse(currentTransform());
+            modelViewWithoutTransform.loadInverse(*currentTransform());
             modelViewWithoutTransform.multiply(mModelView);
             mModelView.load(modelViewWithoutTransform);
         }
@@ -1845,7 +1795,8 @@
             GL_FALSE, &transform.data[0]);
 }
 
-void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
+void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
+        const GLvoid* texCoords, GLuint vbo) {
     bool force = false;
     if (!vertices || vbo) {
         force = mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo);
@@ -1861,7 +1812,8 @@
     mCaches.unbindIndicesBuffer();
 }
 
-void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors) {
+void OpenGLRenderer::setupDrawMesh(const GLvoid* vertices,
+        const GLvoid* texCoords, const GLvoid* colors) {
     bool force = mCaches.unbindMeshBuffer();
     GLsizei stride = sizeof(ColorTextureVertex);
 
@@ -1878,7 +1830,8 @@
     mCaches.unbindIndicesBuffer();
 }
 
-void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) {
+void OpenGLRenderer::setupDrawMeshIndices(const GLvoid* vertices,
+        const GLvoid* texCoords, GLuint vbo) {
     bool force = false;
     // If vbo is != 0 we want to treat the vertices parameter as an offset inside
     // a VBO. However, if vertices is set to NULL and vbo == 0 then we want to
@@ -1929,7 +1882,7 @@
         }
 
         bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
-        DeferredDisplayList deferredList(*(mSnapshot->clipRect), avoidOverdraw);
+        DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
         DeferStateStruct deferStruct(deferredList, *this, replayFlags);
         displayList->defer(deferStruct, 0);
 
@@ -1942,7 +1895,7 @@
     return DrawGlInfo::kStatusDone;
 }
 
-void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint) {
+void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, const SkPaint* paint) {
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
@@ -1955,9 +1908,9 @@
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
 
     bool ignoreTransform = false;
-    if (currentTransform().isPureTranslate()) {
-        x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
-        y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
+    if (currentTransform()->isPureTranslate()) {
+        x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f);
+        y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f);
         ignoreTransform = true;
 
         texture->setFilter(GL_NEAREST, true);
@@ -1977,8 +1930,9 @@
  * will not set the scissor enable or dirty the current layer, if any.
  * The caller is responsible for properly dirtying the current layer.
  */
-status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, AssetAtlas::Entry* entry, int bitmapCount,
-        TextureVertex* vertices, bool pureTranslate, const Rect& bounds, SkPaint* paint) {
+status_t OpenGLRenderer::drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
+        int bitmapCount, TextureVertex* vertices, bool pureTranslate,
+        const Rect& bounds, const SkPaint* paint) {
     mCaches.activeTexture(0);
     Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
     if (!texture) return DrawGlInfo::kStatusDone;
@@ -2012,7 +1966,8 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
+status_t OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, float left, float top,
+        const SkPaint* paint) {
     const float right = left + bitmap->width();
     const float bottom = top + bitmap->height();
 
@@ -2034,7 +1989,8 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
+status_t OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkMatrix* matrix,
+        const SkPaint* paint) {
     Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height());
     const mat4 transform(*matrix);
     transform.mapRect(r);
@@ -2062,7 +2018,8 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
+status_t OpenGLRenderer::drawBitmapData(const SkBitmap* bitmap, float left, float top,
+        const SkPaint* paint) {
     const float right = left + bitmap->width();
     const float bottom = top + bitmap->height();
 
@@ -2083,9 +2040,9 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
-        float* vertices, int* colors, SkPaint* paint) {
-    if (!vertices || mSnapshot->isIgnored()) {
+status_t OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+        const float* vertices, const int* colors, const SkPaint* paint) {
+    if (!vertices || currentSnapshot()->isIgnored()) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2099,14 +2056,16 @@
 
     const uint32_t count = meshWidth * meshHeight * 6;
 
-    ColorTextureVertex mesh[count];
-    ColorTextureVertex* vertex = mesh;
+    Vector<ColorTextureVertex> mesh; // TODO: use C++11 unique_ptr
+    mesh.setCapacity(count);
+    ColorTextureVertex* vertex = mesh.editArray();
 
     bool cleanupColors = false;
     if (!colors) {
         uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1);
-        colors = new int[colorsCount];
-        memset(colors, 0xff, colorsCount * sizeof(int));
+        int* newColors = new int[colorsCount];
+        memset(newColors, 0xff, colorsCount * sizeof(int));
+        colors = newColors;
         cleanupColors = true;
     }
 
@@ -2173,7 +2132,7 @@
     float a = alpha / 255.0f;
 
     if (hasLayer()) {
-        dirtyLayer(left, top, right, bottom, currentTransform());
+        dirtyLayer(left, top, right, bottom, *currentTransform());
     }
 
     setupDraw();
@@ -2201,10 +2160,10 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
+status_t OpenGLRenderer::drawBitmap(const SkBitmap* bitmap,
          float srcLeft, float srcTop, float srcRight, float srcBottom,
          float dstLeft, float dstTop, float dstRight, float dstBottom,
-         SkPaint* paint) {
+         const SkPaint* paint) {
     if (quickRejectSetupScissor(dstLeft, dstTop, dstRight, dstBottom)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2243,9 +2202,9 @@
     bool useScaleTransform = mDrawModifiers.mShader && scaled;
     bool ignoreTransform = false;
 
-    if (CC_LIKELY(currentTransform().isPureTranslate() && !useScaleTransform)) {
-        float x = (int) floorf(dstLeft + currentTransform().getTranslateX() + 0.5f);
-        float y = (int) floorf(dstTop + currentTransform().getTranslateY() + 0.5f);
+    if (CC_LIKELY(currentTransform()->isPureTranslate() && !useScaleTransform)) {
+        float x = (int) floorf(dstLeft + currentTransform()->getTranslateX() + 0.5f);
+        float y = (int) floorf(dstTop + currentTransform()->getTranslateY() + 0.5f);
 
         dstRight = x + (dstRight - dstLeft);
         dstBottom = y + (dstBottom - dstTop);
@@ -2293,8 +2252,8 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-        float left, float top, float right, float bottom, SkPaint* paint) {
+status_t OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
+        float left, float top, float right, float bottom, const SkPaint* paint) {
     if (quickRejectSetupScissor(left, top, right, bottom)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2306,8 +2265,9 @@
     return drawPatch(bitmap, mesh, entry, left, top, right, bottom, paint);
 }
 
-status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
-        float left, float top, float right, float bottom, SkPaint* paint) {
+status_t OpenGLRenderer::drawPatch(const SkBitmap* bitmap, const Patch* mesh,
+        AssetAtlas::Entry* entry, float left, float top, float right, float bottom,
+        const SkPaint* paint) {
     if (quickRejectSetupScissor(left, top, right, bottom)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2325,11 +2285,11 @@
         SkXfermode::Mode mode;
         getAlphaAndMode(paint, &alpha, &mode);
 
-        const bool pureTranslate = currentTransform().isPureTranslate();
+        const bool pureTranslate = currentTransform()->isPureTranslate();
         // Mark the current layer dirty where we are going to draw the patch
         if (hasLayer() && mesh->hasEmptyQuads) {
-            const float offsetX = left + currentTransform().getTranslateX();
-            const float offsetY = top + currentTransform().getTranslateY();
+            const float offsetX = left + currentTransform()->getTranslateX();
+            const float offsetY = top + currentTransform()->getTranslateY();
             const size_t count = mesh->quads.size();
             for (size_t i = 0; i < count; i++) {
                 const Rect& bounds = mesh->quads.itemAt(i);
@@ -2339,15 +2299,15 @@
                     dirtyLayer(x, y, x + bounds.getWidth(), y + bounds.getHeight());
                 } else {
                     dirtyLayer(left + bounds.left, top + bounds.top,
-                            left + bounds.right, top + bounds.bottom, currentTransform());
+                            left + bounds.right, top + bounds.bottom, *currentTransform());
                 }
             }
         }
 
         bool ignoreTransform = false;
         if (CC_LIKELY(pureTranslate)) {
-            const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
-            const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
+            const float x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f);
+            const float y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f);
 
             right = x + right - left;
             bottom = y + bottom - top;
@@ -2369,8 +2329,8 @@
  * will not set the scissor enable or dirty the current layer, if any.
  * The caller is responsible for properly dirtying the current layer.
  */
-status_t OpenGLRenderer::drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry,
-        TextureVertex* vertices, uint32_t indexCount, SkPaint* paint) {
+status_t OpenGLRenderer::drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
+        TextureVertex* vertices, uint32_t indexCount, const SkPaint* paint) {
     mCaches.activeTexture(0);
     Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap);
     if (!texture) return DrawGlInfo::kStatusDone;
@@ -2390,7 +2350,7 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint,
+status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, const SkPaint* paint,
         bool useOffset) {
     // not missing call to quickReject/dirtyLayer, always done at a higher level
 
@@ -2450,15 +2410,15 @@
  *
  * Doesn't yet support joins, caps, or path effects.
  */
-status_t OpenGLRenderer::drawConvexPath(const SkPath& path, SkPaint* paint) {
+status_t OpenGLRenderer::drawConvexPath(const SkPath& path, const SkPaint* paint) {
     VertexBuffer vertexBuffer;
     // TODO: try clipping large paths to viewport
-    PathTessellator::tessellatePath(path, paint, mSnapshot->transform, vertexBuffer);
+    PathTessellator::tessellatePath(path, paint, *currentTransform(), vertexBuffer);
 
     if (hasLayer()) {
         SkRect bounds = path.getBounds();
         PathTessellator::expandBoundsForStroke(bounds, paint);
-        dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
+        dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
     }
 
     return drawVertexBuffer(vertexBuffer, paint);
@@ -2475,41 +2435,41 @@
  * TODO: try using a fixed input buffer for non-capped lines as in text rendering. this may reduce
  * memory transfer by removing need for degenerate vertices.
  */
-status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
-    if (mSnapshot->isIgnored() || count < 4) return DrawGlInfo::kStatusDone;
+status_t OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* paint) {
+    if (currentSnapshot()->isIgnored() || count < 4) return DrawGlInfo::kStatusDone;
 
     count &= ~0x3; // round down to nearest four
 
     VertexBuffer buffer;
     SkRect bounds;
-    PathTessellator::tessellateLines(points, count, paint, mSnapshot->transform, bounds, buffer);
+    PathTessellator::tessellateLines(points, count, paint, *currentTransform(), bounds, buffer);
 
     // can't pass paint, since style would be checked for outset. outset done by tessellation.
     if (quickRejectSetupScissor(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) {
         return DrawGlInfo::kStatusDone;
     }
 
-    dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
+    dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
 
     bool useOffset = !paint->isAntiAlias();
     return drawVertexBuffer(buffer, paint, useOffset);
 }
 
-status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
-    if (mSnapshot->isIgnored() || count < 2) return DrawGlInfo::kStatusDone;
+status_t OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) {
+    if (currentSnapshot()->isIgnored() || count < 2) return DrawGlInfo::kStatusDone;
 
     count &= ~0x1; // round down to nearest two
 
     VertexBuffer buffer;
     SkRect bounds;
-    PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer);
+    PathTessellator::tessellatePoints(points, count, paint, *currentTransform(), bounds, buffer);
 
     // can't pass paint, since style would be checked for outset. outset done by tessellation.
     if (quickRejectSetupScissor(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) {
         return DrawGlInfo::kStatusDone;
     }
 
-    dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());
+    dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, *currentTransform());
 
     bool useOffset = !paint->isAntiAlias();
     return drawVertexBuffer(buffer, paint, useOffset);
@@ -2517,9 +2477,9 @@
 
 status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
     // No need to check against the clip, we fill the clip region
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
 
-    Rect& clip(*mSnapshot->clipRect);
+    Rect clip(*currentClipRect());
     clip.snapToPixelBoundaries();
 
     drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
@@ -2528,7 +2488,7 @@
 }
 
 status_t OpenGLRenderer::drawShape(float left, float top, const PathTexture* texture,
-        SkPaint* paint) {
+        const SkPaint* paint) {
     if (!texture) return DrawGlInfo::kStatusDone;
     const AutoTexture autoCleanup(texture);
 
@@ -2541,8 +2501,8 @@
 }
 
 status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom,
-        float rx, float ry, SkPaint* p) {
-    if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+        float rx, float ry, const SkPaint* p) {
+    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
             (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2566,8 +2526,8 @@
     return drawConvexPath(path, p);
 }
 
-status_t OpenGLRenderer::drawCircle(float x, float y, float radius, SkPaint* p) {
-    if (mSnapshot->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
+status_t OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) {
+    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(x - radius, y - radius,
             x + radius, y + radius, p) ||
             (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
         return DrawGlInfo::kStatusDone;
@@ -2588,8 +2548,8 @@
 }
 
 status_t OpenGLRenderer::drawOval(float left, float top, float right, float bottom,
-        SkPaint* p) {
-    if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+        const SkPaint* p) {
+    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
             (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2610,8 +2570,8 @@
 }
 
 status_t OpenGLRenderer::drawArc(float left, float top, float right, float bottom,
-        float startAngle, float sweepAngle, bool useCenter, SkPaint* p) {
-    if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+        float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) {
+    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
             (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2647,8 +2607,9 @@
 // See SkPaintDefaults.h
 #define SkPaintDefaults_MiterLimit SkIntToScalar(4)
 
-status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom, SkPaint* p) {
-    if (mSnapshot->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
+status_t OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
+        const SkPaint* p) {
+    if (currentSnapshot()->isIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) ||
             (p->getAlpha() == 0 && getXfermode(p->getXfermode()) != SkXfermode::kClear_Mode)) {
         return DrawGlInfo::kStatusDone;
     }
@@ -2672,7 +2633,7 @@
         return drawConvexPath(path, p);
     }
 
-    if (p->isAntiAlias() && !currentTransform().isSimple()) {
+    if (p->isAntiAlias() && !currentTransform()->isSimple()) {
         SkPath path;
         path.addRect(left, top, right, bottom);
         return drawConvexPath(path, p);
@@ -2682,9 +2643,9 @@
     }
 }
 
-void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
-        const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
-        float x, float y) {
+void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text,
+        int bytesCount, int count, const float* positions,
+        FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode, float x, float y) {
     mCaches.activeTexture(0);
 
     // NOTE: The drop shadow will not perform gamma correction
@@ -2730,13 +2691,13 @@
 }
 
 status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count,
-        const float* positions, SkPaint* paint) {
-    if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
+        const float* positions, const SkPaint* paint) {
+    if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) {
         return DrawGlInfo::kStatusDone;
     }
 
     // NOTE: Skia does not support perspective transform on drawPosText yet
-    if (!currentTransform().isSimple()) {
+    if (!currentTransform()->isSimple()) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2744,10 +2705,10 @@
 
     float x = 0.0f;
     float y = 0.0f;
-    const bool pureTranslate = currentTransform().isPureTranslate();
+    const bool pureTranslate = currentTransform()->isPureTranslate();
     if (pureTranslate) {
-        x = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
-        y = (int) floorf(y + currentTransform().getTranslateY() + 0.5f);
+        x = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
+        y = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f);
     }
 
     FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(paint);
@@ -2763,7 +2724,7 @@
     }
 
     // Pick the appropriate texture filtering
-    bool linearFilter = currentTransform().changesBounds();
+    bool linearFilter = currentTransform()->changesBounds();
     if (pureTranslate && !linearFilter) {
         linearFilter = fabs(y - (int) y) > 0.0f || fabs(x - (int) x) > 0.0f;
     }
@@ -2779,7 +2740,7 @@
             positions, hasActiveLayer ? &bounds : NULL, &functor)) {
         if (hasActiveLayer) {
             if (!pureTranslate) {
-                currentTransform().mapRect(bounds);
+                currentTransform()->mapRect(bounds);
             }
             dirtyLayerUnchecked(bounds, getRegion());
         }
@@ -2797,7 +2758,7 @@
             fontTransform = mat4::identity();
         } else {
             float sx, sy;
-            currentTransform().decomposeScale(sx, sy);
+            currentTransform()->decomposeScale(sx, sy);
             fontTransform.loadScale(sx, sy, 1.0f);
         }
     }
@@ -2805,13 +2766,13 @@
 }
 
 status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y,
-        const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds,
+        const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
         DrawOpMode drawOpMode) {
 
     if (drawOpMode == kDrawOpMode_Immediate) {
         // The checks for corner-case ignorable text and quick rejection is only done for immediate
         // drawing as ops from DeferredDisplayList are already filtered for these
-        if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint) ||
+        if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint) ||
                 quickRejectSetupScissor(bounds)) {
             return DrawGlInfo::kStatusDone;
         }
@@ -2820,7 +2781,7 @@
     const float oldX = x;
     const float oldY = y;
 
-    const mat4& transform = currentTransform();
+    const mat4& transform = *currentTransform();
     const bool pureTranslate = transform.isPureTranslate();
 
     if (CC_LIKELY(pureTranslate)) {
@@ -2861,7 +2822,7 @@
     fontRenderer.setTextureFiltering(linearFilter);
 
     // TODO: Implement better clipping for scaled/rotated text
-    const Rect* clip = !pureTranslate ? NULL : mSnapshot->clipRect;
+    const Rect* clip = !pureTranslate ? NULL : currentClipRect();
     Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f);
 
     bool status;
@@ -2891,9 +2852,9 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
-        float hOffset, float vOffset, SkPaint* paint) {
-    if (text == NULL || count == 0 || mSnapshot->isIgnored() || canSkipText(paint)) {
+status_t OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
+        const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) {
+    if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2917,7 +2878,7 @@
     if (fontRenderer.renderTextOnPath(paint, clip, text, 0, bytesCount, count, path,
             hOffset, vOffset, hasActiveLayer ? &bounds : NULL, &functor)) {
         if (hasActiveLayer) {
-            currentTransform().mapRect(bounds);
+            currentTransform()->mapRect(bounds);
             dirtyLayerUnchecked(bounds, getRegion());
         }
     }
@@ -2925,8 +2886,8 @@
     return DrawGlInfo::kStatusDrew;
 }
 
-status_t OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+status_t OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) {
+    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
 
     mCaches.activeTexture(0);
 
@@ -2990,9 +2951,9 @@
             setupDrawPureColorUniforms();
             setupDrawColorFilterUniforms();
             setupDrawTexture(layer->getTexture());
-            if (CC_LIKELY(currentTransform().isPureTranslate())) {
-                int tx = (int) floorf(x + currentTransform().getTranslateX() + 0.5f);
-                int ty = (int) floorf(y + currentTransform().getTranslateY() + 0.5f);
+            if (CC_LIKELY(currentTransform()->isPureTranslate())) {
+                int tx = (int) floorf(x + currentTransform()->getTranslateX() + 0.5f);
+                int ty = (int) floorf(y + currentTransform()->getTranslateY() + 0.5f);
 
                 layer->setFilter(GL_NEAREST);
                 setupDrawModelView(kModelViewMode_Translate, false, tx, ty,
@@ -3102,7 +3063,7 @@
     mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
 }
 
-SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint) {
+const SkPaint* OpenGLRenderer::filterPaint(const SkPaint* paint) {
     if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) {
         return paint;
     }
@@ -3120,7 +3081,7 @@
 // Drawing implementation
 ///////////////////////////////////////////////////////////////////////////////
 
-Texture* OpenGLRenderer::getTexture(SkBitmap* bitmap) {
+Texture* OpenGLRenderer::getTexture(const SkBitmap* bitmap) {
     Texture* texture = mCaches.assetAtlas.getEntryTexture(bitmap);
     if (!texture) {
         return mCaches.textureCache.get(bitmap);
@@ -3129,7 +3090,7 @@
 }
 
 void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
-        float x, float y, SkPaint* paint) {
+        float x, float y, const SkPaint* paint) {
     if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) {
         return;
     }
@@ -3161,7 +3122,8 @@
 #define kStdUnderline_Offset    (1.0f / 9.0f)
 #define kStdUnderline_Thickness (1.0f / 18.0f)
 
-void OpenGLRenderer::drawTextDecorations(float underlineWidth, float x, float y, SkPaint* paint) {
+void OpenGLRenderer::drawTextDecorations(float underlineWidth, float x, float y,
+        const SkPaint* paint) {
     // Handle underline and strike-through
     uint32_t flags = paint->getFlags();
     if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
@@ -3205,8 +3167,8 @@
     }
 }
 
-status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
-    if (mSnapshot->isIgnored()) {
+status_t OpenGLRenderer::drawRects(const float* rects, int count, const SkPaint* paint) {
+    if (currentSnapshot()->isIgnored()) {
         return DrawGlInfo::kStatusDone;
     }
 
@@ -3222,7 +3184,7 @@
 
 status_t OpenGLRenderer::drawShadow(const mat4& casterTransform, float casterAlpha,
         float width, float height) {
-    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
+    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
 
     // For now, always and scissor
     // TODO: use quickReject
@@ -3275,7 +3237,7 @@
 
     setupDraw();
     setupDrawNoTexture();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
     setupDrawShader();
     setupDrawColorFilter();
     setupDrawBlending(mode);
@@ -3288,7 +3250,7 @@
     setupDrawColorFilterUniforms();
 
     if (dirty && hasLayer()) {
-        dirtyLayer(left, top, right, bottom, currentTransform());
+        dirtyLayer(left, top, right, bottom, *currentTransform());
     }
 
     issueIndexedQuadDraw(&mesh[0], count / 4);
@@ -3305,7 +3267,7 @@
 
     setupDraw();
     setupDrawNoTexture();
-    setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
+    setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
     setupDrawShader();
     setupDrawColorFilter();
     setupDrawBlending(mode);
@@ -3321,7 +3283,7 @@
 }
 
 void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
-        Texture* texture, SkPaint* paint) {
+        Texture* texture, const SkPaint* paint) {
     int alpha;
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
@@ -3341,9 +3303,9 @@
         resetDrawTextureTexCoords(uvs.left, uvs.top, uvs.right, uvs.bottom);
     }
 
-    if (CC_LIKELY(currentTransform().isPureTranslate())) {
-        const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f);
-        const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f);
+    if (CC_LIKELY(currentTransform()->isPureTranslate())) {
+        const float x = (int) floorf(left + currentTransform()->getTranslateX() + 0.5f);
+        const float y = (int) floorf(top + currentTransform()->getTranslateY() + 0.5f);
 
         texture->setFilter(GL_NEAREST, true);
         drawTextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
@@ -3510,13 +3472,13 @@
     TextureVertex::setUV(v++, u2, v2);
 }
 
-void OpenGLRenderer::getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const {
+void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const {
     getAlphaAndModeDirect(paint, alpha,  mode);
     if (mDrawModifiers.mOverrideLayerAlpha < 1.0f) {
         // if drawing a layer, ignore the paint's alpha
         *alpha = mDrawModifiers.mOverrideLayerAlpha * 255;
     }
-    *alpha *= mSnapshot->alpha;
+    *alpha *= currentSnapshot()->alpha;
 }
 
 float OpenGLRenderer::getLayerAlpha(Layer* layer) const {
@@ -3526,7 +3488,7 @@
     } else {
         alpha = layer->getAlpha() / 255.0f;
     }
-    return alpha * mSnapshot->alpha;
+    return alpha * currentSnapshot()->alpha;
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 1325bf7..fb780ce 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -170,47 +170,48 @@
     int saveLayerDeferred(float left, float top, float right, float bottom,
             int alpha, SkXfermode::Mode mode, int flags);
 
-    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
-    virtual bool clipPath(SkPath* path, SkRegion::Op op);
-    virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
-
     virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t replayFlags);
     virtual status_t drawLayer(Layer* layer, float x, float y);
-    virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
-    status_t drawBitmaps(SkBitmap* bitmap, AssetAtlas::Entry* entry, int bitmapCount,
-            TextureVertex* vertices, bool pureTranslate, const Rect& bounds, SkPaint* paint);
-    virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
-    virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
+    virtual status_t drawBitmap(const SkBitmap* bitmap, float left, float top,
+            const SkPaint* paint);
+    status_t drawBitmaps(const SkBitmap* bitmap, AssetAtlas::Entry* entry, int bitmapCount,
+            TextureVertex* vertices, bool pureTranslate, const Rect& bounds, const SkPaint* paint);
+    virtual status_t drawBitmap(const SkBitmap* bitmap, const SkMatrix* matrix,
+            const SkPaint* paint);
+    virtual status_t drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, SkPaint* paint);
-    virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint);
-    virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
-            float* vertices, int* colors, SkPaint* paint);
-    status_t drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry,
-            TextureVertex* vertices, uint32_t indexCount, SkPaint* paint);
-    virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-            float left, float top, float right, float bottom, SkPaint* paint);
-    status_t drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
-            float left, float top, float right, float bottom, SkPaint* paint);
+            float dstRight, float dstBottom, const SkPaint* paint);
+    virtual status_t drawBitmapData(const SkBitmap* bitmap, float left, float top,
+            const SkPaint* paint);
+    virtual status_t drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint);
+    status_t drawPatches(const SkBitmap* bitmap, AssetAtlas::Entry* entry,
+            TextureVertex* vertices, uint32_t indexCount, const SkPaint* paint);
+    virtual status_t drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
+            float left, float top, float right, float bottom, const SkPaint* paint);
+    status_t drawPatch(const SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry,
+            float left, float top, float right, float bottom, const SkPaint* paint);
     virtual status_t drawColor(int color, SkXfermode::Mode mode);
-    virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint);
+    virtual status_t drawRect(float left, float top, float right, float bottom,
+            const SkPaint* paint);
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, SkPaint* paint);
-    virtual status_t drawCircle(float x, float y, float radius, SkPaint* paint);
-    virtual status_t drawOval(float left, float top, float right, float bottom, SkPaint* paint);
+            float rx, float ry, const SkPaint* paint);
+    virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint);
+    virtual status_t drawOval(float left, float top, float right, float bottom,
+            const SkPaint* paint);
     virtual status_t drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
-    virtual status_t drawPath(SkPath* path, SkPaint* paint);
-    virtual status_t drawLines(float* points, int count, SkPaint* paint);
-    virtual status_t drawPoints(float* points, int count, SkPaint* paint);
-    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
-            float hOffset, float vOffset, SkPaint* paint);
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint);
+    virtual status_t drawPath(const SkPath* path, const SkPaint* paint);
+    virtual status_t drawLines(const float* points, int count, const SkPaint* paint);
+    virtual status_t drawPoints(const float* points, int count, const SkPaint* paint);
+    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path,
+            float hOffset, float vOffset, const SkPaint* paint);
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
-            const float* positions, SkPaint* paint);
+            const float* positions, const SkPaint* paint);
     virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds,
+            const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
             DrawOpMode drawOpMode = kDrawOpMode_Immediate);
-    virtual status_t drawRects(const float* rects, int count, SkPaint* paint);
+    virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
 
     status_t drawShadow(const mat4& casterTransform, float casterAlpha,
             float width, float height);
@@ -230,7 +231,7 @@
     // If this value is set to < 1.0, it overrides alpha set on layer (see drawBitmap, drawLayer)
     void setOverrideLayerAlpha(float alpha) { mDrawModifiers.mOverrideLayerAlpha = alpha; }
 
-    SkPaint* filterPaint(SkPaint* paint);
+    const SkPaint* filterPaint(const SkPaint* paint);
 
     /**
      * Store the current display state (most importantly, the current clip and transform), and
@@ -246,7 +247,7 @@
     void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
 
     ANDROID_API bool isCurrentTransformSimple() {
-        return currentTransform().isSimple();
+        return currentTransform()->isSimple();
     }
 
     Caches& getCaches() {
@@ -258,8 +259,8 @@
         return mSnapshot->clipRegion->isEmpty();
     }
 
-    int getViewportWidth() { return getSnapshot()->viewport.getWidth(); }
-    int getViewportHeight() { return getSnapshot()->viewport.getHeight(); }
+    int getViewportWidth() { return currentSnapshot()->viewport.getWidth(); }
+    int getViewportHeight() { return currentSnapshot()->viewport.getHeight(); }
 
     /**
      * Scales the alpha on the current snapshot. This alpha value will be modulated
@@ -296,12 +297,12 @@
      * @param alpha Where to store the resulting alpha
      * @param mode Where to store the resulting xfermode
      */
-    static inline void getAlphaAndModeDirect(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
+    static inline void getAlphaAndModeDirect(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
         *mode = getXfermodeDirect(paint);
         *alpha = getAlphaDirect(paint);
     }
 
-    static inline SkXfermode::Mode getXfermodeDirect(SkPaint* paint) {
+    static inline SkXfermode::Mode getXfermodeDirect(const SkPaint* paint) {
         if (!paint) return SkXfermode::kSrcOver_Mode;
         return getXfermode(paint->getXfermode());
     }
@@ -374,8 +375,8 @@
     void attachStencilBufferToLayer(Layer* layer);
 
     bool quickRejectSetupScissor(float left, float top, float right, float bottom,
-            SkPaint* paint = NULL);
-    bool quickRejectSetupScissor(const Rect& bounds, SkPaint* paint = NULL) {
+            const SkPaint* paint = NULL);
+    bool quickRejectSetupScissor(const Rect& bounds, const SkPaint* paint = NULL) {
         return quickRejectSetupScissor(bounds.left, bounds.top,
                 bounds.right, bounds.bottom, paint);
     }
@@ -396,10 +397,6 @@
      */
     void dirtyLayerUnchecked(Rect& bounds, Region* region);
 
-    sp<Snapshot> getSnapshot() const {
-        return mSnapshot;
-    }
-
     /**
      * Returns the region of the current layer.
      */
@@ -438,7 +435,7 @@
      * @param alpha Where to store the resulting alpha
      * @param mode Where to store the resulting xfermode
      */
-    inline void getAlphaAndMode(SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const;
+    inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) const;
 
     /**
      * Gets the alpha from a layer, accounting for snapshot alpha and overrideLayerAlpha
@@ -482,12 +479,11 @@
 
     /**
      * Tells the GPU what part of the screen is about to be redrawn.
-     * This method will use the clip rect that we started drawing the
-     * frame with.
+     * This method will use the current layer space clip rect.
      * This method needs to be invoked every time getTargetFbo() is
      * bound again.
      */
-    void startTiling(const Snapshot& snapshot, bool opaque = false);
+    void startTilingCurrentClip(bool opaque = false);
 
     /**
      * Tells the GPU what part of the screen is about to be redrawn.
@@ -633,7 +629,7 @@
      * @param texture The texture reprsenting the shape
      * @param paint The paint to draw the shape with
      */
-    status_t drawShape(float left, float top, const PathTexture* texture, SkPaint* paint);
+    status_t drawShape(float left, float top, const PathTexture* texture, const SkPaint* paint);
 
     /**
      * Draws the specified texture as an alpha bitmap. Alpha bitmaps obey
@@ -644,7 +640,7 @@
      * @param top The y coordinate of the bitmap
      * @param paint The paint to render with
      */
-    void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint);
+    void drawAlphaBitmap(Texture* texture, float left, float top, const SkPaint* paint);
 
     /**
      * Renders a strip of polygons with the specified paint, used for tessellated geometry.
@@ -653,7 +649,7 @@
      * @param paint The paint to render with
      * @param useOffset Offset the vertexBuffer (used in drawing non-AA lines)
      */
-    status_t drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint,
+    status_t drawVertexBuffer(const VertexBuffer& vertexBuffer, const SkPaint* paint,
             bool useOffset = false);
 
     /**
@@ -662,7 +658,7 @@
      * @param path The hull of the path to draw
      * @param paint The paint to render with
      */
-    status_t drawConvexPath(const SkPath& path, SkPaint* paint);
+    status_t drawConvexPath(const SkPath& path, const SkPaint* paint);
 
     /**
      * Draws a textured rectangle with the specified texture. The specified coordinates
@@ -692,7 +688,7 @@
      * @param paint The paint containing the alpha, blending mode, etc.
      */
     void drawTextureRect(float left, float top, float right, float bottom,
-            Texture* texture, SkPaint* paint);
+            Texture* texture, const SkPaint* paint);
 
     /**
      * Draws a textured mesh with the specified texture. If the indices are omitted,
@@ -751,7 +747,7 @@
      * @param y The y coordinate where the text will be drawn
      * @param paint The paint to draw the text with
      */
-    void drawTextDecorations(float totalAdvance, float x, float y, SkPaint* paint);
+    void drawTextDecorations(float totalAdvance, float x, float y, const SkPaint* paint);
 
    /**
      * Draws shadow layer on text (with optional positions).
@@ -767,7 +763,7 @@
      * @param x The x coordinate where the shadow will be drawn
      * @param y The y coordinate where the shadow will be drawn
      */
-    void drawTextShadow(SkPaint* paint, const char* text, int bytesCount, int count,
+    void drawTextShadow(const SkPaint* paint, const char* text, int bytesCount, int count,
             const float* positions, FontRenderer& fontRenderer, int alpha, SkXfermode::Mode mode,
             float x, float y);
 
@@ -780,7 +776,7 @@
      * @param y The y coordinate where the texture will be drawn
      * @param paint The paint to draw the texture with
      */
-     void drawPathTexture(const PathTexture* texture, float x, float y, SkPaint* paint);
+     void drawPathTexture(const PathTexture* texture, float x, float y, const SkPaint* paint);
 
     /**
      * Resets the texture coordinates stored in mMeshVertices. Setting the values
@@ -870,7 +866,7 @@
      * transformations are stored in the modelView matrix and uploaded to the shader.
      *
      * @param offset Set to true if the the matrix should be fudged (translated) slightly to disambiguate
-     * geometry pixel positioning. See Vertex::gGeometryFudgeFactor.
+     * geometry pixel positioning. See Vertex::GeometryFudgeFactor().
      *
      * @param ignoreTransform Set to true if l,t,r,b coordinates already in layer space,
      * currentTransform() will be ignored. (e.g. when drawing clip in layer coordinates to stencil,
@@ -888,9 +884,9 @@
     void setupDrawTextureTransform();
     void setupDrawTextureTransformUniforms(mat4& transform);
     void setupDrawTextGammaUniforms();
-    void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
-    void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
-    void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
+    void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords = NULL, GLuint vbo = 0);
+    void setupDrawMesh(const GLvoid* vertices, const GLvoid* texCoords, const GLvoid* colors);
+    void setupDrawMeshIndices(const GLvoid* vertices, const GLvoid* texCoords, GLuint vbo = 0);
     void setupDrawIndexedVertices(GLvoid* vertices);
     void accountForClear(SkXfermode::Mode mode);
 
@@ -939,7 +935,7 @@
      * come from the texture cache or an atlas. If this method returns
      * NULL, the texture could not be found and/or allocated.
      */
-    Texture* getTexture(SkBitmap* bitmap);
+    Texture* getTexture(const SkBitmap* bitmap);
 
     // Matrix used for view/projection in shaders
     mat4 mViewProjMatrix;
@@ -988,9 +984,6 @@
     // List of layers to update at the beginning of a frame
     Vector<Layer*> mLayerUpdates;
 
-    // Indicates whether the clip must be restored
-    bool mDirtyClip;
-
     // The following fields are used to setup drawing
     // Used to describe the shaders to generate
     ProgramDescription mDescription;
diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h
index 763a785..489064b 100644
--- a/libs/hwui/Patch.h
+++ b/libs/hwui/Patch.h
@@ -36,7 +36,8 @@
 // 9-patch structures
 ///////////////////////////////////////////////////////////////////////////////
 
-struct Patch {
+class Patch {
+public:
     Patch();
     ~Patch();
 
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 5df6408..9459885 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -51,7 +51,7 @@
     memset(&shape, 0, sizeof(Shape));
 }
 
-PathDescription::PathDescription(ShapeType type, SkPaint* paint):
+PathDescription::PathDescription(ShapeType type, const SkPaint* paint):
         type(type),
         join(paint->getStrokeJoin()),
         cap(paint->getStrokeCap()),
@@ -82,7 +82,7 @@
 // Utilities
 ///////////////////////////////////////////////////////////////////////////////
 
-bool PathCache::canDrawAsConvexPath(SkPath* path, SkPaint* paint) {
+bool PathCache::canDrawAsConvexPath(SkPath* path, const SkPaint* paint) {
     // NOTE: This should only be used after PathTessellator handles joins properly
     return paint->getPathEffect() == NULL && path->getConvexity() == SkPath::kConvex_Convexity;
 }
@@ -413,7 +413,7 @@
  * in the cache. The source path is also used to reclaim garbage when a
  * Dalvik Path object is collected.
  */
-static SkPath* getSourcePath(SkPath* path) {
+static const SkPath* getSourcePath(const SkPath* path) {
     const SkPath* sourcePath = path->getSourcePath();
     if (sourcePath && sourcePath->getGenerationID() == path->getGenerationID()) {
         return const_cast<SkPath*>(sourcePath);
@@ -421,7 +421,7 @@
     return path;
 }
 
-PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
+PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) {
     path = getSourcePath(path);
 
     PathDescription entry(kShapePath, paint);
@@ -459,7 +459,7 @@
     return texture;
 }
 
-void PathCache::precache(SkPath* path, SkPaint* paint) {
+void PathCache::precache(const SkPath* path, const SkPaint* paint) {
     if (!Caches::getInstance().tasks.canRunTasks()) {
         return;
     }
@@ -507,7 +507,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 PathTexture* PathCache::getRoundRect(float width, float height,
-        float rx, float ry, SkPaint* paint) {
+        float rx, float ry, const SkPaint* paint) {
     PathDescription entry(kShapeRoundRect, paint);
     entry.shape.roundRect.mWidth = width;
     entry.shape.roundRect.mHeight = height;
@@ -532,7 +532,7 @@
 // Circles
 ///////////////////////////////////////////////////////////////////////////////
 
-PathTexture* PathCache::getCircle(float radius, SkPaint* paint) {
+PathTexture* PathCache::getCircle(float radius, const SkPaint* paint) {
     PathDescription entry(kShapeCircle, paint);
     entry.shape.circle.mRadius = radius;
 
@@ -552,7 +552,7 @@
 // Ovals
 ///////////////////////////////////////////////////////////////////////////////
 
-PathTexture* PathCache::getOval(float width, float height, SkPaint* paint) {
+PathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) {
     PathDescription entry(kShapeOval, paint);
     entry.shape.oval.mWidth = width;
     entry.shape.oval.mHeight = height;
@@ -575,7 +575,7 @@
 // Rects
 ///////////////////////////////////////////////////////////////////////////////
 
-PathTexture* PathCache::getRect(float width, float height, SkPaint* paint) {
+PathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) {
     PathDescription entry(kShapeRect, paint);
     entry.shape.rect.mWidth = width;
     entry.shape.rect.mHeight = height;
@@ -599,7 +599,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 PathTexture* PathCache::getArc(float width, float height,
-        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
+        float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
     PathDescription entry(kShapeArc, paint);
     entry.shape.arc.mWidth = width;
     entry.shape.arc.mHeight = height;
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 16d20a8..847853a 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -32,7 +32,7 @@
 class SkCanvas;
 class SkPaint;
 class SkPath;
-class SkRect;
+struct SkRect;
 
 namespace android {
 namespace uirenderer {
@@ -116,7 +116,7 @@
     SkPathEffect* pathEffect;
     union Shape {
         struct Path {
-            SkPath* mPath;
+            const SkPath* mPath;
         } path;
         struct RoundRect {
             float mWidth;
@@ -145,7 +145,7 @@
     } shape;
 
     PathDescription();
-    PathDescription(ShapeType shapeType, SkPaint* paint);
+    PathDescription(ShapeType shapeType, const SkPaint* paint);
 
     hash_t hash() const;
 
@@ -207,13 +207,13 @@
      */
     uint32_t getSize();
 
-    PathTexture* getRoundRect(float width, float height, float rx, float ry, SkPaint* paint);
-    PathTexture* getCircle(float radius, SkPaint* paint);
-    PathTexture* getOval(float width, float height, SkPaint* paint);
-    PathTexture* getRect(float width, float height, SkPaint* paint);
+    PathTexture* getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint);
+    PathTexture* getCircle(float radius, const SkPaint* paint);
+    PathTexture* getOval(float width, float height, const SkPaint* paint);
+    PathTexture* getRect(float width, float height, const SkPaint* paint);
     PathTexture* getArc(float width, float height, float startAngle, float sweepAngle,
-            bool useCenter, SkPaint* paint);
-    PathTexture* get(SkPath* path, SkPaint* paint);
+            bool useCenter, const SkPaint* paint);
+    PathTexture* get(const SkPath* path, const SkPaint* paint);
 
     /**
      * Removes the specified path. This is meant to be called from threads
@@ -239,9 +239,9 @@
     /**
      * Precaches the specified path using background threads.
      */
-    void precache(SkPath* path, SkPaint* paint);
+    void precache(const SkPath* path, const SkPaint* paint);
 
-    static bool canDrawAsConvexPath(SkPath* path, SkPaint* paint);
+    static bool canDrawAsConvexPath(SkPath* path, const SkPaint* paint);
     static void computePathBounds(const SkPath* path, const SkPaint* paint,
             float& left, float& top, float& offset, uint32_t& width, uint32_t& height);
     static void computeBounds(const SkRect& bounds, const SkPaint* paint,
@@ -292,7 +292,7 @@
 
     class PathTask: public Task<SkBitmap*> {
     public:
-        PathTask(SkPath* path, SkPaint* paint, PathTexture* texture):
+        PathTask(const SkPath* path, const SkPaint* paint, PathTexture* texture):
             path(path), paint(paint), texture(texture) {
         }
 
@@ -300,8 +300,8 @@
             delete future()->get();
         }
 
-        SkPath* path;
-        SkPaint* paint;
+        const SkPath* path;
+        const SkPaint* paint;
         PathTexture* texture;
     };
 
diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp
index 7a86dfc..c6ce67c 100644
--- a/libs/hwui/PathTessellator.cpp
+++ b/libs/hwui/PathTessellator.cpp
@@ -88,16 +88,16 @@
  */
 struct PaintInfo {
 public:
-    PaintInfo(const SkPaint* paint, const mat4 *transform) :
+    PaintInfo(const SkPaint* paint, const mat4& transform) :
             style(paint->getStyle()), cap(paint->getStrokeCap()), isAA(paint->isAntiAlias()),
             inverseScaleX(1.0f), inverseScaleY(1.0f),
             halfStrokeWidth(paint->getStrokeWidth() * 0.5f), maxAlpha(1.0f) {
         // compute inverse scales
-        if (CC_UNLIKELY(!transform->isPureTranslate())) {
-            float m00 = transform->data[Matrix4::kScaleX];
-            float m01 = transform->data[Matrix4::kSkewY];
-            float m10 = transform->data[Matrix4::kSkewX];
-            float m11 = transform->data[Matrix4::kScaleY];
+        if (CC_UNLIKELY(!transform.isPureTranslate())) {
+            float m00 = transform.data[Matrix4::kScaleX];
+            float m01 = transform.data[Matrix4::kSkewY];
+            float m10 = transform.data[Matrix4::kSkewX];
+            float m11 = transform.data[Matrix4::kScaleY];
             float scaleX = sqrt(m00 * m00 + m01 * m01);
             float scaleY = sqrt(m10 * m10 + m11 * m11);
             inverseScaleX = (scaleX != 0) ? (1.0f / scaleX) : 1.0f;
@@ -162,8 +162,8 @@
     void expandBoundsForStrokeAA(SkRect& bounds) const {
         float outset = halfStrokeWidth;
         if (outset == 0) outset = 0.5f;
-        bounds.outset(outset * inverseScaleX + Vertex::gGeometryFudgeFactor,
-                outset * inverseScaleY + Vertex::gGeometryFudgeFactor);
+        bounds.outset(outset * inverseScaleX + Vertex::GeometryFudgeFactor(),
+                outset * inverseScaleY + Vertex::GeometryFudgeFactor());
     }
 };
 
@@ -718,7 +718,7 @@
 }
 
 void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
-        const mat4 *transform, VertexBuffer& vertexBuffer) {
+        const mat4& transform, VertexBuffer& vertexBuffer) {
     ATRACE_CALL();
 
     const PaintInfo paintInfo(paint, transform);
@@ -805,8 +805,8 @@
     dstBuffer.createDegenerateSeparators<TYPE>(verticesPerPoint);
 }
 
-void PathTessellator::tessellatePoints(const float* points, int count, SkPaint* paint,
-        const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
+void PathTessellator::tessellatePoints(const float* points, int count, const SkPaint* paint,
+        const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
     const PaintInfo paintInfo(paint, transform);
 
     // determine point shape
@@ -845,8 +845,8 @@
 
 }
 
-void PathTessellator::tessellateLines(const float* points, int count, SkPaint* paint,
-        const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
+void PathTessellator::tessellateLines(const float* points, int count, const SkPaint* paint,
+        const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
     ATRACE_CALL();
     const PaintInfo paintInfo(paint, transform);
 
diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h
index 236658d..e43b101 100644
--- a/libs/hwui/PathTessellator.h
+++ b/libs/hwui/PathTessellator.h
@@ -32,13 +32,13 @@
     static void expandBoundsForStroke(SkRect& bounds, const SkPaint* paint);
 
     static void tessellatePath(const SkPath& path, const SkPaint* paint,
-            const mat4 *transform, VertexBuffer& vertexBuffer);
+            const mat4& transform, VertexBuffer& vertexBuffer);
 
-    static void tessellatePoints(const float* points, int count, SkPaint* paint,
-            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
+    static void tessellatePoints(const float* points, int count, const SkPaint* paint,
+            const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);
 
-    static void tessellateLines(const float* points, int count, SkPaint* paint,
-            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
+    static void tessellateLines(const float* points, int count, const SkPaint* paint,
+            const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);
 
 private:
     static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index 7814a01..a679552 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -173,7 +173,7 @@
             // up and to the left.
             // This offset value is based on an assumption that some hardware may use as
             // little as 12.4 precision, so we offset by slightly more than 1/16.
-            p.translate(Vertex::gGeometryFudgeFactor, Vertex::gGeometryFudgeFactor);
+            p.translate(Vertex::GeometryFudgeFactor(), Vertex::GeometryFudgeFactor());
             glUniformMatrix4fv(projection, 1, GL_FALSE, &p.data[0]);
         }
         mProjection = projectionMatrix;
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 83b3436..c230149 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -190,19 +190,19 @@
              * from this inset will only incur similarly small errors in output, due to transparency
              * in extreme outside of the geometry.
              */
-            left = floorf(left + Vertex::gGeometryFudgeFactor);
-            top = floorf(top + Vertex::gGeometryFudgeFactor);
-            right = ceilf(right - Vertex::gGeometryFudgeFactor);
-            bottom = ceilf(bottom - Vertex::gGeometryFudgeFactor);
+            left = floorf(left + Vertex::GeometryFudgeFactor());
+            top = floorf(top + Vertex::GeometryFudgeFactor());
+            right = ceilf(right - Vertex::GeometryFudgeFactor());
+            bottom = ceilf(bottom - Vertex::GeometryFudgeFactor());
         } else {
             /* For other geometry, we do the regular rounding in order to snap, but also outset the
              * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
              * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
              */
-            left = floorf(left + 0.5f - Vertex::gGeometryFudgeFactor);
-            top = floorf(top + 0.5f - Vertex::gGeometryFudgeFactor);
-            right = floorf(right + 0.5f + Vertex::gGeometryFudgeFactor);
-            bottom = floorf(bottom + 0.5f + Vertex::gGeometryFudgeFactor);
+            left = floorf(left + 0.5f - Vertex::GeometryFudgeFactor());
+            top = floorf(top + 0.5f - Vertex::GeometryFudgeFactor());
+            right = floorf(right + 0.5f + Vertex::GeometryFudgeFactor());
+            bottom = floorf(bottom + 0.5f + Vertex::GeometryFudgeFactor());
         }
     }
 
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index faf663a..38e1c91 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -27,7 +27,7 @@
 namespace android {
 
 class Functor;
-class Res_png_9patch;
+struct Res_png_9patch;
 
 namespace uirenderer {
 
@@ -190,16 +190,16 @@
     virtual void scale(float sx, float sy) = 0;
     virtual void skew(float sx, float sy) = 0;
 
-    virtual void setMatrix(SkMatrix* matrix) = 0;
-    virtual void concatMatrix(SkMatrix* matrix) = 0;
+    virtual void setMatrix(const SkMatrix* matrix) = 0;
+    virtual void concatMatrix(const SkMatrix* matrix) = 0;
 
     // clip
     virtual const Rect& getClipBounds() const = 0;
     virtual bool quickRejectConservative(float left, float top,
             float right, float bottom) const = 0;
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0;
-    virtual bool clipPath(SkPath* path, SkRegion::Op op) = 0;
-    virtual bool clipRegion(SkRegion* region, SkRegion::Op op) = 0;
+    virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
+    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
 
     // Misc - should be implemented with SkPaint inspection
     virtual void resetShader() = 0;
@@ -220,38 +220,43 @@
     virtual status_t drawColor(int color, SkXfermode::Mode mode) = 0;
 
     // Bitmap-based
-    virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) = 0;
-    virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) = 0;
-    virtual status_t drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
+    virtual status_t drawBitmap(const SkBitmap* bitmap, float left, float top,
+            const SkPaint* paint) = 0;
+    virtual status_t drawBitmap(const SkBitmap* bitmap, const SkMatrix* matrix,
+            const SkPaint* paint) = 0;
+    virtual status_t drawBitmap(const SkBitmap* bitmap, float srcLeft, float srcTop,
             float srcRight, float srcBottom, float dstLeft, float dstTop,
-            float dstRight, float dstBottom, SkPaint* paint) = 0;
-    virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint) = 0;
-    virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
-            float* vertices, int* colors, SkPaint* paint) = 0;
-    virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
-            float left, float top, float right, float bottom, SkPaint* paint) = 0;
+            float dstRight, float dstBottom, const SkPaint* paint) = 0;
+    virtual status_t drawBitmapData(const SkBitmap* bitmap, float left, float top,
+            const SkPaint* paint) = 0;
+    virtual status_t drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
+            const float* vertices, const int* colors, const SkPaint* paint) = 0;
+    virtual status_t drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
+            float left, float top, float right, float bottom, const SkPaint* paint) = 0;
 
     // Shapes
-    virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint) = 0;
-    virtual status_t drawRects(const float* rects, int count, SkPaint* paint) = 0;
+    virtual status_t drawRect(float left, float top, float right, float bottom,
+            const SkPaint* paint) = 0;
+    virtual status_t drawRects(const float* rects, int count, const SkPaint* paint) = 0;
     virtual status_t drawRoundRect(float left, float top, float right, float bottom,
-            float rx, float ry, SkPaint* paint) = 0;
-    virtual status_t drawCircle(float x, float y, float radius, SkPaint* paint) = 0;
-    virtual status_t drawOval(float left, float top, float right, float bottom, SkPaint* paint) = 0;
+            float rx, float ry, const SkPaint* paint) = 0;
+    virtual status_t drawCircle(float x, float y, float radius, const SkPaint* paint) = 0;
+    virtual status_t drawOval(float left, float top, float right, float bottom,
+            const SkPaint* paint) = 0;
     virtual status_t drawArc(float left, float top, float right, float bottom,
-            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) = 0;
-    virtual status_t drawPath(SkPath* path, SkPaint* paint) = 0;
-    virtual status_t drawLines(float* points, int count, SkPaint* paint) = 0;
-    virtual status_t drawPoints(float* points, int count, SkPaint* paint) = 0;
+            float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) = 0;
+    virtual status_t drawPath(const SkPath* path, const SkPaint* paint) = 0;
+    virtual status_t drawLines(const float* points, int count, const SkPaint* paint) = 0;
+    virtual status_t drawPoints(const float* points, int count, const SkPaint* paint) = 0;
 
     // Text
     virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y,
-            const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds,
+            const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds,
             DrawOpMode drawOpMode = kDrawOpMode_Immediate) = 0;
-    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, SkPath* path,
-            float hOffset, float vOffset, SkPaint* paint) = 0;
+    virtual status_t drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path,
+            float hOffset, float vOffset, const SkPaint* paint) = 0;
     virtual status_t drawPosText(const char* text, int bytesCount, int count,
-            const float* positions, SkPaint* paint) = 0;
+            const float* positions, const SkPaint* paint) = 0;
 
 // ----------------------------------------------------------------------------
 // Canvas draw operations - special
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 3f77021..e58857c 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -40,7 +40,7 @@
 
 ResourceCache::ResourceCache() {
     Mutex::Autolock _l(mLock);
-    mCache = new KeyedVector<void*, ResourceReference*>();
+    mCache = new KeyedVector<const void*, ResourceReference*>();
 }
 
 ResourceCache::~ResourceCache() {
@@ -61,13 +61,13 @@
     incrementRefcountLocked(resource, resourceType);
 }
 
-void ResourceCache::incrementRefcount(SkBitmap* bitmapResource) {
+void ResourceCache::incrementRefcount(const SkBitmap* bitmapResource) {
     bitmapResource->pixelRef()->globalRef();
     SkSafeRef(bitmapResource->getColorTable());
     incrementRefcount((void*) bitmapResource, kBitmap);
 }
 
-void ResourceCache::incrementRefcount(SkPath* pathResource) {
+void ResourceCache::incrementRefcount(const SkPath* pathResource) {
     incrementRefcount((void*) pathResource, kPath);
 }
 
@@ -81,7 +81,7 @@
     incrementRefcount((void*) filterResource, kColorFilter);
 }
 
-void ResourceCache::incrementRefcount(Res_png_9patch* patchResource) {
+void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
     incrementRefcount((void*) patchResource, kNinePatch);
 }
 
@@ -99,13 +99,13 @@
     ref->refCount++;
 }
 
-void ResourceCache::incrementRefcountLocked(SkBitmap* bitmapResource) {
+void ResourceCache::incrementRefcountLocked(const SkBitmap* bitmapResource) {
     bitmapResource->pixelRef()->globalRef();
     SkSafeRef(bitmapResource->getColorTable());
     incrementRefcountLocked((void*) bitmapResource, kBitmap);
 }
 
-void ResourceCache::incrementRefcountLocked(SkPath* pathResource) {
+void ResourceCache::incrementRefcountLocked(const SkPath* pathResource) {
     incrementRefcountLocked((void*) pathResource, kPath);
 }
 
@@ -119,7 +119,7 @@
     incrementRefcountLocked((void*) filterResource, kColorFilter);
 }
 
-void ResourceCache::incrementRefcountLocked(Res_png_9patch* patchResource) {
+void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) {
     incrementRefcountLocked((void*) patchResource, kNinePatch);
 }
 
@@ -132,13 +132,13 @@
     decrementRefcountLocked(resource);
 }
 
-void ResourceCache::decrementRefcount(SkBitmap* bitmapResource) {
+void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) {
     bitmapResource->pixelRef()->globalUnref();
     SkSafeUnref(bitmapResource->getColorTable());
     decrementRefcount((void*) bitmapResource);
 }
 
-void ResourceCache::decrementRefcount(SkPath* pathResource) {
+void ResourceCache::decrementRefcount(const SkPath* pathResource) {
     decrementRefcount((void*) pathResource);
 }
 
@@ -152,7 +152,7 @@
     decrementRefcount((void*) filterResource);
 }
 
-void ResourceCache::decrementRefcount(Res_png_9patch* patchResource) {
+void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
     decrementRefcount((void*) patchResource);
 }
 
@@ -173,13 +173,13 @@
     }
 }
 
-void ResourceCache::decrementRefcountLocked(SkBitmap* bitmapResource) {
+void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) {
     bitmapResource->pixelRef()->globalUnref();
     SkSafeUnref(bitmapResource->getColorTable());
     decrementRefcountLocked((void*) bitmapResource);
 }
 
-void ResourceCache::decrementRefcountLocked(SkPath* pathResource) {
+void ResourceCache::decrementRefcountLocked(const SkPath* pathResource) {
     decrementRefcountLocked((void*) pathResource);
 }
 
@@ -193,7 +193,7 @@
     decrementRefcountLocked((void*) filterResource);
 }
 
-void ResourceCache::decrementRefcountLocked(Res_png_9patch* patchResource) {
+void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
     decrementRefcountLocked((void*) patchResource);
 }
 
@@ -223,12 +223,12 @@
     }
 }
 
-void ResourceCache::destructor(SkBitmap* resource) {
+void ResourceCache::destructor(const SkBitmap* resource) {
     Mutex::Autolock _l(mLock);
     destructorLocked(resource);
 }
 
-void ResourceCache::destructorLocked(SkBitmap* resource) {
+void ResourceCache::destructorLocked(const SkBitmap* resource) {
     ssize_t index = mCache->indexOfKey(resource);
     ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
     if (ref == NULL) {
@@ -345,7 +345,7 @@
  * This method should only be called while the mLock mutex is held (that mutex is grabbed
  * by the various destructor() and recycle() methods which call this method).
  */
-void ResourceCache::deleteResourceReferenceLocked(void* resource, ResourceReference* ref) {
+void ResourceCache::deleteResourceReferenceLocked(const void* resource, ResourceReference* ref) {
     if (ref->recycled && ref->resourceType == kBitmap) {
         ((SkBitmap*) resource)->setPixels(NULL, NULL);
     }
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index ea0c1b5..c06b09b 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -70,42 +70,42 @@
     void lock();
     void unlock();
 
-    void incrementRefcount(SkPath* resource);
-    void incrementRefcount(SkBitmap* resource);
+    void incrementRefcount(const SkPath* resource);
+    void incrementRefcount(const SkBitmap* resource);
     void incrementRefcount(SkiaShader* resource);
     void incrementRefcount(SkiaColorFilter* resource);
-    void incrementRefcount(Res_png_9patch* resource);
+    void incrementRefcount(const Res_png_9patch* resource);
     void incrementRefcount(Layer* resource);
 
-    void incrementRefcountLocked(SkPath* resource);
-    void incrementRefcountLocked(SkBitmap* resource);
+    void incrementRefcountLocked(const SkPath* resource);
+    void incrementRefcountLocked(const SkBitmap* resource);
     void incrementRefcountLocked(SkiaShader* resource);
     void incrementRefcountLocked(SkiaColorFilter* resource);
-    void incrementRefcountLocked(Res_png_9patch* resource);
+    void incrementRefcountLocked(const Res_png_9patch* resource);
     void incrementRefcountLocked(Layer* resource);
 
-    void decrementRefcount(SkBitmap* resource);
-    void decrementRefcount(SkPath* resource);
+    void decrementRefcount(const SkBitmap* resource);
+    void decrementRefcount(const SkPath* resource);
     void decrementRefcount(SkiaShader* resource);
     void decrementRefcount(SkiaColorFilter* resource);
-    void decrementRefcount(Res_png_9patch* resource);
+    void decrementRefcount(const Res_png_9patch* resource);
     void decrementRefcount(Layer* resource);
 
-    void decrementRefcountLocked(SkBitmap* resource);
-    void decrementRefcountLocked(SkPath* resource);
+    void decrementRefcountLocked(const SkBitmap* resource);
+    void decrementRefcountLocked(const SkPath* resource);
     void decrementRefcountLocked(SkiaShader* resource);
     void decrementRefcountLocked(SkiaColorFilter* resource);
-    void decrementRefcountLocked(Res_png_9patch* resource);
+    void decrementRefcountLocked(const Res_png_9patch* resource);
     void decrementRefcountLocked(Layer* resource);
 
     void destructor(SkPath* resource);
-    void destructor(SkBitmap* resource);
+    void destructor(const SkBitmap* resource);
     void destructor(SkiaShader* resource);
     void destructor(SkiaColorFilter* resource);
     void destructor(Res_png_9patch* resource);
 
     void destructorLocked(SkPath* resource);
-    void destructorLocked(SkBitmap* resource);
+    void destructorLocked(const SkBitmap* resource);
     void destructorLocked(SkiaShader* resource);
     void destructorLocked(SkiaColorFilter* resource);
     void destructorLocked(Res_png_9patch* resource);
@@ -114,7 +114,7 @@
     bool recycleLocked(SkBitmap* resource);
 
 private:
-    void deleteResourceReferenceLocked(void* resource, ResourceReference* ref);
+    void deleteResourceReferenceLocked(const void* resource, ResourceReference* ref);
 
     void incrementRefcount(void* resource, ResourceType resourceType);
     void incrementRefcountLocked(void* resource, ResourceType resourceType);
@@ -131,7 +131,7 @@
      */
     mutable Mutex mLock;
 
-    KeyedVector<void*, ResourceReference*>* mCache;
+    KeyedVector<const void*, ResourceReference*>* mCache;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaColorFilter.h b/libs/hwui/SkiaColorFilter.h
index 2feb834..c222a2d 100644
--- a/libs/hwui/SkiaColorFilter.h
+++ b/libs/hwui/SkiaColorFilter.h
@@ -36,7 +36,8 @@
  * Represents a Skia color filter. A color filter modifies a ProgramDescription
  * and sets uniforms on the resulting shaders.
  */
-struct SkiaColorFilter {
+class SkiaColorFilter {
+public:
     /**
      * Type of Skia color filter in use.
      */
@@ -80,7 +81,8 @@
 /**
  * A color filter that multiplies the source color with a matrix and adds a vector.
  */
-struct SkiaColorMatrixFilter: public SkiaColorFilter {
+class SkiaColorMatrixFilter: public SkiaColorFilter {
+public:
     ANDROID_API SkiaColorMatrixFilter(SkColorFilter *skFilter, float* matrix, float* vector);
     ~SkiaColorMatrixFilter();
 
@@ -96,7 +98,8 @@
  * A color filters that multiplies the source color with a fixed value and adds
  * another fixed value. Ignores the alpha channel of both arguments.
  */
-struct SkiaLightingFilter: public SkiaColorFilter {
+class SkiaLightingFilter: public SkiaColorFilter {
+public:
     ANDROID_API SkiaLightingFilter(SkColorFilter *skFilter, int multiply, int add);
 
     void describe(ProgramDescription& description, const Extensions& extensions);
@@ -111,7 +114,8 @@
  * A color filters that blends the source color with a specified destination color
  * and PorterDuff blending mode.
  */
-struct SkiaBlendFilter: public SkiaColorFilter {
+class SkiaBlendFilter: public SkiaColorFilter {
+public:
     ANDROID_API SkiaBlendFilter(SkColorFilter *skFilter, int color, SkXfermode::Mode mode);
 
     void describe(ProgramDescription& description, const Extensions& extensions);
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 9fc99a4..d71f8ee 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -43,7 +43,8 @@
  * Represents a Skia shader. A shader will modify the GL context and active
  * program to recreate the original effect.
  */
-struct SkiaShader {
+class SkiaShader {
+public:
     /**
      * Type of Skia shader in use.
      */
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index cc8b14f..05f6cf8 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -22,6 +22,7 @@
 namespace uirenderer {
 
 StatefulBaseRenderer::StatefulBaseRenderer() :
+        mDirtyClip(false), mWidth(-1), mHeight(-1),
         mSaveCount(1), mFirstSnapshot(new Snapshot), mSnapshot(mFirstSnapshot) {
 }
 
@@ -113,7 +114,7 @@
     mSnapshot->transform->skew(sx, sy);
 }
 
-void StatefulBaseRenderer::setMatrix(SkMatrix* matrix) {
+void StatefulBaseRenderer::setMatrix(const SkMatrix* matrix) {
     if (matrix) {
         mSnapshot->transform->load(*matrix);
     } else {
@@ -125,7 +126,7 @@
     mSnapshot->transform->load(matrix);
 }
 
-void StatefulBaseRenderer::concatMatrix(SkMatrix* matrix) {
+void StatefulBaseRenderer::concatMatrix(const SkMatrix* matrix) {
     mat4 transform(*matrix);
     mSnapshot->transform->multiply(transform);
 }
@@ -138,6 +139,48 @@
 // Clip
 ///////////////////////////////////////////////////////////////////////////////
 
+bool StatefulBaseRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
+    if (CC_LIKELY(currentTransform()->rectToRect())) {
+        mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op);
+        return !mSnapshot->clipRect->isEmpty();
+    }
+
+    SkPath path;
+    path.addRect(left, top, right, bottom);
+
+    return StatefulBaseRenderer::clipPath(&path, op);
+}
+
+bool StatefulBaseRenderer::clipPath(const SkPath* path, SkRegion::Op op) {
+    SkMatrix transform;
+    currentTransform()->copyTo(transform);
+
+    SkPath transformed;
+    path->transform(transform, &transformed);
+
+    SkRegion clip;
+    if (!mSnapshot->previous->clipRegion->isEmpty()) {
+        clip.setRegion(*mSnapshot->previous->clipRegion);
+    } else {
+        if (mSnapshot->previous == firstSnapshot()) {
+            clip.setRect(0, 0, getWidth(), getHeight());
+        } else {
+            Rect* bounds = mSnapshot->previous->clipRect;
+            clip.setRect(bounds->left, bounds->top, bounds->right, bounds->bottom);
+        }
+    }
+
+    SkRegion region;
+    region.setPath(transformed, clip);
+
+    mDirtyClip |= mSnapshot->clipRegionTransformed(region, op);
+    return !mSnapshot->clipRect->isEmpty();
+}
+
+bool StatefulBaseRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
+    mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op);
+    return !mSnapshot->clipRect->isEmpty();
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 // Quick Rejection
@@ -160,10 +203,10 @@
     }
 
     Rect r(left, top, right, bottom);
-    currentTransform().mapRect(r);
+    currentTransform()->mapRect(r);
     r.snapGeometryToPixelBoundaries(snapOut);
 
-    Rect clipRect(currentClipRect());
+    Rect clipRect(*currentClipRect());
     clipRect.snapToPixelBoundaries();
 
     if (!clipRect.intersects(r)) return true;
@@ -191,10 +234,10 @@
     }
 
     Rect r(left, top, right, bottom);
-    currentTransform().mapRect(r);
+    currentTransform()->mapRect(r);
     r.roundOut(); // rounded out to be conservative
 
-    Rect clipRect(currentClipRect());
+    Rect clipRect(*currentClipRect());
     clipRect.snapToPixelBoundaries();
 
     if (!clipRect.intersects(r)) return true;
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index 2bd196e..bf34bec 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -26,10 +26,18 @@
 namespace uirenderer {
 
 /**
- * Implementation for Renderer state methods
+ * Abstract Renderer subclass, which implements Canvas state methods.
  *
- * Eventually, this class should have abstract protected methods
- * for allowing subclasses to hook into save/saveLayer and restore
+ * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the
+ * Renderer interface. Drawing and recording classes that extend StatefulBaseRenderer will have
+ * different use cases:
+ *
+ * Drawing subclasses (i.e. OpenGLRenderer) can query attributes (such as transform) or hook into
+ * changes (e.g. save/restore) with minimal surface area for manipulating the stack itself.
+ *
+ * Recording subclasses (i.e. DisplayListRenderer) can both record and pass through state operations
+ * to StatefulBaseRenderer, so that not only will querying operations work (getClip/Matrix), but so
+ * that quickRejection can also be used.
  */
 class StatefulBaseRenderer : public Renderer {
 public:
@@ -43,7 +51,7 @@
 
     // getters
     bool hasRectToRectTransform() const {
-        return CC_LIKELY(currentTransform().rectToRect());
+        return CC_LIKELY(currentTransform()->rectToRect());
     }
 
     // Save (layer)
@@ -61,19 +69,18 @@
     virtual void scale(float sx, float sy);
     virtual void skew(float sx, float sy);
 
-    virtual void setMatrix(SkMatrix* matrix);
+    virtual void setMatrix(const SkMatrix* matrix);
     void setMatrix(const Matrix4& matrix); // internal only convenience method
-    virtual void concatMatrix(SkMatrix* matrix);
+    virtual void concatMatrix(const SkMatrix* matrix);
     void concatMatrix(const Matrix4& matrix); // internal only convenience method
 
     // Clip
     const Rect& getClipBounds() const { return mSnapshot->getLocalClip(); }
     virtual bool quickRejectConservative(float left, float top, float right, float bottom) const;
 
-    // TODO: implement these with hooks to enable scissor/stencil usage in OpenGLRenderer
-    // virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
-    // virtual bool clipPath(SkPath* path, SkRegion::Op op);
-    // virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
+    virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
+    virtual bool clipPath(const SkPath* path, SkRegion::Op op);
+    virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
 
 protected:
     int getWidth() { return mWidth; }
@@ -101,20 +108,28 @@
      */
     virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {};
 
-    inline const Rect& currentClipRect() const {
-        return *(mSnapshot->clipRect);
+    inline const Rect* currentClipRect() const {
+        return mSnapshot->clipRect;
     }
 
-    inline const mat4& currentTransform() const {
-        return *(mSnapshot->transform);
+    inline const mat4* currentTransform() const {
+        return mSnapshot->transform;
     }
 
-    inline const Snapshot& currentSnapshot() const {
-        return mSnapshot != NULL ? *mSnapshot : *mFirstSnapshot;
+    inline const Snapshot* currentSnapshot() const {
+        return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get();
     }
 
-    // TODO: below should be private so that snapshot stack manipulation
-    // goes though (mostly) public methods
+    inline const Snapshot* firstSnapshot() const {
+        return mFirstSnapshot.get();
+    }
+
+    // indicites that the clip has been changed since the last time it was consumed
+    bool mDirtyClip;
+
+private:
+    // Dimensions of the drawing surface
+    int mWidth, mHeight;
 
     // Number of saved states
     int mSaveCount;
@@ -122,13 +137,11 @@
     // Base state
     sp<Snapshot> mFirstSnapshot;
 
+protected:
     // Current state
+    // TODO: should become private, once hooks needed by OpenGLRenderer are added
     sp<Snapshot> mSnapshot;
 
-private:
-    // Dimensions of the drawing surface
-    int mWidth, mHeight;
-
 }; // class StatefulBaseRenderer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Stencil.cpp b/libs/hwui/Stencil.cpp
index 2764523..8ce57db 100644
--- a/libs/hwui/Stencil.cpp
+++ b/libs/hwui/Stencil.cpp
@@ -35,7 +35,7 @@
 Stencil::Stencil(): mState(kDisabled) {
 }
 
-uint32_t Stencil::getStencilSize() {
+uint8_t Stencil::getStencilSize() {
     return STENCIL_BUFFER_SIZE;
 }
 
diff --git a/libs/hwui/Stencil.h b/libs/hwui/Stencil.h
index 83ad668..c5e5186 100644
--- a/libs/hwui/Stencil.h
+++ b/libs/hwui/Stencil.h
@@ -40,7 +40,7 @@
      * Returns the desired size for the stencil buffer. If the returned value
      * is 0, then no stencil buffer is required.
      */
-    ANDROID_API static uint32_t getStencilSize();
+    ANDROID_API static uint8_t getStencilSize();
 
     /**
      * Returns the smallest stencil format accepted by render buffers.
diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp
index 6f27b36..4eec462 100644
--- a/libs/hwui/TextDropShadowCache.cpp
+++ b/libs/hwui/TextDropShadowCache.cpp
@@ -168,7 +168,7 @@
     mCache.clear();
 }
 
-ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32_t len,
+ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* text, uint32_t len,
         int numGlyphs, float radius, const float* positions) {
     ShadowText entry(paint, radius, len, text, positions);
     ShadowTexture* texture = mCache.get(entry);
diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h
index 04d7357..54b930b 100644
--- a/libs/hwui/TextDropShadowCache.h
+++ b/libs/hwui/TextDropShadowCache.h
@@ -38,7 +38,7 @@
     }
 
     // len is the number of bytes in text
-    ShadowText(SkPaint* paint, float radius, uint32_t len, const char* srcText,
+    ShadowText(const SkPaint* paint, float radius, uint32_t len, const char* srcText,
             const float* positions):
             len(len), radius(radius), positions(positions) {
         // TODO: Propagate this through the API, we should not cast here
@@ -135,7 +135,7 @@
      */
     void operator()(ShadowText& text, ShadowTexture*& texture);
 
-    ShadowTexture* get(SkPaint* paint, const char* text, uint32_t len,
+    ShadowTexture* get(const SkPaint* paint, const char* text, uint32_t len,
             int numGlyphs, float radius, const float* positions);
 
     /**
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 1d4af7f..457ca59 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -34,7 +34,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 TextureCache::TextureCache():
-        mCache(LruCache<SkBitmap*, Texture*>::kUnlimitedCapacity),
+        mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
         mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
         mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) {
     char property[PROPERTY_VALUE_MAX];
@@ -58,7 +58,7 @@
 }
 
 TextureCache::TextureCache(uint32_t maxByteSize):
-        mCache(LruCache<SkBitmap*, Texture*>::kUnlimitedCapacity),
+        mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
         mSize(0), mMaxSize(maxByteSize) {
     init();
 }
@@ -103,7 +103,7 @@
 // Callbacks
 ///////////////////////////////////////////////////////////////////////////////
 
-void TextureCache::operator()(SkBitmap*&, Texture*& texture) {
+void TextureCache::operator()(const SkBitmap*&, Texture*& texture) {
     // This will be called already locked
     if (texture) {
         mSize -= texture->bitmapSize;
@@ -121,7 +121,7 @@
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
 
-Texture* TextureCache::get(SkBitmap* bitmap) {
+Texture* TextureCache::get(const SkBitmap* bitmap) {
     Texture* texture = mCache.get(bitmap);
 
     if (!texture) {
@@ -161,7 +161,7 @@
     return texture;
 }
 
-Texture* TextureCache::getTransient(SkBitmap* bitmap) {
+Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
     Texture* texture = new Texture();
     texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
     texture->cleanup = true;
@@ -171,11 +171,11 @@
     return texture;
 }
 
-void TextureCache::remove(SkBitmap* bitmap) {
+void TextureCache::remove(const SkBitmap* bitmap) {
     mCache.remove(bitmap);
 }
 
-void TextureCache::removeDeferred(SkBitmap* bitmap) {
+void TextureCache::removeDeferred(const SkBitmap* bitmap) {
     Mutex::Autolock _l(mLock);
     mGarbage.push(bitmap);
 }
@@ -209,7 +209,7 @@
     }
 }
 
-void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) {
+void TextureCache::generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate) {
     SkAutoLockPixels alp(*bitmap);
 
     if (!bitmap->readyToDraw()) {
@@ -282,7 +282,7 @@
     }
 }
 
-void TextureCache::uploadLoFiTexture(bool resize, SkBitmap* bitmap,
+void TextureCache::uploadLoFiTexture(bool resize, const SkBitmap* bitmap,
         uint32_t width, uint32_t height) {
     SkBitmap rgbaBitmap;
     rgbaBitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 57fc19a..e33c60d 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -49,7 +49,7 @@
  * Any texture added to the cache causing the cache to grow beyond the maximum
  * allowed size will also cause the oldest texture to be kicked out.
  */
-class TextureCache: public OnEntryRemoved<SkBitmap*, Texture*> {
+class TextureCache: public OnEntryRemoved<const SkBitmap*, Texture*> {
 public:
     TextureCache();
     TextureCache(uint32_t maxByteSize);
@@ -59,28 +59,28 @@
      * Used as a callback when an entry is removed from the cache.
      * Do not invoke directly.
      */
-    void operator()(SkBitmap*& bitmap, Texture*& texture);
+    void operator()(const SkBitmap*& bitmap, Texture*& texture);
 
     /**
      * Returns the texture associated with the specified bitmap. If the texture
      * cannot be found in the cache, a new texture is generated.
      */
-    Texture* get(SkBitmap* bitmap);
+    Texture* get(const SkBitmap* bitmap);
     /**
      * Returns the texture associated with the specified bitmap. The generated
      * texture is not kept in the cache. The caller must destroy the texture.
      */
-    Texture* getTransient(SkBitmap* bitmap);
+    Texture* getTransient(const SkBitmap* bitmap);
     /**
      * Removes the texture associated with the specified bitmap.
      * Upon remove the texture is freed.
      */
-    void remove(SkBitmap* bitmap);
+    void remove(const SkBitmap* bitmap);
     /**
      * Removes the texture associated with the specified bitmap. This is meant
      * to be called from threads that are not the EGL context thread.
      */
-    void removeDeferred(SkBitmap* bitmap);
+    void removeDeferred(const SkBitmap* bitmap);
     /**
      * Process deferred removals.
      */
@@ -122,15 +122,15 @@
      * @param regenerate If true, the bitmap data is reuploaded into the texture, but
      *        no new texture is generated.
      */
-    void generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate = false);
+    void generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate = false);
 
-    void uploadLoFiTexture(bool resize, SkBitmap* bitmap, uint32_t width, uint32_t height);
+    void uploadLoFiTexture(bool resize, const SkBitmap* bitmap, uint32_t width, uint32_t height);
     void uploadToTexture(bool resize, GLenum format, GLsizei stride,
             GLsizei width, GLsizei height, GLenum type, const GLvoid * data);
 
     void init();
 
-    LruCache<SkBitmap*, Texture*> mCache;
+    LruCache<const SkBitmap*, Texture*> mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;
@@ -140,7 +140,7 @@
 
     bool mDebugEnabled;
 
-    Vector<SkBitmap*> mGarbage;
+    Vector<const SkBitmap*> mGarbage;
     mutable Mutex mLock;
 }; // class TextureCache
 
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index 351ce71..5d7a199 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -33,7 +33,8 @@
      * Program::set()), and used to make geometry damage rect calculation conservative (see
      * Rect::snapGeometryToPixelBoundaries())
      */
-    static const float gGeometryFudgeFactor = 0.0656f;
+    static float GeometryFudgeFactor() { return 0.0656f; }
+
 
     float x, y;
 
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 12a9c235..b0945c6 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -267,7 +267,7 @@
             glyph->mCacheTexture);
 }
 
-CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching) {
+CachedGlyphInfo* Font::getCachedGlyph(const SkPaint* paint, glyph_t textUnit, bool precaching) {
     CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueFor(textUnit);
     if (cachedGlyph) {
         // Is the glyph still in texture cache?
@@ -283,14 +283,14 @@
     return cachedGlyph;
 }
 
-void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+void Font::render(const SkPaint* paint, const char *text, uint32_t start, uint32_t len,
             int numGlyphs, int x, int y, const float* positions) {
     render(paint, text, start, len, numGlyphs, x, y, FRAMEBUFFER, NULL,
             0, 0, NULL, positions);
 }
 
-void Font::render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
-        int numGlyphs, SkPath* path, float hOffset, float vOffset) {
+void Font::render(const SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+        int numGlyphs, const SkPath* path, float hOffset, float vOffset) {
     if (numGlyphs == 0 || text == NULL || len == 0) {
         return;
     }
@@ -339,7 +339,7 @@
     }
 }
 
-void Font::measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::measure(const SkPaint* paint, const char* text, uint32_t start, uint32_t len,
         int numGlyphs, Rect *bounds, const float* positions) {
     if (bounds == NULL) {
         ALOGE("No return rectangle provided to measure text");
@@ -349,7 +349,7 @@
     render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
 }
 
-void Font::precache(SkPaint* paint, const char* text, int numGlyphs) {
+void Font::precache(const SkPaint* paint, const char* text, int numGlyphs) {
     ATRACE_NAME("precacheText");
 
     if (numGlyphs == 0 || text == NULL) {
@@ -370,7 +370,7 @@
     }
 }
 
-void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+void Font::render(const SkPaint* paint, const char* text, uint32_t start, uint32_t len,
         int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
         uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) {
     if (numGlyphs == 0 || text == NULL || len == 0) {
@@ -416,8 +416,8 @@
     }
 }
 
-void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, SkGlyphCache* skiaGlyphCache,
-        CachedGlyphInfo* glyph, bool precaching) {
+void Font::updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph,
+        SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching) {
     glyph->mAdvanceX = skiaGlyph.fAdvanceX;
     glyph->mAdvanceY = skiaGlyph.fAdvanceY;
     glyph->mBitmapLeft = skiaGlyph.fLeft;
@@ -460,7 +460,7 @@
     }
 }
 
-CachedGlyphInfo* Font::cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching) {
+CachedGlyphInfo* Font::cacheGlyph(const SkPaint* paint, glyph_t glyph, bool precaching) {
     CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
     mCachedGlyphs.add(glyph, newGlyph);
 
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index f68b430..02197bc 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -77,11 +77,11 @@
 
     ~Font();
 
-    void render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+    void render(const SkPaint* paint, const char* text, uint32_t start, uint32_t len,
             int numGlyphs, int x, int y, const float* positions);
 
-    void render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
-            int numGlyphs, SkPath* path, float hOffset, float vOffset);
+    void render(const SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+            int numGlyphs, const SkPath* path, float hOffset, float vOffset);
 
     const Font::FontDescription& getDescription() const {
         return mDescription;
@@ -106,20 +106,20 @@
         MEASURE,
     };
 
-    void precache(SkPaint* paint, const char* text, int numGlyphs);
+    void precache(const SkPaint* paint, const char* text, int numGlyphs);
 
-    void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
+    void render(const SkPaint* paint, const char *text, uint32_t start, uint32_t len,
             int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
             uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
 
-    void measure(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
+    void measure(const SkPaint* paint, const char* text, uint32_t start, uint32_t len,
             int numGlyphs, Rect *bounds, const float* positions);
 
     void invalidateTextureCache(CacheTexture* cacheTexture = NULL);
 
-    CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching);
-    void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, SkGlyphCache* skiaGlyphCache,
-            CachedGlyphInfo* glyph, bool precaching);
+    CachedGlyphInfo* cacheGlyph(const SkPaint* paint, glyph_t glyph, bool precaching);
+    void updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph,
+            SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching);
 
     void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
             uint8_t *bitmap, uint32_t bitmapW, uint32_t bitmapH,
@@ -136,7 +136,8 @@
     void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset,
             SkPathMeasure& measure, SkPoint* position, SkVector* tangent);
 
-    CachedGlyphInfo* getCachedGlyph(SkPaint* paint, glyph_t textUnit, bool precaching = false);
+    CachedGlyphInfo* getCachedGlyph(const SkPaint* paint, glyph_t textUnit,
+            bool precaching = false);
 
     FontRenderer* mState;
     FontDescription mDescription;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
new file mode 100644
index 0000000..ffb8a32
--- /dev/null
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#define LOG_TAG "CanvasContext"
+
+#include "CanvasContext.h"
+
+#include <cutils/properties.h>
+#include <strings.h>
+
+#include "../Caches.h"
+#include "../Stencil.h"
+
+#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
+#define GLES_VERSION 2
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+#define ERROR_CASE(x) case x: return #x;
+static const char* egl_error_str(EGLint error) {
+    switch (error) {
+        ERROR_CASE(EGL_SUCCESS)
+        ERROR_CASE(EGL_NOT_INITIALIZED)
+        ERROR_CASE(EGL_BAD_ACCESS)
+        ERROR_CASE(EGL_BAD_ALLOC)
+        ERROR_CASE(EGL_BAD_ATTRIBUTE)
+        ERROR_CASE(EGL_BAD_CONFIG)
+        ERROR_CASE(EGL_BAD_CONTEXT)
+        ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
+        ERROR_CASE(EGL_BAD_DISPLAY)
+        ERROR_CASE(EGL_BAD_MATCH)
+        ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
+        ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
+        ERROR_CASE(EGL_BAD_PARAMETER)
+        ERROR_CASE(EGL_BAD_SURFACE)
+        ERROR_CASE(EGL_CONTEXT_LOST)
+    default:
+        return "Unknown error";
+    }
+}
+static const char* egl_error_str() {
+    return egl_error_str(eglGetError());
+}
+
+static bool load_dirty_regions_property() {
+    char buf[PROPERTY_VALUE_MAX];
+    int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
+    return !strncasecmp("true", buf, len);
+}
+
+// This class contains the shared global EGL objects, such as EGLDisplay
+// and EGLConfig, which are re-used by CanvasContext
+class GlobalContext {
+public:
+    static GlobalContext* get();
+
+    // Returns true if EGL was initialized,
+    // false if it was already initialized
+    bool initialize();
+
+    bool usePBufferSurface();
+    EGLSurface createSurface(EGLNativeWindowType window);
+    void destroySurface(EGLSurface surface);
+
+    void destroy();
+
+    bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
+    bool makeCurrent(EGLSurface surface);
+    bool swapBuffers(EGLSurface surface);
+
+    bool enableDirtyRegions(EGLSurface surface);
+
+private:
+    GlobalContext();
+    // GlobalContext is never destroyed, method is purposely not implemented
+    ~GlobalContext();
+
+    bool loadConfig();
+    bool createContext();
+
+    static GlobalContext* sContext;
+
+    EGLDisplay mEglDisplay;
+    EGLConfig mEglConfig;
+    EGLContext mEglContext;
+    EGLSurface mPBufferSurface;
+
+    const bool mRequestDirtyRegions;
+    bool mCanSetDirtyRegions;
+
+    EGLSurface mCurrentSurface;
+};
+
+GlobalContext* GlobalContext::sContext = 0;
+
+GlobalContext* GlobalContext::get() {
+    if (!sContext) {
+        sContext = new GlobalContext();
+    }
+    return sContext;
+}
+
+GlobalContext::GlobalContext()
+        : mEglDisplay(EGL_NO_DISPLAY)
+        , mEglConfig(0)
+        , mEglContext(EGL_NO_CONTEXT)
+        , mPBufferSurface(EGL_NO_SURFACE)
+        , mRequestDirtyRegions(load_dirty_regions_property())
+        , mCurrentSurface(EGL_NO_SURFACE) {
+    mCanSetDirtyRegions = mRequestDirtyRegions;
+    ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
+}
+
+bool GlobalContext::initialize() {
+    if (mEglDisplay != EGL_NO_DISPLAY) return false;
+
+    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    if (mEglDisplay == EGL_NO_DISPLAY) {
+        ALOGE("Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
+        return false;
+    }
+
+    EGLint major, minor;
+    if (eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE) {
+        ALOGE("Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
+        return false;
+    }
+    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
+
+    if (!loadConfig()) {
+        return false;
+    }
+    if (!createContext()) {
+        return false;
+    }
+
+    return true;
+}
+
+bool GlobalContext::loadConfig() {
+    EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+    EGLint attribs[] = {
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_BLUE_SIZE, 8,
+            EGL_ALPHA_SIZE, 8,
+            EGL_DEPTH_SIZE, 0,
+            EGL_CONFIG_CAVEAT, EGL_NONE,
+            EGL_STENCIL_SIZE, Stencil::getStencilSize(),
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
+            EGL_NONE
+    };
+
+    EGLint num_configs = 1;
+    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
+            || num_configs != 1) {
+        // Failed to get a valid config
+        if (mCanSetDirtyRegions) {
+            ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
+            // Try again without dirty regions enabled
+            mCanSetDirtyRegions = false;
+            loadConfig();
+        } else {
+            ALOGE("Failed to choose config, error = %s", egl_error_str());
+            return false;
+        }
+    }
+    return true;
+}
+
+bool GlobalContext::createContext() {
+    EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
+    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
+    if (mEglContext == EGL_NO_CONTEXT) {
+        ALOGE("Failed to create context, error = %s", egl_error_str());
+        return false;
+    }
+    return true;
+}
+
+bool GlobalContext::usePBufferSurface() {
+    if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+    if (mPBufferSurface == EGL_NO_SURFACE) {
+        EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+        mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
+    }
+    return makeCurrent(mPBufferSurface);
+}
+
+EGLSurface GlobalContext::createSurface(EGLNativeWindowType window) {
+    initialize();
+    return eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
+}
+
+void GlobalContext::destroySurface(EGLSurface surface) {
+    if (isCurrent(surface)) {
+        makeCurrent(EGL_NO_SURFACE);
+    }
+    if (!eglDestroySurface(mEglDisplay, surface)) {
+        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
+    }
+}
+
+void GlobalContext::destroy() {
+    if (mEglDisplay == EGL_NO_DISPLAY) return;
+
+    usePBufferSurface();
+    if (Caches::hasInstance()) {
+        Caches::getInstance().terminate();
+    }
+
+    eglDestroyContext(mEglDisplay, mEglContext);
+    eglDestroySurface(mEglDisplay, mPBufferSurface);
+    eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(mEglDisplay);
+    eglReleaseThread();
+
+    mEglDisplay = EGL_NO_DISPLAY;
+    mEglContext = EGL_NO_CONTEXT;
+    mPBufferSurface = EGL_NO_SURFACE;
+    mCurrentSurface = EGL_NO_SURFACE;
+}
+
+bool GlobalContext::makeCurrent(EGLSurface surface) {
+    if (isCurrent(surface)) return true;
+
+    if (surface == EGL_NO_SURFACE) {
+        // If we are setting EGL_NO_SURFACE we don't care about any of the potential
+        // return errors, which would only happen if mEglDisplay had already been
+        // destroyed in which case the current context is already NO_CONTEXT
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
+        ALOGE("Failed to make current on surface %p, error=%s", (void*)surface, egl_error_str());
+        return false;
+    }
+    mCurrentSurface = surface;
+    return true;
+}
+
+bool GlobalContext::swapBuffers(EGLSurface surface) {
+    if (!eglSwapBuffers(mEglDisplay, surface)) {
+        ALOGW("eglSwapBuffers failed on surface %p, error=%s", (void*)surface, egl_error_str());
+        return false;
+    }
+    return true;
+}
+
+bool GlobalContext::enableDirtyRegions(EGLSurface surface) {
+    if (!mRequestDirtyRegions) return false;
+
+    if (mCanSetDirtyRegions) {
+        if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
+            ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
+                    (void*) surface, egl_error_str());
+            return false;
+        }
+        return true;
+    }
+    // Perhaps it is already enabled?
+    EGLint value;
+    if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
+        ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
+                (void*) surface, egl_error_str());
+        return false;
+    }
+    return value == EGL_BUFFER_PRESERVED;
+}
+
+CanvasContext::CanvasContext()
+        : mEglSurface(EGL_NO_SURFACE)
+        , mDirtyRegionsEnabled(false) {
+    mGlobalContext = GlobalContext::get();
+}
+
+CanvasContext::~CanvasContext() {
+    setSurface(NULL);
+}
+
+bool CanvasContext::setSurface(EGLNativeWindowType window) {
+    if (mEglSurface != EGL_NO_SURFACE) {
+        mGlobalContext->destroySurface(mEglSurface);
+        mEglSurface = EGL_NO_SURFACE;
+    }
+
+    if (window) {
+        mEglSurface = mGlobalContext->createSurface(window);
+    }
+
+    if (mEglSurface != EGL_NO_SURFACE) {
+        mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
+    }
+    return !window || mEglSurface != EGL_NO_SURFACE;
+}
+
+bool CanvasContext::swapBuffers() {
+    return mGlobalContext->swapBuffers(mEglSurface);
+}
+
+bool CanvasContext::makeCurrent() {
+    return mGlobalContext->makeCurrent(mEglSurface);
+}
+
+bool CanvasContext::useGlobalPBufferSurface() {
+    return GlobalContext::get()->usePBufferSurface();
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
new file mode 100644
index 0000000..77ae737
--- /dev/null
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef CANVASCONTEXT_H_
+#define CANVASCONTEXT_H_
+
+#include <cutils/compiler.h>
+#include <EGL/egl.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class GlobalContext;
+
+// This per-renderer class manages the bridge between the global EGL context
+// and the render surface.
+class CanvasContext {
+public:
+    ANDROID_API CanvasContext();
+    ANDROID_API ~CanvasContext();
+
+    ANDROID_API bool setSurface(EGLNativeWindowType window);
+    ANDROID_API bool swapBuffers();
+    ANDROID_API bool makeCurrent();
+
+    ANDROID_API static bool useGlobalPBufferSurface();
+
+private:
+
+    GlobalContext* mGlobalContext;
+    EGLSurface mEglSurface;
+    bool mDirtyRegionsEnabled;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+#endif /* CANVASCONTEXT_H_ */
diff --git a/media/java/android/media/AmrInputStream.java b/media/java/android/media/AmrInputStream.java
index abee9e9..f90f1e2 100644
--- a/media/java/android/media/AmrInputStream.java
+++ b/media/java/android/media/AmrInputStream.java
@@ -39,7 +39,7 @@
     private InputStream mInputStream;
     
     // native handle
-    private int mGae;
+    private long mGae;
     
     // result amr stream
     private final byte[] mBuf = new byte[SAMPLES_PER_FRAME * 2];
@@ -128,11 +128,11 @@
     //
     // AudioRecord JNI interface
     //
-    private static native int GsmAmrEncoderNew();
-    private static native void GsmAmrEncoderInitialize(int gae);
-    private static native int GsmAmrEncoderEncode(int gae,
+    private static native long GsmAmrEncoderNew();
+    private static native void GsmAmrEncoderInitialize(long gae);
+    private static native int GsmAmrEncoderEncode(long gae,
             byte[] pcm, int pcmOffset, byte[] amr, int amrOffset) throws IOException;
-    private static native void GsmAmrEncoderCleanup(int gae);
-    private static native void GsmAmrEncoderDelete(int gae);
+    private static native void GsmAmrEncoderCleanup(long gae);
+    private static native void GsmAmrEncoderDelete(long gae);
 
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 8dcbd6b..7b7c06c 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -124,6 +124,18 @@
     public native void setCamera(Camera c);
 
     /**
+     * Gets the surface to record from when using SURFACE video source.
+     * <p>
+     * Should only be called after prepare(). Frames rendered before start()
+     * will be discarded.
+     * </p>
+     * @throws IllegalStateException if it is called before prepare(), after
+     * stop() or is called when VideoSource is not set to SURFACE.
+     * @see android.media.MediaRecorder.VideoSource
+     */
+    public native Surface getSurface();
+
+    /**
      * Sets a Surface to show a preview of recorded media (video). Calls this
      * before prepare() to make sure that the desirable preview display is
      * set. If {@link #setCamera(Camera)} is used and the surface has been
@@ -225,10 +237,23 @@
        */
         private VideoSource() {}
         public static final int DEFAULT = 0;
-        /** Camera video source */
+        /** Camera video source
+         * <p>
+         * Using android.hardware.Camera as video source.
+         * </p>
+         */
         public static final int CAMERA = 1;
-        /** @hide */
-        public static final int GRALLOC_BUFFER = 2;
+        /** Surface video source
+         * <p>
+         * Using a Surface as video source.
+         * </p><p>
+         * This flag must be used when recording from an
+         * android.hardware.camera2.CameraDevice source.
+         * </p><p>
+         * When using this video source type, use {@link MediaRecorder#getSurface()}
+         * to retrieve the surface created by MediaRecorder.
+         */
+        public static final int SURFACE = 2;
     }
 
     /**
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index cdeb4fe..cd3ce1f 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -401,7 +401,7 @@
      * @throws IllegalArgumentException
      */
     public boolean setSynchronizationMode(int sync) throws IllegalArgumentException {
-        if ((sync != POSITION_SYNCHRONIZATION_NONE) || (sync != POSITION_SYNCHRONIZATION_CHECK)) {
+        if ((sync != POSITION_SYNCHRONIZATION_NONE) && (sync != POSITION_SYNCHRONIZATION_CHECK)) {
             throw new IllegalArgumentException("Unknown synchronization mode " + sync);
         }
         if (!mIsRegistered) {
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 3706884..9b381cc 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -314,8 +314,8 @@
     private int mId;
 
     // accessed by native methods
-    private int mNativeAudioEffect;
-    private int mJniData;
+    private long mNativeAudioEffect;
+    private long mJniData;
 
     /**
      * Effect descriptor
diff --git a/media/java/android/media/audiofx/Visualizer.java b/media/java/android/media/audiofx/Visualizer.java
index 6bc3f09..24c74ac 100644
--- a/media/java/android/media/audiofx/Visualizer.java
+++ b/media/java/android/media/audiofx/Visualizer.java
@@ -183,8 +183,8 @@
     private OnServerDiedListener mServerDiedListener = null;
 
     // accessed by native methods
-    private int mNativeVisualizer;
-    private int mJniData;
+    private long mNativeVisualizer;
+    private long mJniData;
 
     //--------------------------------------------------------------------------
     // Constructor, Finalize
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index da68674..2d3de85 100644
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -117,7 +117,7 @@
     private boolean mErrorFlagSet = false;
 
     @SuppressWarnings("unused")
-    private int mManualEditContext;
+    private long mManualEditContext;
 
     /* Listeners */
 
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 187500d..cc464db 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -1034,7 +1034,7 @@
     }
 
     // used by the JNI code
-    private int mNativeContext;
+    private long mNativeContext;
 
     private native final void native_setup();
     private native final void native_finalize();
diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java
index 926364f..72dcaa8 100644
--- a/media/java/android/mtp/MtpDevice.java
+++ b/media/java/android/mtp/MtpDevice.java
@@ -235,7 +235,7 @@
     }
 
     // used by the JNI code
-    private int mNativeContext;
+    private long mNativeContext;
 
     private native boolean native_open(String deviceName, int fd);
     private native void native_close();
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index f561cc0..266f78e 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -22,7 +22,7 @@
  */
 public class MtpServer implements Runnable {
 
-    private int mNativeContext; // accessed by native methods
+    private long mNativeContext; // accessed by native methods
 
     static {
         System.loadLibrary("media_jni");
diff --git a/media/jni/android_media_AmrInputStream.cpp b/media/jni/android_media_AmrInputStream.cpp
index b5220fe..3df6530 100644
--- a/media/jni/android_media_AmrInputStream.cpp
+++ b/media/jni/android_media_AmrInputStream.cpp
@@ -49,17 +49,17 @@
     int32_t mLastModeUsed;
 };
 
-static jint android_media_AmrInputStream_GsmAmrEncoderNew
+static jlong android_media_AmrInputStream_GsmAmrEncoderNew
         (JNIEnv *env, jclass clazz) {
     GsmAmrEncoderState* gae = new GsmAmrEncoderState();
     if (gae == NULL) {
         jniThrowRuntimeException(env, "Out of memory");
     }
-    return (jint)gae;
+    return (jlong)gae;
 }
 
 static void android_media_AmrInputStream_GsmAmrEncoderInitialize
-        (JNIEnv *env, jclass clazz, jint gae) {
+        (JNIEnv *env, jclass clazz, jlong gae) {
     GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
     int32_t nResult = AMREncodeInit(&state->mEncState, &state->mSidState, false);
     if (nResult != OK) {
@@ -70,7 +70,7 @@
 
 static jint android_media_AmrInputStream_GsmAmrEncoderEncode
         (JNIEnv *env, jclass clazz,
-         jint gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
+         jlong gae, jbyteArray pcm, jint pcmOffset, jbyteArray amr, jint amrOffset) {
 
     jbyte inBuf[BYTES_PER_FRAME];
     jbyte outBuf[MAX_OUTPUT_BUFFER_SIZE];
@@ -86,7 +86,7 @@
     if (length < 0) {
         jniThrowExceptionFmt(env, "java/io/IOException",
                 "Failed to encode a frame with error code: %d", length);
-        return -1;
+        return (jint)-1;
     }
 
     // The 1st byte of PV AMR frames are WMF (Wireless Multimedia Forum)
@@ -101,30 +101,30 @@
 
     env->SetByteArrayRegion(amr, amrOffset, length, outBuf);
 
-    return length;
+    return (jint)length;
 }
 
 static void android_media_AmrInputStream_GsmAmrEncoderCleanup
-        (JNIEnv *env, jclass clazz, jint gae) {
-    GsmAmrEncoderState *state = (GsmAmrEncoderState *)gae;
+        (JNIEnv *env, jclass clazz, jlong gae) {
+    GsmAmrEncoderState *state = (GsmAmrEncoderState *) gae;
     AMREncodeExit(&state->mEncState, &state->mSidState);
     state->mEncState = NULL;
     state->mSidState = NULL;
 }
 
 static void android_media_AmrInputStream_GsmAmrEncoderDelete
-        (JNIEnv *env, jclass clazz, jint gae) {
+        (JNIEnv *env, jclass clazz, jlong gae) {
     delete (GsmAmrEncoderState*)gae;
 }
 
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"GsmAmrEncoderNew",        "()I",        (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
-    {"GsmAmrEncoderInitialize", "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
-    {"GsmAmrEncoderEncode",     "(I[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
-    {"GsmAmrEncoderCleanup",    "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderCleanup},
-    {"GsmAmrEncoderDelete",     "(I)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderDelete},
+    {"GsmAmrEncoderNew",        "()J",        (void*)android_media_AmrInputStream_GsmAmrEncoderNew},
+    {"GsmAmrEncoderInitialize", "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderInitialize},
+    {"GsmAmrEncoderEncode",     "(J[BI[BI)I", (void*)android_media_AmrInputStream_GsmAmrEncoderEncode},
+    {"GsmAmrEncoderCleanup",    "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderCleanup},
+    {"GsmAmrEncoderDelete",     "(J)V",       (void*)android_media_AmrInputStream_GsmAmrEncoderDelete},
 };
 
 
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 9888591..ac863e1 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -344,6 +344,26 @@
     return result;
 }
 
+static jobject
+android_media_MediaRecorder_getSurface(JNIEnv *env, jobject thiz)
+{
+    ALOGV("getSurface");
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+
+    sp<IGraphicBufferProducer> bufferProducer = mr->querySurfaceMediaSourceFromMediaServer();
+    if (bufferProducer == NULL) {
+        jniThrowException(
+                env,
+                "java/lang/IllegalStateException",
+                "failed to get surface");
+        return NULL;
+    }
+
+    // Wrap the IGBP in a Java-language Surface.
+    return android_view_Surface_createFromIGraphicBufferProducer(env,
+            bufferProducer);
+}
+
 static void
 android_media_MediaRecorder_start(JNIEnv *env, jobject thiz)
 {
@@ -470,6 +490,7 @@
     {"setMaxDuration",       "(I)V",                            (void *)android_media_MediaRecorder_setMaxDuration},
     {"setMaxFileSize",       "(J)V",                            (void *)android_media_MediaRecorder_setMaxFileSize},
     {"_prepare",             "()V",                             (void *)android_media_MediaRecorder_prepare},
+    {"getSurface",           "()Landroid/view/Surface;",        (void *)android_media_MediaRecorder_getSurface},
     {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
     {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
     {"stop",                 "()V",                             (void *)android_media_MediaRecorder_stop},
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 77c7966..72ce3cc 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -77,7 +77,7 @@
 
 
 MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
-    return (MtpDatabase *)env->GetIntField(database, field_context);
+    return (MtpDatabase *)env->GetLongField(database, field_context);
 }
 
 // ----------------------------------------------------------------------------
@@ -1075,17 +1075,17 @@
 android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
 {
     MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
-    env->SetIntField(thiz, field_context, (int)database);
+    env->SetLongField(thiz, field_context, (jlong)database);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
 
 static void
 android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
 {
-    MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
+    MyMtpDatabase* database = (MyMtpDatabase *)env->GetLongField(thiz, field_context);
     database->cleanup(env);
     delete database;
-    env->SetIntField(thiz, field_context, 0);
+    env->SetLongField(thiz, field_context, 0);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
 
@@ -1217,7 +1217,7 @@
         return -1;
     }
 
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
+    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
     if (field_context == NULL) {
         ALOGE("Can't find MtpDatabase.mNativeContext");
         return -1;
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index b61b66c..8e013a0 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -88,7 +88,7 @@
 
 MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
 {
-    return (MtpDevice*)env->GetIntField(javaDevice, field_context);
+    return (MtpDevice*)env->GetLongField(javaDevice, field_context);
 }
 
 static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
@@ -106,15 +106,15 @@
 {
     const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
     if (deviceNameStr == NULL) {
-        return false;
+        return JNI_FALSE;
     }
 
     MtpDevice* device = MtpDevice::open(deviceNameStr, fd);
     env->ReleaseStringUTFChars(deviceName, deviceNameStr);
 
     if (device)
-        env->SetIntField(thiz, field_context, (int)device);
-    return (device != NULL);
+        env->SetLongField(thiz, field_context,  (jlong)device);
+    return (jboolean)(device != NULL);
 }
 
 static void
@@ -124,7 +124,7 @@
     if (device) {
         device->close();
         delete device;
-        env->SetIntField(thiz, field_context, 0);
+        env->SetLongField(thiz, field_context, 0);
     }
 }
 
@@ -356,10 +356,11 @@
 android_mtp_MtpDevice_delete_object(JNIEnv *env, jobject thiz, jint object_id)
 {
     MtpDevice* device = get_device_from_object(env, thiz);
-    if (device)
-        return device->deleteObject(object_id);
-    else
-        return NULL;
+    if (device && device->deleteObject(object_id)) {
+        return JNI_TRUE;
+    } else {
+        return JNI_FALSE;
+    }
 }
 
 static jlong
@@ -367,7 +368,7 @@
 {
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
-        return device->getParent(object_id);
+        return (jlong)device->getParent(object_id);
     else
         return -1;
 }
@@ -377,7 +378,7 @@
 {
     MtpDevice* device = get_device_from_object(env, thiz);
     if (device)
-        return device->getStorageID(object_id);
+        return (jlong)device->getStorageID(object_id);
     else
         return -1;
 }
@@ -389,15 +390,15 @@
     if (device) {
         const char *destPathStr = env->GetStringUTFChars(dest_path, NULL);
         if (destPathStr == NULL) {
-            return false;
+            return JNI_FALSE;
         }
 
-        bool result = device->readObject(object_id, destPathStr, AID_SDCARD_RW, 0664);
+        jboolean result = device->readObject(object_id, destPathStr, AID_SDCARD_RW, 0664);
         env->ReleaseStringUTFChars(dest_path, destPathStr);
         return result;
     }
 
-    return false;
+    return JNI_FALSE;
 }
 
 // ----------------------------------------------------------------------------
@@ -618,7 +619,7 @@
         ALOGE("Can't find android/mtp/MtpDevice");
         return -1;
     }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
+    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
     if (field_context == NULL) {
         ALOGE("Can't find MtpDevice.mNativeContext");
         return -1;
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 5252a3a..9d7f1c2 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -53,7 +53,7 @@
 extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
 
 static inline MtpServer* getMtpServer(JNIEnv *env, jobject thiz) {
-    return (MtpServer*)env->GetIntField(thiz, field_MtpServer_nativeContext);
+    return (MtpServer*)env->GetLongField(thiz, field_MtpServer_nativeContext);
 }
 
 static void
@@ -63,7 +63,7 @@
     if (fd >= 0) {
         MtpServer* server = new MtpServer(fd, getMtpDatabase(env, javaDatabase),
                 usePtp, AID_MEDIA_RW, 0664, 0775);
-        env->SetIntField(thiz, field_MtpServer_nativeContext, (int)server);
+        env->SetLongField(thiz, field_MtpServer_nativeContext, (jlong)server);
     } else {
         ALOGE("could not open MTP driver, errno: %d", errno);
     }
@@ -87,7 +87,7 @@
     MtpServer* server = getMtpServer(env, thiz);
     if (server) {
         delete server;
-        env->SetIntField(thiz, field_MtpServer_nativeContext, 0);
+        env->SetLongField(thiz, field_MtpServer_nativeContext, 0);
     } else {
         ALOGE("server is null in cleanup");
     }
@@ -226,7 +226,7 @@
         ALOGE("Can't find android/mtp/MtpServer");
         return -1;
     }
-    field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
+    field_MtpServer_nativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
     if (field_MtpServer_nativeContext == NULL) {
         ALOGE("Can't find MtpServer.mNativeContext");
         return -1;
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index bcab4f3..be37aa8 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -214,7 +214,7 @@
     //      nativeTrackInJavaObj
     fields.fidNativeAudioEffect = env->GetFieldID(
             fields.clazzEffect,
-            "mNativeAudioEffect", "I");
+            "mNativeAudioEffect", "J");
     if (fields.fidNativeAudioEffect == NULL) {
         ALOGE("Can't find AudioEffect.%s", "mNativeAudioEffect");
         return;
@@ -222,7 +222,7 @@
     //      fidJniData;
     fields.fidJniData = env->GetFieldID(
             fields.clazzEffect,
-            "mJniData", "I");
+            "mJniData", "J");
     if (fields.fidJniData == NULL) {
         ALOGE("Can't find AudioEffect.%s", "mJniData");
         return;
@@ -388,11 +388,11 @@
 
     env->SetObjectArrayElement(javadesc, 0, jdesc);
 
-    env->SetIntField(thiz, fields.fidNativeAudioEffect, (int)lpAudioEffect);
+    env->SetLongField(thiz, fields.fidNativeAudioEffect, (jlong)lpAudioEffect);
 
-    env->SetIntField(thiz, fields.fidJniData, (int)lpJniStorage);
+    env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
 
-    return AUDIOEFFECT_SUCCESS;
+    return (jint) AUDIOEFFECT_SUCCESS;
 
     // failures:
 setup_failure:
@@ -404,12 +404,12 @@
     if (lpAudioEffect) {
         delete lpAudioEffect;
     }
-    env->SetIntField(thiz, fields.fidNativeAudioEffect, 0);
+    env->SetLongField(thiz, fields.fidNativeAudioEffect, 0);
 
     if (lpJniStorage) {
         delete lpJniStorage;
     }
-    env->SetIntField(thiz, fields.fidJniData, 0);
+    env->SetLongField(thiz, fields.fidJniData, 0);
 
     if (uuidStr != NULL) {
         env->ReleaseStringUTFChars(uuid, uuidStr);
@@ -419,27 +419,27 @@
         env->ReleaseStringUTFChars(type, typeStr);
     }
 
-    return lStatus;
+    return (jint)lStatus;
 }
 
 
 // ----------------------------------------------------------------------------
 static void android_media_AudioEffect_native_finalize(JNIEnv *env,  jobject thiz) {
-    ALOGV("android_media_AudioEffect_native_finalize jobject: %x\n", (int)thiz);
+    ALOGV("android_media_AudioEffect_native_finalize jobject: %p\n", thiz);
 
     // delete the AudioEffect object
-    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
+    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
         thiz, fields.fidNativeAudioEffect);
     if (lpAudioEffect) {
-        ALOGV("deleting AudioEffect: %x\n", (int)lpAudioEffect);
+        ALOGV("deleting AudioEffect: %p\n", lpAudioEffect);
         delete lpAudioEffect;
     }
 
     // delete the JNI data
-    AudioEffectJniStorage* lpJniStorage = (AudioEffectJniStorage *)env->GetIntField(
+    AudioEffectJniStorage* lpJniStorage = (AudioEffectJniStorage *)env->GetLongField(
         thiz, fields.fidJniData);
     if (lpJniStorage) {
-        ALOGV("deleting pJniStorage: %x\n", (int)lpJniStorage);
+        ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
         delete lpJniStorage;
     }
 }
@@ -451,15 +451,15 @@
     android_media_AudioEffect_native_finalize(env, thiz);
     // + reset the native resources in the Java object so any attempt to access
     // them after a call to release fails.
-    env->SetIntField(thiz, fields.fidNativeAudioEffect, 0);
-    env->SetIntField(thiz, fields.fidJniData, 0);
+    env->SetLongField(thiz, fields.fidNativeAudioEffect, 0);
+    env->SetLongField(thiz, fields.fidJniData, 0);
 }
 
 static jint
 android_media_AudioEffect_native_setEnabled(JNIEnv *env, jobject thiz, jboolean enabled)
 {
     // retrieve the AudioEffect object
-    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
+    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
         thiz, fields.fidNativeAudioEffect);
 
     if (lpAudioEffect == NULL) {
@@ -468,23 +468,27 @@
         return AUDIOEFFECT_ERROR_NO_INIT;
     }
 
-    return translateError(lpAudioEffect->setEnabled(enabled));
+    return (jint) translateError(lpAudioEffect->setEnabled(enabled));
 }
 
 static jboolean
 android_media_AudioEffect_native_getEnabled(JNIEnv *env, jobject thiz)
 {
     // retrieve the AudioEffect object
-    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
+    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
         thiz, fields.fidNativeAudioEffect);
 
     if (lpAudioEffect == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve AudioEffect pointer for getEnabled()");
-        return false;
+        return JNI_FALSE;
     }
 
-    return (jboolean)lpAudioEffect->getEnabled();
+    if (lpAudioEffect->getEnabled()) {
+        return JNI_TRUE;
+    } else {
+        return JNI_FALSE;
+    }
 }
 
 
@@ -492,24 +496,24 @@
 android_media_AudioEffect_native_hasControl(JNIEnv *env, jobject thiz)
 {
     // retrieve the AudioEffect object
-    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetIntField(
+    AudioEffect* lpAudioEffect = (AudioEffect *)env->GetLongField(
         thiz, fields.fidNativeAudioEffect);
 
     if (lpAudioEffect == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException",
             "Unable to retrieve AudioEffect pointer for hasControl()");
-        return false;
+        return JNI_FALSE;
     }
 
     if (lpAudioEffect->initCheck() == NO_ERROR) {
-        return true;
+        return JNI_TRUE;
     } else {
-        return false;
+        return JNI_FALSE;
     }
 }
 
 static jint android_media_AudioEffect_native_setParameter(JNIEnv *env,
-        jobject thiz, int psize, jbyteArray pJavaParam, int vsize,
+        jobject thiz, jint psize, jbyteArray pJavaParam, jint vsize,
         jbyteArray pJavaValue) {
     // retrieve the AudioEffect object
     jbyte* lpValue = NULL;
@@ -518,7 +522,7 @@
     effect_param_t *p;
     int voffset;
 
-    AudioEffect* lpAudioEffect = (AudioEffect *) env->GetIntField(thiz,
+    AudioEffect* lpAudioEffect = (AudioEffect *) env->GetLongField(thiz,
             fields.fidNativeAudioEffect);
 
     if (lpAudioEffect == NULL) {
@@ -567,7 +571,7 @@
     if (lpValue != NULL) {
         env->ReleasePrimitiveArrayCritical(pJavaValue, lpValue, 0);
     }
-    return translateError(lStatus);
+    return (jint) translateError(lStatus);
 }
 
 static jint
@@ -581,7 +585,7 @@
     effect_param_t *p;
     int voffset;
 
-    AudioEffect* lpAudioEffect = (AudioEffect *) env->GetIntField(thiz,
+    AudioEffect* lpAudioEffect = (AudioEffect *) env->GetLongField(thiz,
             fields.fidNativeAudioEffect);
 
     if (lpAudioEffect == NULL) {
@@ -637,7 +641,7 @@
     if (lStatus == NO_ERROR) {
         return vsize;
     }
-    return translateError(lStatus);
+    return (jint) translateError(lStatus);
 }
 
 static jint android_media_AudioEffect_native_command(JNIEnv *env, jobject thiz,
@@ -648,7 +652,7 @@
     jint lStatus = AUDIOEFFECT_ERROR_BAD_VALUE;
 
     // retrieve the AudioEffect object
-    AudioEffect* lpAudioEffect = (AudioEffect *) env->GetIntField(thiz,
+    AudioEffect* lpAudioEffect = (AudioEffect *) env->GetLongField(thiz,
             fields.fidNativeAudioEffect);
 
     if (lpAudioEffect == NULL) {
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 40cd06b..8463d94 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -231,7 +231,7 @@
 
 static Visualizer *getVisualizer(JNIEnv* env, jobject thiz)
 {
-    Visualizer *v = (Visualizer *)env->GetIntField(
+    Visualizer *v = (Visualizer *)env->GetLongField(
         thiz, fields.fidNativeVisualizer);
     if (v == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException",
@@ -282,7 +282,7 @@
     //      nativeTrackInJavaObj
     fields.fidNativeVisualizer = env->GetFieldID(
             fields.clazzEffect,
-            "mNativeVisualizer", "I");
+            "mNativeVisualizer", "J");
     if (fields.fidNativeVisualizer == NULL) {
         ALOGE("Can't find Visualizer.%s", "mNativeVisualizer");
         return;
@@ -290,7 +290,7 @@
     //      fidJniData;
     fields.fidJniData = env->GetFieldID(
             fields.clazzEffect,
-            "mJniData", "I");
+            "mJniData", "J");
     if (fields.fidJniData == NULL) {
         ALOGE("Can't find Visualizer.%s", "mJniData");
         return;
@@ -391,9 +391,9 @@
     env->ReleasePrimitiveArrayCritical(jId, nId, 0);
     nId = NULL;
 
-    env->SetIntField(thiz, fields.fidNativeVisualizer, (int)lpVisualizer);
+    env->SetLongField(thiz, fields.fidNativeVisualizer, (jlong)lpVisualizer);
 
-    env->SetIntField(thiz, fields.fidJniData, (int)lpJniStorage);
+    env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
 
     return VISUALIZER_SUCCESS;
 
@@ -407,33 +407,33 @@
     if (lpVisualizer) {
         delete lpVisualizer;
     }
-    env->SetIntField(thiz, fields.fidNativeVisualizer, 0);
+    env->SetLongField(thiz, fields.fidNativeVisualizer, 0);
 
     if (lpJniStorage) {
         delete lpJniStorage;
     }
-    env->SetIntField(thiz, fields.fidJniData, 0);
+    env->SetLongField(thiz, fields.fidJniData, 0);
 
-    return lStatus;
+    return (jint) lStatus;
 }
 
 // ----------------------------------------------------------------------------
 static void android_media_visualizer_native_finalize(JNIEnv *env,  jobject thiz) {
-    ALOGV("android_media_visualizer_native_finalize jobject: %x\n", (int)thiz);
+    ALOGV("android_media_visualizer_native_finalize jobject: %p\n", thiz);
 
     // delete the Visualizer object
-    Visualizer* lpVisualizer = (Visualizer *)env->GetIntField(
+    Visualizer* lpVisualizer = (Visualizer *)env->GetLongField(
         thiz, fields.fidNativeVisualizer);
     if (lpVisualizer) {
-        ALOGV("deleting Visualizer: %x\n", (int)lpVisualizer);
+        ALOGV("deleting Visualizer: %p\n", lpVisualizer);
         delete lpVisualizer;
     }
 
     // delete the JNI data
-    visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetIntField(
+    visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(
         thiz, fields.fidJniData);
     if (lpJniStorage) {
-        ALOGV("deleting pJniStorage: %x\n", (int)lpJniStorage);
+        ALOGV("deleting pJniStorage: %p\n", lpJniStorage);
         delete lpJniStorage;
     }
 }
@@ -445,8 +445,8 @@
     android_media_visualizer_native_finalize(env, thiz);
     // + reset the native resources in the Java object so any attempt to access
     // them after a call to release fails.
-    env->SetIntField(thiz, fields.fidNativeVisualizer, 0);
-    env->SetIntField(thiz, fields.fidJniData, 0);
+    env->SetLongField(thiz, fields.fidNativeVisualizer, 0);
+    env->SetLongField(thiz, fields.fidJniData, 0);
 }
 
 static jint
@@ -460,7 +460,7 @@
     jint retVal = translateError(lpVisualizer->setEnabled(enabled));
 
     if (!enabled) {
-        visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetIntField(
+        visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(
             thiz, fields.fidJniData);
 
         if (NULL != lpJniStorage)
@@ -475,10 +475,14 @@
 {
     Visualizer* lpVisualizer = getVisualizer(env, thiz);
     if (lpVisualizer == NULL) {
-        return false;
+        return JNI_FALSE;
     }
 
-    return (jboolean)lpVisualizer->getEnabled();
+    if (lpVisualizer->getEnabled()) {
+        return JNI_TRUE;
+    } else {
+        return JNI_FALSE;
+    }
 }
 
 static jintArray
@@ -496,7 +500,7 @@
 static jint
 android_media_visualizer_native_getMaxCaptureRate(JNIEnv *env, jobject thiz)
 {
-    return Visualizer::getMaxCaptureRate();
+    return (jint) Visualizer::getMaxCaptureRate();
 }
 
 static jint
@@ -517,7 +521,7 @@
     if (lpVisualizer == NULL) {
         return -1;
     }
-    return lpVisualizer->getCaptureSize();
+    return (jint) lpVisualizer->getCaptureSize();
 }
 
 static jint
@@ -538,7 +542,7 @@
     if (lpVisualizer == NULL) {
         return -1;
     }
-    return lpVisualizer->getScalingMode();
+    return (jint)lpVisualizer->getScalingMode();
 }
 
 static jint
@@ -568,7 +572,7 @@
     if (lpVisualizer == NULL) {
         return -1;
     }
-    return lpVisualizer->getSamplingRate();
+    return (jint) lpVisualizer->getSamplingRate();
 }
 
 static jint
@@ -634,7 +638,7 @@
     if (lpVisualizer == NULL) {
         return VISUALIZER_ERROR_NO_INIT;
     }
-    visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetIntField(thiz,
+    visualizerJniStorage* lpJniStorage = (visualizerJniStorage *)env->GetLongField(thiz,
             fields.fidJniData);
     if (lpJniStorage == NULL) {
         return VISUALIZER_ERROR_NO_INIT;
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index d8099dd..d29fad3 100644
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -609,7 +609,7 @@
 
 VIDEOEDIT_JAVA_DEFINE_FIELDS(Engine)
 {
-    VIDEOEDIT_JAVA_FIELD_INIT("mManualEditContext", "I")
+    VIDEOEDIT_JAVA_FIELD_INIT("mManualEditContext", "J")
 };
 
 VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME)
@@ -3096,7 +3096,7 @@
     if (*pResult)
     {
         // Retrieve the context pointer.
-        pContext = (void *)pEnv->GetIntField(object, fieldIds.context);
+        pContext = (void *)pEnv->GetLongField(object, fieldIds.context);
     }
 
     // Return the context pointer.
@@ -3132,15 +3132,15 @@
     {
         // Set the context field.
         VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                        "The context value from JAVA before setting is = 0x%x",
-                        pEnv->GetIntField(object, fieldIds.context));
+                        "The context value from JAVA before setting is = %p",
+                        (void *)pEnv->GetLongField(object, fieldIds.context));
 
-        pEnv->SetIntField(object, fieldIds.context, (int)pContext);
-        M4OSA_TRACE1_1("The context value in JNI is = 0x%x",pContext);
+        pEnv->SetLongField(object, fieldIds.context, (jlong)pContext);
+        M4OSA_TRACE1_1("The context value in JNI is = %p",pContext);
 
         VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                         "The context value from JAVA after setting is = 0x%x",
-                         pEnv->GetIntField(object, fieldIds.context));
+                         "The context value from JAVA after setting is = %p",
+                         (void *)pEnv->GetLongField(object, fieldIds.context));
     }
 }
 
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index c1ad516..058012b 100644
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -170,7 +170,7 @@
 static void videoEditor_release(
                 JNIEnv*                             pEnv,
                 jobject                             thiz);
-static int videoEditor_getPixels(
+static jint videoEditor_getPixels(
                                  JNIEnv*                  env,
                                  jobject                  thiz,
                                  jstring                  path,
@@ -178,7 +178,7 @@
                                  M4OSA_UInt32             width,
                                  M4OSA_UInt32             height,
                                  M4OSA_UInt32             timeMS);
-static int videoEditor_getPixelsList(
+static jint videoEditor_getPixelsList(
                                      JNIEnv*                  env,
                                      jobject                  thiz,
                                      jstring                  path,
@@ -209,7 +209,7 @@
                 jobject                 object,
                 jobject                 audioSettingObject);
 
-static int videoEditor_stopPreview(JNIEnv*  pEnv,
+static jint videoEditor_stopPreview(JNIEnv*  pEnv,
                               jobject  thiz);
 
 static jobject
@@ -218,7 +218,7 @@
                 jobject                             thiz,
                 jstring                             file);
 
-static int videoEditor_renderPreviewFrame(JNIEnv* pEnv,
+static jint videoEditor_renderPreviewFrame(JNIEnv* pEnv,
                                     jobject thiz,
                                     jobject    mSurface,
                                     jlong fromMs,
@@ -231,7 +231,7 @@
 static void jniPreviewProgressCallback(void* cookie, M4OSA_UInt32 msgType,
                                         void *argc);
 
-static int videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
+static jint videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
                                                     jobject thiz,
                                                     jobject mSurface,
                                                     jstring filePath,
@@ -241,7 +241,7 @@
                                                     jint surfaceHeight,
                                                     jlong fromMs);
 
-static int videoEditor_generateAudioWaveFormSync ( JNIEnv*     pEnv,
+static jint videoEditor_generateAudioWaveFormSync ( JNIEnv*     pEnv,
                                                   jobject     thiz,
                                                   jstring     pcmfilePath,
                                                   jstring     outGraphfilePath,
@@ -258,7 +258,7 @@
                                     M4OSA_Char* infilePath,
                                     M4OSA_Char* pcmfilePath );
 
-static int
+static jint
 videoEditor_generateClip(
                 JNIEnv*                             pEnv,
                 jobject                             thiz,
@@ -572,7 +572,7 @@
 
     return result;
 }
-static int videoEditor_stopPreview(JNIEnv*  pEnv,
+static jint videoEditor_stopPreview(JNIEnv*  pEnv,
                               jobject  thiz)
 {
     ManualEditContext* pContext = M4OSA_NULL;
@@ -594,7 +594,7 @@
         pContext->mOverlayFileName = NULL;
     }
 
-    return lastProgressTimeMs;
+    return (jint)lastProgressTimeMs;
 }
 
 static void videoEditor_clearSurface(JNIEnv* pEnv,
@@ -654,7 +654,7 @@
 
   }
 
-static int videoEditor_renderPreviewFrame(JNIEnv* pEnv,
+static jint videoEditor_renderPreviewFrame(JNIEnv* pEnv,
                                     jobject thiz,
                                     jobject    mSurface,
                                     jlong fromMs,
@@ -976,10 +976,10 @@
         free(yuvPlane);
     }
 
-    return tnTimeMs;
+    return (jint)tnTimeMs;
 }
 
-static int videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
+static jint videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
                                                     jobject thiz,
                                                     jobject mSurface,
                                                     jstring filePath,
@@ -1033,7 +1033,7 @@
     /* get thumbnail*/
     result = ThumbnailOpen(&tnContext,(const M4OSA_Char*)pString, M4OSA_TRUE);
     if (result != M4NO_ERROR || tnContext  == M4OSA_NULL) {
-        return timeMs;
+        return (jint)timeMs;
     }
 
     framesizeYuv = ((frameWidth)*(frameHeight)*1.5);
@@ -1046,7 +1046,7 @@
         ThumbnailClose(tnContext);
         pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
         jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-        return timeMs;
+        return (jint)timeMs;
     }
 
     result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray,
@@ -1055,7 +1055,7 @@
     if (result != M4NO_ERROR) {
         free(pixelArray);
         ThumbnailClose(tnContext);
-        return fromMs;
+        return (jint)fromMs;
     }
 
 #ifdef DUMPTOFILESYSTEM
@@ -1131,10 +1131,10 @@
         pEnv->ReleaseStringUTFChars(filePath, pString);
     }
 
-    return timeMs;
+    return (jint)timeMs;
 }
 
-int videoEditor_generateAudioRawFile(   JNIEnv*     pEnv,
+jint videoEditor_generateAudioRawFile(  JNIEnv*     pEnv,
                                         jobject     thiz,
                                         jstring     infilePath,
                                         jstring     pcmfilePath)
@@ -1178,7 +1178,7 @@
         pEnv->ReleaseStringUTFChars(pcmfilePath, pStringOutPCMFilePath);
     }
 
-    return result;
+    return (jint)result;
 }
 
 M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext,
@@ -2182,7 +2182,7 @@
     return object;
 
 }
-static int videoEditor_getPixels(
+static jint videoEditor_getPixels(
                     JNIEnv*                     env,
                     jobject                     thiz,
                     jstring                     path,
@@ -2234,10 +2234,10 @@
         env->ReleaseStringUTFChars(path, pString);
     }
 
-    return timeMS;
+    return (jint)timeMS;
 }
 
-static int videoEditor_getPixelsList(
+static jint videoEditor_getPixelsList(
                 JNIEnv*                 env,
                 jobject                 thiz,
                 jstring                 path,
@@ -2257,7 +2257,7 @@
     const char *pString = env->GetStringUTFChars(path, NULL);
     if (pString == M4OSA_NULL) {
         jniThrowException(env, "java/lang/RuntimeException", "Input string null");
-        return M4ERR_ALLOC;
+        return (jint)M4ERR_ALLOC;
     }
 
     err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE);
@@ -2266,7 +2266,7 @@
         if (pString != NULL) {
             env->ReleaseStringUTFChars(path, pString);
         }
-        return err;
+        return (jint)err;
     }
 
     jlong duration = (endTime - startTime);
@@ -2307,7 +2307,7 @@
                 "ThumbnailGetPixels32 failed");
     }
 
-    return err;
+    return (jint)err;
 }
 
 static M4OSA_ERR
@@ -2892,7 +2892,7 @@
 }
 /*+ PROGRESS CB */
 
-static int
+static jint
 videoEditor_generateClip(
                 JNIEnv*                             pEnv,
                 jobject                             thiz,
@@ -2934,7 +2934,7 @@
     }
 
     ALOGV("videoEditor_generateClip END 0x%x", (unsigned int) result);
-    return result;
+    return (jint)result;
 }
 
 static void
@@ -3556,7 +3556,7 @@
     return err;
 }
 
-static int videoEditor_generateAudioWaveFormSync (JNIEnv*  pEnv, jobject thiz,
+static jint videoEditor_generateAudioWaveFormSync (JNIEnv*  pEnv, jobject thiz,
                                                   jstring pcmfilePath,
                                                   jstring outGraphfilePath,
                                                   jint frameDuration, jint channels,
@@ -3619,7 +3619,7 @@
     VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
         "videoEditor_generateAudioWaveFormSync pContext->bSkipState ");
 
-    return result;
+    return (jint)result;
 }
 
 /******** End Audio Graph *******/
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index e560d6e..e3d8d05 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -2206,12 +2206,16 @@
                         // Select the old color mode - nothing really changed.
                         setColorModeSpinnerSelectionNoCallback(oldColorModeNewIndex);
                     } else {
-                        final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
-                                    (colorModes & defaultAttributes.getColorMode()));
-                        setColorModeSpinnerSelectionNoCallback(selectedColorModeIndex);
-                        mCurrPrintAttributes.setColorMode(mColorModeSpinnerAdapter
-                                .getItem(selectedColorModeIndex).value);
-                        someAttributeSelectionChanged = true;
+                        final int selectedColorMode = colorModes & defaultAttributes.getColorMode();
+                        final int itemCount = mColorModeSpinnerAdapter.getCount();
+                        for (int i = 0; i < itemCount; i++) {
+                            SpinnerItem<Integer> item = mColorModeSpinnerAdapter.getItem(i);
+                            if (selectedColorMode == item.value) {
+                                setColorModeSpinnerSelectionNoCallback(i);
+                                mCurrPrintAttributes.setColorMode(selectedColorMode);
+                                someAttributeSelectionChanged = true;
+                            }
+                        }
                     }
                 }
                 mColorModeSpinner.setEnabled(true);
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 41f617e..c613e24 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -29,7 +29,7 @@
     <item quantity="one" msgid="5854176083865845541">"1 seneste app"</item>
     <item quantity="other" msgid="1040784359794890744">"%d seneste apps"</item>
   </plurals>
-    <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
+    <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen underretninger"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string>
     <string name="battery_low_title" msgid="2783104807551211639">"Tilslut oplader"</string>
@@ -166,7 +166,7 @@
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Søger efter GPS"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive placeringsanmodninger"</string>
-    <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
+    <string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle underretninger."</string>
     <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Oplysninger om appen"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Skærmen er nu låst i liggende retning."</string>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index 48a02ab..b77f1e0 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -29,9 +29,6 @@
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
 
-    <!-- Whether rotation lock shows up in quick settings or not -->
-    <bool name="quick_settings_show_rotation_lock">true</bool>
-
     <!-- Enable the "flip settings" panel -->
     <bool name="config_hasFlipSettingsPanel">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 3869db3..1dd9300 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -50,7 +50,7 @@
     <!-- When true, show 1/2G networks as 3G. -->
     <bool name="config_showMin3G">false</bool>
 
-    <!-- Show rotation lock button in phone-style notification panel. -->
+    <!-- Show rotation lock toggle in System UI-->
     <bool name="config_showRotationLock">true</bool>
 
     <!-- Amount of time to hold off before showing the search panel when the user presses home -->
@@ -84,9 +84,6 @@
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
 
-    <!-- Whether rotation lock shows up in quick settings or not -->
-    <bool name="quick_settings_show_rotation_lock">false</bool>
-
     <!-- Whether or not the RSSI tile is capitalized or not. -->
     <bool name="quick_settings_rssi_tile_capitalization">true</bool>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5afd55b..94796af 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -464,6 +464,10 @@
     <string name="quick_settings_rotation_unlocked_label">Auto Rotate</string>
     <!-- QuickSettings: Rotation Locked [CHAR LIMIT=NONE] -->
     <string name="quick_settings_rotation_locked_label">Rotation Locked</string>
+    <!-- QuickSettings: Locked to Portrait [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_rotation_locked_portrait_label">Locked to Portrait</string>
+    <!-- QuickSettings: Locked to Landscape [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_rotation_locked_landscape_label">Locked to Landscape</string>
     <!-- QuickSettings: IME [CHAR LIMIT=NONE] -->
     <string name="quick_settings_ime_label">Input Method</string>
     <!-- QuickSettings: Location [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index bbac4ef..b181658 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -534,7 +534,10 @@
         mBatteryController = new BatteryController(mContext);
         mNetworkController = new NetworkController(mContext);
         mBluetoothController = new BluetoothController(mContext);
-        mRotationLockController = new RotationLockController(mContext);
+        if (mContext.getResources().getBoolean(R.bool.config_showRotationLock)
+                || QuickSettings.DEBUG_GONE_TILES) {
+            mRotationLockController = new RotationLockController(mContext);
+        }
         final SignalClusterView signalCluster =
                 (SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index e6fd7d0..4d7ff5e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -176,7 +176,9 @@
         bluetoothController.addStateChangedCallback(mModel);
         batteryController.addStateChangedCallback(mModel);
         locationController.addSettingsChangedCallback(mModel);
-        rotationLockController.addRotationLockControllerCallback(mModel);
+        if (rotationLockController != null) {
+            rotationLockController.addRotationLockControllerCallback(mModel);
+        }
     }
 
     private void queryForSslCaCerts() {
@@ -503,8 +505,7 @@
         }
 
         // Rotation Lock
-        if (mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)
-                || DEBUG_GONE_TILES) {
+        if (mRotationLockController != null) {
             final QuickSettingsBasicTile rotationLockTile
                     = new QuickSettingsBasicTile(mContext);
             rotationLockTile.setOnClickListener(new View.OnClickListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 12e08d0..11cba7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.drawable.Drawable;
@@ -409,6 +410,7 @@
     private State mSslCaCertWarningState = new State();
 
     private RotationLockController mRotationLockController;
+    private int mRotationLockedLabel;
 
     public QuickSettingsModel(Context context) {
         mContext = context;
@@ -919,6 +921,12 @@
         mRotationLockTile = view;
         mRotationLockCallback = cb;
         mRotationLockController = rotationLockController;
+        final int lockOrientation = mRotationLockController.getRotationLockOrientation();
+        mRotationLockedLabel = lockOrientation == Configuration.ORIENTATION_PORTRAIT
+                    ? R.string.quick_settings_rotation_locked_portrait_label
+                    : lockOrientation == Configuration.ORIENTATION_LANDSCAPE
+                    ? R.string.quick_settings_rotation_locked_landscape_label
+                    : R.string.quick_settings_rotation_locked_label;
         onRotationLockChanged();
     }
     void onRotationLockChanged() {
@@ -933,7 +941,7 @@
                 ? R.drawable.ic_qs_rotation_locked
                 : R.drawable.ic_qs_auto_rotate;
         mRotationLockState.label = rotationLocked
-                ? mContext.getString(R.string.quick_settings_rotation_locked_label)
+                ? mContext.getString(mRotationLockedLabel)
                 : mContext.getString(R.string.quick_settings_rotation_unlocked_label);
         mRotationLockCallback.refreshView(mRotationLockTile, mRotationLockState);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
index 6f61ec8..98d205a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockController.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.policy;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.os.UserHandle;
 
 import com.android.internal.view.RotationPolicy;
@@ -42,42 +43,32 @@
 
     public RotationLockController(Context context) {
         mContext = context;
-        notifyChanged();
-        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
-            RotationPolicy.registerRotationPolicyListener(mContext,
-                    mRotationPolicyListener, UserHandle.USER_ALL);
-        }
+        RotationPolicy.registerRotationPolicyListener(mContext,
+                mRotationPolicyListener, UserHandle.USER_ALL);
     }
 
     public void addRotationLockControllerCallback(RotationLockControllerCallback callback) {
         mCallbacks.add(callback);
     }
 
+    public int getRotationLockOrientation() {
+        return RotationPolicy.getRotationLockOrientation(mContext);
+    }
+
     public boolean isRotationLocked() {
-        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
-            return RotationPolicy.isRotationLocked(mContext);
-        }
-        return false;
+        return RotationPolicy.isRotationLocked(mContext);
     }
 
     public void setRotationLocked(boolean locked) {
-        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
-            RotationPolicy.setRotationLock(mContext, locked);
-        }
+        RotationPolicy.setRotationLock(mContext, locked);
     }
 
     public boolean isRotationLockAffordanceVisible() {
-        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
-            return RotationPolicy.isRotationLockToggleVisible(mContext);
-        }
-        return false;
+        return RotationPolicy.isRotationLockToggleVisible(mContext);
     }
 
     public void release() {
-        if (RotationPolicy.isRotationLockToggleSupported(mContext)) {
-            RotationPolicy.unregisterRotationPolicyListener(mContext,
-                    mRotationPolicyListener);
-        }
+        RotationPolicy.unregisterRotationPolicyListener(mContext, mRotationPolicyListener);
     }
 
     private void notifyChanged() {
diff --git a/services/core/java/com/android/server/am/CompatModePackages.java b/services/core/java/com/android/server/am/CompatModePackages.java
index 59e6787..4d5577b 100644
--- a/services/core/java/com/android/server/am/CompatModePackages.java
+++ b/services/core/java/com/android/server/am/CompatModePackages.java
@@ -64,9 +64,14 @@
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
             int eventType = parser.getEventType();
-            while (eventType != XmlPullParser.START_TAG) {
+            while (eventType != XmlPullParser.START_TAG &&
+                    eventType != XmlPullParser.END_DOCUMENT) {
                 eventType = parser.next();
             }
+            if (eventType == XmlPullParser.END_DOCUMENT) {
+                return;
+            }
+
             String tagName = parser.getName();
             if ("compat-packages".equals(tagName)) {
                 eventType = parser.next();
diff --git a/services/core/java/com/android/server/am/UsageStatsService.java b/services/core/java/com/android/server/am/UsageStatsService.java
index 2260c7f..587f949 100644
--- a/services/core/java/com/android/server/am/UsageStatsService.java
+++ b/services/core/java/com/android/server/am/UsageStatsService.java
@@ -394,9 +394,14 @@
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
             int eventType = parser.getEventType();
-            while (eventType != XmlPullParser.START_TAG) {
+            while (eventType != XmlPullParser.START_TAG &&
+                    eventType != XmlPullParser.END_DOCUMENT) {
                 eventType = parser.next();
             }
+            if (eventType == XmlPullParser.END_DOCUMENT) {
+                return;
+            }
+
             String tagName = parser.getName();
             if ("usage-history".equals(tagName)) {
                 String pkg = null;
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 10f0ea7..5df7fc6 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -1820,9 +1820,15 @@
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
             int eventType = parser.getEventType();
-            while (eventType != XmlPullParser.START_TAG) {
+            while (eventType != XmlPullParser.START_TAG &&
+                    eventType != XmlPullParser.END_DOCUMENT) {
                 eventType = parser.next();
             }
+            if (eventType == XmlPullParser.END_DOCUMENT) {
+                Log.i(TAG, "No initial accounts");
+                return;
+            }
+
             String tagName = parser.getName();
             if ("accounts".equals(tagName)) {
                 String listen = parser.getAttributeValue(null, XML_ATTR_LISTEN_FOR_TICKLES);
diff --git a/tests/SmokeTest/tests/AndroidManifest.xml b/tests/SmokeTest/tests/AndroidManifest.xml
index cad37c5..f1a0a4c 100644
--- a/tests/SmokeTest/tests/AndroidManifest.xml
+++ b/tests/SmokeTest/tests/AndroidManifest.xml
@@ -27,15 +27,6 @@
     </application>
 
     <!--
-    This declares that this app uses the instrumentation test runner targeting the package of
-    com.android.smoketest.  To run the tests use the command:
-    `adb shell am instrument -w com.android.smoketest.tests/android.test.InstrumentationTestRunner`
-    -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
-                     android:targetPackage="com.android.smoketest"
-                     android:label="System Smoke Tests"/>
-
-    <!--
     This declares a method to run the instrumentation with a special runner, which will run each
     app as a separate testcase.  To do so, use the command:
     `adb shell am instrument -w com.android.smoketest.tests/com.android.smoketest.SmokeTestRunner`
diff --git a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
index 03c2923..946299b 100644
--- a/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
+++ b/tests/SmokeTest/tests/src/com/android/smoketest/ProcessErrorsTest.java
@@ -154,6 +154,11 @@
 
         // launch app, and wait 7 seconds for it to start/settle
         final Intent intent = intentForActivity(app);
+        if (intent == null) {
+            Log.i(TAG, String.format("Activity %s/%s is disabled, skipping",
+                    app.activityInfo.packageName, app.activityInfo.name));
+            return Collections.EMPTY_LIST;
+        }
         getContext().startActivity(intent);
         try {
             Thread.sleep(appLaunchWait);
@@ -238,10 +243,16 @@
     /**
      * A helper function to create an {@link Intent} to run, given a {@link ResolveInfo} specifying
      * an activity to be launched.
+     * 
+     * @return the {@link Intent} or <code>null</code> if given app is disabled
      */
-    static Intent intentForActivity(ResolveInfo app) {
+    Intent intentForActivity(ResolveInfo app) {
         final ComponentName component = new ComponentName(app.activityInfo.packageName,
                 app.activityInfo.name);
+        if (getContext().getPackageManager().getComponentEnabledSetting(component) == 
+                PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+            return null;
+        }
         final Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.setComponent(component);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);