Separate thread updates into a job and other perf improvements.

fork-5.53.8
Greyson Parrelli 2021-08-24 11:11:48 -04:00 zatwierdzone przez Alex Hart
rodzic db7272730e
commit 665d9e31f6
19 zmienionych plików z 268 dodań i 110 usunięć

Wyświetl plik

@ -36,6 +36,9 @@ import org.thoughtcrime.securesms.migrations.LegacyMigrationJob;
import org.thoughtcrime.securesms.util.SqlUtil; import org.thoughtcrime.securesms.util.SqlUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.io.Closeable;
import java.io.IOException;
public class DatabaseFactory { public class DatabaseFactory {
private static final Object lock = new Object(); private static final Object lock = new Object();
@ -311,4 +314,17 @@ public class DatabaseFactory {
public boolean hasTable(String table) { public boolean hasTable(String table) {
return SqlUtil.tableExists(databaseHelper.getRawReadableDatabase(), table); return SqlUtil.tableExists(databaseHelper.getRawReadableDatabase(), table);
} }
public @NonNull Transaction transaction() {
getRawDatabase().beginTransaction();
return () -> {
getRawDatabase().setTransactionSuccessful();
getRawDatabase().endTransaction();
};
}
public interface Transaction extends Closeable {
@Override
void close();
}
} }

Wyświetl plik

@ -102,7 +102,6 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract void markExpireStarted(Collection<Long> messageId, long startTime); public abstract void markExpireStarted(Collection<Long> messageId, long startTime);
public abstract void markAsEndSession(long id); public abstract void markAsEndSession(long id);
public abstract void markAsPreKeyBundle(long id);
public abstract void markAsInvalidVersionKeyExchange(long id); public abstract void markAsInvalidVersionKeyExchange(long id);
public abstract void markAsSecure(long id); public abstract void markAsSecure(long id);
public abstract void markAsInsecure(long id); public abstract void markAsInsecure(long id);
@ -111,7 +110,6 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract void markAsRateLimited(long id); public abstract void markAsRateLimited(long id);
public abstract void clearRateLimitStatus(Collection<Long> ids); public abstract void clearRateLimitStatus(Collection<Long> ids);
public abstract void markAsDecryptFailed(long id); public abstract void markAsDecryptFailed(long id);
public abstract void markAsDecryptDuplicate(long id);
public abstract void markAsNoSession(long id); public abstract void markAsNoSession(long id);
public abstract void markAsUnsupportedProtocolVersion(long id); public abstract void markAsUnsupportedProtocolVersion(long id);
public abstract void markAsInvalidMessage(long id); public abstract void markAsInvalidMessage(long id);
@ -119,8 +117,8 @@ public abstract class MessageDatabase extends Database implements MmsSmsColumns
public abstract void markAsOutbox(long id); public abstract void markAsOutbox(long id);
public abstract void markAsPendingInsecureSmsFallback(long id); public abstract void markAsPendingInsecureSmsFallback(long id);
public abstract void markAsSent(long messageId, boolean secure); public abstract void markAsSent(long messageId, boolean secure);
public abstract void markAsSentFailed(long id);
public abstract void markUnidentified(long messageId, boolean unidentified); public abstract void markUnidentified(long messageId, boolean unidentified);
public abstract void markAsSentFailed(long id);
public abstract void markAsSending(long messageId); public abstract void markAsSending(long messageId);
public abstract void markAsRemoteDelete(long messageId); public abstract void markAsRemoteDelete(long messageId);
public abstract void markAsMissedCall(long id, boolean isVideoOffer); public abstract void markAsMissedCall(long id, boolean isVideoOffer);

Wyświetl plik

@ -56,6 +56,7 @@ import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList; import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange; import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
import org.thoughtcrime.securesms.jobs.ThreadUpdateJob;
import org.thoughtcrime.securesms.jobs.TrimThreadJob; import org.thoughtcrime.securesms.jobs.TrimThreadJob;
import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
@ -296,11 +297,6 @@ public class MmsDatabase extends MessageDatabase {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public void markAsPreKeyBundle(long id) {
throw new UnsupportedOperationException();
}
@Override @Override
public void markAsInvalidVersionKeyExchange(long id) { public void markAsInvalidVersionKeyExchange(long id) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -321,11 +317,6 @@ public class MmsDatabase extends MessageDatabase {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public void markAsDecryptDuplicate(long id) {
throw new UnsupportedOperationException();
}
@Override @Override
public void markAsNoSession(long id) { public void markAsNoSession(long id) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -759,7 +750,7 @@ public class MmsDatabase extends MessageDatabase {
" WHERE " + ID + " = ?", new String[] {id + ""}); " WHERE " + ID + " = ?", new String[] {id + ""});
if (threadId.isPresent()) { if (threadId.isPresent()) {
DatabaseFactory.getThreadDatabase(context).update(threadId.get(), false); DatabaseFactory.getThreadDatabase(context).updateSnippetTypeSilently(threadId.get());
} }
} }
@ -1352,7 +1343,7 @@ public class MmsDatabase extends MessageDatabase {
if (!Types.isExpirationTimerUpdate(mailbox)) { if (!Types.isExpirationTimerUpdate(mailbox)) {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
} }
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
@ -1445,12 +1436,13 @@ public class MmsDatabase extends MessageDatabase {
@Override @Override
public void markIncomingNotificationReceived(long threadId) { public void markIncomingNotificationReceived(long threadId) {
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
if (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context)) { if (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context)) {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
} }
ThreadUpdateJob.enqueue(threadId);
TrimThreadJob.enqueueAsync(threadId); TrimThreadJob.enqueueAsync(threadId);
} }
@ -1658,9 +1650,11 @@ public class MmsDatabase extends MessageDatabase {
insertListener.onComplete(); insertListener.onComplete();
} }
notifyConversationListeners(contentValues.getAsLong(THREAD_ID)); long contentValuesThreadId = contentValues.getAsLong(THREAD_ID);
DatabaseFactory.getThreadDatabase(context).setLastScrolled(contentValues.getAsLong(THREAD_ID), 0);
DatabaseFactory.getThreadDatabase(context).update(contentValues.getAsLong(THREAD_ID), true); notifyConversationListeners(contentValuesThreadId);
DatabaseFactory.getThreadDatabase(context).setLastScrolled(contentValuesThreadId, 0);
ThreadUpdateJob.enqueue(contentValuesThreadId);
} }
} }

