Move OpenGL support out of ViewRoot into a new HardwareRenderer class.

Change-Id: Iffaed924a5defc3c4df26223c390dc27eee115b1
diff --git a/api/current.xml b/api/current.xml
index 287b3f3..6557674 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -65146,7 +65146,7 @@
  type="android.graphics.Canvas"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="gl" type="javax.microedition.khronos.opengles.GL">
@@ -66075,7 +66075,7 @@
  synchronized="false"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -66132,7 +66132,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -66193,6 +66193,17 @@
  visibility="public"
 >
 </method>
+<method name="isHardwareAccelerated"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isOpaque"
  return="boolean"
  abstract="false"
@@ -66506,7 +66517,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="width" type="int">
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
new file mode 100644
index 0000000..d4e229c
--- /dev/null
+++ b/core/java/android/view/HardwareRenderer.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.view;
+
+import android.content.res.CompatibilityInfo;
+import android.graphics.Canvas;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+
+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.GL11;
+
+import static javax.microedition.khronos.opengles.GL10.GL_COLOR_BUFFER_BIT;
+import static javax.microedition.khronos.opengles.GL10.GL_SCISSOR_TEST;
+
+/**
+ * Interface for rendering a ViewRoot using hardware acceleration.
+ * 
+ * @hide
+ */
+abstract class HardwareRenderer {
+    private boolean mEnabled;
+    private boolean mRequested = true;
+
+    /**
+     * Destroys the hardware rendering context.
+     */
+    abstract void destroy();
+
+    /**
+     * Initializes the hardware renderer for the specified surface.
+     * 
+     * @param holder The holder for the surface to hardware accelerate.
+     * 
+     * @return True if the initialization was successful, false otherwise.
+     */
+    abstract boolean initialize(SurfaceHolder holder);
+
+    /**
+     * Setup the hardware renderer for drawing. This is called for every
+     * frame to draw.
+     * 
+     * @param width Width of the drawing surface.
+     * @param height Height of the drawing surface.
+     * @param attachInfo The AttachInfo used to render the ViewRoot. 
+     */
+    abstract void setup(int width, int height, View.AttachInfo attachInfo);
+
+    /**
+     * Draws the specified view.
+     * 
+     * @param view The view to draw.
+     * @param attachInfo AttachInfo tied to the specified view.
+     * @param translator Translator used to draw applications in compatibility mode.
+     * @param yoff The vertical offset for the drawing.
+     * @param scalingRequired Whether drawing should be scaled.
+     */
+    abstract void draw(View view, View.AttachInfo attachInfo,
+            CompatibilityInfo.Translator translator, int yoff, boolean scalingRequired);
+
+    /**
+     * Initializes the hardware renderer for the specified surface and setup the
+     * renderer for drawing, if needed. This is invoked when the ViewRoot has
+     * potentially lost the hardware renderer. The hardware renderer should be
+     * reinitialized and setup when the render {@link #isRequested()} and
+     * {@link #isEnabled()}.
+     * 
+     * @param width The width of the drawing surface.
+     * @param height The height of the drawing surface.
+     * @param attachInfo The 
+     * @param holder
+     */
+    void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
+            SurfaceHolder holder) {
+
+        if (isRequested()) {
+            // We lost the gl context, so recreate it.
+            if (!isEnabled()) {
+                if (initialize(holder)) {
+                    setup(width, height, attachInfo);
+                }
+            }
+        }        
+    }
+
+    /**
+     * Creates a hardware renderer using OpenGL.
+     * 
+     * @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.)
+     * 
+     * @return A hardware renderer backed by OpenGL.
+     */
+    static HardwareRenderer createGlRenderer(int glVersion) {
+        switch (glVersion) {
+            case 1:
+                return new Gl10Renderer();
+        }
+        throw new IllegalArgumentException("Unknown GL version: " + glVersion);
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently enabled.
+     * 
+     * @return True if hardware acceleration is in use, false otherwise.
+     */
+    boolean isEnabled() {
+        return mEnabled;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently enabled.
+     * 
+     * @param enabled True if the hardware renderer is in use, false otherwise.
+     */
+    void setEnabled(boolean enabled) {
+        mEnabled = enabled;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently request but not
+     * necessarily enabled yet.
+     * 
+     * @return True if requested, false otherwise.
+     */
+    boolean isRequested() {
+        return mRequested;
+    }
+
+    /**
+     * Indicates whether hardware acceleration is currently request but not
+     * necessarily enabled yet.
+     * 
+     * @return True to request hardware acceleration, false otherwise.
+     */
+    void setRequested(boolean requested) {
+        mRequested = requested;
+    }
+
+    /**
+     * Hardware renderer using OpenGL ES 1.0.
+     */
+    @SuppressWarnings({"deprecation"})
+    static class Gl10Renderer extends HardwareRenderer {
+        private EGL10 mEgl;
+        private EGLDisplay mEglDisplay;
+        private EGLContext mEglContext;
+        private EGLSurface mEglSurface;
+        private GL11 mGL;
+
+        private Canvas mGlCanvas;
+
+        private Gl10Renderer() {
+        }
+
+        private void initializeGL(SurfaceHolder holder) {
+            initializeGLInner(holder);
+            int err = mEgl.eglGetError();
+            if (err != EGL10.EGL_SUCCESS) {
+                destroy();
+                setRequested(false);
+            }
+        }
+
+        private void initializeGLInner(SurfaceHolder holder) {
+            final EGL10 egl = (EGL10) EGLContext.getEGL();
+            mEgl = egl;
+    
+            final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+            mEglDisplay = eglDisplay;
+    
+            int[] version = new int[2];
+            egl.eglInitialize(eglDisplay, version);
+    
+            final int[] configSpec = {
+                    EGL10.EGL_RED_SIZE,      8,
+                    EGL10.EGL_GREEN_SIZE,    8,
+                    EGL10.EGL_BLUE_SIZE,     8,
+                    EGL10.EGL_DEPTH_SIZE,    0,
+                    EGL10.EGL_NONE
+            };
+            final EGLConfig[] configs = new EGLConfig[1];
+            final int[] numConfig = new int[1];
+            egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig);
+            final EGLConfig config = configs[0];
+
+            /*
+             * Create an OpenGL ES context. This must be done only once, an
+             * OpenGL context is a somewhat heavy object.
+             */
+            final EGLContext context = egl.eglCreateContext(eglDisplay, config,
+                    EGL10.EGL_NO_CONTEXT, null);
+            mEglContext = context;
+    
+            /*
+             * Create an EGL surface we can render into.
+             */
+            EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, holder, null);
+            mEglSurface = surface;
+    
+            /*
+             * Before we can issue GL commands, we need to make sure
+             * the context is current and bound to a surface.
+             */
+            egl.eglMakeCurrent(eglDisplay, surface, surface, context);
+    
+            /*
+             * Get to the appropriate GL interface.
+             * This is simply done by casting the GL context to either
+             * GL10 or GL11.
+             */
+            final GL11 gl = (GL11) context.getGL();
+            mGL = gl;
+            mGlCanvas = new Canvas(gl);
+            setEnabled(true);
+        }
+
+        @Override
+        void destroy() {
+            if (!isEnabled()) return;
+            
+            // inform skia that the context is gone
+            nativeAbandonGlCaches();
+    
+            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
+                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+            mEgl.eglTerminate(mEglDisplay);
+
+            mEglContext = null;
+            mEglSurface = null;
+            mEglDisplay = null;
+            mEgl = null;
+            mGlCanvas = null;
+            mGL = null;
+
+            setEnabled(false);
+        }
+    
+        private void checkErrors() {
+            if (isEnabled()) {
+                int err = mEgl.eglGetError();
+                if (err != EGL10.EGL_SUCCESS) {
+                    // something bad has happened revert to
+                    // normal rendering.
+                    destroy();
+                    if (err != EGL11.EGL_CONTEXT_LOST) {
+                        // we'll try again if it was context lost
+                        setRequested(false);
+                    }
+                }
+            }
+        }
+
+        @Override
+        boolean initialize(SurfaceHolder holder) {
+            if (isRequested() && !isEnabled()) {
+                initializeGL(holder);
+                return mGlCanvas != null;
+            }
+            return false;
+        }
+
+        @Override
+        void setup(int width, int height, View.AttachInfo attachInfo) {
+            final float scale = attachInfo.mApplicationScale;
+            mGlCanvas.setViewport((int) (width * scale + 0.5f), (int) (height * scale + 0.5f));
+        }
+
+        @Override
+        void draw(View view, View.AttachInfo attachInfo, CompatibilityInfo.Translator translator,
+                int yoff, boolean scalingRequired) {
+
+            Canvas canvas = mGlCanvas;
+            if (mGL != null && canvas != null) {
+                mGL.glDisable(GL_SCISSOR_TEST);
+                mGL.glClearColor(0, 0, 0, 0);
+                mGL.glClear(GL_COLOR_BUFFER_BIT);
+                mGL.glEnable(GL_SCISSOR_TEST);
+    
+                attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+                attachInfo.mIgnoreDirtyState = true;
+                view.mPrivateFlags |= View.DRAWN;
+    
+                int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+                try {
+                    canvas.translate(0, -yoff);
+                    if (translator != null) {
+                        translator.translateCanvas(canvas);
+                    }
+                    canvas.setScreenDensity(scalingRequired ?
+                            DisplayMetrics.DENSITY_DEVICE : 0);
+    
+                    view.draw(canvas);
+    
+                } finally {
+                    canvas.restoreToCount(saveCount);
+                }
+    
+                attachInfo.mIgnoreDirtyState = false;
+    
+                mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
+                checkErrors();
+            }
+        }
+
+        @Override
+        void initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
+                SurfaceHolder holder) {
+
+            if (isRequested()) {
+                checkErrors();
+                super.initializeIfNeeded(width, height, attachInfo, holder);
+            }
+        }
+    }
+
+    // inform Skia to just abandon its texture cache IDs
+    // doesn't call glDeleteTextures
+    private static native void nativeAbandonGlCaches();    
+}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1fc0251..9ca9d24 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1566,7 +1566,7 @@
 
         boolean scalingRequired = false;
         Bitmap cache = null;
