From 2c02f8f355e023a28841274299ecdb840973b5a4 Mon Sep 17 00:00:00 2001 From: Dimitris Papavasiliou Date: Sun, 15 Oct 2017 21:01:34 +0300 Subject: [PATCH] Periodically "prod" the message pipe, when GCM is disabled Added an AlarmManager alarm, to periodically "prod" the SignalServiceMessagePipe, waking any threads that may be stuck in blocking wait, while the device sleeping. Fixes #6644 // FREEBIE --- .../service/MessageRetrievalService.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java index 8d82c0134be..6c26b2915e0 100644 --- a/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java +++ b/src/org/thoughtcrime/securesms/service/MessageRetrievalService.java @@ -1,9 +1,14 @@ package org.thoughtcrime.securesms.service; import android.app.Service; +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.os.IBinder; +import android.os.SystemClock; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.util.Log; @@ -45,6 +50,8 @@ public class MessageRetrievalService extends Service implements InjectableType, private NetworkRequirement networkRequirement; private NetworkRequirementProvider networkRequirementProvider; + private ProdAlarmReceiver prodAlarmReceiver = null; + @Inject public SignalServiceMessageReceiver receiver; @@ -68,6 +75,7 @@ public void onCreate() { retrievalThread.start(); setForegroundIfNecessary(); + enableProddingIfNecessary(); } public int onStartCommand(Intent intent, int flags, int startId) { @@ -88,6 +96,11 @@ public void onDestroy() { retrievalThread.stopThread(); } + if (prodAlarmReceiver != null) { + prodAlarmReceiver.stop(); + unregisterReceiver(prodAlarmReceiver); + } + sendBroadcast(new Intent("org.thoughtcrime.securesms.RESTART")); } @@ -103,6 +116,14 @@ public IBinder onBind(Intent intent) { return null; } + private void enableProddingIfNecessary() { + if (TextSecurePreferences.isGcmDisabled(this)) { + prodAlarmReceiver = new ProdAlarmReceiver(); + registerReceiver(prodAlarmReceiver, + new IntentFilter(ProdAlarmReceiver.WAKE_UP_THREADS_ACTION)); + } + } + private void setForegroundIfNecessary() { if (TextSecurePreferences.isGcmDisabled(this)) { NotificationCompat.Builder builder = new NotificationCompat.Builder(this); @@ -184,6 +205,72 @@ public static void registerActivityStopped(Context activity) { return pipe; } + public class ProdAlarmReceiver extends BroadcastReceiver { + + private final int PRODDING_TIMEOUT_SECONDS = 60; + + private int pipes; + + public static final String WAKE_UP_THREADS_ACTION = "org.thoughtcrime.securesms.ProdAlarReceiver.WAKE_UP_THREADS"; + + private void setOrCancelAlarm(Context context, boolean set) { + Intent intent = new Intent(WAKE_UP_THREADS_ACTION); + PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0); + AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); + + alarmManager.cancel(pendingIntent); + + if (set) { + Log.w(TAG, "Setting repeating alarm to prod the message pipe."); + + alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, + SystemClock.elapsedRealtime() + TimeUnit.SECONDS.toMillis(PRODDING_TIMEOUT_SECONDS), + TimeUnit.SECONDS.toMillis(PRODDING_TIMEOUT_SECONDS), + pendingIntent); + } else { + Log.w(TAG, "Canceling message pipe prodding alarm."); + } + } + + public synchronized void incrementPipes() { + if (pipes < 0) { + return; + } + + pipes++; + + if (pipes == 1) { + setOrCancelAlarm(MessageRetrievalService.this, true); + } + } + + public synchronized void decrementPipes() { + if (pipes < 0) { + return; + } + + pipes--; + + assert (pipes >= 0); + + if (pipes == 0) { + setOrCancelAlarm(MessageRetrievalService.this, false); + } + } + + public synchronized void stop() { + pipes = -1; + setOrCancelAlarm(MessageRetrievalService.this, false); + } + + @Override + public void onReceive(Context context, Intent intent) { + Log.w(TAG, "Prodding the message pipe."); + SignalServiceMessagePipe.prod(); + } + + } + private class MessageRetrievalThread extends Thread implements Thread.UncaughtExceptionHandler { private AtomicBoolean stopThread = new AtomicBoolean(false); @@ -204,6 +291,10 @@ public void run() { SignalServiceMessagePipe localPipe = pipe; + if (prodAlarmReceiver != null) { + prodAlarmReceiver.incrementPipes(); + } + try { while (isConnectionNecessary() && !stopThread.get()) { try { @@ -230,6 +321,11 @@ public void onMessage(SignalServiceEnvelope envelope) { Log.w(TAG, e); } finally { Log.w(TAG, "Shutting down pipe..."); + + if (prodAlarmReceiver != null) { + prodAlarmReceiver.decrementPipes(); + } + shutdown(localPipe); }