From 2f7a141ee68789175b59a39f4b62dbc8c691a1e3 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Sun, 21 Jan 2018 15:05:26 +0100 Subject: postpone notification actions (mark as read, reply) until after messages are loaded --- .../messenger/services/XmppConnectionService.java | 72 ++++++++++++++++------ .../java/de/pixart/messenger/utils/Namespace.java | 1 + .../de/pixart/messenger/xmpp/XmppConnection.java | 10 +-- 3 files changed, 59 insertions(+), 24 deletions(-) (limited to 'src/main/java') diff --git a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java index 50eace97b..6dbd07209 100644 --- a/src/main/java/de/pixart/messenger/services/XmppConnectionService.java +++ b/src/main/java/de/pixart/messenger/services/XmppConnectionService.java @@ -66,6 +66,7 @@ import java.util.ListIterator; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -163,6 +164,7 @@ public class XmppConnectionService extends Service { private final SerialSingleThreadExecutor mVideoCompressionExecutor = new SerialSingleThreadExecutor("VideoCompression"); private final SerialSingleThreadExecutor mDatabaseWriterExecutor = new SerialSingleThreadExecutor("DatabaseWriter"); private final SerialSingleThreadExecutor mDatabaseReaderExecutor = new SerialSingleThreadExecutor("DatabaseReader"); + private final SerialSingleThreadExecutor mNotificationExecutor = new SerialSingleThreadExecutor("NotificationExecutor"); private final IBinder mBinder = new XmppConnectionBinder(); private final List conversations = new CopyOnWriteArrayList<>(); private final IqGenerator mIqGenerator = new IqGenerator(this); @@ -426,14 +428,14 @@ public class XmppConnectionService extends Service { private LruCache mBitmapCache; private EventReceiver mEventReceiver = new EventReceiver(); - private boolean mRestoredFromDatabase = false; + public final CountDownLatch restoredFromDatabaseLatch = new CountDownLatch(1); private static String generateFetchKey(Account account, final Avatar avatar) { return account.getJid().toBareJid() + "_" + avatar.owner + "_" + avatar.sha1sum; } public boolean areMessagesInitialized() { - return this.mRestoredFromDatabase; + return this.restoredFromDatabaseLatch.getCount() == 0; } public PgpEngine getPgpEngine() { @@ -573,7 +575,6 @@ public class XmppConnectionService extends Service { boolean interactive = false; if (action != null) { final String uuid = intent.getStringExtra("uuid"); - final Conversation c = findConversationByUuid(uuid); switch (action) { case ConnectivityManager.CONNECTIVITY_ACTION: if (hasInternetConnection() && Config.RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE) { @@ -581,7 +582,7 @@ public class XmppConnectionService extends Service { } break; case ACTION_MERGE_PHONE_CONTACTS: - if (mRestoredFromDatabase) { + if (restoredFromDatabaseLatch.getCount() == 0) { loadPhoneContacts(); } return START_STICKY; @@ -589,11 +590,20 @@ public class XmppConnectionService extends Service { logoutAndSave(true); return START_NOT_STICKY; case ACTION_CLEAR_NOTIFICATION: - if (c != null) { - mNotificationService.clear(c); - } else { - mNotificationService.clear(); - } + mNotificationExecutor.execute(() -> { + try { + final Conversation c = findConversationByUuid(uuid); + if (c != null) { + mNotificationService.clear(c); + } else { + mNotificationService.clear(); + } + restoredFromDatabaseLatch.await(); + + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process clear notification"); + } + }); break; case ACTION_DISMISS_ERROR_NOTIFICATIONS: dismissErrorNotifications(); @@ -604,19 +614,41 @@ public class XmppConnectionService extends Service { break; case ACTION_REPLY_TO_CONVERSATION: Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); - if (remoteInput != null && c != null) { - final CharSequence body = remoteInput.getCharSequence("text_reply"); - if (body != null && body.length() > 0) { - directReply(c, body.toString(), intent.getBooleanExtra("dismiss_notification", false)); - } + if (remoteInput == null) { + break; + } + final CharSequence body = remoteInput.getCharSequence("text_reply"); + final boolean dismissNotification = intent.getBooleanExtra("dismiss_notification", false); + if (body == null || body.length() <= 0) { + break; } + mNotificationExecutor.execute(() -> { + try { + restoredFromDatabaseLatch.await(); + final Conversation c = findConversationByUuid(uuid); + if (c != null) { + directReply(c, body.toString(), dismissNotification); + } + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process direct reply"); + } + }); break; case ACTION_MARK_AS_READ: - if (c != null) { - sendReadMarker(c); - } else { - Log.d(Config.LOGTAG, "received mark read intent for unknown conversation (" + uuid + ")"); - } + mNotificationExecutor.execute(() -> { + final Conversation c = findConversationByUuid(uuid); + if (c == null) { + Log.d(Config.LOGTAG, "received mark read intent for unknown conversation (" + uuid + ")"); + return; + } + try { + restoredFromDatabaseLatch.await(); + sendReadMarker(c); + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, "unable to process notification read marker for conversation " + c.getName()); + } + + }); break; case AudioManager.RINGER_MODE_CHANGED_ACTION: if (dndOnSilentMode()) { @@ -1591,7 +1623,7 @@ public class XmppConnectionService extends Service { }); } mNotificationService.finishBacklog(false); - mRestoredFromDatabase = true; + restoredFromDatabaseLatch.countDown(); final long diffMessageRestore = SystemClock.elapsedRealtime() - startMessageRestore; Log.d(Config.LOGTAG, "finished restoring messages in " + diffMessageRestore + "ms"); updateConversationUi(); diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java index 75e3855a4..cdf8f8650 100644 --- a/src/main/java/de/pixart/messenger/utils/Namespace.java +++ b/src/main/java/de/pixart/messenger/utils/Namespace.java @@ -17,4 +17,5 @@ public final class Namespace { public static final String PUBSUB_ERROR = "http://jabber.org/protocol/pubsub#errors"; public static final String NICK = "http://jabber.org/protocol/nick"; public static final String FLEXIBLE_OFFLINE_MESSAGE_RETRIEVAL = "http://jabber.org/protocol/offline"; + public static final String BIND = "urn:ietf:params:xml:ns:xmpp-bind"; } diff --git a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java index 0e168ca3b..f015544ed 100644 --- a/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java +++ b/src/main/java/de/pixart/messenger/xmpp/XmppConnection.java @@ -1073,14 +1073,16 @@ public class XmppConnection implements Runnable { } private void sendBindRequest() { - while (!mXmppConnectionService.areMessagesInitialized() && socket != null && !socket.isClosed()) { - uninterruptedSleep(500); + try { + mXmppConnectionService.restoredFromDatabaseLatch.await(); + } catch (InterruptedException e) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": interrupted while waiting for DB restore during bind"); + return; } needsBinding = false; clearIqCallbacks(); final IqPacket iq = new IqPacket(IqPacket.TYPE.SET); - iq.addChild("bind", "urn:ietf:params:xml:ns:xmpp-bind") - .addChild("resource").setContent(account.getResource()); + iq.addChild("bind", Namespace.BIND).addChild("resource").setContent(account.getResource()); this.sendUnmodifiedIqPacket(iq, new OnIqPacketReceived() { @Override public void onIqPacketReceived(final Account account, final IqPacket packet) { -- cgit v1.2.3