-        if (canvas.getGL() == null &&
+        if (!canvas.isHardwareAccelerated() &&
                 (flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                 (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
             cache = child.getDrawingCache(true);
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 15c6910..6a80b9f 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -56,10 +56,6 @@
 import java.io.OutputStream;
 import java.util.ArrayList;
 
-import javax.microedition.khronos.egl.*;
-import javax.microedition.khronos.opengles.*;
-import static javax.microedition.khronos.opengles.GL10.*;
-
 /**
  * The top of a view hierarchy, implementing the needed protocol between View
  * and the WindowManager.  This is for the most part an internal implementation
@@ -264,9 +260,8 @@
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
 
         // Try to enable hardware acceleration if requested
-        if ((context.getApplicationInfo().flags &
-                ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
-            mHwRenderer = new HardwareRenderer();
+        if ((context.getApplicationInfo().flags & ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
+            mHwRenderer = HardwareRenderer.createGlRenderer(1);
         }
     }
 
@@ -615,8 +610,6 @@
         boolean viewVisibilityChanged = mViewVisibility != viewVisibility
                 || mNewSurfaceNeeded;
 
-        float appScale = mAttachInfo.mApplicationScale;
-
         WindowManager.LayoutParams params = null;
         if (mWindowAttributesChanged) {
             mWindowAttributesChanged = false;
@@ -665,7 +658,7 @@
             host.dispatchWindowVisibilityChanged(viewVisibility);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
                 if (mHwRenderer != null) {
-                    mHwRenderer.destroyGL();
+                    mHwRenderer.destroy();
                 }
             }
             if (viewVisibility == View.GONE) {
@@ -873,7 +866,7 @@
                         mPreviousTransparentRegion.setEmpty();
 
                         if (mHwRenderer != null) {
-                            hwIntialized = mHwRenderer.initialize();
+                            hwIntialized = mHwRenderer.initialize(mHolder);
                         }
                     }
                 } else if (!mSurface.isValid()) {
@@ -952,7 +945,7 @@
             }
             
             if (hwIntialized) {
-                mHwRenderer.setup(appScale);
+                mHwRenderer.setup(mWidth, mHeight, mAttachInfo);
             }
 
             boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -1248,9 +1241,9 @@
             return;
         }
         
-        if (mHwRenderer != null && mHwRenderer.mEnabled) {
+        if (mHwRenderer != null && mHwRenderer.isEnabled()) {
             if (!dirty.isEmpty()) {
-                mHwRenderer.draw(yoff, scalingRequired);
+                mHwRenderer.draw(mView, mAttachInfo, mTranslator, yoff, scalingRequired);
             }
 
             if (scrolling) {
@@ -1578,7 +1571,7 @@
         mAttachInfo.mSurface = null;
 
         if (mHwRenderer != null) {
-            mHwRenderer.destroyGL();
+            mHwRenderer.destroy();
         }
         mSurface.release();
 
@@ -1842,7 +1835,7 @@
                     ensureTouchModeLocally(inTouchMode);
 
                     if (mHwRenderer != null) {
-                        mHwRenderer.initializeAndSetup();
+                        mHwRenderer.initializeIfNeeded(mWidth, mHeight, mAttachInfo, mHolder);
                     }
                 }
 
@@ -3313,183 +3306,5 @@
         }
     }
 
-    class HardwareRenderer {
-        private EGL10 mEgl;
-        private EGLDisplay mEglDisplay;
-        private EGLContext mEglContext;
-        private EGLSurface mEglSurface;
-        private GL11 mGL;
-
-        private Canvas mGlCanvas;
-
-        boolean mEnabled;
-        boolean mRequested = true;
-
-        private void initializeGL() {
-            initializeGLInner();
-            int err = mEgl.eglGetError();
-            if (err != EGL10.EGL_SUCCESS) {
-                destroyGL();
-                mRequested = false;
-            }
-        }
-
-        private void initializeGLInner() {
-            final EGL10 egl = (EGL10) EGLContext.getEGL();
-            mEgl = egl;
-    
-            final EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-            mEglDisplay = eglDisplay;
-    
-            int[] version = new int[2];
-            egl.eglInitialize(eglDisplay, version);
-    
-            final int[] configSpec = {
-                    EGL10.EGL_RED_SIZE,      8,
-                    EGL10.EGL_GREEN_SIZE,    8,
-                    EGL10.EGL_BLUE_SIZE,     8,
-                    EGL10.EGL_DEPTH_SIZE,    0,
-                    EGL10.EGL_NONE
-            };
-            final EGLConfig[] configs = new EGLConfig[1];
-            final int[] numConfig = new int[1];
-            egl.eglChooseConfig(eglDisplay, configSpec, configs, 1, numConfig);
-            final EGLConfig config = configs[0];
-
-            /*
-             * Create an OpenGL ES context. This must be done only once, an
-             * OpenGL context is a somewhat heavy object.
-             */
-            final EGLContext context = egl.eglCreateContext(eglDisplay, config,
-                    EGL10.EGL_NO_CONTEXT, null);
-            mEglContext = context;
-    
-            /*
-             * Create an EGL surface we can render into.
-             */
-            EGLSurface surface = egl.eglCreateWindowSurface(eglDisplay, config, mHolder, null);
-            mEglSurface = surface;
-    
-            /*
-             * Before we can issue GL commands, we need to make sure
-             * the context is current and bound to a surface.
-             */
-            egl.eglMakeCurrent(eglDisplay, surface, surface, context);
-    
-            /*
-             * Get to the appropriate GL interface.
-             * This is simply done by casting the GL context to either
-             * GL10 or GL11.
-             */
-            final GL11 gl = (GL11) context.getGL();
-            mGL = gl;
-            mGlCanvas = new Canvas(gl);
-            mEnabled = true;
-        }
-
-        void destroyGL() {
-            if (!mEnabled) return;
-            
-            // inform skia that the context is gone
-            nativeAbandonGlCaches();
-    
-            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
-                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-            mEgl.eglTerminate(mEglDisplay);
-
-            mEglContext = null;
-            mEglSurface = null;
-            mEglDisplay = null;
-            mEgl = null;
-            mGlCanvas = null;
-            mGL = null;
-
-            mEnabled = false;
-        }
-    
-        private void checkErrors() {
-            if (mEnabled) {
-                int err = mEgl.eglGetError();
-                if (err != EGL10.EGL_SUCCESS) {
-                    // something bad has happened revert to
-                    // normal rendering.
-                    destroyGL();
-                    if (err != EGL11.EGL_CONTEXT_LOST) {
-                        // we'll try again if it was context lost
-                        mRequested = false;
-                    }
-                }
-            }
-        }
-
-        boolean initialize() {
-            if (mRequested && !mEnabled) {
-                initializeGL();
-                return mGlCanvas != null;
-            }
-            return false;
-        }
-
-        void setup(float appScale) {
-            mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f),
-                    (int) (mHeight * appScale + 0.5f));
-        }
-
-        void draw(int yoff, boolean scalingRequired) {
-            Canvas canvas = mGlCanvas;
-            if (mGL != null && canvas != null) {
-                mGL.glDisable(GL_SCISSOR_TEST);
-                mGL.glClearColor(0, 0, 0, 0);
-                mGL.glClear(GL_COLOR_BUFFER_BIT);
-                mGL.glEnable(GL_SCISSOR_TEST);
-    
-                mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
-                mAttachInfo.mIgnoreDirtyState = true;
-                mView.mPrivateFlags |= View.DRAWN;
-    
-                int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
-                try {
-                    canvas.translate(0, -yoff);
-                    if (mTranslator != null) {
-                        mTranslator.translateCanvas(canvas);
-                    }
-                    canvas.setScreenDensity(scalingRequired ?
-                            DisplayMetrics.DENSITY_DEVICE : 0);
-    
-                    mView.draw(canvas);
-    
-                } finally {
-                    canvas.restoreToCount(saveCount);
-                }
-    
-                mAttachInfo.mIgnoreDirtyState = false;
-    
-                mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
-                checkErrors();
-            }
-        }
-
-        void initializeAndSetup() {
-            if (mRequested) {
-                checkErrors();
-                // we lost the gl context, so recreate it.
-                if (mRequested && !mEnabled) {
-                    initializeGL();
-                    if (mGlCanvas != null) {
-                        float appScale = mAttachInfo.mApplicationScale;
-                        mGlCanvas.setViewport((int) (mWidth * appScale + 0.5f),
-                                (int) (mHeight * appScale + 0.5f));
-                    }
-                }
-            }
-        }
-    }
-    
     private static native void nativeShowFPS(Canvas canvas, int durationMillis);
