Search in sources :

Example 16 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by signalapp.

the class MessageSender method sendMediaBroadcast.

public static void sendMediaBroadcast(@NonNull Context context, @NonNull List<OutgoingSecureMediaMessage> messages, @NonNull Collection<PreUploadResult> preUploadResults) {
    Log.i(TAG, "Sending media broadcast to " + Stream.of(messages).map(m -> m.getRecipient().getId()).toList());
    Preconditions.checkArgument(messages.size() > 0, "No messages!");
    Preconditions.checkArgument(Stream.of(messages).allMatch(m -> m.getAttachments().isEmpty()), "Messages can't have attachments! They should be pre-uploaded.");
    JobManager jobManager = ApplicationDependencies.getJobManager();
    AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
    MessageDatabase mmsDatabase = SignalDatabase.mms();
    ThreadDatabase threadDatabase = SignalDatabase.threads();
    List<AttachmentId> preUploadAttachmentIds = Stream.of(preUploadResults).map(PreUploadResult::getAttachmentId).toList();
    List<String> preUploadJobIds = Stream.of(preUploadResults).map(PreUploadResult::getJobIds).flatMap(Stream::of).toList();
    List<Long> messageIds = new ArrayList<>(messages.size());
    List<String> messageDependsOnIds = new ArrayList<>(preUploadJobIds);
    mmsDatabase.beginTransaction();
    try {
        OutgoingSecureMediaMessage primaryMessage = messages.get(0);
        long primaryThreadId = threadDatabase.getOrCreateThreadIdFor(primaryMessage.getRecipient(), primaryMessage.getDistributionType());
        long primaryMessageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, primaryMessage.getRecipient(), primaryMessage, primaryThreadId), primaryThreadId, false, null);
        attachmentDatabase.updateMessageId(preUploadAttachmentIds, primaryMessageId);
        messageIds.add(primaryMessageId);
        if (messages.size() > 0) {
            List<OutgoingSecureMediaMessage> secondaryMessages = messages.subList(1, messages.size());
            List<List<AttachmentId>> attachmentCopies = new ArrayList<>();
            List<DatabaseAttachment> preUploadAttachments = Stream.of(preUploadAttachmentIds).map(attachmentDatabase::getAttachment).toList();
            for (int i = 0; i < preUploadAttachmentIds.size(); i++) {
                attachmentCopies.add(new ArrayList<>(messages.size()));
            }
            for (OutgoingSecureMediaMessage secondaryMessage : secondaryMessages) {
                long allocatedThreadId = threadDatabase.getOrCreateThreadIdFor(secondaryMessage.getRecipient(), secondaryMessage.getDistributionType());
                long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, secondaryMessage.getRecipient(), secondaryMessage, allocatedThreadId), allocatedThreadId, false, null);
                List<AttachmentId> attachmentIds = new ArrayList<>(preUploadAttachmentIds.size());
                for (int i = 0; i < preUploadAttachments.size(); i++) {
                    AttachmentId attachmentId = attachmentDatabase.insertAttachmentForPreUpload(preUploadAttachments.get(i)).getAttachmentId();
                    attachmentCopies.get(i).add(attachmentId);
                    attachmentIds.add(attachmentId);
                }
                attachmentDatabase.updateMessageId(attachmentIds, messageId);
                messageIds.add(messageId);
            }
            for (int i = 0; i < attachmentCopies.size(); i++) {
                Job copyJob = new AttachmentCopyJob(preUploadAttachmentIds.get(i), attachmentCopies.get(i));
                jobManager.add(copyJob, preUploadJobIds);
                messageDependsOnIds.add(copyJob.getId());
            }
        }
        for (int i = 0; i < messageIds.size(); i++) {
            long messageId = messageIds.get(i);
            OutgoingSecureMediaMessage message = messages.get(i);
            Recipient recipient = message.getRecipient();
            if (isLocalSelfSend(context, recipient, false)) {
                sendLocalMediaSelf(context, messageId);
            } else if (isGroupPushSend(recipient)) {
                jobManager.add(new PushGroupSendJob(messageId, recipient.getId(), null, true), messageDependsOnIds, recipient.getId().toQueueKey());
            } else {
                jobManager.add(new PushMediaSendJob(messageId, recipient, true), messageDependsOnIds, recipient.getId().toQueueKey());
            }
        }
        onMessageSent();
        mmsDatabase.setTransactionSuccessful();
    } catch (MmsException e) {
        Log.w(TAG, "Failed to send messages.", e);
    } finally {
        mmsDatabase.endTransaction();
    }
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) Arrays(java.util.Arrays) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) NonNull(androidx.annotation.NonNull) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) RecipientUtil(org.thoughtcrime.securesms.recipients.RecipientUtil) AttachmentMarkUploadedJob(org.thoughtcrime.securesms.jobs.AttachmentMarkUploadedJob) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) SmsDatabase(org.thoughtcrime.securesms.database.SmsDatabase) Preconditions(org.whispersystems.libsignal.util.guava.Preconditions) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) ParcelUtil(org.thoughtcrime.securesms.util.ParcelUtil) ReactionSendJob(org.thoughtcrime.securesms.jobs.ReactionSendJob) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SyncMessageId(org.thoughtcrime.securesms.database.MessageDatabase.SyncMessageId) PushMediaSendJob(org.thoughtcrime.securesms.jobs.PushMediaSendJob) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Collection(java.util.Collection) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage) ReactionRecord(org.thoughtcrime.securesms.database.model.ReactionRecord) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) Log(org.signal.core.util.logging.Log) List(java.util.List) Nullable(androidx.annotation.Nullable) Job(org.thoughtcrime.securesms.jobmanager.Job) ResumableUploadSpecJob(org.thoughtcrime.securesms.jobs.ResumableUploadSpecJob) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) PushGroupSendJob(org.thoughtcrime.securesms.jobs.PushGroupSendJob) NoSuchMessageException(org.thoughtcrime.securesms.database.NoSuchMessageException) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) AttachmentCompressionJob(org.thoughtcrime.securesms.jobs.AttachmentCompressionJob) Context(android.content.Context) MmsSmsDatabase(org.thoughtcrime.securesms.database.MmsSmsDatabase) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) ProfileKeySendJob(org.thoughtcrime.securesms.jobs.ProfileKeySendJob) Stream(com.annimon.stream.Stream) DirectoryHelper(org.thoughtcrime.securesms.contacts.sync.DirectoryHelper) SignalLocalMetrics(org.thoughtcrime.securesms.util.SignalLocalMetrics) WorkerThread(androidx.annotation.WorkerThread) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) Parcel(android.os.Parcel) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) ArrayList(java.util.ArrayList) RemoteDeleteSendJob(org.thoughtcrime.securesms.jobs.RemoteDeleteSendJob) TextSecurePreferences(org.thoughtcrime.securesms.util.TextSecurePreferences) MmsSendJob(org.thoughtcrime.securesms.jobs.MmsSendJob) AttachmentUploadJob(org.thoughtcrime.securesms.jobs.AttachmentUploadJob) PushTextSendJob(org.thoughtcrime.securesms.jobs.PushTextSendJob) EventBus(org.greenrobot.eventbus.EventBus) AttachmentCopyJob(org.thoughtcrime.securesms.jobs.AttachmentCopyJob) LinkedList(java.util.LinkedList) Parcelable(android.os.Parcelable) MessageId(org.thoughtcrime.securesms.database.model.MessageId) Contact(org.thoughtcrime.securesms.contactshare.Contact) MmsException(org.thoughtcrime.securesms.mms.MmsException) IOException(java.io.IOException) Optional(org.whispersystems.libsignal.util.guava.Optional) TimeUnit(java.util.concurrent.TimeUnit) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) SmsSendJob(org.thoughtcrime.securesms.jobs.SmsSendJob) ExpiringMessageManager(org.thoughtcrime.securesms.service.ExpiringMessageManager) SmsMessageRecord(org.thoughtcrime.securesms.database.model.SmsMessageRecord) Collections(java.util.Collections) PushGroupSendJob(org.thoughtcrime.securesms.jobs.PushGroupSendJob) ArrayList(java.util.ArrayList) JobManager(org.thoughtcrime.securesms.jobmanager.JobManager) MmsException(org.thoughtcrime.securesms.mms.MmsException) AttachmentCopyJob(org.thoughtcrime.securesms.jobs.AttachmentCopyJob) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) PushMediaSendJob(org.thoughtcrime.securesms.jobs.PushMediaSendJob) AttachmentMarkUploadedJob(org.thoughtcrime.securesms.jobs.AttachmentMarkUploadedJob) ReactionSendJob(org.thoughtcrime.securesms.jobs.ReactionSendJob) PushMediaSendJob(org.thoughtcrime.securesms.jobs.PushMediaSendJob) Job(org.thoughtcrime.securesms.jobmanager.Job) ResumableUploadSpecJob(org.thoughtcrime.securesms.jobs.ResumableUploadSpecJob) PushGroupSendJob(org.thoughtcrime.securesms.jobs.PushGroupSendJob) AttachmentCompressionJob(org.thoughtcrime.securesms.jobs.AttachmentCompressionJob) ProfileKeySendJob(org.thoughtcrime.securesms.jobs.ProfileKeySendJob) RemoteDeleteSendJob(org.thoughtcrime.securesms.jobs.RemoteDeleteSendJob) MmsSendJob(org.thoughtcrime.securesms.jobs.MmsSendJob) AttachmentUploadJob(org.thoughtcrime.securesms.jobs.AttachmentUploadJob) PushTextSendJob(org.thoughtcrime.securesms.jobs.PushTextSendJob) AttachmentCopyJob(org.thoughtcrime.securesms.jobs.AttachmentCopyJob) SmsSendJob(org.thoughtcrime.securesms.jobs.SmsSendJob) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage)

