Fix onTrimMemory for HardwareRenderer

 Also fixes detachFunctor possibly drawing after return

 Bug: 15189843
 Bug: 15990672

Change-Id: I64c48cb674c461a8eeaba407b697e09f72c98ce3
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f5514f8..422d88c 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3962,10 +3962,6 @@
 
         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
 
-        // Cleanup hardware accelerated stuff
-        // TODO: Do we actually want to do this in response to all config changes?
-        WindowManagerGlobal.getInstance().trimLocalMemory();
-
         freeTextLayoutCachesIfNeeded(configDiff);
 
         if (callbacks != null) {
@@ -4100,9 +4096,6 @@
     final void handleTrimMemory(int level) {
         if (DEBUG_MEMORY_TRIM) Slog.v(TAG, "Trimming memory to level: " + level);
 
-        final WindowManagerGlobal windowManager = WindowManagerGlobal.getInstance();
-        windowManager.startTrimMemory(level);
-
         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(true, null);
 
         final int N = callbacks.size();
@@ -4110,7 +4103,7 @@
             callbacks.get(i).onTrimMemory(level);
         }
 
-        windowManager.endTrimMemory();
+        WindowManagerGlobal.getInstance().trimMemory(level);
     }
 
     private void setupGraphicsSupport(LoadedApk info, File cacheDir) {
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index dcd9ba9..d7d3c72 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -203,31 +203,6 @@
     private static native int nCallDrawGLFunction(long renderer, long drawGLFunction);
 
     ///////////////////////////////////////////////////////////////////////////
-    // Memory
-    ///////////////////////////////////////////////////////////////////////////
-
-    /**
-     * Must match Caches::FlushMode values
-     *
-     * @see #flushCaches(int)
-     */
-    static final int FLUSH_CACHES_LAYERS = 0;
-
-    /**
-     * Must match Caches::FlushMode values
-     *
-     * @see #flushCaches(int)
-     */
-    static final int FLUSH_CACHES_MODERATE = 1;
-
-    /**
-     * Must match Caches::FlushMode values
-     *
-     * @see #flushCaches(int)
-     */
-    static final int FLUSH_CACHES_FULL = 2;
-
-    ///////////////////////////////////////////////////////////////////////////
     // Display list
     ///////////////////////////////////////////////////////////////////////////
 
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index e9bdcae..d69d01d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -18,8 +18,6 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
 import android.util.DisplayMetrics;
 import android.view.Surface.OutOfResourcesException;
 
@@ -200,10 +198,8 @@
 
     /**
      * Destroys the hardware rendering context.
-     *
-     * @param full If true, destroys all associated resources.
      */
-    abstract void destroy(boolean full);
+    abstract void destroy();
 
     /**
      * Initializes the hardware renderer for the specified surface.
@@ -435,28 +431,7 @@
      *              see {@link android.content.ComponentCallbacks}
      */
     static void trimMemory(int level) {
-        startTrimMemory(level);
-        endTrimMemory();
-    }
-
-    /**
-     * Starts the process of trimming memory. Usually this call will setup
-     * hardware rendering context and reclaim memory.Extra cleanup might
-     * be required by calling {@link #endTrimMemory()}.
-     *
-     * @param level Hint about the amount of memory that should be trimmed,
-     *              see {@link android.content.ComponentCallbacks}
-     */
-    static void startTrimMemory(int level) {
-        ThreadedRenderer.startTrimMemory(level);
-    }
-
-    /**
-     * Finishes the process of trimming memory. This method will usually
-     * cleanup special resources used by the memory trimming process.
-     */
-    static void endTrimMemory() {
-        ThreadedRenderer.endTrimMemory();
+        ThreadedRenderer.trimMemory(level);
     }
 
     /**
@@ -503,8 +478,15 @@
     abstract void fence();
 
     /**
+     * Prevents any further drawing until draw() is called. This is a signal
+     * that the contents of the RenderNode tree are no longer safe to play back.
+     * In practice this usually means that there are Functor pointers in the
+     * display list that are no longer valid.
+     */
+    abstract void stopDrawing();
+
+    /**
      * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
      */
-    public void notifyFramePending() {
-    }
+    abstract void notifyFramePending();
 }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 45714ff..fcc51ec 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -90,7 +90,7 @@
     }
 
     @Override
