Cover capture startup failures that overlap a replacement group

This commit is contained in:
evgeny committed 2026-10-29 13:34:23 +01:00
1 parent 6677b3abfe
commit 17caeb0a9c
2 files changed
+19 -2

No files matched your search

@@ -46,6 +46,7 @@ object NativeLib {
@Volatile var radioPullResult = 0
val radioPullResults = ConcurrentLinkedQueue<Int>()
@Volatile var onRadioFeed: (Long) -> Unit = {}
@Volatile var onRadioCaptureStart: (Long) -> Unit = {}
val radioFeeds: MutableList<Long> = Collections.synchronizedList(mutableListOf())
fun radioSetActive(group: Long, active: Boolean) { radioCommands.add(RadioCommand("active=$active", group)) }
fun radioConfigure(request: Long, settings: RadioAutoSettings): Boolean { radioRequest = request; return settings.valid() }
@@ -75,6 +76,7 @@ object NativeLib {
if ("capture reject" in radioFailures) return false
radioMode = if ("detector off" in radioFailures) 0 else mode
radioCaptureAlive = true
onRadioCaptureStart(group)
check("capture start" !in radioFailures) { "native capture start failed after effect" }
return true
}
@@ -29,7 +29,7 @@ class RadioWorkerLifecycleTest {
AudioManager.shared = AudioManager(); CallController.blocked = false
AndroidMicrophoneCapture.reset(); AudioTrack.created.clear(); AudioTrack.nextFailures = emptySet(); AudioTrack.minimumBuffer = 1920
NativeLib.radioFailures = emptySet(); NativeLib.radioPullResult = 0; NativeLib.radioPullResults.clear()
NativeLib.onRadioFeed = {}; NativeLib.radioCommands.clear(); NativeLib.radioFeeds.clear()
NativeLib.onRadioFeed = {}; NativeLib.onRadioCaptureStart = {}; NativeLib.radioCommands.clear(); NativeLib.radioFeeds.clear()
Handler.rejectDelayed = false; Handler.rejectImmediate = false
LogManager.entries.clear(); LogManager.console = true
engine = RadioAudioEngine()
@@ -39,7 +39,8 @@ class RadioWorkerLifecycleTest {
@After fun release() {
gates.forEach { it.countDown() }
NativeLib.onRadioFeed = {}; NativeLib.radioFailures = emptySet(); NativeLib.radioPullResult = 0; NativeLib.radioPullResults.clear()
NativeLib.onRadioFeed = {}; NativeLib.onRadioCaptureStart = {}; NativeLib.radioFailures = emptySet()
NativeLib.radioPullResult = 0; NativeLib.radioPullResults.clear()
Handler.rejectImmediate = false; Handler.rejectDelayed = false
AudioTrack.created.forEach { it.failures = emptySet(); it.forcedWriteResult = null; it.onWrite = {} }
engine.stop().get(5, TimeUnit.SECONDS); main.advanceBy(10_000); drain()
@@ -257,4 +258,18 @@ class RadioWorkerLifecycleTest {
await("new manual request") { NativeLib.radioTransmitting() }
assertEquals(8L, engine.activeGroup.value); assertTrue(engine.isTalking())
}
@Test fun aLateCaptureStartupFailureCannotClearANewGroupsManualRequest() {
val entered = CountDownLatch(1)
val gate = CountDownLatch(1).also { gates.add(it) }
NativeLib.onRadioCaptureStart = { group ->
if (group == 7L) { entered.countDown(); gate.await(5, TimeUnit.SECONDS); throw IllegalStateException("old capture startup failed") }
}
assertTrue(engine.talkBegin()); assertTrue(entered.await(5, TimeUnit.SECONDS))
engine.start(8); assertTrue(engine.talkBegin(RadioPttSource.VOLUME))
gate.countDown(); drain(); main.dispatchAll()
NativeLib.onRadioCaptureStart = {}; engine.onSettingsApplied(NativeLib.radioRequest, true); drain()
await("new manual request after old startup failure") { NativeLib.radioTransmitting() }
assertEquals(8L, engine.activeGroup.value); assertTrue(engine.isTalking())
}
}