Example 17 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by signalapp.

the class MessageSender method sendPushWithPreUploadedMedia.

public static long sendPushWithPreUploadedMedia(final Context context, final OutgoingMediaMessage message, final Collection<PreUploadResult> preUploadResults, final long threadId, final SmsDatabase.InsertListener insertListener) {
    Log.i(TAG, "Sending media message with pre-uploads to " + message.getRecipient().getId() + ", thread: " + threadId);
    Preconditions.checkArgument(message.getAttachments().isEmpty(), "If the media is pre-uploaded, there should be no attachments on the message.");
    try {
        ThreadDatabase threadDatabase = SignalDatabase.threads();
        MessageDatabase mmsDatabase = SignalDatabase.mms();
        AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
        long allocatedThreadId;
        if (threadId == -1) {
            allocatedThreadId = threadDatabase.getOrCreateThreadIdFor(message.getRecipient(), message.getDistributionType());
        } else {
            allocatedThreadId = threadId;
        }
        Recipient recipient = message.getRecipient();
        long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId), allocatedThreadId, false, insertListener);
        List<AttachmentId> attachmentIds = Stream.of(preUploadResults).map(PreUploadResult::getAttachmentId).toList();
        List<String> jobIds = Stream.of(preUploadResults).map(PreUploadResult::getJobIds).flatMap(Stream::of).toList();
        attachmentDatabase.updateMessageId(attachmentIds, messageId);
        sendMediaMessage(context, recipient, false, messageId, jobIds);
        onMessageSent();
        threadDatabase.update(threadId, true);
        return allocatedThreadId;
    } catch (MmsException e) {
        Log.w(TAG, e);
        return threadId;
    }
}
Also used : MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) MmsException(org.thoughtcrime.securesms.mms.MmsException) Recipient(org.thoughtcrime.securesms.recipients.Recipient) ThreadDatabase(org.thoughtcrime.securesms.database.ThreadDatabase) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId)

