Suppress checking for messages on application foreground.

This commit is contained in:
Alex Hart
2023-10-11 14:59:16 -04:00
committed by Cody Henthorne
parent 65d26d753d
commit ab928be1b3

View File

@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.os.Build;
import androidx.annotation.NonNull;
@@ -7,19 +8,20 @@ import androidx.annotation.Nullable;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Job;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.messages.WebSocketDrainer;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.service.DelayedNotificationController;
import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.service.NotificationController;
import org.thoughtcrime.securesms.util.AppForegroundObserver;
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
/**
* Fetches messages from the service, posting a foreground service if possible.
* Fetches messages from the service, posting a foreground service if possible if the app is in the background.
*/
public final class MessageFetchJob extends BaseJob {
@@ -54,19 +56,8 @@ public final class MessageFetchJob extends BaseJob {
public void onRun() throws IOException {
boolean success;
if (Build.VERSION.SDK_INT < 31) {
try (DelayedNotificationController unused = GenericForegroundService.startForegroundTaskDelayed(context, context.getString(R.string.BackgroundMessageRetriever_checking_for_messages), 300, R.drawable.ic_signal_refresh)) {
success = WebSocketDrainer.blockUntilDrainedAndProcessed();
}
} else {
try {
try (NotificationController unused = GenericForegroundService.startForegroundTask(context, context.getString(R.string.BackgroundMessageRetriever_checking_for_messages), NotificationChannels.getInstance().OTHER, R.drawable.ic_signal_refresh)) {
success = WebSocketDrainer.blockUntilDrainedAndProcessed();
}
} catch (UnableToStartException e) {
Log.w(TAG, "Failed to start foreground service. Running in the background.");
success = WebSocketDrainer.blockUntilDrainedAndProcessed();
}
try (ForegroundServiceController controller = ForegroundServiceController.create(context)) {
success = controller.awaitResult();
}
if (success) {
@@ -86,6 +77,92 @@ public final class MessageFetchJob extends BaseJob {
public void onFailure() {
}
/**
* Controls whether or not the ForegroundService is started, based off of whether the application process is
* in the foreground or background.
*/
private static final class ForegroundServiceController implements AppForegroundObserver.Listener, AutoCloseable {
private final @NonNull Context context;
private final @NonNull AtomicReference<AutoCloseable> notificationController = new AtomicReference<>();
private volatile boolean isRunning;
private ForegroundServiceController(@NonNull Context context) {
this.context = context;
}
@Override
public void onForeground() {
if (!isRunning) {
return;
}
closeNotificationController();
}
@Override
public void onBackground() {
if (!isRunning) {
return;
}
if (notificationController.get() != null) {
Log.w(TAG, "Already displaying or displayed a foreground notification.");
return;
}
if (Build.VERSION.SDK_INT < 31) {
notificationController.set(GenericForegroundService.startForegroundTaskDelayed(context, context.getString(R.string.BackgroundMessageRetriever_checking_for_messages), 300, R.drawable.ic_signal_refresh));
} else {
try {
notificationController.set(GenericForegroundService.startForegroundTask(context, context.getString(R.string.BackgroundMessageRetriever_checking_for_messages), NotificationChannels.getInstance().OTHER, R.drawable.ic_signal_refresh));
} catch (UnableToStartException e) {
Log.w(TAG, "Failed to start foreground service. Running without a foreground service.");
}
}
}
@Override
public void close() {
ApplicationDependencies.getAppForegroundObserver().removeListener(this);
closeNotificationController();
}
public boolean awaitResult() {
isRunning = true;
boolean success;
try {
success = WebSocketDrainer.blockUntilDrainedAndProcessed();
} finally {
isRunning = false;
}
return success;
}
private void closeNotificationController() {
AutoCloseable controller = notificationController.get();
if (controller == null) {
return;
}
try {
controller.close();
} catch (Exception e) {
Log.w(TAG, "Exception thrown while closing notification controller", e);
}
}
static ForegroundServiceController create(@NonNull Context context) {
ForegroundServiceController instance = new ForegroundServiceController(context);
ApplicationDependencies.getAppForegroundObserver().addListener(instance);
return instance;
}
}
public static final class Factory implements Job.Factory<MessageFetchJob> {
@Override
public @NonNull MessageFetchJob create(@NonNull Parameters parameters, @Nullable byte[] serializedData) {