diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/AttachmentCancelClickListener.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/AttachmentCancelClickListener.kt index 0a1c612243..cab7c620a7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/AttachmentCancelClickListener.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/AttachmentCancelClickListener.kt @@ -5,6 +5,8 @@ package org.thoughtcrime.securesms.conversation.clicklisteners import android.view.View +import kotlinx.collections.immutable.toPersistentList +import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.attachments.DatabaseAttachment import org.thoughtcrime.securesms.dependencies.AppDependencies @@ -14,27 +16,37 @@ import org.thoughtcrime.securesms.jobs.AttachmentUploadJob import org.thoughtcrime.securesms.mms.Slide import org.thoughtcrime.securesms.mms.SlidesClickedListener +/** + * Cancels all attachments passed through to the callback. + * + * Creates a persistent copy of the handed list of slides to prevent off-thread + * manipulation. + */ internal class AttachmentCancelClickListener : SlidesClickedListener { - override fun onClick(v: View, slides: List) { - Log.i(TAG, "Canceling compression/upload/download jobs for ${slides.size} items") - val jobManager = AppDependencies.jobManager - var cancelCount = 0 - for (slide in slides) { - val attachmentId = (slide.asAttachment() as DatabaseAttachment).attachmentId - val jobsToCancel = jobManager.find { - when (it.factoryKey) { - AttachmentDownloadJob.KEY -> AttachmentDownloadJob.jobSpecMatchesAttachmentId(it, attachmentId) - AttachmentCompressionJob.KEY -> AttachmentCompressionJob.jobSpecMatchesAttachmentId(it, attachmentId) - AttachmentUploadJob.KEY -> AttachmentUploadJob.jobSpecMatchesAttachmentId(it, attachmentId) - else -> false + override fun onClick(unused: View, slides: List) { + val toCancel = slides.toPersistentList() + + Log.i(TAG, "Canceling compression/upload/download jobs for ${toCancel.size} items") + + SignalExecutors.BOUNDED_IO.execute { + var cancelCount = 0 + for (slide in toCancel) { + val attachmentId = (slide.asAttachment() as DatabaseAttachment).attachmentId + val jobsToCancel = AppDependencies.jobManager.find { + when (it.factoryKey) { + AttachmentDownloadJob.KEY -> AttachmentDownloadJob.jobSpecMatchesAttachmentId(it, attachmentId) + AttachmentCompressionJob.KEY -> AttachmentCompressionJob.jobSpecMatchesAttachmentId(it, attachmentId) + AttachmentUploadJob.KEY -> AttachmentUploadJob.jobSpecMatchesAttachmentId(it, attachmentId) + else -> false + } + } + jobsToCancel.forEach { + AppDependencies.jobManager.cancel(it.id) + cancelCount++ } } - jobsToCancel.forEach { - jobManager.cancel(it.id) - cancelCount++ - } + Log.i(TAG, "Canceled $cancelCount jobs.") } - Log.i(TAG, "Canceled $cancelCount jobs.") } companion object { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/ResendClickListener.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/ResendClickListener.kt index 60dede9140..c00b7f4fde 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/ResendClickListener.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/clicklisteners/ResendClickListener.kt @@ -6,6 +6,7 @@ package org.thoughtcrime.securesms.conversation.clicklisteners import android.view.View +import org.signal.core.util.concurrent.SignalExecutors import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.database.model.MessageRecord import org.thoughtcrime.securesms.mms.Slide @@ -19,7 +20,9 @@ class ResendClickListener(private val messageRecord: MessageRecord) : SlidesClic return } - MessageSender.resend(v.context, messageRecord) + SignalExecutors.BOUNDED.execute { + MessageSender.resend(v.context, messageRecord) + } } companion object { diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java index 3be335af51..cdc1ab318d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java @@ -288,6 +288,7 @@ public class JobManager implements ConstraintObserver.Notifier { * Search through the list of pending jobs and find all that match a given predicate. Note that there will always be races here, and the result you get back * may not be valid anymore by the time you get it. Use with caution. */ + @WorkerThread public @NonNull List find(@NonNull Predicate predicate) { waitUntilInitialized(); return jobController.findJobs(predicate); diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java b/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java index c76c30cdf3..8789ce585a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java @@ -478,6 +478,7 @@ public class MessageSender { onMessageSent(); } + @WorkerThread public static void resend(Context context, MessageRecord messageRecord) { long messageId = messageRecord.getId(); boolean forceSms = messageRecord.isForcedSms(); @@ -517,6 +518,7 @@ public class MessageSender { return outgoingMessage; } + @WorkerThread private static void sendMessageInternal(Context context, Recipient recipient, SendType sendType, @@ -534,6 +536,7 @@ public class MessageSender { } } + @WorkerThread private static void sendMediaPush(Context context, Recipient recipient, long messageId, @NonNull Collection uploadJobIds) { JobManager jobManager = AppDependencies.getJobManager(); @@ -545,6 +548,7 @@ public class MessageSender { } } + @WorkerThread private static void sendGroupPush(@NonNull Context context, @NonNull Recipient recipient, long messageId, @NonNull Set filterRecipientIds, @NonNull Collection uploadJobIds) { JobManager jobManager = AppDependencies.getJobManager(); @@ -556,6 +560,7 @@ public class MessageSender { } } + @WorkerThread private static void sendDistributionList(@NonNull Context context, @NonNull Recipient recipient, long messageId, @NonNull Set filterRecipientIds, @NonNull Collection uploadJobIds) { JobManager jobManager = AppDependencies.getJobManager();