Example 18 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by signalapp.

the class AttachmentCompressionJob method transcodeVideoIfNeededToDatabase.

@NonNull
private static DatabaseAttachment transcodeVideoIfNeededToDatabase(@NonNull Context context, @NonNull AttachmentDatabase attachmentDatabase, @NonNull DatabaseAttachment attachment, @NonNull MediaConstraints constraints, @NonNull EventBus eventBus, @NonNull TranscoderCancelationSignal cancelationSignal) throws UndeliverableMessageException {
    AttachmentDatabase.TransformProperties transformProperties = attachment.getTransformProperties();
    boolean allowSkipOnFailure = false;
    if (!MediaConstraints.isVideoTranscodeAvailable()) {
        if (transformProperties.isVideoEdited()) {
            throw new UndeliverableMessageException("Video edited, but transcode is not available");
        }
        return attachment;
    }
    try (NotificationController notification = GenericForegroundService.startForegroundTask(context, context.getString(R.string.AttachmentUploadJob_compressing_video_start))) {
        notification.setIndeterminateProgress();
        try (MediaDataSource dataSource = attachmentDatabase.mediaDataSourceFor(attachment.getAttachmentId())) {
            if (dataSource == null) {
                throw new UndeliverableMessageException("Cannot get media data source for attachment.");
            }
            allowSkipOnFailure = !transformProperties.isVideoEdited();
            TranscoderOptions options = null;
            if (transformProperties.isVideoTrim()) {
                options = new TranscoderOptions(transformProperties.getVideoTrimStartTimeUs(), transformProperties.getVideoTrimEndTimeUs());
            }
            if (FeatureFlags.useStreamingVideoMuxer() || !MemoryFileDescriptor.supported()) {
                StreamingTranscoder transcoder = new StreamingTranscoder(dataSource, options, constraints.getCompressedVideoMaxSize(context));
                if (transcoder.isTranscodeRequired()) {
                    Log.i(TAG, "Compressing with streaming muxer");
                    AttachmentSecret attachmentSecret = AttachmentSecretProvider.getInstance(context).getOrCreateAttachmentSecret();
                    File file = SignalDatabase.attachments().newFile();
                    file.deleteOnExit();
                    try {
                        try (OutputStream outputStream = ModernEncryptingPartOutputStream.createFor(attachmentSecret, file, true).second) {
                            transcoder.transcode(percent -> {
                                notification.setProgress(100, percent);
                                eventBus.postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.COMPRESSION, 100, percent));
                            }, outputStream, cancelationSignal);
                        }
                        MediaStream mediaStream = new MediaStream(ModernDecryptingPartInputStream.createFor(attachmentSecret, file, 0), MimeTypes.VIDEO_MP4, 0, 0);
                        attachmentDatabase.updateAttachmentData(attachment, mediaStream, transformProperties.isVideoEdited());
                    } finally {
                        if (!file.delete()) {
                            Log.w(TAG, "Failed to delete temp file");
                        }
                    }
                    attachmentDatabase.markAttachmentAsTransformed(attachment.getAttachmentId());
                    return Objects.requireNonNull(attachmentDatabase.getAttachment(attachment.getAttachmentId()));
                } else {
                    Log.i(TAG, "Transcode was not required");
                }
            } else {
                try (InMemoryTranscoder transcoder = new InMemoryTranscoder(context, dataSource, options, constraints.getCompressedVideoMaxSize(context))) {
                    if (transcoder.isTranscodeRequired()) {
                        Log.i(TAG, "Compressing with android in-memory muxer");
                        MediaStream mediaStream = transcoder.transcode(percent -> {
                            notification.setProgress(100, percent);
                            eventBus.postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.COMPRESSION, 100, percent));
                        }, cancelationSignal);
                        attachmentDatabase.updateAttachmentData(attachment, mediaStream, transformProperties.isVideoEdited());
                        attachmentDatabase.markAttachmentAsTransformed(attachment.getAttachmentId());
                        return Objects.requireNonNull(attachmentDatabase.getAttachment(attachment.getAttachmentId()));
                    } else {
                        Log.i(TAG, "Transcode was not required (in-memory transcoder)");
                    }
                }
            }
        }
    } catch (VideoSourceException | EncodingException | MemoryFileException e) {
        if (attachment.getSize() > constraints.getVideoMaxSize(context)) {
            throw new UndeliverableMessageException("Duration not found, attachment too large to skip transcode", e);
        } else {
            if (allowSkipOnFailure) {
                Log.w(TAG, "Problem with video source, but video small enough to skip transcode", e);
            } else {
                throw new UndeliverableMessageException("Failed to transcode and cannot skip due to editing", e);
            }
        }
    } catch (IOException | MmsException e) {
        throw new UndeliverableMessageException("Failed to transcode", e);
    }
    return attachment;
}
Also used : VideoSourceException(org.thoughtcrime.securesms.video.VideoSourceException) MemoryFileException(org.thoughtcrime.securesms.util.MemoryFileDescriptor.MemoryFileException) EncodingException(org.thoughtcrime.securesms.video.videoconverter.EncodingException) OutputStream(java.io.OutputStream) ModernEncryptingPartOutputStream(org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream) PartProgressEvent(org.thoughtcrime.securesms.events.PartProgressEvent) IOException(java.io.IOException) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) TranscoderOptions(org.thoughtcrime.securesms.video.TranscoderOptions) MmsException(org.thoughtcrime.securesms.mms.MmsException) InMemoryTranscoder(org.thoughtcrime.securesms.video.InMemoryTranscoder) MediaStream(org.thoughtcrime.securesms.mms.MediaStream) MediaDataSource(android.media.MediaDataSource) UndeliverableMessageException(org.thoughtcrime.securesms.transport.UndeliverableMessageException) StreamingTranscoder(org.thoughtcrime.securesms.video.StreamingTranscoder) AttachmentSecret(org.thoughtcrime.securesms.crypto.AttachmentSecret) File(java.io.File) NotificationController(org.thoughtcrime.securesms.service.NotificationController) NonNull(androidx.annotation.NonNull)

