Use a more accurate starting point for message send timings.

This commit is contained in:
Greyson Parrelli 2021-08-23 10:05:48 -04:00 committed by Alex Hart
parent 1e050915ef
commit b7a067e954
18 changed files with 232 additions and 120 deletions

View file

@ -283,7 +283,7 @@ public class InviteActivity extends PassphraseRequiredActivity implements Contac
Recipient recipient = Recipient.resolved(recipientId);
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
MessageSender.send(context, new OutgoingTextMessage(recipient, message, subscriptionId), -1L, true, null);
MessageSender.send(context, new OutgoingTextMessage(recipient, message, subscriptionId), -1L, true, null, null);
if (recipient.getContactUri() != null) {
DatabaseFactory.getRecipientDatabase(context).setHasSentInvite(recipient.getId());

View file

@ -38,7 +38,7 @@ class ExpireTimerSettingsRepository(val context: Context) {
} else {
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipientId, newExpirationTime)
val outgoingMessage = OutgoingExpirationUpdateMessage(Recipient.resolved(recipientId), System.currentTimeMillis(), newExpirationTime * 1000L)
MessageSender.send(context, outgoingMessage, getThreadId(recipientId), false, null)
MessageSender.send(context, outgoingMessage, getThreadId(recipientId), false, null, null)
consumer.invoke(Result.success(newExpirationTime))
}
}

View file