-    void destroy(boolean full) {
+    void destroy() {
         mInitialized = false;
         updateEnabledState(null);
         nDestroyCanvasAndSurface(mNativeProxy);
@@ -125,7 +125,7 @@
     @Override
     void destroyHardwareResources(View view) {
         destroyResources(view);
-        nFlushCaches(mNativeProxy, GLES20Canvas.FLUSH_CACHES_LAYERS);
+        nDestroyHardwareResources(mNativeProxy);
     }
 
     private static void destroyResources(View view) {
@@ -289,6 +289,11 @@
     }
 
     @Override
+    void stopDrawing() {
+        nStopDrawing(mNativeProxy);
+    }
+
+    @Override
     public void notifyFramePending() {
         nNotifyFramePending(mNativeProxy);
     }
@@ -303,12 +308,8 @@
         }
     }
 
-    static void startTrimMemory(int level) {
-        // TODO
-    }
-
-    static void endTrimMemory() {
-        // TODO
+    static void trimMemory(int level) {
+        nTrimMemory(level);
     }
 
     private static class AtlasInitializer {
@@ -403,9 +404,11 @@
     private static native void nCancelLayerUpdate(long nativeProxy, long layer);
     private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
 
-    private static native void nFlushCaches(long nativeProxy, int flushMode);
+    private static native void nDestroyHardwareResources(long nativeProxy);
+    private static native void nTrimMemory(int level);
 
     private static native void nFence(long nativeProxy);
+    private static native void nStopDrawing(long nativeProxy);
     private static native void nNotifyFramePending(long nativeProxy);
 
     private static native void nDumpProfileInfo(long nativeProxy, FileDescriptor fd);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 829e089..6cfc019 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13598,7 +13598,9 @@
      * @hide
      */
     protected void destroyHardwareResources() {
-        resetDisplayList();
+        // Intentionally empty. RenderNode's lifecycle is now fully managed
+        // by the hardware renderer.
+        // However some subclasses (eg, WebView, TextureView) still need this signal
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4c9d3f9..3219330 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -632,21 +632,17 @@
     void destroyHardwareResources() {
         if (mAttachInfo.mHardwareRenderer != null) {
             mAttachInfo.mHardwareRenderer.destroyHardwareResources(mView);
-            mAttachInfo.mHardwareRenderer.destroy(false);
+            mAttachInfo.mHardwareRenderer.destroy();
         }
     }
 
-    void destroyHardwareLayers() {
-        // TODO Implement
-    }
-
     public void detachFunctor(long functor) {
         // TODO: Make the resize buffer some other way to not need this block
         mBlockResizeBuffer = true;
         if (mAttachInfo.mHardwareRenderer != null) {
             // Fence so that any pending invokeFunctor() messages will be processed
             // before we return from detachFunctor.
-            mAttachInfo.mHardwareRenderer.fence();
+            mAttachInfo.mHardwareRenderer.stopDrawing();
         }
     }
 
@@ -696,7 +692,7 @@
             if (!HardwareRenderer.sRendererDisabled || (HardwareRenderer.sSystemRendererDisabled
                     && forceHwAccelerated)) {
                 if (mAttachInfo.mHardwareRenderer != null) {
-                    mAttachInfo.mHardwareRenderer.destroy(true);
+                    mAttachInfo.mHardwareRenderer.destroy();
                 }
 
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE;
@@ -1613,7 +1609,7 @@
                     // Our surface is gone
                     if (mAttachInfo.mHardwareRenderer != null &&
                             mAttachInfo.mHardwareRenderer.isEnabled()) {
-                        mAttachInfo.mHardwareRenderer.destroy(true);
+                        mAttachInfo.mHardwareRenderer.destroy();
                     }
                 } else if (surfaceGenerationId != mSurface.getGenerationId() &&
                         mSurfaceHolder == null && mAttachInfo.mHardwareRenderer != null) {
@@ -5436,7 +5432,7 @@
             if (mView != null) {
                 hardwareRenderer.destroyHardwareResources(mView);
             }
-            hardwareRenderer.destroy(true);
+            hardwareRenderer.destroy();
             hardwareRenderer.setRequested(false);
 
             attachInfo.mHardwareRenderer = null;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 0ebf2e1..74bc186 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -20,7 +20,6 @@
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
 import android.content.res.Configuration;
-import android.opengl.ManagedEGLContext;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -114,7 +113,6 @@
     private final ArrayList<WindowManager.LayoutParams> mParams =
             new ArrayList<WindowManager.LayoutParams>();
     private final ArraySet<View> mDyingViews = new ArraySet<View>();
-    private boolean mNeedsEglTerminate;
 
     private Runnable mSystemPropertyUpdater;
 
@@ -377,13 +375,22 @@
         return index;
     }
 
-    public void startTrimMemory(int level) {
+    public static boolean shouldDestroyEglContext(int trimLevel) {
+        // On low-end gfx devices we trim when memory is moderate;
+        // on high-end devices we do this when low.
+        if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
+            return true;
+        }
+        if (trimLevel >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
+                && !ActivityManager.isHighEndGfx()) {
+            return true;
+        }
+        return false;
+    }
+
+    public void trimMemory(int level) {
         if (HardwareRenderer.isAvailable()) {
-            // On low-end gfx devices we trim when memory is moderate;
-            // on high-end devices we do this when low.
-            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
-                    || (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE
-                            && !ActivityManager.isHighEndGfx())) {
+            if (shouldDestroyEglContext(level)) {
                 // Destroy all hardware surfaces and resources associated to
                 // known windows
                 synchronized (mLock) {
@@ -392,29 +399,10 @@
                     }
                 }
                 // Force a full memory flush
-                mNeedsEglTerminate = true;
-                HardwareRenderer.startTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-                return;
+                level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             }
 
-            HardwareRenderer.startTrimMemory(level);
-        }
-    }
-
-    public void endTrimMemory() {
-        HardwareRenderer.endTrimMemory();
-
-        if (mNeedsEglTerminate) {
-            ManagedEGLContext.doTerminate();
-            mNeedsEglTerminate = false;
-        }
-    }
-
-    public void trimLocalMemory() {
-        synchronized (mLock) {
-            for (int i = mRoots.size() - 1; i >= 0; --i) {
-                mRoots.get(i).destroyHardwareLayers();
-            }
+            HardwareRenderer.trimMemory(level);
         }
     }
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index e63c475..aab48b3 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -298,10 +298,15 @@
     proxy->detachSurfaceTexture(layer);
 }
 
-static void android_view_ThreadedRenderer_flushCaches(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jint flushMode) {
+static void android_view_ThreadedRenderer_destroyHardwareResources(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->flushCaches(static_cast<Caches::FlushMode>(flushMode));
+    proxy->destroyHardwareResources();
+}
+
+static void android_view_ThreadedRenderer_trimMemory(JNIEnv* env, jobject clazz,
+        jint level) {
+    RenderProxy::trimMemory(level);
 }
 
 static void android_view_ThreadedRenderer_fence(JNIEnv* env, jobject clazz,
@@ -310,6 +315,12 @@
     proxy->fence();
 }
 
+static void android_view_ThreadedRenderer_stopDrawing(JNIEnv* env, jobject clazz,
+        jlong proxyPtr) {
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->stopDrawing();
+}
+
 static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
         jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
@@ -365,8 +376,10 @@
     { "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
     { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
     { "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
-    { "nFlushCaches", "(JI)V", (void*) android_view_ThreadedRenderer_flushCaches },
+    { "nDestroyHardwareResources", "(J)V", (void*) android_view_ThreadedRenderer_destroyHardwareResources },
+    { "nTrimMemory", "(I)V", (void*) android_view_ThreadedRenderer_trimMemory },
     { "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
+    { "nStopDrawing", "(J)V", (void*) android_view_ThreadedRenderer_stopDrawing },
     { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
     { "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
 #endif
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index e803ec3..89105ea 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -195,17 +195,28 @@
 
 void RenderNode::prepareTreeImpl(TreeInfo& info) {
     info.damageAccumulator->pushTransform(this);
-    if (info.mode == TreeInfo::MODE_FULL) {
+
+    switch (info.mode) {
+    case TreeInfo::MODE_FULL:
         pushStagingPropertiesChanges(info);
         mAnimatorManager.animate(info);
-    } else if (info.mode == TreeInfo::MODE_MAYBE_DETACHING) {
+        break;
+    case TreeInfo::MODE_MAYBE_DETACHING:
         pushStagingPropertiesChanges(info);
-    } else if (info.mode == TreeInfo::MODE_RT_ONLY) {
+        break;
+    case TreeInfo::MODE_RT_ONLY:
         mAnimatorManager.animate(info);
+        break;
+    case TreeInfo::MODE_DESTROY_RESOURCES:
+        // This will also release the hardware layer if we have one as
+        // isRenderable() will return false, thus causing pushLayerUpdate
+        // to recycle the hardware layer
+        setStagingDisplayList(NULL);
+        break;
     }
 
     prepareLayer(info);
-    if (info.mode == TreeInfo::MODE_FULL) {
+    if (info.mode == TreeInfo::MODE_FULL || info.mode == TreeInfo::MODE_DESTROY_RESOURCES) {
         pushStagingDisplayListChanges(info);
     }
     prepareSubTree(info, mDisplayListData);
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 083100e..9746ac53 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -65,7 +65,8 @@
         // but don't evaluate animators and such as if it isn't detached as a
         // MODE_FULL will follow shortly.
         MODE_MAYBE_DETACHING,
-        // TODO: TRIM_MEMORY?
+        // Destroy all hardware resources, including DisplayListData, in the tree.
+        MODE_DESTROY_RESOURCES,
     };
 
     explicit TreeInfo(TraversalMode mode, RenderState& renderState)
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 9c3cf44..524ee62dd 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -30,6 +30,9 @@
 #include "../OpenGLRenderer.h"
 #include "../Stencil.h"
 
+#define TRIM_MEMORY_COMPLETE 80
+#define TRIM_MEMORY_UI_HIDDEN 20
+
 namespace android {
 namespace uirenderer {
 namespace renderthread {
@@ -156,6 +159,10 @@
     }
 }
 
+void CanvasContext::stopDrawing() {
+    mRenderThread.removeFrameCallback(this);
+}
+
 void CanvasContext::notifyFramePending() {
     ATRACE_CALL();
     mRenderThread.pushBackFrameCallback(this);
@@ -216,8 +223,6 @@
     profiler().startFrame();
 
     TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
-    info.prepareTextures = false;
-
     prepareTree(info);
     if (info.out.canDrawThisFrame) {
         draw();
@@ -241,10 +246,25 @@
     return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
 }
 
-void CanvasContext::flushCaches(Caches::FlushMode flushMode) {
+void CanvasContext::destroyHardwareResources() {
+    stopDrawing();
     if (mEglManager.hasEglContext()) {
         requireGlContext();
-        Caches::getInstance().flush(flushMode);
+        TreeInfo info(TreeInfo::MODE_DESTROY_RESOURCES, mRenderThread.renderState());
+        mRootRenderNode->prepareTree(info);
+        Caches::getInstance().flush(Caches::kFlushMode_Layers);
+    }
+}
+
+void CanvasContext::trimMemory(RenderThread& thread, int level) {
+    // No context means nothing to free
+    if (!thread.eglManager().hasEglContext()) return;
+
+    if (level >= TRIM_MEMORY_COMPLETE) {
+        Caches::getInstance().flush(Caches::kFlushMode_Full);
+        thread.eglManager().destroy();
+    } else if (level >= TRIM_MEMORY_UI_HIDDEN) {
+        Caches::getInstance().flush(Caches::kFlushMode_Moderate);
     }
 }
 
@@ -264,11 +284,7 @@
 }
 
 void CanvasContext::requireGlContext() {
-    if (mEglSurface != EGL_NO_SURFACE) {
-        makeCurrent();
-    } else {
-        mEglManager.usePBufferSurface();
-    }
+    mEglManager.requireGlContext();
 }
 
 void CanvasContext::setTextureAtlas(RenderThread& thread,
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index dbfb3d2..1bab1b1 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -66,7 +66,8 @@
 
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
 
-    void flushCaches(Caches::FlushMode flushMode);
+    void destroyHardwareResources();
+    static void trimMemory(RenderThread& thread, int level);
 
     static void invokeFunctor(RenderThread& thread, Functor* functor);
 
@@ -78,6 +79,7 @@
     ANDROID_API static void setTextureAtlas(RenderThread& thread,
             const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
 
+    void stopDrawing();
     void notifyFramePending();
 
     DrawProfiler& profiler() { return mProfiler; }
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index e1ee620..6cd3d0b 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -312,18 +312,30 @@
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(flushCaches, CanvasContext* context, Caches::FlushMode flushMode) {
-    args->context->flushCaches(args->flushMode);
+CREATE_BRIDGE1(destroyHardwareResources, CanvasContext* context) {
+    args->context->destroyHardwareResources();
     return NULL;
 }
 
-void RenderProxy::flushCaches(Caches::FlushMode flushMode) {
-    SETUP_TASK(flushCaches);
+void RenderProxy::destroyHardwareResources() {
+    SETUP_TASK(destroyHardwareResources);
     args->context = mContext;
-    args->flushMode = flushMode;
     post(task);
 }
 
+CREATE_BRIDGE2(timMemory, RenderThread* thread, int level) {
+    CanvasContext::trimMemory(*args->thread, args->level);
+    return NULL;
+}
+
+void RenderProxy::trimMemory(int level) {
+    RenderThread& thread = RenderThread::getInstance();
+    SETUP_TASK(timMemory);
+    args->thread = &thread;
+    args->level = level;
+    thread.queue(task);
+}
+
 CREATE_BRIDGE0(fence) {
     // Intentionally empty
     return NULL;
@@ -334,6 +346,17 @@
     postAndWait(task);
 }
 
+CREATE_BRIDGE1(stopDrawing, CanvasContext* context) {
+    args->context->stopDrawing();
+    return NULL;
+}
+
+void RenderProxy::stopDrawing() {
+    SETUP_TASK(stopDrawing);
+    args->context = mContext;
+    postAndWait(task);
+}
+
 CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
     args->context->notifyFramePending();
     return NULL;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index c7358e6..0027403 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -85,9 +85,11 @@
     ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
     ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
 
-    ANDROID_API void flushCaches(Caches::FlushMode flushMode);
+    ANDROID_API void destroyHardwareResources();
+    ANDROID_API static void trimMemory(int level);
 
     ANDROID_API void fence();
+    ANDROID_API void stopDrawing();
     ANDROID_API void notifyFramePending();
 
     ANDROID_API void dumpProfileInfo(int fd);
diff --git a/opengl/java/android/opengl/ManagedEGLContext.java b/opengl/java/android/opengl/ManagedEGLContext.java
deleted file mode 100644
index 61fa565..0000000
--- a/opengl/java/android/opengl/ManagedEGLContext.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.opengl;
-
-import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
-
-import java.util.ArrayList;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-
-import android.os.Looper;
-import android.util.Log;
-
-import com.google.android.gles_jni.EGLImpl;
-
-/**
- * The per-process memory overhead of hardware accelerated graphics can
- * be quite large on some devices.  For small memory devices, being able to
- * terminate all EGL contexts so that this graphics driver memory can be
- * reclaimed can significant improve the overall behavior of the device.  This
- * class helps app developers participate in releasing their EGL context
- * when appropriate and possible.
- * 
- * <p>To use, simple instantiate this class with the EGLContext you create.
- * When you have done this, if the device is getting low on memory and all
- * of the currently created EGL contexts in the process are being managed
- * through this class, then they will all be asked to terminate through the
- * call to {@link #onTerminate}.
- * 
- * @hide
- */
-public abstract class ManagedEGLContext {
-    static final String TAG = "ManagedEGLContext";
-
-    static final ArrayList<ManagedEGLContext> sActive = new ArrayList<ManagedEGLContext>();
-
-    final EGLContext mContext;
-
-    /**
-     * Instantiate to manage the given EGLContext.
-     */
-    public ManagedEGLContext(EGLContext context) {
-        mContext = context;
-        synchronized (sActive) {
-            sActive.add(this);
-        }
-    }
-
-    /**
-     * Retrieve the EGLContext being managed by the class.
-     */
-    public EGLContext getContext() {
-        return mContext;
-    }
-
-    /**
-     * Force-terminate the ManagedEGLContext.  This will cause
-     * {@link #onTerminate(EGLContext)} to be called.  You <em>must</em>
-     * call this when destroying the EGLContext, so that the framework
-     * knows to stop managing it.
-     */
-    public void terminate() {
-        execTerminate();
-    }
-
-    void execTerminate() {
-        onTerminate(mContext);
-    }
-
-    /**
-     * Override this method to destroy the EGLContext when appropriate.
-     * <em>Note that this method is always called on the main thread
-     * of the process.</em>  If your EGLContext was created on a different
-     * thread, you will need to implement this method to hand off the work
-     * of destroying the context to that thread.
-     */
-    public abstract void onTerminate(EGLContext context);
-
-    /** @hide */
-    public static boolean doTerminate() {
-        ArrayList<ManagedEGLContext> active;
-
-        if (Looper.getMainLooper() != Looper.myLooper()) {
-            throw new IllegalStateException("Called on wrong thread");
-        }
-
-        synchronized (sActive) {
-            // If there are no active managed contexts, we will not even
-            // try to terminate.
-            if (sActive.size() <= 0) {
-                return false;
-            }
-
-            // Need to check how many EGL contexts are actually running,
-            // to compare with how many we are managing.
-            EGL10 egl = (EGL10) EGLContext.getEGL();
-            EGLDisplay display = egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
-            if (display == EGL_NO_DISPLAY) {
-                Log.w(TAG, "doTerminate failed: no display");
-                return false;
-            }
-
-            if (EGLImpl.getInitCount(display) != sActive.size()) {
-                Log.w(TAG, "doTerminate failed: EGL count is " + EGLImpl.getInitCount(display)
-                        + " but managed count is " + sActive.size());
-                return false;
-            }
-
-            active = new ArrayList<ManagedEGLContext>(sActive);
-            sActive.clear();
-        }
-
-        for (int i = 0; i < active.size(); i++) {
-            active.get(i).execTerminate();
-        }
-
-        return true;
-    }
-}