Example 19 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by signalapp.

the class AttachmentUploadJob method onRun.

@Override
public void onRun() throws Exception {
    if (!Recipient.self().isRegistered()) {
        throw new NotPushRegisteredException();
    }
    Data inputData = getInputData();
    ResumableUploadSpec resumableUploadSpec;
    if (forceV2) {
        Log.d(TAG, "Forcing utilization of V2");
        resumableUploadSpec = null;
    } else if (inputData != null && inputData.hasString(ResumableUploadSpecJob.KEY_RESUME_SPEC)) {
        Log.d(TAG, "Using attachments V3");
        resumableUploadSpec = ResumableUploadSpec.deserialize(inputData.getString(ResumableUploadSpecJob.KEY_RESUME_SPEC));
    } else {
        Log.d(TAG, "Using attachments V2");
        resumableUploadSpec = null;
    }
    SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender();
    AttachmentDatabase database = SignalDatabase.attachments();
    DatabaseAttachment databaseAttachment = database.getAttachment(attachmentId);
    if (databaseAttachment == null) {
        throw new InvalidAttachmentException("Cannot find the specified attachment.");
    }
    long timeSinceUpload = System.currentTimeMillis() - databaseAttachment.getUploadTimestamp();
    if (timeSinceUpload < UPLOAD_REUSE_THRESHOLD && !TextUtils.isEmpty(databaseAttachment.getLocation())) {
        Log.i(TAG, "We can re-use an already-uploaded file. It was uploaded " + timeSinceUpload + " ms ago. Skipping.");
        return;
    } else if (databaseAttachment.getUploadTimestamp() > 0) {
        Log.i(TAG, "This file was previously-uploaded, but too long ago to be re-used. Age: " + timeSinceUpload + " ms");
    }
    Log.i(TAG, "Uploading attachment for message " + databaseAttachment.getMmsId() + " with ID " + databaseAttachment.getAttachmentId());
    try (NotificationController notification = getNotificationForAttachment(databaseAttachment)) {
        SignalServiceAttachment localAttachment = getAttachmentFor(databaseAttachment, notification, resumableUploadSpec);
        SignalServiceAttachmentPointer remoteAttachment = messageSender.uploadAttachment(localAttachment.asStream());
        Attachment attachment = PointerAttachment.forPointer(Optional.of(remoteAttachment), null, databaseAttachment.getFastPreflightId()).get();
        database.updateAttachmentAfterUpload(databaseAttachment.getAttachmentId(), attachment, remoteAttachment.getUploadTimestamp());
    } catch (NonSuccessfulResumableUploadResponseCodeException e) {
        if (e.getCode() == 400) {
            Log.w(TAG, "Failed to upload due to a 400 when getting resumable upload information. Downgrading to attachments v2", e);
            forceV2 = true;
        }
    }
}
Also used : NotPushRegisteredException(org.thoughtcrime.securesms.net.NotPushRegisteredException) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) SignalServiceMessageSender(org.whispersystems.signalservice.api.SignalServiceMessageSender) SignalServiceAttachmentPointer(org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer) Data(org.thoughtcrime.securesms.jobmanager.Data) PointerAttachment(org.thoughtcrime.securesms.attachments.PointerAttachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) NonSuccessfulResumableUploadResponseCodeException(org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResumableUploadResponseCodeException) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) ResumableUploadSpec(org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec) NotificationController(org.thoughtcrime.securesms.service.NotificationController)

