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