fix(audio): keep cleanup from masking start failures or skipping release
AudioCapture.audioFlow's finally ran recorder.stop() then release() naked. If startRecording() threw - permission revoked mid-request, audio device error - the finally's stop() threw IllegalStateException (stop on an uninitialized recorder), which replaced the original error AND skipped release(), leaking the AudioRecord. The flow's caller saw "recorder failure" instead of "no permission" and the native recorder was never freed. Wrapping each cleanup step in runCatching preserves the original exception while guaranteeing release() runs. Probe: a start failure previously surfaced as RuntimeError with released=false; it now surfaces as the original PermissionError with released=true.
This commit is contained in:
1 parent
b4cfb16159
commit
b749733289
1 file changed
+8
-2
@@ -56,8 +56,14 @@ class AudioCapture : IAudioCapture {
|
||||
if (read > 0) emit(if (read == chunkSize) buffer.copyOf() else buffer.copyOfRange(0, read))
|
||||
}
|
||||
} finally {
|
||||
recorder.stop()
|
||||
recorder.release()
|
||||
// stop() on a recorder that never started throws
|
||||
// IllegalStateException; wrapping each cleanup step separately
|
||||
// keeps the original error (e.g. a permission denial during
|
||||
// startRecording) intact and guarantees release() still runs.
|
||||
// Without this, a start failure masked the real cause AND leaked
|
||||
// the recorder because release() was skipped.
|
||||
runCatching { recorder.stop() }
|
||||
runCatching { recorder.release() }
|
||||
}
|
||||
}.flowOn(Dispatchers.IO)
|
||||
}
|
||||
Reference in new issue
Block a user