Don't unnecessarily stack GCM message processing.

If we already have two active processing GCM messages, there's no
benefit to a third. In fact, enqueuing additional ones will likely only
end up showing the foreground notification unnecessariliy.
This commit is contained in:
Greyson Parrelli 2018-10-12 14:07:40 -07:00
parent 20c059280c
commit ead323c1af
2 changed files with 52 additions and 20 deletions

View File

@ -19,10 +19,12 @@ import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob;
import org.thoughtcrime.securesms.service.GenericForegroundService; import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.util.PowerManagerCompat; import org.thoughtcrime.securesms.util.PowerManagerCompat;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.concurrent.SignalExecutors;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.signalservice.internal.util.Util;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject; import javax.inject.Inject;
@ -31,6 +33,10 @@ public class GcmBroadcastReceiver extends WakefulBroadcastReceiver implements In
private static final String TAG = GcmBroadcastReceiver.class.getSimpleName(); private static final String TAG = GcmBroadcastReceiver.class.getSimpleName();
private static final Executor MESSAGE_EXECUTOR = SignalExecutors.newCachedSingleThreadExecutor("GcmMessageProcessing");
private static int activeCount = 0;
@Inject SignalServiceMessageReceiver messageReceiver; @Inject SignalServiceMessageReceiver messageReceiver;
@Override @Override
@ -62,6 +68,11 @@ public class GcmBroadcastReceiver extends WakefulBroadcastReceiver implements In
} }
private void handleReceivedNotification(Context context) { private void handleReceivedNotification(Context context) {
if (!incrementActiveGcmCount()) {
Log.i(TAG, "Skipping GCM processing -- there's already one enqueued.");
return;
}
TextSecurePreferences.setNeedsMessagePull(context, true); TextSecurePreferences.setNeedsMessagePull(context, true);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
@ -81,9 +92,7 @@ public class GcmBroadcastReceiver extends WakefulBroadcastReceiver implements In
callback.finish(); callback.finish();
} }
new Thread("GcmMessageProcessing") { MESSAGE_EXECUTOR.execute(() -> {
@Override
public void run() {
try { try {
new PushNotificationReceiveJob(context).pullAndProcessMessages(messageReceiver, TAG, startTime); new PushNotificationReceiveJob(context).pullAndProcessMessages(messageReceiver, TAG, startTime);
} catch (IOException e) { } catch (IOException e) {
@ -100,10 +109,11 @@ public class GcmBroadcastReceiver extends WakefulBroadcastReceiver implements In
} }
taskCompleted.set(true); taskCompleted.set(true);
} }
decrementActiveGcmCount();
Log.i(TAG, "Processing complete."); Log.i(TAG, "Processing complete.");
} }
} });
}.start();
if (!foregroundRunning.get()) { if (!foregroundRunning.get()) {
new Thread("GcmForegroundServiceTimer") { new Thread("GcmForegroundServiceTimer") {
@ -121,4 +131,16 @@ public class GcmBroadcastReceiver extends WakefulBroadcastReceiver implements In
}.start(); }.start();
} }
} }
private static synchronized boolean incrementActiveGcmCount() {
if (activeCount < 2) {
activeCount++;
return true;
}
return false;
}
private static synchronized void decrementActiveGcmCount() {
activeCount--;
}
} }

View File

@ -4,7 +4,10 @@ import android.support.annotation.NonNull;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class SignalExecutors { public class SignalExecutors {
@ -16,4 +19,11 @@ public class SignalExecutors {
return new Thread(r, "signal-io-" + counter.getAndIncrement()); return new Thread(r, "signal-io-" + counter.getAndIncrement());
} }
}); });
public static ExecutorService newCachedSingleThreadExecutor(final String name) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 15, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), r -> new Thread(r, name));
executor.allowCoreThreadTimeOut(true);
return executor;
}
} }