Wyświetl plik

@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateD
import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails; import org.thoughtcrime.securesms.database.model.databaseprotos.ProfileChangeDetails;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange; import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange;
import org.thoughtcrime.securesms.jobs.ThreadUpdateJob;
import org.thoughtcrime.securesms.jobs.TrimThreadJob; import org.thoughtcrime.securesms.jobs.TrimThreadJob;
import org.thoughtcrime.securesms.mms.IncomingMediaMessage; import org.thoughtcrime.securesms.mms.IncomingMediaMessage;
import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.MmsException;
@ -58,6 +59,7 @@ import org.thoughtcrime.securesms.util.Base64;
import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.CursorUtil;
import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.JsonUtils;
import org.thoughtcrime.securesms.util.SqlUtil; import org.thoughtcrime.securesms.util.SqlUtil;
import org.thoughtcrime.securesms.util.Stopwatch;
import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.Pair;
@ -177,14 +179,24 @@ public class SmsDatabase extends MessageDatabase {
private void updateTypeBitmask(long id, long maskOff, long maskOn) { private void updateTypeBitmask(long id, long maskOff, long maskOn) {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long threadId;
db.beginTransaction();
try {
db.execSQL("UPDATE " + TABLE_NAME + db.execSQL("UPDATE " + TABLE_NAME +
" SET " + TYPE + " = (" + TYPE + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + " )" + " SET " + TYPE + " = (" + TYPE + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + " )" +
" WHERE " + ID + " = ?", SqlUtil.buildArgs(id)); " WHERE " + ID + " = ?", SqlUtil.buildArgs(id));
long threadId = getThreadIdForMessage(id); threadId = getThreadIdForMessage(id);
DatabaseFactory.getThreadDatabase(context).updateSnippetTypeSilently(threadId); DatabaseFactory.getThreadDatabase(context).updateSnippetTypeSilently(threadId);
notifyConversationListListeners(); db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
} }
@ -267,11 +279,6 @@ public class SmsDatabase extends MessageDatabase {
updateTypeBitmask(id, Types.KEY_EXCHANGE_MASK, Types.END_SESSION_BIT); updateTypeBitmask(id, Types.KEY_EXCHANGE_MASK, Types.END_SESSION_BIT);
} }
@Override
public void markAsPreKeyBundle(long id) {
updateTypeBitmask(id, Types.KEY_EXCHANGE_MASK, Types.KEY_EXCHANGE_BIT | Types.KEY_EXCHANGE_BUNDLE_BIT);
}
@Override @Override
public void markAsInvalidVersionKeyExchange(long id) { public void markAsInvalidVersionKeyExchange(long id) {
updateTypeBitmask(id, 0, Types.KEY_EXCHANGE_INVALID_VERSION_BIT); updateTypeBitmask(id, 0, Types.KEY_EXCHANGE_INVALID_VERSION_BIT);
@ -323,11 +330,6 @@ public class SmsDatabase extends MessageDatabase {
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT); updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_FAILED_BIT);
} }
@Override
public void markAsDecryptDuplicate(long id) {
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_DUPLICATE_BIT);
}
@Override @Override
public void markAsNoSession(long id) { public void markAsNoSession(long id) {
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_NO_SESSION_BIT); updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_NO_SESSION_BIT);
@ -656,9 +658,8 @@ public class SmsDatabase extends MessageDatabase {
long threadId = getThreadIdForMessage(messageId); long threadId = getThreadIdForMessage(messageId);
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
notifyConversationListListeners();
return new InsertResult(messageId, threadId); return new InsertResult(messageId, threadId);
} }
@ -741,7 +742,7 @@ public class SmsDatabase extends MessageDatabase {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
} }
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
@ -818,7 +819,7 @@ public class SmsDatabase extends MessageDatabase {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
} }
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
db.setTransactionSuccessful(); db.setTransactionSuccessful();
} finally { } finally {
@ -886,11 +887,12 @@ public class SmsDatabase extends MessageDatabase {
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long messageId = db.insert(TABLE_NAME, null, values); long messageId = db.insert(TABLE_NAME, null, values);
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
if (unread) { if (unread) {
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
} }
ThreadUpdateJob.enqueue(threadId);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
TrimThreadJob.enqueueAsync(threadId); TrimThreadJob.enqueueAsync(threadId);
@ -1109,7 +1111,7 @@ public class SmsDatabase extends MessageDatabase {
} }
if (!silent) { if (!silent) {
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
} }
if (message.getSubscriptionId() != -1) { if (message.getSubscriptionId() != -1) {
@ -1152,7 +1154,7 @@ public class SmsDatabase extends MessageDatabase {
long messageId = db.insert(TABLE_NAME, null, values); long messageId = db.insert(TABLE_NAME, null, values);
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
@ -1176,7 +1178,7 @@ public class SmsDatabase extends MessageDatabase {
databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values); databaseHelper.getSignalWritableDatabase().insert(TABLE_NAME, null, values);
DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1); DatabaseFactory.getThreadDatabase(context).incrementUnread(threadId, 1);
DatabaseFactory.getThreadDatabase(context).update(threadId, true); ThreadUpdateJob.enqueue(threadId);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
@ -1226,7 +1228,6 @@ public class SmsDatabase extends MessageDatabase {
if (!message.isIdentityVerified() && !message.isIdentityDefault()) { if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
DatabaseFactory.getThreadDatabase(context).setLastScrolled(threadId, 0); DatabaseFactory.getThreadDatabase(context).setLastScrolled(threadId, 0);
DatabaseFactory.getThreadDatabase(context).updateSilently(threadId, true);
DatabaseFactory.getThreadDatabase(context).setLastSeenSilently(threadId); DatabaseFactory.getThreadDatabase(context).setLastSeenSilently(threadId);
} }
@ -1237,7 +1238,6 @@ public class SmsDatabase extends MessageDatabase {
} }
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
notifyConversationListListeners();
if (!message.isIdentityVerified() && !message.isIdentityDefault()) { if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
TrimThreadJob.enqueueAsync(threadId); TrimThreadJob.enqueueAsync(threadId);

Wyświetl plik

@ -224,8 +224,6 @@ public class ThreadDatabase extends Database {
StorageSyncHelper.scheduleSyncForDataChange(); StorageSyncHelper.scheduleSyncForDataChange();
} }
} }
notifyConversationListListeners();
} }
public void updateSnippet(long threadId, String snippet, @Nullable Uri attachment, long date, long type, boolean unarchive) { public void updateSnippet(long threadId, String snippet, @Nullable Uri attachment, long date, long type, boolean unarchive) {

Wyświetl plik

@ -13,6 +13,7 @@ import androidx.annotation.RequiresApi;
import com.annimon.stream.Collectors; import com.annimon.stream.Collectors;
import com.annimon.stream.Stream; import com.annimon.stream.Stream;
import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.core.util.logging.Log; import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
@ -33,6 +34,7 @@ public final class JobSchedulerScheduler implements Scheduler {
@RequiresApi(26) @RequiresApi(26)
@Override @Override
public void schedule(long delay, @NonNull List<Constraint> constraints) { public void schedule(long delay, @NonNull List<Constraint> constraints) {
SignalExecutors.BOUNDED.execute(() -> {
JobScheduler jobScheduler = application.getSystemService(JobScheduler.class); JobScheduler jobScheduler = application.getSystemService(JobScheduler.class);
String constraintNames = constraints.isEmpty() ? "" String constraintNames = constraints.isEmpty() ? ""
@ -59,6 +61,7 @@ public final class JobSchedulerScheduler implements Scheduler {
} }
jobScheduler.schedule(jobInfoBuilder.build()); jobScheduler.schedule(jobInfoBuilder.build());
});
} }
@RequiresApi(api = 26) @RequiresApi(api = 26)

Wyświetl plik

@ -162,6 +162,7 @@ public final class JobManagerFactories {
put(StorageForcePushJob.KEY, new StorageForcePushJob.Factory()); put(StorageForcePushJob.KEY, new StorageForcePushJob.Factory());
put(StorageSyncJob.KEY, new StorageSyncJob.Factory()); put(StorageSyncJob.KEY, new StorageSyncJob.Factory());
put(SubmitRateLimitPushChallengeJob.KEY, new SubmitRateLimitPushChallengeJob.Factory()); put(SubmitRateLimitPushChallengeJob.KEY, new SubmitRateLimitPushChallengeJob.Factory());
put(ThreadUpdateJob.KEY, new ThreadUpdateJob.Factory());
put(TrimThreadJob.KEY, new TrimThreadJob.Factory()); put(TrimThreadJob.KEY, new TrimThreadJob.Factory());
put(TypingSendJob.KEY, new TypingSendJob.Factory()); put(TypingSendJob.KEY, new TypingSendJob.Factory());
put(UpdateApkJob.KEY, new UpdateApkJob.Factory()); put(UpdateApkJob.KEY, new UpdateApkJob.Factory());

Wyświetl plik

@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalServiceMessageSender.IndividualSendEvents;
import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SendMessageResult;
@ -109,7 +110,7 @@ public final class PaymentNotificationSendJob extends BaseJob {
.withPayment(new SignalServiceDataMessage.Payment(new SignalServiceDataMessage.PaymentNotification(payment.getReceipt(), payment.getNote()))) .withPayment(new SignalServiceDataMessage.Payment(new SignalServiceDataMessage.PaymentNotification(payment.getReceipt(), payment.getNote())))
.build(); .build();
SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage); SendMessageResult sendMessageResult = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.DEFAULT, dataMessage, IndividualSendEvents.EMPTY);
if (sendMessageResult.getIdentityFailure() != null) { if (sendMessageResult.getIdentityFailure() != null) {
Log.w(TAG, "Identity failure for " + recipient.getId()); Log.w(TAG, "Identity failure for " + recipient.getId());

Wyświetl plik

@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalServiceMessageSender.IndividualSendEvents;
import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
@ -137,7 +138,8 @@ public class PushGroupUpdateJob extends BaseJob {
messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, sourceRecipient), messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, sourceRecipient),
UnidentifiedAccessUtil.getAccessFor(context, sourceRecipient), UnidentifiedAccessUtil.getAccessFor(context, sourceRecipient),
ContentHint.DEFAULT, ContentHint.DEFAULT,
message); message,
IndividualSendEvents.EMPTY);
} }
@Override @Override