-
-    // inform skia to just abandon its texture cache IDs
-    // doesn't call glDeleteTextures
-    private static native void nativeAbandonGlCaches();
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 03989fd..30e9a6a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -131,7 +131,8 @@
 	android_backup_BackupDataInput.cpp \
 	android_backup_BackupDataOutput.cpp \
 	android_backup_FileBackupHelperBase.cpp \
-	android_backup_BackupHelperDispatcher.cpp
+	android_backup_BackupHelperDispatcher.cpp \
+	android_view_HardwareRenderer.cpp \
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
diff --git a/core/jni/android_view_HardwareRenderer.cpp b/core/jni/android_view_HardwareRenderer.cpp
new file mode 100644
index 0000000..abd788b
--- /dev/null
+++ b/core/jni/android_view_HardwareRenderer.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/SkGLCanvas.h>
+
+#include "jni.h"
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static void android_view_HardwareRenderer_abandonGlCaches(JNIEnv* env, jobject) {
+    SkGLCanvas::AbandonAllTextures();
+}
+
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/view/HardwareRenderer";
+
+static JNINativeMethod gMethods[] = {
+    {   "nativeAbandonGlCaches", "()V", 
+                                (void*)android_view_HardwareRenderer_abandonGlCaches },
+};
+
+int register_android_view_HardwareRenderer(JNIEnv* env) {
+    return AndroidRuntime::registerNativeMethods(env,
+            kClassPathName, gMethods, NELEM(gMethods));
+}
+
+};
diff --git a/core/jni/android_view_ViewRoot.cpp b/core/jni/android_view_ViewRoot.cpp
index 70ad8c5..0f3a877 100644
--- a/core/jni/android_view_ViewRoot.cpp
+++ b/core/jni/android_view_ViewRoot.cpp
@@ -76,10 +76,6 @@
     canvas->restore();
 }
 
