From 57e8684bb3314ec866e12457e4298bc9cc41c929 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 27 Feb 2023 19:52:09 -0500 Subject: [PATCH] Always use a foreground service when processing high-priority FCM pushes. --- .../securesms/gcm/FcmReceiveService.java | 11 ++++++++--- .../messages/IncomingMessageObserver.java | 16 +++++++++++++++- .../securesms/messages/WebSocketStrategy.java | 1 - .../securesms/util/FeatureFlags.java | 3 ++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java b/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java index c23bd4be9a..cb226c5ef1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java +++ b/app/src/main/java/org/thoughtcrime/securesms/gcm/FcmReceiveService.java @@ -81,13 +81,18 @@ public class FcmReceiveService extends FirebaseMessagingService { boolean enqueueSuccessful = false; try { - long timeSinceLastRefresh = System.currentTimeMillis() - SignalStore.misc().getLastFcmForegroundServiceTime(); + boolean highPriority = remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH; + long timeSinceLastRefresh = System.currentTimeMillis() - SignalStore.misc().getLastFcmForegroundServiceTime(); + Log.d(TAG, String.format(Locale.US, "[handleReceivedNotification] API: %s, FeatureFlag: %s, RemoteMessagePriority: %s, TimeSinceLastRefresh: %s ms", Build.VERSION.SDK_INT, FeatureFlags.useFcmForegroundService(), remoteMessage != null ? remoteMessage.getPriority() : "n/a", timeSinceLastRefresh)); - if (FeatureFlags.useFcmForegroundService() && Build.VERSION.SDK_INT >= 31 && remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH && timeSinceLastRefresh > FCM_FOREGROUND_INTERVAL) { + if (highPriority && FeatureFlags.useFcmForegroundService()) { enqueueSuccessful = FcmFetchManager.enqueue(context, true); SignalStore.misc().setLastFcmForegroundServiceTime(System.currentTimeMillis()); - } else if (Build.VERSION.SDK_INT < 26 || remoteMessage == null || remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH) { + } else if (highPriority && Build.VERSION.SDK_INT >= 31 && timeSinceLastRefresh > FCM_FOREGROUND_INTERVAL) { + enqueueSuccessful = FcmFetchManager.enqueue(context, true); + SignalStore.misc().setLastFcmForegroundServiceTime(System.currentTimeMillis()); + } else if (highPriority || Build.VERSION.SDK_INT < 26 || remoteMessage == null) { enqueueSuccessful = FcmFetchManager.enqueue(context, false); } } catch (Exception e) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.java b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.java index 74e33704fc..2188010061 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/IncomingMessageObserver.java @@ -43,6 +43,8 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import io.reactivex.rxjava3.disposables.Disposable; + /** * The application-level manager of our websocket connection. *

@@ -198,7 +200,7 @@ public class IncomingMessageObserver { String needsConnectionString = conclusion ? "Needs Connection" : "Does Not Need Connection"; - Log.d(TAG, String.format(Locale.US, "[" + needsConnectionString + "] Network: %s, Foreground: %s, Time Since Last Interaction: %s, FCM: %s, Stay open requests: [%s], Registered: %s, Proxy: %s, Force websocket: %s", + Log.d(TAG, String.format(Locale.US, "[" + needsConnectionString + "] Network: %s, Foreground: %s, Time Since Last Interaction: %s, FCM: %s, Stay open requests: [%s], Registered: %s, Proxy: %s, Force websocket: %s", hasNetwork, appVisible, lastInteractionString, fcmEnabled, Util.join(keepAliveTokens.entrySet(), ","), registered, hasProxy, forceWebsocket)); return conclusion; @@ -263,6 +265,15 @@ public class IncomingMessageObserver { Log.i(TAG, "Making websocket connection...."); SignalWebSocket signalWebSocket = ApplicationDependencies.getSignalWebSocket(); + + Disposable webSocketDisposable = signalWebSocket.getWebSocketState().subscribe(state -> { + Log.d(TAG, "WebSocket State: " + state); + + // Any state change at all means that we are not drained + networkDrained = false; + decryptionDrained = false; + }); + signalWebSocket.connect(); try { @@ -281,6 +292,8 @@ public class IncomingMessageObserver { Log.i(TAG, "Network was newly-drained. Enqueuing a job to listen for decryption draining."); networkDrained = true; ApplicationDependencies.getJobManager().add(new PushDecryptDrainedJob()); + } else if (!result.isPresent()) { + Log.w(TAG, "Got tombstone, but we thought the network was already drained!"); } } catch (WebSocketUnavailableException e) { Log.i(TAG, "Pipe unexpectedly unavailable, connecting"); @@ -300,6 +313,7 @@ public class IncomingMessageObserver { } finally { Log.w(TAG, "Shutting down pipe..."); disconnect(); + webSocketDisposable.dispose(); } Log.i(TAG, "Looping..."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/WebSocketStrategy.java b/app/src/main/java/org/thoughtcrime/securesms/messages/WebSocketStrategy.java index cb4b67e318..58b1e3f942 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/WebSocketStrategy.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/WebSocketStrategy.java @@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.jobmanager.JobTracker; import org.thoughtcrime.securesms.jobs.MarkerJob; -import org.thoughtcrime.securesms.jobs.PushDecryptMessageJob; import org.thoughtcrime.securesms.jobs.PushProcessMessageJob; import java.util.Optional; diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index 7aca3d065d..0f8e650b83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -87,7 +87,7 @@ public final class FeatureFlags { private static final String USE_AEC3 = "android.calling.useAec3"; private static final String PAYMENTS_COUNTRY_BLOCKLIST = "global.payments.disabledRegions"; public static final String PHONE_NUMBER_PRIVACY = "android.pnp"; - private static final String USE_FCM_FOREGROUND_SERVICE = "android.useFcmForegroundService.3"; + private static final String USE_FCM_FOREGROUND_SERVICE = "android.useFcmForegroundService.4"; private static final String STORIES_AUTO_DOWNLOAD_MAXIMUM = "android.stories.autoDownloadMaximum"; private static final String TELECOM_MANUFACTURER_ALLOWLIST = "android.calling.telecomAllowList"; private static final String TELECOM_MODEL_BLOCKLIST = "android.calling.telecomModelBlockList"; @@ -487,6 +487,7 @@ public final class FeatureFlags { return getBoolean(USE_AEC3, true); } + /** Whether or not we show a foreground service on every high-priority FCM push. */ public static boolean useFcmForegroundService() { return getBoolean(USE_FCM_FOREGROUND_SERVICE, false); }