From 917e764b6f4ef1f1f915f371cf57a5195e07324d Mon Sep 17 00:00:00 2001 From: wchen342 Date: Mon, 27 Apr 2026 14:34:51 -0400 Subject: [PATCH] Promote call FGS asap (#4377) * Promote call FGS as soon as possible * Add resource strings for call notification * Launch with only phone call type on 14+ --- src/main/AndroidManifest.xml | 3 +- .../securesms/calls/CallCoordinator.java | 26 ++++++++-- .../securesms/calls/CallService.java | 48 +++++++++++++++++-- src/main/res/values/strings.xml | 2 + 4 files changed, 69 insertions(+), 10 deletions(-) diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 191e1e81a..0e66c7835 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -71,6 +71,7 @@ android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" /> + @@ -490,7 +491,7 @@ android:name=".calls.CallService" android:enabled="true" android:exported="false" - android:foregroundServiceType="camera|microphone" /> + android:foregroundServiceType="camera|microphone|phoneCall" /> startForegroundWithNotification(id, notification)); + return; + } + + Log.d(TAG, "Starting call FGS with notification id: " + id); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + startForeground(id, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + int types = + ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE + | ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA; + startForeground(id, notification, types); + } else { + startForeground(id, notification); + } + } catch (Exception e) { + Log.e(TAG, "startForeground failed", e); + if (callCoordinator != null) { + callCoordinator.reportError("Failed to activate call FGS: " + e.getMessage()); + } + } } public void stopForegroundAndDismiss() { - Log.d(TAG, "Stopping foreground and dismissing notification"); - stopForeground(STOP_FOREGROUND_REMOVE); + if (Looper.myLooper() != Looper.getMainLooper()) { + new Handler(Looper.getMainLooper()).post(this::stopForegroundAndDismiss); + return; + } + Log.d(TAG, "Stopping call FGS and dismissing notification"); + try { + stopForeground(STOP_FOREGROUND_REMOVE); + } catch (Exception e) { + Log.w(TAG, "stopForeground failed", e); + } } // Cleanup diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 2a032296f..0de5e12c6 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -430,6 +430,8 @@ Already in a call Call answered on another device Microphone permission is required for calls + Call with %1$s + Calling %1$s…