Wyświetl plik

@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalServiceMessageSender.IndividualSendEvents;
import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
@ -233,7 +234,7 @@ public class PushMediaSendJob extends PushSendJob {
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true)); DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
return syncAccess.isPresent(); return syncAccess.isPresent();
} else { } else {
SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage); SendMessageResult result = messageSender.sendDataMessage(address, UnidentifiedAccessUtil.getAccessFor(context, messageRecipient), ContentHint.RESENDABLE, mediaMessage, IndividualSendEvents.EMPTY);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true)); DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true));
return result.getSuccess().isUnidentified(); return result.getSuccess().isUnidentified();
} }

Wyświetl plik

@ -47,7 +47,7 @@ public class PushTextSendJob extends PushSendJob {
private static final String KEY_MESSAGE_ID = "message_id"; private static final String KEY_MESSAGE_ID = "message_id";
private long messageId; private final long messageId;
public PushTextSendJob(long messageId, @NonNull Recipient recipient) { public PushTextSendJob(long messageId, @NonNull Recipient recipient) {
this(constructParameters(recipient, false), messageId); this(constructParameters(recipient, false), messageId);
@ -91,12 +91,13 @@ public class PushTextSendJob extends PushSendJob {
RecipientUtil.shareProfileIfFirstSecureMessage(context, record.getRecipient()); RecipientUtil.shareProfileIfFirstSecureMessage(context, record.getRecipient());
Recipient recipient = record.getRecipient().fresh(); Recipient recipient = record.getRecipient().resolve();
byte[] profileKey = recipient.getProfileKey(); byte[] profileKey = recipient.getProfileKey();
UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode(); UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode();
boolean unidentified = deliver(record); boolean unidentified = deliver(record);
try (DatabaseFactory.Transaction unused = DatabaseFactory.getInstance(context).transaction()) {
database.markAsSent(messageId, true); database.markAsSent(messageId, true);
database.markUnidentified(messageId, unidentified); database.markUnidentified(messageId, unidentified);
@ -121,6 +122,7 @@ public class PushTextSendJob extends PushSendJob {
database.markExpireStarted(messageId); database.markExpireStarted(messageId);
expirationManager.scheduleDeletion(record.getId(), record.isMms(), record.getExpiresIn()); expirationManager.scheduleDeletion(record.getId(), record.isMms(), record.getExpiresIn());
} }
}
log(TAG, String.valueOf(record.getDateSent()), "Sent message: " + messageId); log(TAG, String.valueOf(record.getDateSent()), "Sent message: " + messageId);
@ -167,7 +169,7 @@ public class PushTextSendJob extends PushSendJob {
try { try {
rotateSenderCertificateIfNecessary(); rotateSenderCertificateIfNecessary();
Recipient messageRecipient = message.getIndividualRecipient().fresh(); Recipient messageRecipient = message.getIndividualRecipient().resolve();
if (messageRecipient.isUnregistered()) { if (messageRecipient.isUnregistered()) {
throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!"); throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!");
@ -192,16 +194,14 @@ public class PushTextSendJob extends PushSendJob {
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess); SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);
SignalLocalMetrics.IndividualMessageSend.onNetworkStarted(messageId); SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
SendMessageResult result = messageSender.sendSyncMessage(syncMessage, syncAccess); SendMessageResult result = messageSender.sendSyncMessage(syncMessage, syncAccess);
SignalLocalMetrics.IndividualMessageSend.onNetworkFinished(messageId);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false)); DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
return syncAccess.isPresent(); return syncAccess.isPresent();
} else { } else {
SignalLocalMetrics.IndividualMessageSend.onNetworkStarted(messageId); SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId);
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage); SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage, new MetricEventListener(messageId));
SignalLocalMetrics.IndividualMessageSend.onNetworkFinished(messageId);
DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false)); DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
return result.getSuccess().isUnidentified(); return result.getSuccess().isUnidentified();
@ -218,6 +218,29 @@ public class PushTextSendJob extends PushSendJob {
return data.getLong(KEY_MESSAGE_ID); return data.getLong(KEY_MESSAGE_ID);
} }
private static class MetricEventListener implements SignalServiceMessageSender.IndividualSendEvents {
private final long messageId;
private MetricEventListener(long messageId) {
this.messageId = messageId;
}
@Override
public void onMessageEncrypted() {
SignalLocalMetrics.IndividualMessageSend.onMessageEncrypted(messageId);
}
@Override
public void onMessageSent() {
SignalLocalMetrics.IndividualMessageSend.onMessageSent(messageId);
}
@Override
public void onSyncMessageSent() {
SignalLocalMetrics.IndividualMessageSend.onSyncMessageSent(messageId);
}
}
public static class Factory implements Job.Factory<PushTextSendJob> { public static class Factory implements Job.Factory<PushTextSendJob> {
@Override @Override
public @NonNull PushTextSendJob create(@NonNull Parameters parameters, @NonNull Data data) { public @NonNull PushTextSendJob create(@NonNull Parameters parameters, @NonNull Data data) {

Wyświetl plik

@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalServiceMessageSender.IndividualSendEvents;
import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.ContentHint;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
@ -94,7 +95,8 @@ public class RequestGroupInfoJob extends BaseJob {
messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, recipient), messageSender.sendDataMessage(RecipientUtil.toSignalServiceAddress(context, recipient),
UnidentifiedAccessUtil.getAccessFor(context, recipient), UnidentifiedAccessUtil.getAccessFor(context, recipient),
ContentHint.IMPLICIT, ContentHint.IMPLICIT,
message); message,
IndividualSendEvents.EMPTY);
} }
@Override @Override

Wyświetl plik

@ -0,0 +1,67 @@
package org.thoughtcrime.securesms.jobs;
import androidx.annotation.NonNull;
import org.signal.core.util.ThreadUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobmanager.Data;
import org.thoughtcrime.securesms.jobmanager.Job;
public final class ThreadUpdateJob extends BaseJob {
public static final String KEY = "ThreadUpdateJob";
private static final String KEY_THREAD_ID = "thread_id";
private final long threadId;
private ThreadUpdateJob(long threadId) {
this(new Parameters.Builder()
.setQueue("ThreadUpdateJob_" + threadId)
.setMaxInstancesForQueue(2)
.build(),
threadId);
}
private ThreadUpdateJob(@NonNull Parameters parameters, long threadId) {
super(parameters);
this.threadId = threadId;
}
public static void enqueue(long threadId) {
ApplicationDependencies.getJobManager().add(new ThreadUpdateJob(threadId));
}
@Override
public @NonNull Data serialize() {
return new Data.Builder().putLong(KEY_THREAD_ID, threadId).build();
}
@Override
public @NonNull String getFactoryKey() {
return KEY;
}
@Override
protected void onRun() throws Exception {
DatabaseFactory.getThreadDatabase(context).update(threadId, true);
ThreadUtil.sleep(1000);
}
@Override
protected boolean onShouldRetry(@NonNull Exception e) {
return false;
}
@Override
public void onFailure() {
}
public static final class Factory implements Job.Factory<ThreadUpdateJob> {
@Override
public @NonNull ThreadUpdateJob create(@NonNull Parameters parameters, @NonNull Data data) {
return new ThreadUpdateJob(parameters, data.getLong(KEY_THREAD_ID));
}
}
}

Wyświetl plik

@ -82,6 +82,7 @@ import org.thoughtcrime.securesms.jobs.RetrieveProfileJob;
import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob; import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob;
import org.thoughtcrime.securesms.jobs.SenderKeyDistributionSendJob; import org.thoughtcrime.securesms.jobs.SenderKeyDistributionSendJob;
import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob; import org.thoughtcrime.securesms.jobs.StickerPackDownloadJob;
import org.thoughtcrime.securesms.jobs.ThreadUpdateJob;
import org.thoughtcrime.securesms.jobs.TrimThreadJob; import org.thoughtcrime.securesms.jobs.TrimThreadJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreview;
@ -721,10 +722,13 @@ public final class MessageContentProcessor {
SecurityEvent.broadcastSecurityUpdateEvent(context); SecurityEvent.broadcastSecurityUpdateEvent(context);
long messageId = database.insertMessageOutbox(threadId, outgoingEndSessionMessage, long messageId = database.insertMessageOutbox(threadId,
false, message.getTimestamp(), outgoingEndSessionMessage,
false,
message.getTimestamp(),
null); null);
database.markAsSent(messageId, true); database.markAsSent(messageId, true);
ThreadUpdateJob.enqueue(threadId);
} }
return threadId; return threadId;
@ -1555,6 +1559,7 @@ public final class MessageContentProcessor {
messageId = DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoingTextMessage, false, message.getTimestamp(), null); messageId = DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoingTextMessage, false, message.getTimestamp(), null);
database = DatabaseFactory.getSmsDatabase(context); database = DatabaseFactory.getSmsDatabase(context);
database.markUnidentified(messageId, isUnidentified(message, recipient)); database.markUnidentified(messageId, isUnidentified(message, recipient));
ThreadUpdateJob.enqueue(threadId);
} }
database.markAsSent(messageId, true); database.markAsSent(messageId, true);