-static void android_view_ViewRoot_abandonGlCaches(JNIEnv* env, jobject) {
-    SkGLCanvas::AbandonAllTextures();
-}
-
 static jintArray android_view_ViewRoot_makeInputChannel(JNIEnv* env, jobject) {
     int fd[2];
     jint* arrayData = NULL;
@@ -120,8 +116,6 @@
 static JNINativeMethod gMethods[] = {
     {   "nativeShowFPS", "(Landroid/graphics/Canvas;I)V",
                                         (void*)android_view_ViewRoot_showFPS },
-    {   "nativeAbandonGlCaches", "()V", 
-                                (void*)android_view_ViewRoot_abandonGlCaches },
     {   "makeInputChannel", "()[I",
                                         (void*)android_view_ViewRoot_makeInputChannel }
 };
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index aec977a..e2634d1 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -117,16 +117,33 @@
      * 
      * <p>The initial target density of the canvas is the same as the initial
      * density of bitmaps as per {@link Bitmap#getDensity() Bitmap.getDensity()}.
+     * 
+     * @deprecated This constructor is not supported and should not be invoked.
      */
     public Canvas(GL gl) {
         mNativeCanvas = initGL();
         mGL = gl;
         mDensity = Bitmap.getDefaultDensity();
     }
+
+    /**
+     * Indicates whether this Canvas uses hardware acceleration.
+     * 
+     * Note that this method does not define what type of hardware acceleration
+     * may or may not be used.
+     * 
+     * @return True if drawing operations are hardware accelerated,
+     *         false otherwise.
+     */
+    public boolean isHardwareAccelerated() {
+        return mGL != null;
+    }
     
     /**
      * Return the GL object associated with this canvas, or null if it is not
      * backed by GL.
+     * 
+     * @deprecated This method is not supported and should not be invoked.
      */
     public GL getGL() {
         return mGL;
@@ -136,6 +153,8 @@
      * Call this to free up OpenGL resources that may be cached or allocated
      * on behalf of the Canvas. Any subsequent drawing with a GL-backed Canvas
      * will have to recreate those resources.
+     * 
+     * @deprecated This method is not supported and should not be invoked.
      */
     public static void freeGlCaches() {
         freeCaches();
@@ -168,8 +187,10 @@
      * Set the viewport dimensions if this canvas is GL based. If it is not,
      * this method is ignored and no exception is thrown.
      *
-     *  @param width    The width of the viewport
-     *  @param height   The height of the viewport
+     *  @param width The width of the viewport
+     *  @param height The height of the viewport
+     * 
+     * @deprecated This method is not supported and should not be invoked.
      */
     public void setViewport(int width, int height) {
         if (mGL != null) {
@@ -1339,8 +1360,8 @@
      *            position (start + length) can be used for shaping context.
      * @param x the x position at which to draw the text
      * @param y the y position at which to draw the text
-     * @param dir the run direction, either {@link DIRECTION_LTR} or 
-     *            {@link DIRECTION_RTL}.
+     * @param dir the run direction, either {@link #DIRECTION_LTR} or 
+     *            {@link #DIRECTION_RTL}.
      * @param paint the paint
      * @hide
      */