Add a DiskSpaceNotLowConstraint and use for automatic attachment restore.

This commit is contained in:
Greyson Parrelli
2025-11-06 15:53:45 -05:00
committed by Michelle Tang
parent be5500e990
commit 44527f3763
5 changed files with 57 additions and 13 deletions

View File

@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.database.DatabaseObserver
import org.thoughtcrime.securesms.database.SignalDatabase
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.impl.BatteryNotLowConstraint
import org.thoughtcrime.securesms.jobmanager.impl.DiskSpaceNotLowConstraint
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.jobmanager.impl.WifiConstraint
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -185,6 +186,7 @@ object ArchiveRestoreProgress {
!WifiConstraint.isMet(AppDependencies.application) && !SignalStore.backup.restoreWithCellular -> ArchiveRestoreProgressState.RestoreStatus.WAITING_FOR_WIFI
!NetworkConstraint.isMet(AppDependencies.application) -> ArchiveRestoreProgressState.RestoreStatus.WAITING_FOR_INTERNET
!BatteryNotLowConstraint.isMet() -> ArchiveRestoreProgressState.RestoreStatus.LOW_BATTERY
!DiskSpaceNotLowConstraint.isMet() -> ArchiveRestoreProgressState.RestoreStatus.NOT_ENOUGH_DISK_SPACE
restoreState == RestoreState.NONE -> if (state.hasActivelyRestoredThisRun) ArchiveRestoreProgressState.RestoreStatus.FINISHED else ArchiveRestoreProgressState.RestoreStatus.NONE
else -> {
val availableBytes = SignalStore.backup.spaceAvailableOnDiskBytes

View File

@@ -7,8 +7,6 @@ package org.thoughtcrime.securesms.backup.v2
import android.app.PendingIntent
import android.database.Cursor
import android.os.Environment
import android.os.StatFs
import androidx.annotation.CheckResult
import androidx.annotation.Discouraged
import androidx.annotation.WorkerThread
@@ -22,7 +20,6 @@ import okio.ByteString.Companion.toByteString
import org.greenrobot.eventbus.EventBus
import org.signal.core.util.Base64
import org.signal.core.util.Base64.decodeBase64OrThrow
import org.signal.core.util.ByteSize
import org.signal.core.util.CursorUtil
import org.signal.core.util.DiskUtil
import org.signal.core.util.EventTimer
@@ -361,16 +358,6 @@ object BackupRepository {
}
}
/**
* Gets the free storage space in the device's data partition.
*/
fun getFreeStorageSpace(): ByteSize {
val statFs = StatFs(Environment.getDataDirectory().absolutePath)
val free = (statFs.availableBlocksLong) * statFs.blockSizeLong
return free.bytes
}
/**
* Checks whether or not we do not have enough storage space for our remaining attachments to be downloaded.
* Caller from the attachment / thumbnail download jobs.

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2025 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.jobmanager.impl
import android.app.job.JobInfo
import android.os.Build
import org.signal.core.util.DiskUtil
import org.signal.core.util.mebiBytes
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.jobmanager.Constraint
import kotlin.time.Duration.Companion.seconds
/**
* A constraint that is met so long as there is [MINIMUM_DISK_SPACE_BYTES] of space remaining on the user's disk.
*/
object DiskSpaceNotLowConstraint : Constraint {
const val KEY = "DiskSpaceAvailableConstraint"
private val MINIMUM_DISK_SPACE_BYTES = 100.mebiBytes.inWholeBytes
private val CHECK_INTERVAL = 5.seconds.inWholeMilliseconds
private var lastKnownBytesRemaining: Long = Long.MAX_VALUE
private var lastCheckTime: Long = 0
override fun isMet(): Boolean {
if (System.currentTimeMillis() - lastCheckTime >= CHECK_INTERVAL) {
lastKnownBytesRemaining = DiskUtil.getAvailableSpace(AppDependencies.application).inWholeBytes
lastCheckTime = System.currentTimeMillis()
}
return lastKnownBytesRemaining > MINIMUM_DISK_SPACE_BYTES
}
override fun getFactoryKey(): String = KEY
override fun applyToJobInfo(jobInfoBuilder: JobInfo.Builder) {
if (Build.VERSION.SDK_INT >= 26) {
jobInfoBuilder.setRequiresStorageNotLow(true)
}
}
class Factory() : Constraint.Factory<DiskSpaceNotLowConstraint> {
override fun create(): DiskSpaceNotLowConstraint {
return DiskSpaceNotLowConstraint
}
}
}

View File

@@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.jobmanager.impl.DataRestoreConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.DecryptionsDrainedConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.DeletionNotAwaitingMediaDownloadConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.DiskSpaceNotLowConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraintObserver;
import org.thoughtcrime.securesms.jobmanager.impl.NetworkOrCellServiceConstraint;
@@ -430,6 +431,7 @@ public final class JobManagerFactories {
put(DataRestoreConstraint.KEY, new DataRestoreConstraint.Factory());
put(DecryptionsDrainedConstraint.KEY, new DecryptionsDrainedConstraint.Factory());
put(DeletionNotAwaitingMediaDownloadConstraint.KEY, new DeletionNotAwaitingMediaDownloadConstraint.Factory());
put(DiskSpaceNotLowConstraint.KEY, new DiskSpaceNotLowConstraint.Factory());
put(NetworkConstraint.KEY, new NetworkConstraint.Factory(application));
put(NetworkOrCellServiceConstraint.KEY, new NetworkOrCellServiceConstraint.Factory(application));
put(NetworkOrCellServiceConstraint.LEGACY_KEY, new NetworkOrCellServiceConstraint.Factory(application));

View File

@@ -37,6 +37,7 @@ import org.thoughtcrime.securesms.jobmanager.Job
import org.thoughtcrime.securesms.jobmanager.JobLogger.format
import org.thoughtcrime.securesms.jobmanager.impl.BackoffUtil
import org.thoughtcrime.securesms.jobmanager.impl.BatteryNotLowConstraint
import org.thoughtcrime.securesms.jobmanager.impl.DiskSpaceNotLowConstraint
import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint
import org.thoughtcrime.securesms.jobmanager.impl.RestoreAttachmentConstraint
import org.thoughtcrime.securesms.jobmanager.impl.StickersNotDownloadingConstraint
@@ -204,6 +205,7 @@ class RestoreAttachmentJob private constructor(
} else {
addConstraint(RestoreAttachmentConstraint.KEY)
addConstraint(BatteryNotLowConstraint.KEY)
addConstraint(DiskSpaceNotLowConstraint.KEY)
}
if (stickerPackId != null && SignalDatabase.stickers.isPackInstalled(stickerPackId)) {