From 87433cd1a09de1c52ec480a13265570cea60d977 Mon Sep 17 00:00:00 2001 From: Denis Hsu Date: Thu, 4 Jan 2018 14:45:34 +0800 Subject: [PATCH] Catch egl errors when drawIntoSurfaces Cts test case: testAbandonRepeatingRequestSurface is used to test the GPU for the ability of detecting the interrupt release of surface. It may have a dequeue buffer action in eglMakeCurrent, so it would return error "EGL_BAD_NATIVE_WINDOW" after surfaceflinger has been disconnected. In this case, the test can be passed only when we catch the errors thrown from GPU when calling eglMakeCurrent, or the test would be interrupted by the error exception. Bug: 72750260 Test: manual, ran the cts test case android.hardware.camera2.cts.RobustnessTest#testAbandonRepeatingRequestSurface Change-Id: I79bacdd3c0382a79786f8eb689eb4f89c830ddcc --- .../legacy/SurfaceTextureRenderer.java | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java index 83a02285e7206..1b28d614a7f22 100644 --- a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java +++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java @@ -521,9 +521,10 @@ public class SurfaceTextureRenderer { clearState(); } - private void makeCurrent(EGLSurface surface) { + private void makeCurrent(EGLSurface surface) + throws LegacyExceptionUtils.BufferQueueAbandonedException { EGL14.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext); - checkEglError("makeCurrent"); + checkEglDrawError("makeCurrent"); } private boolean swapBuffers(EGLSurface surface) @@ -557,6 +558,17 @@ public class SurfaceTextureRenderer { } } + private void checkEglDrawError(String msg) + throws LegacyExceptionUtils.BufferQueueAbandonedException { + int error; + if ((error = EGL14.eglGetError()) == EGL14.EGL_BAD_NATIVE_WINDOW) { + throw new LegacyExceptionUtils.BufferQueueAbandonedException(); + } + if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) { + throw new IllegalStateException(msg + ": EGL error: 0x" + Integer.toHexString(error)); + } + } + private void checkEglError(String msg) { int error; if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) { @@ -709,8 +721,14 @@ public class SurfaceTextureRenderer { if (mConversionSurfaces.size() > 0) { configureEGLPbufferSurfaces(mConversionSurfaces); } - makeCurrent((mSurfaces.size() > 0) ? mSurfaces.get(0).eglSurface : + + try { + makeCurrent((mSurfaces.size() > 0) ? mSurfaces.get(0).eglSurface : mConversionSurfaces.get(0).eglSurface); + } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) { + Log.w(TAG, "Surface abandoned, skipping configuration... ", e); + } + initializeGLState(); mSurfaceTexture = new SurfaceTexture(getTextureId()); @@ -798,9 +816,9 @@ public class SurfaceTextureRenderer { } for (EGLSurfaceHolder holder : mConversionSurfaces) { if (LegacyCameraDevice.containsSurfaceId(holder.surface, targetSurfaceIds)) { - makeCurrent(holder.eglSurface); // glReadPixels reads from the bottom of the buffer, so add an extra vertical flip try { + makeCurrent(holder.eglSurface); drawFrame(mSurfaceTexture, holder.width, holder.height, (mFacing == CameraCharacteristics.LENS_FACING_FRONT) ? FLIP_TYPE_BOTH : FLIP_TYPE_VERTICAL);