Example 20 with AttachmentDatabase

use of org.thoughtcrime.securesms.database.AttachmentDatabase in project Signal-Android by signalapp.

the class PartDataSource method open.

@Override
public long open(DataSpec dataSpec) throws IOException {
    this.uri = dataSpec.uri;
    AttachmentDatabase attachmentDatabase = SignalDatabase.attachments();
    PartUriParser partUri = new PartUriParser(uri);
    Attachment attachment = attachmentDatabase.getAttachment(partUri.getPartId());
    if (attachment == null)
        throw new IOException("Attachment not found");
    this.inputSteam = attachmentDatabase.getAttachmentStream(partUri.getPartId(), dataSpec.position);
    if (listener != null) {
        listener.onTransferStart(this, dataSpec, false);
    }
    if (attachment.getSize() - dataSpec.position <= 0)
        throw new EOFException("No more data");
    return attachment.getSize() - dataSpec.position;
}
Also used : PartUriParser(org.thoughtcrime.securesms.mms.PartUriParser) EOFException(java.io.EOFException) Attachment(org.thoughtcrime.securesms.attachments.Attachment) IOException(java.io.IOException) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase)

Aggregations

AttachmentDatabase (org.thoughtcrime.securesms.database.AttachmentDatabase)35 DatabaseAttachment (org.thoughtcrime.securesms.attachments.DatabaseAttachment)20 Attachment (org.thoughtcrime.securesms.attachments.Attachment)14 MmsException (org.thoughtcrime.securesms.mms.MmsException)13 IOException (java.io.IOException)12 AttachmentId (org.thoughtcrime.securesms.attachments.AttachmentId)10 NonNull (androidx.annotation.NonNull)6 LinkedList (java.util.LinkedList)6 MessageDatabase (org.thoughtcrime.securesms.database.MessageDatabase)6 Job (org.thoughtcrime.securesms.jobmanager.Job)6 UndeliverableMessageException (org.thoughtcrime.securesms.transport.UndeliverableMessageException)6 File (java.io.File)5 PartProgressEvent (org.thoughtcrime.securesms.events.PartProgressEvent)5 Stream (com.annimon.stream.Stream)4 MessageRecord (org.thoughtcrime.securesms.database.model.MessageRecord)4 MediaStream (org.thoughtcrime.securesms.mms.MediaStream)4 SignalServiceAttachmentPointer (org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer)4 Nullable (androidx.annotation.Nullable)3 InputStream (java.io.InputStream)3 List (java.util.List)3