@ -276,6 +276,7 @@ import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.MessageUtil;
import org.thoughtcrime.securesms.util.PlayStoreUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.SmsUtil;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
@ -788,7 +789,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
result.isViewOnce(),
subscriptionId,
initiating,
true).addListener(new AssertedSuccessListener<Void>() {
true,
null).addListener(new AssertedSuccessListener<Void>() {
@Override
public void onSuccess(Void result) {
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
@ -1280,7 +1282,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
new AsyncTask<OutgoingEndSessionMessage, Void, Long>() {
@Override
protected Long doInBackground(OutgoingEndSessionMessage... messages) {
return MessageSender.send(context, messages[0], threadId, false, null);
return MessageSender.send(context, messages[0], threadId, false, null, null);
}
@Override
@ -1526,7 +1528,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
initializeIdentityRecords().addListener(new AssertedSuccessListener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
sendMessage();
sendMessage(null);
}
});
}
@ -2587,7 +2589,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.get().getExpiresInSeconds());
boolean initiating = threadId == -1;
sendMediaMessage(recipient.getId(), isSmsForced(), "", attachmentManager.buildSlideDeck(), null, contacts, Collections.emptyList(), Collections.emptyList(), expiresIn, false, subscriptionId, initiating, false);
sendMediaMessage(recipient.getId(), isSmsForced(), "", attachmentManager.buildSlideDeck(), null, contacts, Collections.emptyList(), Collections.emptyList(), expiresIn, false, subscriptionId, initiating, false, null);
}
private void selectContactInfo(ContactData contactData) {
@ -2848,7 +2850,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
updateLinkPreviewState();
}
private void sendMessage() {
private void sendMessage(@Nullable String metricId) {
if (inputPanel.isRecordingInLockedMode()) {
inputPanel.releaseRecordingLock();
return;
@ -2892,9 +2894,9 @@ public class ConversationActivity extends PassphraseRequiredActivity
} else if (!forceSms && (identityRecords.isUnverified(true) || identityRecords.isUntrusted(true))) {
handleRecentSafetyNumberChange();
} else if (isMediaMessage) {
sendMediaMessage(forceSms, expiresIn, false, subscriptionId, initiating);
sendMediaMessage(forceSms, expiresIn, false, subscriptionId, initiating, metricId);
} else {
sendTextMessage(forceSms, expiresIn, subscriptionId, initiating);
sendTextMessage(forceSms, expiresIn, subscriptionId, initiating, metricId);
}
} catch (RecipientFormattingException ex) {
Toast.makeText(ConversationActivity.this,
@ -2934,7 +2936,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
}, this::sendComplete);
}
private void sendMediaMessage(final boolean forceSms, final long expiresIn, final boolean viewOnce, final int subscriptionId, final boolean initiating)
private void sendMediaMessage(final boolean forceSms, final long expiresIn, final boolean viewOnce, final int subscriptionId, final boolean initiating, @Nullable String metricId)
throws InvalidMessageException
{
Log.i(TAG, "Sending media message...");
@ -2951,7 +2953,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
viewOnce,
subscriptionId,
initiating,
true);
true,
metricId);
}
private ListenableFuture<Void> sendMediaMessage(@NonNull RecipientId recipientId,
@ -2966,7 +2969,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
final boolean viewOnce,
final int subscriptionId,
final boolean initiating,
final boolean clearComposeBox)
final boolean clearComposeBox,
final @Nullable String metricId)
{
if (!isDefaultSms && (!isSecureText || forceSms) && recipient.get().hasSmsAddress()) {
showDefaultSmsPrompt();
@ -3013,7 +3017,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
final long id = fragment.stageOutgoingMessage(outgoingMessage);
SimpleTask.run(() -> {
return MessageSender.send(context, outgoingMessage, thread, forceSms, () -> fragment.releaseOutgoingMessage(id));
return MessageSender.send(context, outgoingMessage, thread, forceSms, metricId, () -> fragment.releaseOutgoingMessage(id));
}, result -> {
sendComplete(result);
future.set(null);
@ -3025,7 +3029,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
return future;
}
private void sendTextMessage(final boolean forceSms, final long expiresIn, final int subscriptionId, final boolean initiating)
private void sendTextMessage(final boolean forceSms, final long expiresIn, final int subscriptionId, final boolean initiating, final @Nullable String metricId)
throws InvalidMessageException
{
if (!isDefaultSms && (!isSecureText || forceSms) && recipient.get().hasSmsAddress()) {
@ -3054,7 +3058,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
.onAllGranted(() -> {
final long id = new SecureRandom().nextLong();
SimpleTask.run(() -> {
return MessageSender.send(context, message, thread, forceSms, () -> fragment.releaseOutgoingMessage(id));
return MessageSender.send(context, message, thread, forceSms, metricId, () -> fragment.releaseOutgoingMessage(id));
}, this::sendComplete);
silentlySetComposeText("");
@ -3283,7 +3287,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
false,
subscriptionId,
initiating,
true);
true,
null);
sendResult.addListener(new AssertedSuccessListener<Void>() {
@Override
@ -3319,7 +3324,7 @@ public class ConversationActivity extends PassphraseRequiredActivity
slideDeck.addSlide(stickerSlide);
sendMediaMessage(recipient.getId(), transport.isSms(), "", slideDeck, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), expiresIn, false, subscriptionId, initiating, clearCompose);
sendMediaMessage(recipient.getId(), transport.isSms(), "", slideDeck, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), expiresIn, false, subscriptionId, initiating, clearCompose, null);
}
private void silentlySetComposeText(String text) {
@ -3455,7 +3460,9 @@ public class ConversationActivity extends PassphraseRequiredActivity
private class SendButtonListener implements OnClickListener, TextView.OnEditorActionListener {
@Override
public void onClick(View v) {
sendMessage();
String metricId = recipient.get().isGroup() ? SignalLocalMetrics.GroupMessageSend.start()
: SignalLocalMetrics.IndividualMessageSend.start();
sendMessage(metricId);
}
@Override
@ -3940,7 +3947,8 @@ public class ConversationActivity extends PassphraseRequiredActivity
false,
subscriptionId,
initiating,
false);
false,
null);
}
private class UnverifiedDismissedListener implements UnverifiedBannerView.DismissListener {

View file

@ -1470,6 +1470,8 @@ public class MmsDatabase extends MessageDatabase {
@Nullable SmsDatabase.InsertListener insertListener)
throws MmsException
{
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long type = Types.BASE_SENDING_TYPE;
if (message.isSecure()) type |= (Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT);
@ -1529,33 +1531,43 @@ public class MmsDatabase extends MessageDatabase {
}
MentionUtil.UpdatedBodyAndMentions updatedBodyAndMentions = MentionUtil.updateBodyAndMentionsWithPlaceholders(message.getBody(), message.getMentions());
long messageId = insertMediaMessage(threadId, updatedBodyAndMentions.getBodyAsString(), message.getAttachments(), quoteAttachments, message.getSharedContacts(), message.getLinkPreviews(), updatedBodyAndMentions.getMentions(), contentValues, insertListener);
if (message.getRecipient().isGroup()) {
OutgoingGroupUpdateMessage outgoingGroupUpdateMessage = (message instanceof OutgoingGroupUpdateMessage) ? (OutgoingGroupUpdateMessage) message : null;
long messageId;
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
Set<RecipientId> members = new HashSet<>();
db.beginTransaction();
try {
messageId = insertMediaMessage(threadId, updatedBodyAndMentions.getBodyAsString(), message.getAttachments(), quoteAttachments, message.getSharedContacts(), message.getLinkPreviews(), updatedBodyAndMentions.getMentions(), contentValues, insertListener);
if (outgoingGroupUpdateMessage != null && outgoingGroupUpdateMessage.isV2Group()) {
MessageGroupContext.GroupV2Properties groupV2Properties = outgoingGroupUpdateMessage.requireGroupV2Properties();
members.addAll(Stream.of(groupV2Properties.getAllActivePendingAndRemovedMembers())
.distinct()
.map(uuid -> RecipientId.from(uuid, null))
.toList());
members.remove(Recipient.self().getId());
} else {
members.addAll(Stream.of(DatabaseFactory.getGroupDatabase(context).getGroupMembers(message.getRecipient().requireGroupId(), GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF)).map(Recipient::getId).toList());
if (message.getRecipient().isGroup()) {
OutgoingGroupUpdateMessage outgoingGroupUpdateMessage = (message instanceof OutgoingGroupUpdateMessage) ? (OutgoingGroupUpdateMessage) message : null;
GroupReceiptDatabase receiptDatabase = DatabaseFactory.getGroupReceiptDatabase(context);
Set<RecipientId> members = new HashSet<>();
if (outgoingGroupUpdateMessage != null && outgoingGroupUpdateMessage.isV2Group()) {
MessageGroupContext.GroupV2Properties groupV2Properties = outgoingGroupUpdateMessage.requireGroupV2Properties();
members.addAll(Stream.of(groupV2Properties.getAllActivePendingAndRemovedMembers())
.distinct()
.map(uuid -> RecipientId.from(uuid, null))
.toList());
members.remove(Recipient.self().getId());
} else {
members.addAll(Stream.of(DatabaseFactory.getGroupDatabase(context).getGroupMembers(message.getRecipient().requireGroupId(), GroupDatabase.MemberSet.FULL_MEMBERS_EXCLUDING_SELF)).map(Recipient::getId).toList());
}
receiptDatabase.insert(members, messageId, defaultReceiptStatus, message.getSentTimeMillis());
for (RecipientId recipientId : earlyDeliveryReceipts.keySet()) receiptDatabase.update(recipientId, messageId, GroupReceiptDatabase.STATUS_DELIVERED, -1);
}
receiptDatabase.insert(members, messageId, defaultReceiptStatus, message.getSentTimeMillis());
DatabaseFactory.getThreadDatabase(context).setLastSeenSilently(threadId);
DatabaseFactory.getThreadDatabase(context).setHasSentSilently(threadId, true);
for (RecipientId recipientId : earlyDeliveryReceipts.keySet()) receiptDatabase.update(recipientId, messageId, GroupReceiptDatabase.STATUS_DELIVERED, -1);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
DatabaseFactory.getThreadDatabase(context).setLastSeenSilently(threadId);
DatabaseFactory.getThreadDatabase(context).setHasSentSilently(threadId, true);
notifyConversationListeners(threadId);
notifyConversationListListeners();

View file

@ -1187,6 +1187,8 @@ public class SmsDatabase extends MessageDatabase {
public long insertMessageOutbox(long threadId, OutgoingTextMessage message,
boolean forceSms, long date, InsertListener insertListener)
{
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long type = Types.BASE_SENDING_TYPE;
if (message.isKeyExchange()) type |= Types.KEY_EXCHANGE_BIT;
@ -1212,21 +1214,28 @@ public class SmsDatabase extends MessageDatabase {
contentValues.put(EXPIRES_IN, message.getExpiresIn());
contentValues.put(DELIVERY_RECEIPT_COUNT, Stream.of(earlyDeliveryReceipts.values()).mapToLong(Long::longValue).sum());
SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
long messageId = db.insert(TABLE_NAME, null, contentValues);
long messageId;
if (insertListener != null) {
insertListener.onComplete();
db.beginTransaction();
try {
messageId = db.insert(TABLE_NAME, null, contentValues);
if (insertListener != null) {
insertListener.onComplete();
}
if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
DatabaseFactory.getThreadDatabase(context).setLastScrolled(threadId, 0);
DatabaseFactory.getThreadDatabase(context).updateSilently(threadId, true);
DatabaseFactory.getThreadDatabase(context).setLastSeenSilently(threadId);
}
DatabaseFactory.getThreadDatabase(context).setHasSentSilently(threadId, true);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
if (!message.isIdentityVerified() && !message.isIdentityDefault()) {
DatabaseFactory.getThreadDatabase(context).setLastScrolled(threadId, 0);
DatabaseFactory.getThreadDatabase(context).updateSilently(threadId, true);
DatabaseFactory.getThreadDatabase(context).setLastSeenSilently(threadId);
}
DatabaseFactory.getThreadDatabase(context).setHasSentSilently(threadId, true);
notifyConversationListeners(threadId);
notifyConversationListListeners();

View file

@ -177,7 +177,7 @@ final class GroupManagerV1 {
}
OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList());
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null);
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null, null);
return new GroupActionResult(groupRecipient, threadId, newMemberCount, Collections.emptyList());
}
@ -201,7 +201,7 @@ final class GroupManagerV1 {
recipientDatabase.setExpireMessages(recipient.getId(), expirationTime);
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(recipient, System.currentTimeMillis(), expirationTime * 1000L);
MessageSender.send(context, outgoingMessage, threadId, false, null);
MessageSender.send(context, outgoingMessage, threadId, false, null, null);
}
@WorkerThread

View file

@ -1151,7 +1151,7 @@ final class GroupManagerV2 {
ApplicationDependencies.getJobManager().add(PushGroupSilentUpdateSendJob.create(context, groupId, groupMutation.getNewGroupState(), outgoingMessage));
return new RecipientAndThread(groupRecipient, -1);
} else {
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null);
long threadId = MessageSender.send(context, outgoingMessage, -1, false, null, null);
return new RecipientAndThread(groupRecipient, threadId);
}
}

View file

@ -81,7 +81,7 @@ public class InsightsRepository implements InsightsDashboardViewModel.Repository
int subscriptionId = resolved.getDefaultSubscriptionId().or(-1);
String message = context.getString(R.string.InviteActivity_lets_switch_to_signal, context.getString(R.string.install_url));
MessageSender.send(context, new OutgoingTextMessage(resolved, message, subscriptionId), -1L, true, null);
MessageSender.send(context, new OutgoingTextMessage(resolved, message, subscriptionId), -1L, true, null, null);
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
database.setHasSentInvite(recipient.getId());

View file

@ -266,6 +266,12 @@ public final class PushGroupSendJob extends PushSendJob {
SignalLocalMetrics.GroupMessageSend.onJobFinished(messageId);
}
@Override
public void onRetry() {
SignalLocalMetrics.GroupMessageSend.cancel(messageId);
super.onRetry();
}
@Override
public void onFailure() {
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId);

View file

@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.Hex;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@ -125,7 +126,6 @@ public abstract class PushSendJob extends SendJob {
@Override
public void onRetry() {
super.onRetry();
Log.i(TAG, "onRetry()");
if (getRunAttempt() > 1) {

View file

@ -143,6 +143,12 @@ public class PushTextSendJob extends PushSendJob {
SignalLocalMetrics.IndividualMessageSend.onJobFinished(messageId);
}
@Override
public void onRetry() {
SignalLocalMetrics.IndividualMessageSend.cancel(messageId);
super.onRetry();
}
@Override
public void onFailure() {
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);

View file

@ -92,17 +92,17 @@ public class RemoteReplyReceiver extends BroadcastReceiver {
Collections.emptyList(),
Collections.emptyList(),
Collections.emptyList());
threadId = MessageSender.send(context, reply, -1, false, null);
threadId = MessageSender.send(context, reply, -1, false, null, null);
break;
}
case SecureMessage: {
OutgoingEncryptedMessage reply = new OutgoingEncryptedMessage(recipient, responseText.toString(), expiresIn);
threadId = MessageSender.send(context, reply, -1, false, null);
threadId = MessageSender.send(context, reply, -1, false, null, null);
break;
}
case UnsecuredSmsMessage: {
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
threadId = MessageSender.send(context, reply, -1, true, null);
threadId = MessageSender.send(context, reply, -1, true, null, null);
break;
}
default:

View file

@ -285,7 +285,7 @@ public class RecipientUtil {
if (threadId == -1 || !DatabaseFactory.getMmsSmsDatabase(context).hasMeaningfulMessage(threadId)) {
DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient.getId(), defaultTimer);
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(recipient, System.currentTimeMillis(), defaultTimer * 1000L);
MessageSender.send(context, outgoingMessage, DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient), false, null);
MessageSender.send(context, outgoingMessage, DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient), false, null, null);
return true;
}
return false;

View file

@ -52,7 +52,7 @@ public class QuickResponseService extends IntentService {
long expiresIn = TimeUnit.SECONDS.toMillis(recipient.getExpiresInSeconds());
if (!TextUtils.isEmpty(content)) {
MessageSender.send(this, new OutgoingTextMessage(recipient, content, expiresIn, subscriptionId), -1, false, null);
MessageSender.send(this, new OutgoingTextMessage(recipient, content, expiresIn, subscriptionId), -1, false, null, null);
}
} catch (URISyntaxException e) {
Toast.makeText(this, R.string.QuickResponseService_problem_sending_message, Toast.LENGTH_LONG).show();

View file

@ -179,9 +179,9 @@ public final class MultiShareSender {
validatedMentions);
if (recipient.isRegistered() && !forceSms) {
MessageSender.send(context, new OutgoingSecureMediaMessage(outgoingMediaMessage), threadId, false, null);
MessageSender.send(context, new OutgoingSecureMediaMessage(outgoingMediaMessage), threadId, false, null, null);
} else {
MessageSender.send(context, outgoingMediaMessage, threadId, forceSms, null);
MessageSender.send(context, outgoingMediaMessage, threadId, forceSms, null, null);
}
}
@ -202,7 +202,7 @@ public final class MultiShareSender {
outgoingTextMessage = new OutgoingTextMessage(recipient, multiShareArgs.getDraftText(), expiresIn, subscriptionId);
}
MessageSender.send(context, outgoingTextMessage, threadId, forceSms, null);
MessageSender.send(context, outgoingTextMessage, threadId, forceSms, null, null);
}
private static @NonNull SlideDeck buildSlideDeck(@NonNull Context context, @NonNull MultiShareArgs multiShareArgs) throws SlideNotFoundException {

View file

@ -101,6 +101,7 @@ public class MessageSender {
final OutgoingTextMessage message,
final long threadId,
final boolean forceSms,
@Nullable final String metricId,
final SmsDatabase.InsertListener insertListener)
{
Log.i(TAG, "Sending text message to " + message.getRecipient().getId() + ", thread: " + threadId);
@ -115,7 +116,7 @@ public class MessageSender {
System.currentTimeMillis(),
insertListener);
SignalLocalMetrics.IndividualMessageSend.start(messageId);
SignalLocalMetrics.IndividualMessageSend.onInsertedIntoDatabase(messageId, metricId);
sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
onMessageSent();
@ -127,6 +128,7 @@ public class MessageSender {
final OutgoingMediaMessage message,
final long threadId,
final boolean forceSms,
@Nullable final String metricId,
final SmsDatabase.InsertListener insertListener)
{
Log.i(TAG, "Sending media message to " + message.getRecipient().getId() + ", thread: " + threadId);
@ -139,7 +141,9 @@ public class MessageSender {
long messageId = database.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId), allocatedThreadId, forceSms, insertListener);
if (message.getRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
SignalLocalMetrics.GroupMessageSend.start(messageId);
SignalLocalMetrics.GroupMessageSend.onInsertedIntoDatabase(messageId, metricId);
} else {
SignalLocalMetrics.GroupMessageSend.cancel(metricId);
}
sendMediaMessage(context, recipient, forceSms, messageId, Collections.emptyList());
@ -152,7 +156,6 @@ public class MessageSender {
}
}
public static long sendPushWithPreUploadedMedia(final Context context,
final OutgoingMediaMessage message,
final Collection<PreUploadResult> preUploadResults,

View file

@ -79,7 +79,7 @@ object LocalMetrics {
/**
* Stop tracking an event you were previously tracking. All future calls to [split] and [end] will do nothing for this id.
*/
fun drop(id: String) {
fun cancel(id: String) {
executor.execute {
eventsById.remove(id)
}

View file

@ -1,6 +1,12 @@
package org.thoughtcrime.securesms.util;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* A nice interface for {@link LocalMetrics} that gives us a place to define string constants and nicer method names.
@ -55,54 +61,15 @@ public final class SignalLocalMetrics {
if (isConversationList) {
LocalMetrics.getInstance().split(conversationListId, SPLIT_RENDER);
LocalMetrics.getInstance().end(conversationListId);
LocalMetrics.getInstance().drop(otherId);
LocalMetrics.getInstance().cancel(otherId);
} else {
LocalMetrics.getInstance().split(otherId, SPLIT_RENDER);
LocalMetrics.getInstance().end(otherId);
LocalMetrics.getInstance().drop(conversationListId);
LocalMetrics.getInstance().cancel(conversationListId);
}
}
}
public static final class IndividualMessageSend {
private static final String NAME = "individual-message-send";
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_NETWORK = "network";
private static final String SPLIT_JOB_POST_NETWORK = "job-post-network";
private static final String SPLIT_UI_UPDATE = "ui-update";
public static void start(long messageId) {
LocalMetrics.getInstance().start(buildId(messageId), NAME);
}
public static void onJobStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_ENQUEUE);
}
public static void onNetworkStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_PRE_NETWORK);
}
public static void onNetworkFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_NETWORK);
}
public static void onJobFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_POST_NETWORK);
}
public static void onUiUpdated(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_UI_UPDATE);
LocalMetrics.getInstance().end(buildId(messageId));
}
private static String buildId(long messageId) {
return NAME + "-" + messageId;
}
}
public static final class ConversationOpen {
private static final String NAME = "conversation-open";
@ -126,42 +93,143 @@ public final class SignalLocalMetrics {
}
}
public static final class GroupMessageSend {
private static final String NAME = "group-message-send";
public static final class IndividualMessageSend {
private static final String NAME = "individual-message-send";
private static final String SPLIT_DB_INSERT = "db-insert";
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_NETWORK = "network";
private static final String SPLIT_JOB_POST_NETWORK = "job-post-network";
private static final String SPLIT_UI_UPDATE = "ui-update";
public static void start(long messageId) {
LocalMetrics.getInstance().start(buildId(messageId), NAME);
private static final Map<Long, String> ID_MAP = new HashMap<>();
public static @NonNull String start() {
String id = NAME + System.currentTimeMillis();
LocalMetrics.getInstance().start(id, NAME);
return id;
}
public static void onInsertedIntoDatabase(long messageId, String id) {
if (id != null) {
ID_MAP.put(messageId, id);
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_DB_INSERT);
}
}
public static void onJobStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_ENQUEUE);
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_ENQUEUE);
}
public static void onNetworkStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_PRE_NETWORK);
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_PRE_NETWORK);
}
public static void onNetworkFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_NETWORK);
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK);
}
public static void onJobFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_POST_NETWORK);
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_POST_NETWORK);
}
public static void onUiUpdated(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_UI_UPDATE);
LocalMetrics.getInstance().end(buildId(messageId));
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_UI_UPDATE);
LocalMetrics.getInstance().end(requireId(messageId));
ID_MAP.remove(messageId);
}
private static String buildId(long messageId) {
return NAME + "-" + messageId;
public static void cancel(@Nullable String id) {
if (id != null) {
LocalMetrics.getInstance().cancel(id);
}
}
public static void cancel(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().cancel(requireId(messageId));
}
private static @NonNull String requireId(long messageId) {
return Objects.requireNonNull(ID_MAP.get(messageId));
}
}
public static final class GroupMessageSend {
private static final String NAME = "group-message-send";
private static final String SPLIT_DB_INSERT = "db-insert";
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_NETWORK = "network";
private static final String SPLIT_JOB_POST_NETWORK = "job-post-network";
private static final String SPLIT_UI_UPDATE = "ui-update";
private static final Map<Long, String> ID_MAP = new HashMap<>();
public static @NonNull String start() {
String id = NAME + System.currentTimeMillis();
LocalMetrics.getInstance().start(id, NAME);
return id;
}
public static void onInsertedIntoDatabase(long messageId, String id) {
if (id != null) {
ID_MAP.put(messageId, id);
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_DB_INSERT);
}
}
public static void onJobStarted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_ENQUEUE);
}
public static void onNetworkStarted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_PRE_NETWORK);
}
public static void onNetworkFinished(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK);
}
public static void onJobFinished(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_POST_NETWORK);
}
public static void onUiUpdated(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_UI_UPDATE);
LocalMetrics.getInstance().end(requireId(messageId));
ID_MAP.remove(messageId);
}
public static void cancel(@Nullable String id) {
if (id != null) {
LocalMetrics.getInstance().cancel(id);
}
}
public static void cancel(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().cancel(requireId(messageId));
}
private static @NonNull String requireId(long messageId) {
return Objects.requireNonNull(ID_MAP.get(messageId));
}
}
}