From 982ed0ca7d0d3ee297d8dd316fd99a0dc22c870b Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 28 Oct 2026 16:52:26 +0100 Subject: [PATCH] Model recoverable receiver and radio output lifecycle failures --- .../main/kotlin/android/content/Context.kt | 19 ++++++++++++++++--- .../main/kotlin/android/media/HostTracks.kt | 15 +++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tools/chatgui-android/router-tests/src/main/kotlin/android/content/Context.kt b/tools/chatgui-android/router-tests/src/main/kotlin/android/content/Context.kt index e588e67de..33081efa4 100644 --- a/tools/chatgui-android/router-tests/src/main/kotlin/android/content/Context.kt +++ b/tools/chatgui-android/router-tests/src/main/kotlin/android/content/Context.kt @@ -38,8 +38,21 @@ class Context { var telephonyManager: TelephonyManager? = TelephonyManager() val configProvider = HostConfigProvider() val receivers = mutableMapOf() - fun registerReceiver(receiver: BroadcastReceiver, filter: IntentFilter, flags: Int = 0) { receivers[receiver] = filter } - fun unregisterReceiver(receiver: BroadcastReceiver) { check(receivers.remove(receiver) != null) { "receiver not registered" } } + var receiverFailures = emptySet() + var registrationAttempts = 0 + var unregistrationAttempts = 0 + fun registerReceiver(receiver: BroadcastReceiver, filter: IntentFilter, flags: Int = 0) { + registrationAttempts++ + check("register" !in receiverFailures) { "receiver registration failed" } + receivers[receiver] = filter + check("register after" !in receiverFailures) { "receiver registration failed after effect" } + } + fun unregisterReceiver(receiver: BroadcastReceiver) { + unregistrationAttempts++ + check("unregister" !in receiverFailures) { "receiver unregistration failed" } + require(receivers.remove(receiver) != null) { "receiver not registered" } + check("unregister after" !in receiverFailures) { "receiver unregistration failed after effect" } + } val applicationContext: Context get() = this fun startActivity(intent: Intent) { activityAttempts.add(Intent(intent)) @@ -49,7 +62,7 @@ class Context { AUDIO_SERVICE -> AudioManager.shared SENSOR_SERVICE -> sensorManager VIBRATOR_SERVICE -> vibrator - POWER_SERVICE -> powerManager + POWER_SERVICE -> { check(!failPowerService) { "power service lookup unavailable" }; powerManager } WIFI_SERVICE -> { check(!failWifiService) { "Wi-Fi service unavailable" }; wifiManager } else -> error("Unknown service: $name") } diff --git a/tools/chatgui-android/router-tests/src/main/kotlin/android/media/HostTracks.kt b/tools/chatgui-android/router-tests/src/main/kotlin/android/media/HostTracks.kt index eb7b0d105..418fc9c38 100644 --- a/tools/chatgui-android/router-tests/src/main/kotlin/android/media/HostTracks.kt +++ b/tools/chatgui-android/router-tests/src/main/kotlin/android/media/HostTracks.kt @@ -12,17 +12,28 @@ class AudioTrack(val id: Int) : AudioRouting { const val MODE_STREAM = 1 private var nextId = 100 val created = mutableListOf() - fun getMinBufferSize(rate: Int, channels: Int, encoding: Int): Int = 1920 + var nextFailures = emptySet() + var minimumBuffer = 1920 + fun getMinBufferSize(rate: Int, channels: Int, encoding: Int): Int = minimumBuffer } constructor(attributes: AudioAttributes, format: AudioFormat, bufferSize: Int, mode: Int, session: Int) : this(++nextId) { check(mode == MODE_STREAM && bufferSize >= 1920 && session == AudioManager.AUDIO_SESSION_ID_GENERATE) + check("create" !in nextFailures) { "track creation failed" } + failures = nextFailures created.add(this) } var playbackHeadPosition = 0 private set fun play() { access("play") } fun stop() { access("stop") } - fun release() { access("release"); released = true } + var releaseCalls = 0 + private set + fun release() { + releaseCalls++ + check("release" !in failures) { "track release failed" } + released = true + check("release after" !in failures) { "track release failed after effect" } + } fun write(samples: ShortArray, offset: Int, count: Int): Int { access("write") check(offset >= 0 && offset + count <= samples.size)