Wyświetl plik

@ -245,6 +245,10 @@ public class RecipientUtil {
@WorkerThread @WorkerThread
public static void shareProfileIfFirstSecureMessage(@NonNull Context context, @NonNull Recipient recipient) { public static void shareProfileIfFirstSecureMessage(@NonNull Context context, @NonNull Recipient recipient) {
if (recipient.isProfileSharing()) {
return;
}
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient.getId()); long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(recipient.getId());
if (isPreMessageRequestThread(context, threadId)) { if (isPreMessageRequestThread(context, threadId)) {

Wyświetl plik

@ -16,6 +16,7 @@
*/ */
package org.thoughtcrime.securesms.sms; package org.thoughtcrime.securesms.sms;
import android.app.Application;
import android.content.Context; import android.content.Context;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
@ -61,6 +62,7 @@ import org.thoughtcrime.securesms.jobs.ReactionSendJob;
import org.thoughtcrime.securesms.jobs.RemoteDeleteSendJob; import org.thoughtcrime.securesms.jobs.RemoteDeleteSendJob;
import org.thoughtcrime.securesms.jobs.ResumableUploadSpecJob; import org.thoughtcrime.securesms.jobs.ResumableUploadSpecJob;
import org.thoughtcrime.securesms.jobs.SmsSendJob; import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.jobs.ThreadUpdateJob;
import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.linkpreview.LinkPreview; import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.MmsException;
@ -120,6 +122,7 @@ public class MessageSender {
sendTextMessage(context, recipient, forceSms, keyExchange, messageId); sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
onMessageSent(); onMessageSent();
ThreadUpdateJob.enqueue(threadId);
return allocatedThreadId; return allocatedThreadId;
} }

Wyświetl plik

@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.MessageDatabase; import org.thoughtcrime.securesms.database.MessageDatabase;
import org.thoughtcrime.securesms.database.MessageDatabase.InsertResult; import org.thoughtcrime.securesms.database.MessageDatabase.InsertResult;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.jobs.ThreadUpdateJob;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage; import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage;
@ -90,6 +91,7 @@ public final class IdentityUtil {
else outgoing = new OutgoingIdentityDefaultMessage(recipient); else outgoing = new OutgoingIdentityDefaultMessage(recipient);
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoing, false, time, null); DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoing, false, time, null);
ThreadUpdateJob.enqueue(threadId);
} }
} }
} }
@ -112,6 +114,7 @@ public final class IdentityUtil {
Log.i(TAG, "Inserting verified outbox..."); Log.i(TAG, "Inserting verified outbox...");
DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoing, false, time, null); DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoing, false, time, null);
ThreadUpdateJob.enqueue(threadId);
} }
} }

