Scheduled messages cleanup

Stephen Paul Weber created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java          |  2 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 51 
2 files changed, 29 insertions(+), 24 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -357,7 +357,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
         final ArrayList<Message> results = new ArrayList<>();
         synchronized (this.messages) {
             for (Message message : this.messages) {
-                if (message.getStatus() == Message.STATUS_WAITING || message.getTimeSent() > System.currentTimeMillis()) {
+                if (message.getStatus() == Message.STATUS_WAITING) {
                     results.add(message);
                 }
             }

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -91,6 +91,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
@@ -269,6 +270,7 @@ public class XmppConnectionService extends Service {
     private final ReplacingSerialSingleThreadExecutor mStickerScanExecutor = new ReplacingSerialSingleThreadExecutor("StickerScan");
     private long mLastActivity = 0;
     private long mLastMucPing = 0;
+    private Map<String, Message> mScheduledMessages = new HashMap<>();
     private long mLastStickerRescan = 0;
     private final FileBackend fileBackend = new FileBackend(this);
     private MemorizingTrustManager mMemorizingTrustManager;
@@ -1067,10 +1069,9 @@ public class XmppConnectionService extends Service {
                 }
                 return START_NOT_STICKY;
         }
+        sendScheduledMessages();
         final var extras =  intent == null ? null : intent.getExtras();
         try {
-            Log.d(Config.LOGTAG, "looking for and sending scheduled messages");
-            sendScheduledMessages();
             internalPingExecutor.execute(() -> manageAccountConnectionStates(action, extras));
         } catch (final RejectedExecutionException e) {
             Log.e(Config.LOGTAG, "can not schedule connection states manager");
@@ -1157,9 +1158,13 @@ public class XmppConnectionService extends Service {
     }
 
     private void sendScheduledMessages() {
-        List<Conversation> conversations = getConversations();
-        for (Conversation conversation : conversations) {
-            final Account account = conversation.getAccount();
+        Log.d(Config.LOGTAG, "looking for and sending scheduled messages");
+
+        for (final var message : new ArrayList<>(mScheduledMessages.values())) {
+            if (message.getTimeSent() > System.currentTimeMillis()) continue;
+
+            final var conversation = message.getConversation();
+            final var account = conversation.getAccount();
             final boolean inProgressJoin;
             synchronized (account.inProgressConferenceJoins) {
                 inProgressJoin = account.inProgressConferenceJoins.contains(conversation);
@@ -1171,7 +1176,7 @@ public class XmppConnectionService extends Service {
             if (conversation.getAccount() == account
                     && !pendingJoin
                     && !inProgressJoin) {
-                sendUnsentMessages(conversation);
+                resendMessage(message, false);
             }
         }
     }
@@ -1852,21 +1857,18 @@ public class XmppConnectionService extends Service {
         }
     }
 
-    private void scheduleNextIdlePing() {
-        scheduleNextIdlePing(0);
-    }
-
     @TargetApi(Build.VERSION_CODES.M)
-    private void scheduleNextIdlePing(long epochMillis) {
-        final long timeToWake;
-        if (epochMillis > 0) {
-            timeToWake = epochMillis;
-            Log.d(Config.LOGTAG, "scheduling next idle ping for " + timeToWake);
-        } else {
-            timeToWake = SystemClock.elapsedRealtime() + (Config.IDLE_PING_INTERVAL * 1000);
+    private void scheduleNextIdlePing() {
+        long timeUntilWake = Config.IDLE_PING_INTERVAL * 1000;
+        final var now = System.currentTimeMillis();
+        for (final var message : mScheduledMessages.values()) {
+            if (message.getTimeSent() <= now) continue; // Just in case
+            if (message.getTimeSent() - now < timeUntilWake) timeUntilWake = message.getTimeSent() - now;
         }
+        final var timeToWake = SystemClock.elapsedRealtime() + timeUntilWake;
         final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
         if (alarmManager == null) {
+            Log.d(Config.LOGTAG, "no alarm manager?");
             return;
         }
         final Intent intent = new Intent(this, SystemEventReceiver.class);
@@ -2059,8 +2061,7 @@ public class XmppConnectionService extends Service {
             }
         }
 
-        // TODO: use timer to grab list of currently scheduled messages from in mem representation and sends them
-        if (account.isOnlineAndConnected() && !inProgressJoin && !waitForPreview && !(message.getTimeSent() > System.currentTimeMillis())) {
+        if (account.isOnlineAndConnected() && !inProgressJoin && !waitForPreview && message.getTimeSent() <= System.currentTimeMillis()) {
             switch (message.getEncryption()) {
                 case Message.ENCRYPTION_NONE:
                     if (message.needsUploading()) {
@@ -2148,16 +2149,20 @@ public class XmppConnectionService extends Service {
             }
         }
 
+        synchronized (mScheduledMessages) {
+            if (message.getTimeSent() > System.currentTimeMillis()) {
+                mScheduledMessages.put(message.getUuid(), message);
+                scheduleNextIdlePing();
+            } else {
+                mScheduledMessages.remove(message.getUuid());
+            }
+        }
 
         boolean mucMessage = conversation.getMode() == Conversation.MODE_MULTI && !message.isPrivateMessage();
         if (mucMessage) {
             message.setCounterpart(conversation.getMucOptions().getSelf().getFullJid());
         }
 
-        if (message.getTimeSent() > System.currentTimeMillis()) {
-            scheduleNextIdlePing(message.getTimeSent());
-        }
-
         if (resend) {
             if (packet != null && addToConversation) {
                 if (account.getXmppConnection().getFeatures().sm() || mucMessage) {