Verify Telecom cleanup blocks media and new foreground ownership

This commit is contained in:
evgeny committed 2026-10-29 13:34:25 +01:00
1 parent b71f992a45
commit 9f1b09aefe
3 files changed
+16

No files matched your search

@@ -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)
@@ -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 {
@@ -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")