Wyświetl plik

@ -99,7 +99,9 @@ public final class SignalLocalMetrics {
private static final String SPLIT_DB_INSERT = "db-insert"; private static final String SPLIT_DB_INSERT = "db-insert";
private static final String SPLIT_JOB_ENQUEUE = "job-enqueue"; private static final String SPLIT_JOB_ENQUEUE = "job-enqueue";
private static final String SPLIT_JOB_PRE_NETWORK = "job-pre-network"; private static final String SPLIT_JOB_PRE_NETWORK = "job-pre-network";
private static final String SPLIT_NETWORK = "network"; private static final String SPLIT_ENCRYPT = "encrypt";
private static final String SPLIT_NETWORK_MAIN = "network-main";
private static final String SPLIT_NETWORK_SYNC = "network-sync";
private static final String SPLIT_JOB_POST_NETWORK = "job-post-network"; private static final String SPLIT_JOB_POST_NETWORK = "job-post-network";
private static final String SPLIT_UI_UPDATE = "ui-update"; private static final String SPLIT_UI_UPDATE = "ui-update";
@ -123,14 +125,24 @@ public final class SignalLocalMetrics {
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_ENQUEUE); LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_ENQUEUE);
} }
public static void onNetworkStarted(long messageId) { public static void onDeliveryStarted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return; if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_PRE_NETWORK); LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_PRE_NETWORK);
} }
public static void onNetworkFinished(long messageId) { public static void onMessageEncrypted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return; if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK); LocalMetrics.getInstance().split(requireId(messageId), SPLIT_ENCRYPT);
}
public static void onMessageSent(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK_MAIN);
}
public static void onSyncMessageSent(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK_SYNC);
} }
public static void onJobFinished(long messageId) { public static void onJobFinished(long messageId) {

Wyświetl plik

@ -319,16 +319,22 @@ public class SignalServiceMessageSender {
public SendMessageResult sendDataMessage(SignalServiceAddress recipient, public SendMessageResult sendDataMessage(SignalServiceAddress recipient,
Optional<UnidentifiedAccessPair> unidentifiedAccess, Optional<UnidentifiedAccessPair> unidentifiedAccess,
ContentHint contentHint, ContentHint contentHint,
SignalServiceDataMessage message) SignalServiceDataMessage message,
IndividualSendEvents sendEvents)
throws UntrustedIdentityException, IOException throws UntrustedIdentityException, IOException
{ {
Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message."); Log.d(TAG, "[" + message.getTimestamp() + "] Sending a data message.");
Content content = createMessageContent(message); Content content = createMessageContent(message);
EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, message.getGroupId()); EnvelopeContent envelopeContent = EnvelopeContent.encrypted(content, contentHint, message.getGroupId());
sendEvents.onMessageEncrypted();
long timestamp = message.getTimestamp(); long timestamp = message.getTimestamp();
SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null); SendMessageResult result = sendMessage(recipient, getTargetUnidentifiedAccess(unidentifiedAccess), timestamp, envelopeContent, false, null);
sendEvents.onMessageSent();
if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) { if (result.getSuccess() != null && result.getSuccess().isNeedsSync()) {
Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false); Content syncMessage = createMultiDeviceSentTranscriptContent(content, Optional.of(recipient), timestamp, Collections.singletonList(result), false);
EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.absent()); EnvelopeContent syncMessageContent = EnvelopeContent.encrypted(syncMessage, ContentHint.IMPLICIT, Optional.absent());
@ -336,6 +342,8 @@ public class SignalServiceMessageSender {
sendMessage(localAddress, Optional.absent(), timestamp, syncMessageContent, false, null); sendMessage(localAddress, Optional.absent(), timestamp, syncMessageContent, false, null);
} }
sendEvents.onSyncMessageSent();
// TODO [greyson][session] Delete this when we delete the button // TODO [greyson][session] Delete this when we delete the button
if (message.isEndSession()) { if (message.isEndSession()) {
store.deleteAllSessions(recipient.getUuid().toString()); store.deleteAllSessions(recipient.getUuid().toString());
@ -2077,4 +2085,21 @@ public class SignalServiceMessageSender {
public interface EventListener { public interface EventListener {
void onSecurityEvent(SignalServiceAddress address); void onSecurityEvent(SignalServiceAddress address);
} }
public interface IndividualSendEvents {
IndividualSendEvents EMPTY = new IndividualSendEvents() {
@Override
public void onMessageEncrypted() { }
@Override
public void onMessageSent() { }
@Override
public void onSyncMessageSent() { }
};
void onMessageEncrypted();
void onMessageSent();
void onSyncMessageSent();
}
} }