Skip to content

Commit f1352d8

Browse files
Romain GuyAndroid (Google) Code Review
authored andcommitted
Merge "Fix SurfaceTexture leak in TextureView Bug #6318631"
2 parents d4fed38 + 1ac4765 commit f1352d8

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

core/java/android/view/HardwareRenderer.java

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,17 @@ public static boolean isAvailable() {
236236
*/
237237
abstract boolean validate();
238238

239+
/**
240+
* This method ensures the hardware renderer is in a valid state
241+
* before executing the specified action.
242+
*
243+
* This method will attempt to set a valid state even if the window
244+
* the renderer is attached to was destroyed.
245+
*
246+
* @return true if the action was run
247+
*/
248+
abstract boolean safelyRun(Runnable action);
249+
239250
/**
240251
* Setup the hardware renderer for drawing. This is called whenever the
241252
* size of the target surface changes or when the surface is first created.
@@ -1380,26 +1391,40 @@ private static void destroyHardwareLayer(View view) {
13801391
}
13811392

13821393
@Override
1383-
void destroyHardwareResources(View view) {
1384-
if (view != null) {
1385-
boolean needsContext = true;
1386-
if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
1387-
1388-
if (needsContext) {
1389-
Gl20RendererEglContext managedContext =
1390-
(Gl20RendererEglContext) sEglContextStorage.get();
1391-
if (managedContext == null) return;
1392-
usePbufferSurface(managedContext.getContext());
1393-
}
1394-
1395-
destroyResources(view);
1396-
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
1394+
boolean safelyRun(Runnable action) {
1395+
boolean needsContext = true;
1396+
if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
1397+
1398+
if (needsContext) {
1399+
Gl20RendererEglContext managedContext =
1400+
(Gl20RendererEglContext) sEglContextStorage.get();
1401+
if (managedContext == null) return false;
1402+
usePbufferSurface(managedContext.getContext());
1403+
}
13971404

1405+
try {
1406+
action.run();
1407+
} finally {
13981408
if (needsContext) {
13991409
sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
14001410
EGL_NO_SURFACE, EGL_NO_CONTEXT);
14011411
}
14021412
}
1413+
1414+
return true;
1415+
}
1416+
1417+
@Override
1418+
void destroyHardwareResources(final View view) {
1419+
if (view != null) {
1420+
safelyRun(new Runnable() {
1421+
@Override
1422+
public void run() {
1423+
destroyResources(view);
1424+
GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
1425+
}
1426+
});
1427+
}
14031428
}
14041429

14051430
private static void destroyResources(View view) {

core/java/android/view/TextureView.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,18 @@ protected void onAttachedToWindow() {
204204
@Override
205205
protected void onDetachedFromWindow() {
206206
super.onDetachedFromWindow();
207-
destroySurface();
207+
if (mLayer != null && mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) {
208+
boolean success = mAttachInfo.mHardwareRenderer.safelyRun(new Runnable() {
209+
@Override
210+
public void run() {
211+
destroySurface();
212+
}
213+
});
214+
215+
if (!success) {
216+
Log.w(LOG_TAG, "TextureView was not able to destroy its surface: " + this);
217+
}
218+
}
208219
}
209220

210221
private void destroySurface() {

0 commit comments

Comments
 (0)