Upload large backup attachments using a foreground service.

This commit is contained in:
jeffrey-signal
2025-06-11 12:02:23 -04:00
committed by GitHub
parent f8d8558cdb
commit cd18db613a
18 changed files with 137 additions and 72 deletions

View File

@@ -4,6 +4,8 @@
*/
package org.whispersystems.signalservice.api.messages
import org.signal.core.util.ByteSize
import org.signal.core.util.bytes
import org.whispersystems.signalservice.internal.push.http.CancelationSignal
import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec
import java.io.InputStream
@@ -160,11 +162,8 @@ abstract class SignalServiceAttachment protected constructor(val contentType: St
interface ProgressListener {
/**
* Called on a progress change event.
*
* @param total The total amount to transmit/receive in bytes.
* @param progress The amount that has been transmitted/received in bytes thus far
*/
fun onAttachmentProgress(total: Long, progress: Long)
fun onAttachmentProgress(progress: AttachmentTransferProgress)
fun shouldCancel(): Boolean
}
@@ -176,3 +175,21 @@ abstract class SignalServiceAttachment protected constructor(val contentType: St
}
}
}
/**
* Progress status for an attachment upload/download operation.
*/
data class AttachmentTransferProgress(
/** The total amount of bytes to transmit/receive. */
val total: ByteSize,
/** The amount of bytes that have been transmitted/received thus far. */
val transmitted: ByteSize
) {
constructor(total: Long, transmitted: Long) : this(total.bytes, transmitted.bytes)
/**
* The fractional progress as a float value between 0.0 and 1.0 (inclusive).
*/
val value = transmitted.inWholeBytes.toFloat() / total.inWholeBytes
}

View File

@@ -28,6 +28,7 @@ import org.whispersystems.signalservice.api.account.AccountAttributes;
import org.whispersystems.signalservice.api.account.PreKeyCollection;
import org.whispersystems.signalservice.api.crypto.SealedSenderAccess;
import org.whispersystems.signalservice.api.groupsv2.GroupsV2AuthorizationString;
import org.whispersystems.signalservice.api.messages.AttachmentTransferProgress;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment.ProgressListener;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId;
import org.whispersystems.signalservice.api.messages.calls.CallingResponse;
@@ -653,7 +654,7 @@ public class PushServiceSocket {
if ((totalRead += read) > maxSizeBytes) throw new PushNetworkException("Response exceeded max size!");
if (listener != null) {
listener.onAttachmentProgress(body.contentLength() + offset, totalRead);
listener.onAttachmentProgress(new AttachmentTransferProgress(body.contentLength() + offset, totalRead));
if (listener.shouldCancel()) {
call.cancel();
throw new PushNetworkException("Canceled by listener check.");

View File

@@ -8,6 +8,7 @@ import org.signal.libsignal.protocol.incrementalmac.ChunkSizeChoice
import org.signal.libsignal.protocol.logging.Log
import org.whispersystems.signalservice.api.crypto.DigestingOutputStream
import org.whispersystems.signalservice.api.crypto.SkippingOutputStream
import org.whispersystems.signalservice.api.messages.AttachmentTransferProgress
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment
import org.whispersystems.signalservice.internal.crypto.AttachmentDigest
import java.io.ByteArrayOutputStream
@@ -58,7 +59,7 @@ class DigestingRequestBody(
throw IOException("Canceled!")
}
outputStream.write(buffer, 0, read)
progressListener?.onAttachmentProgress(contentLength, outputStream.totalBytesWritten)
progressListener?.onAttachmentProgress(AttachmentTransferProgress(total = contentLength, transmitted = outputStream.totalBytesWritten))
}
outputStream.flush()