From 4eb1191748c06cf3da4e0c19573051aa3d286808 Mon Sep 17 00:00:00 2001 From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com> Date: Fri, 10 Oct 2025 19:59:17 +0530 Subject: [PATCH] feat: enhance background streaming functionality with improved wake lock management - Updated the wake lock duration in BackgroundStreamingHandler to 3 hours, ensuring the service remains active for longer periods. - Modified the keepAlive method to support both iOS and Android, allowing for better background task management across platforms. - Implemented a periodic keep-alive timer in VoiceCallService to refresh the wake lock every 5 minutes, enhancing service reliability during voice calls. - Added debug logging for successful keep-alive invocations, improving traceability of background operations. --- .../conduit/BackgroundStreamingHandler.kt | 4 ++-- .../services/background_streaming_handler.dart | 8 ++++++-- .../chat/services/voice_call_service.dart | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/kotlin/app/cogwheel/conduit/BackgroundStreamingHandler.kt b/android/app/src/main/kotlin/app/cogwheel/conduit/BackgroundStreamingHandler.kt index 9f21635..e07ea85 100644 --- a/android/app/src/main/kotlin/app/cogwheel/conduit/BackgroundStreamingHandler.kt +++ b/android/app/src/main/kotlin/app/cogwheel/conduit/BackgroundStreamingHandler.kt @@ -144,13 +144,13 @@ class BackgroundStreamingService : Service() { private fun acquireWakeLock() { if (wakeLock?.isHeld == true) return - + val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager wakeLock = powerManager.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "Conduit::StreamingWakeLock" ).apply { - acquire(15 * 60 * 1000L) // 15 minutes max + acquire(3 * 60 * 60 * 1000L) // 3 hours max (refreshed every 5 minutes) } println("BackgroundStreamingService: Wake lock acquired") } diff --git a/lib/core/services/background_streaming_handler.dart b/lib/core/services/background_streaming_handler.dart index 278004a..f2aa3f8 100644 --- a/lib/core/services/background_streaming_handler.dart +++ b/lib/core/services/background_streaming_handler.dart @@ -169,12 +169,16 @@ class BackgroundStreamingHandler { return _streamStates[streamId]; } - /// Keep alive the background task (iOS only) + /// Keep alive the background task + /// + /// On iOS: Refreshes background task to prevent early termination + /// On Android: Refreshes wake lock to keep service running Future keepAlive() async { - if (!Platform.isIOS) return; + if (!Platform.isIOS && !Platform.isAndroid) return; try { await _channel.invokeMethod('keepAlive'); + DebugLogger.stream('keepalive-success', scope: 'background'); } catch (e) { DebugLogger.error('keepalive-failed', scope: 'background', error: e); } diff --git a/lib/features/chat/services/voice_call_service.dart b/lib/features/chat/services/voice_call_service.dart index 3f97944..da4d1c1 100644 --- a/lib/features/chat/services/voice_call_service.dart +++ b/lib/features/chat/services/voice_call_service.dart @@ -42,6 +42,7 @@ class VoiceCallService { bool _isDisposed = false; bool _isMuted = false; SocketEventSubscription? _socketSubscription; + Timer? _keepAliveTimer; final StreamController _stateController = StreamController.broadcast(); @@ -137,6 +138,13 @@ class VoiceCallService { _voiceCallStreamId, ], requiresMicrophone: true); + // Set up periodic keep-alive to refresh wake lock (every 5 minutes) + _keepAliveTimer?.cancel(); + _keepAliveTimer = Timer.periodic( + const Duration(minutes: 5), + (_) => BackgroundStreamingHandler.instance.keepAlive(), + ); + // Set up socket event listener for assistant responses _socketSubscription = _socketService.addChatEventHandler( conversationId: conversationId, @@ -149,6 +157,8 @@ class VoiceCallService { await _startListening(); } catch (e) { _updateState(VoiceCallState.error); + _keepAliveTimer?.cancel(); + _keepAliveTimer = null; await WakelockPlus.disable(); await _notificationService.cancelNotification(); await BackgroundStreamingHandler.instance.stopBackgroundExecution(const [ @@ -334,6 +344,10 @@ class VoiceCallService { Future stopCall() async { if (_isDisposed) return; + // Cancel keep-alive timer + _keepAliveTimer?.cancel(); + _keepAliveTimer = null; + await _transcriptSubscription?.cancel(); await _intensitySubscription?.cancel(); _socketSubscription?.dispose(); @@ -436,6 +450,10 @@ class VoiceCallService { Future dispose() async { _isDisposed = true; + // Cancel keep-alive timer + _keepAliveTimer?.cancel(); + _keepAliveTimer = null; + await _transcriptSubscription?.cancel(); await _intensitySubscription?.cancel(); _socketSubscription?.dispose();