From 21eea0d5e0d2ffd03b90473974ca6f79a1c79aff Mon Sep 17 00:00:00 2001 From: Kushal Agrawal Date: Thu, 3 Sep 2026 13:46:21 +0530 Subject: [PATCH] =?UTF-8?q?fix(=F0=9F=A4=96):=20release=20the=20Java=20Sur?= =?UTF-8?q?face=20wrapper=20on=20the=20non-opaque=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit surfaceAvailable creates an android.view.Surface to wrap the SurfaceTexture and passes it to ANativeWindow_fromSurface, but only drops the JNI local reference afterwards. DeleteLocalRef does not call Surface.release(), so the underlying buffer producer is left to the finalizer and CloseGuard logs 'A resource failed to call Surface.release.' once per Canvas. ANativeWindow_fromSurface acquires its own reference, so the wrapper can be released immediately. The WebGPU path already documents this ownership rule in JniWebGPUView.cpp. --- .../rnskia-android/RNSkOpenGLCanvasProvider.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index 34d0fc75ef..b05121fe80 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -100,6 +100,20 @@ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, _updateTexImageMethod = env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V"); + // ANativeWindow_fromSurface acquires its own reference on the underlying + // buffer producer, so the Java Surface wrapper can be released here. + // Without this, every Canvas leaks one android.view.Surface until + // finalization and CloseGuard reports "A resource failed to call + // Surface.release." + jmethodID surfaceRelease = + env->GetMethodID(surfaceClass, "release", "()V"); + if (surfaceRelease != nullptr) { + env->CallVoidMethod(jSurface, surfaceRelease); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + } + } + // Acquire the native window from the Surface // Clean up local references env->DeleteLocalRef(jSurface);