margelo / margelo/react-native-vision-camera

🐛 Android: every <Camera> mount leaks its SurfaceView and camera output stream

Open
#4,180 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

🐛 bug
Dominant language
TypeScript
Stars
9.6k
Forks
1.4k
Avg merge
1d 28m
Merged PRs (30d)
4

Description

Prerequisites
Reproduction

https://github.com/Gogn/react-native-vision-camera_issue-reproducing

Steps to reproduce
  1. Clone the attached repository or create a bare React-Native project
  2. Run the app
  3. Watch logcat: adb logcat | grep -E "SurfaceView\[|BufferQueue has been abandoned|Camera3-OutputStream"
  4. Optionally check a heap dump: adb shell am dumpheap com.vcpreviewleak /something/heap.hprof
What did you expect to happen?

Mounting and unmounting a screen with <Camera> should release the SurfaceView and its camera output stream. After some time, the number of live SurfaceView / PreviewView / HybridPreviewView instances should stay at the same amount regardless of how many times the component is mounted.

What actually happened?

Every mount leaks the preview's SurfaceView and creates a new camera output stream, nothing is released. After the surface is destroyed on unmount, the camera pipeline keeps trying to queue buffers into the abandoned BufferQueue.

With every new mount/unmount cycle:

  • a new SurfaceView surface is created and the previous one is never released
  • Those surfaces emitts BufferQueue has been abandoned errors after being destroyed
  • a new camera3 output stream is created
  • just one MainActivity throughout, so this is not an Activity leak
Affected platforms

Android (emulator)

Device(s) affected

Android 11 emulator, arm64-v8a

VisionCamera version

5.2.3

React Native version

0.86.3

React Native architecture

New Architecture (Fabric / bridgeless)

Features being used
  • Preview
  • Photo capture
  • Video capture
  • Frame Processors (worklets)
  • Skia Frame Processors
  • Code/Barcode Scanner
  • Location metadata
  • Multi-cam
  • Depth data
  • HDR / custom dynamic range
  • Custom format / FPS / resolution
Relevant logs / stack trace

One cycle, showing the surface being destroyed and then still written to:

D SurfaceViewImpl: Surface destroyed.
D SurfaceViewImpl: Surface closed androidx.camera.core.SurfaceRequest@f6f2cf
E BufferQueueProducer: [1e02dbf SurfaceView[com.vcpreviewleak/com.vcpreviewleak.MainActivity]#431(BLAST Consumer)431](id:7f8e000001af,api:4,p:596,c:32654) queueBuffer: BufferQueue has been abandoned
E Surface  : queueBuffer: error queuing buffer, -19
D StreamStateObserver: Update Preview stream state to IDLE
I HybridPreviewViewSpec: PreviewView stopped!
E Camera3-OutputStream: returnBufferCheckedLocked: Stream 544: Error queueing buffer to native window: No such device (-19)
E Camera3-OutputStream: getBufferLockedCommon: Stream 544: Can't dequeue next output buffer: No such device (-19)
D CXCP    : Closing capture session for CaptureSessionState-432

Heap dump after 30 cycles (app heap only):

     31  com.margelo.nitro.camera.views.HybridPreviewView
     31  com.margelo.nitro.camera.hybrids.outputs.HybridPreviewOutput
     25  com.margelo.nitro.camera.hybrids.HybridCameraSession
     25  com.margelo.nitro.camera.hybrids.HybridCameraController
      9  com.margelo.nitro.camera.hybrids.inputs.HybridCameraDevice
Additional context
  • Seems not a duplicate of #4095. That issue was fixed by nitro#1460 and the fix is working here.
  • In our app the leaked SurfaceView sits inside a navigation screen, so it pins the react-native-screens and that screen whole view hierarchy. The leak becomes Java heap growth.
Submission
  • The reproduction I linked is either (preferred) a PR against this repo that adds a failing harness test following the harness-tests README, or (fallback) a public repo that reproduces the bug on a fresh clone. I understand the issue will be closed without one.
  • I pasted logs as text (not screenshots).
  • I wrote this report in my own words. I did not paste AI-generated descriptions of the bug.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked reproduction repository and run the app while observing the provided adb logcat filter. Use the heap-dump command and the harness-tests README in apps/simple-camera/tests to compare repeated Camera mount/unmount cycles. Done means old SurfaceView and camera output instances are released without BufferQueue or Camera3-OutputStream errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
android
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.