fix(🤖): release the Java Surface wrapper on the non-opaque path - #4046
Open
kushal-matiks wants to merge 1 commit into
Open
fix(🤖): release the Java Surface wrapper on the non-opaque path#4046kushal-matiks wants to merge 1 commit into
kushal-matiks wants to merge 1 commit into
Conversation
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.
Author
|
I have signed the CLA! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4045
Problem
On Android, every non-opaque
<Canvas>leaks oneandroid.view.Surface.surfaceAvailablebuilds aSurfaceto wrap theSurfaceTexture, hands it toANativeWindow_fromSurface, then drops it withDeleteLocalRef. That only releases the JNI local reference —Surface.release()is never called, so the underlying buffer producer is left to the finalizer and CloseGuard logs:once per Canvas.
surfaceDestroyed()releases_jSurfaceTextureandOpenGLWindowContextreleases theANativeWindow, but nothing owns the intermediateSurface.Fix
Release the Java wrapper once
ANativeWindow_fromSurfacehas taken its own reference on the producer. The lookup is null-guarded and the call is exception-guarded, so it degrades to the current behaviour rather than throwing if anything is unexpected.This mirrors the ownership rule the WebGPU path already documents in
JniWebGPUView.cpp:Only the
!opaquebranch is touched; the opaque branch never creates the wrapper.Verification
Measured on an app with 6
<Canvas>components (a tab bar of Skia icons), countingSurface.releasewarnings per launch:The unpatched release build was measured first as an instrument check — CloseGuard is normally gated on the debuggable flag, so a patched
0would be meaningless if the unpatched release were also silent. It reported 6, so the0is a real measurement.No regressions across 20 navigations plus 3 background/foreground cycles on the release build:
SIGSEGV/SIGABRT/Fatal signal/ tombstone / ANR — 0BufferQueue has been abandoned— 0EGL_BAD_SURFACE,EGL_BAD_NATIVE_WINDOW— 0R8 does not affect the change:
GetMethodID(surfaceClass, "release", "()V")resolvesandroid.view.Surface.releasefrom the platform framework at runtime, and minification never rewritesandroid.*.Not addressed here
surfaceSizeChangedre-enterssurfaceAvailable, which assigns_jSurfaceTexture = env->NewGlobalRef(...)withoutDeleteGlobalRefon the previous value — a separate JNI global-ref leak on the resize/rotation path. Left alone deliberately: it is a distinct defect, and I could not exercise that path to verify a fix (the app I reproduced on is portrait-locked). Noted in #4045.Testing done
Verified by rebuilding the Android native library from source and measuring on device via logcat, in both debug and minified release builds, on a physical Mali device and an emulator. I did not run the repo's own example app or test suite locally — happy to do so, or to adjust the approach, if you'd prefer.