diff --git a/tools/chatgui-android/call-service-tests/src/main/kotlin/com/utun/chat/data/CallServiceHost.kt b/tools/chatgui-android/call-service-tests/src/main/kotlin/com/utun/chat/data/CallServiceHost.kt index c2eac9ff8..215889356 100644 --- a/tools/chatgui-android/call-service-tests/src/main/kotlin/com/utun/chat/data/CallServiceHost.kt +++ b/tools/chatgui-android/call-service-tests/src/main/kotlin/com/utun/chat/data/CallServiceHost.kt @@ -63,6 +63,9 @@ class CallVideoEngine(context: Context, val id: Long) { } object TelecomCallManager { + var pending = false + fun cleanupPending() = pending + fun requireReleased() { check(!pending) { "Telecom connection cleanup pending" } } interface Listener { fun onConnectionAvailable(callId: Long, connection: UtunConnection) fun onAnswer(callId: Long) diff --git a/tools/chatgui-android/call-service-tests/src/test/kotlin/com/utun/chat/data/CallServiceLifecycleTest.kt b/tools/chatgui-android/call-service-tests/src/test/kotlin/com/utun/chat/data/CallServiceLifecycleTest.kt index 90447e6f8..a77b8d9a6 100644 --- a/tools/chatgui-android/call-service-tests/src/test/kotlin/com/utun/chat/data/CallServiceLifecycleTest.kt +++ b/tools/chatgui-android/call-service-tests/src/test/kotlin/com/utun/chat/data/CallServiceLifecycleTest.kt @@ -44,6 +44,7 @@ class CallServiceLifecycleTest { AppLanguage.failText = false; AppLanguage.language = "en"; NotificationCompat.failBuild = false Handler.rejectImmediate = false; Handler.rejectDelayed = false; PendingIntent.reset() MediaAudioController.beforeIdle = {} + TelecomCallManager.pending = false CallVideoEngine.failCreate = false; CallVideoEngine.created.clear() CallController.reset(); RadioAudioEngine.instance().activeGroup.value = null; RadioAudioEngine.instance().restored.clear() NativeLib.callCommands.clear(); LogManager.entries.clear(); LogManager.console = true @@ -52,6 +53,7 @@ class CallServiceLifecycleTest { @After fun release() { gates.forEach { it.countDown() }; MediaAudioController.beforeIdle = {} + TelecomCallManager.pending = false NativeLib.failActivityRequest = false Handler.rejectImmediate = false; Handler.rejectDelayed = false AppLanguage.failText = false; NotificationCompat.failBuild = false; CallVideoEngine.failCreate = false @@ -73,6 +75,14 @@ class CallServiceLifecycleTest { private fun diagnostic(fragment: String) = synchronized(LogManager.entries) { assertTrue("Missing diagnostic: $fragment", LogManager.entries.any { fragment in it.message && it.level in listOf("WARN", "ERROR") }) } + + @Test fun pendingTelecomCleanupBlocksNewServiceAndOtherMediaUntilAcknowledged() { + TelecomCallManager.pending = true + assertTrue(CallController.blocksMedia()) + assertThrows(IllegalStateException::class.java) { CallService.start(context, 17) } + assertTrue(context.serviceStarts.isEmpty()) + TelecomCallManager.pending = false; CallService.requireReleased(); assertFalse(CallController.blocksMedia()) + } private fun field(service: CallService, name: String) = CallService::class.java.getDeclaredField(name) .apply { isAccessible = true }.get(service) private fun create(): CallService = CallService().also { diff --git a/tools/chatgui-android/video-tests/src/test/kotlin/com/utun/chat/data/TelecomLifecycleTest.kt b/tools/chatgui-android/video-tests/src/test/kotlin/com/utun/chat/data/TelecomLifecycleTest.kt index 8f87052e1..1558b3f4d 100644 --- a/tools/chatgui-android/video-tests/src/test/kotlin/com/utun/chat/data/TelecomLifecycleTest.kt +++ b/tools/chatgui-android/video-tests/src/test/kotlin/com/utun/chat/data/TelecomLifecycleTest.kt @@ -100,7 +100,10 @@ class TelecomLifecycleTest { @Test fun rejectedRetryTimerRetainsTheOwnerForExplicitRemovalRetry() { val conn = registered(); conn.failures = setOf("destroy"); Handler.rejectDelayed = true TelecomCallManager.setDisconnected(17, 2); TelecomCallManager.removeConnection(17); assertFalse(conn.destroyed) + assertTrue(TelecomCallManager.cleanupPending()) + assertThrows(IllegalStateException::class.java) { TelecomCallManager.requireReleased() } conn.failures = emptySet(); Handler.rejectDelayed = false; TelecomCallManager.removeConnection(17); assertTrue(conn.destroyed) + TelecomCallManager.requireReleased(); assertFalse(TelecomCallManager.cleanupPending()) } @Test fun destroyFailureAfterEffectStillNeedsAnAcknowledgedRetry() { val conn = registered(); conn.failures = setOf("destroy after")