Remove setting for unlimited quota
we set a hard limit for 1 GiB per app for now, but leave code in to make it configurable in the future
This commit is contained in:
parent
176a703720
commit
03d2946c93
16 changed files with 26 additions and 86 deletions
|
@ -37,7 +37,7 @@ class KoinInstrumentationTestApp : App() {
|
|||
|
||||
single { spyk(BackupNotificationManager(context)) }
|
||||
single { spyk(FullBackup(get(), get(), get(), get())) }
|
||||
single { spyk(KVBackup(get(), get(), get(), get())) }
|
||||
single { spyk(KVBackup(get(), get(), get())) }
|
||||
single { spyk(InputFactory()) }
|
||||
|
||||
single { spyk(FullRestore(get(), get(), get(), get(), get(), get())) }
|
||||
|
|
|
@ -40,7 +40,6 @@ class KvBackupInstrumentationTest : KoinComponent {
|
|||
private val dbManager: KvDbManager by inject()
|
||||
|
||||
private val backup = KVBackup(
|
||||
settingsManager = settingsManager,
|
||||
backupReceiver = backupReceiver,
|
||||
inputFactory = inputFactory,
|
||||
dbManager = dbManager,
|
||||
|
|
|
@ -11,7 +11,6 @@ import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
|
|||
import androidx.preference.Preference
|
||||
import androidx.preference.Preference.OnPreferenceChangeListener
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import androidx.preference.TwoStatePreference
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.mms.ContentType.TEXT_PLAIN
|
||||
|
@ -65,13 +64,6 @@ class ExpertSettingsFragment : PreferenceFragmentCompat() {
|
|||
createFileLauncher.launch(name)
|
||||
true
|
||||
}
|
||||
|
||||
val quotaPreference = findPreference<SwitchPreferenceCompat>(PREF_KEY_UNLIMITED_QUOTA)
|
||||
|
||||
quotaPreference?.setOnPreferenceChangeListener { _, newValue ->
|
||||
quotaPreference.isChecked = newValue as Boolean
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
|
|
|
@ -55,7 +55,6 @@ private const val PREF_KEY_WEBDAV_PASS = "webDavPass"
|
|||
private const val PREF_KEY_BACKUP_APP_BLACKLIST = "backupAppBlacklist"
|
||||
|
||||
private const val PREF_KEY_BACKUP_STORAGE = "backup_storage"
|
||||
internal const val PREF_KEY_UNLIMITED_QUOTA = "unlimited_quota"
|
||||
internal const val PREF_KEY_LAST_BACKUP = "lastBackup"
|
||||
|
||||
class SettingsManager(private val context: Context) {
|
||||
|
@ -246,7 +245,7 @@ class SettingsManager(private val context: Context) {
|
|||
prefs.edit().putStringSet(PREF_KEY_BACKUP_APP_BLACKLIST, blacklistedApps).apply()
|
||||
}
|
||||
|
||||
fun isQuotaUnlimited() = prefs.getBoolean(PREF_KEY_UNLIMITED_QUOTA, false)
|
||||
val quota: Long = 1024 * 1024 * 1024 // 1 GiB for now
|
||||
|
||||
/**
|
||||
* This assumes that if there's no storage plugin set, it is the first start.
|
||||
|
|
|
@ -134,7 +134,7 @@ internal class BackupCoordinator(
|
|||
fun getBackupQuota(packageName: String, isFullBackup: Boolean): Long {
|
||||
// report back quota
|
||||
Log.i(TAG, "Get backup quota for $packageName. Is full backup: $isFullBackup.")
|
||||
val quota = if (isFullBackup) full.quota else kv.quota
|
||||
val quota = settingsManager.quota
|
||||
Log.i(TAG, "Reported quota of $quota bytes.")
|
||||
return quota
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ val backupModule = module {
|
|||
single<KvDbManager> { KvDbManagerImpl(androidContext()) }
|
||||
single {
|
||||
KVBackup(
|
||||
settingsManager = get(),
|
||||
backupReceiver = get(),
|
||||
inputFactory = get(),
|
||||
dbManager = get(),
|
||||
|
|
|
@ -32,8 +32,6 @@ private class FullBackupState(
|
|||
var size: Long = 0
|
||||
}
|
||||
|
||||
const val DEFAULT_QUOTA_FULL_BACKUP = (2 * (25 * 1024 * 1024)).toLong()
|
||||
|
||||
private val TAG = FullBackup::class.java.simpleName
|
||||
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
|
@ -48,12 +46,7 @@ internal class FullBackup(
|
|||
|
||||
val hasState: Boolean get() = state != null
|
||||
val currentPackageInfo get() = state?.packageInfo
|
||||
val quota
|
||||
get() = if (settingsManager.isQuotaUnlimited()) {
|
||||
Long.MAX_VALUE
|
||||
} else {
|
||||
DEFAULT_QUOTA_FULL_BACKUP
|
||||
}
|
||||
val quota get() = settingsManager.quota
|
||||
|
||||
fun checkFullBackupSize(size: Long): Int {
|
||||
Log.i(TAG, "Check full backup size of $size bytes.")
|
||||
|
|
|
@ -16,7 +16,6 @@ import android.os.ParcelFileDescriptor
|
|||
import android.util.Log
|
||||
import com.stevesoltys.seedvault.repo.BackupData
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import java.io.IOException
|
||||
|
||||
class KVBackupState(
|
||||
|
@ -24,12 +23,9 @@ class KVBackupState(
|
|||
val db: KVDb,
|
||||
)
|
||||
|
||||
const val DEFAULT_QUOTA_KEY_VALUE_BACKUP = (2 * (5 * 1024 * 1024)).toLong()
|
||||
|
||||
private val TAG = KVBackup::class.java.simpleName
|
||||
|
||||
internal class KVBackup(
|
||||
private val settingsManager: SettingsManager,
|
||||
private val backupReceiver: BackupReceiver,
|
||||
private val inputFactory: InputFactory,
|
||||
private val dbManager: KvDbManager,
|
||||
|
@ -39,12 +35,6 @@ internal class KVBackup(
|
|||
|
||||
val hasState get() = state != null
|
||||
val currentPackageInfo get() = state?.packageInfo
|
||||
val quota: Long
|
||||
get() = if (settingsManager.isQuotaUnlimited()) {
|
||||
Long.MAX_VALUE
|
||||
} else {
|
||||
DEFAULT_QUOTA_KEY_VALUE_BACKUP
|
||||
}
|
||||
|
||||
fun performBackup(
|
||||
packageInfo: PackageInfo,
|
||||
|
|
|
@ -67,8 +67,6 @@
|
|||
<string name="settings_scheduling_charging_title">Back up only when charging</string>
|
||||
|
||||
<string name="settings_expert_title">Expert settings</string>
|
||||
<string name="settings_expert_quota_title">Unlimited app quota</string>
|
||||
<string name="settings_expert_quota_summary">Do not impose a limitation on the size of app backups.\n\nWarning: This can fill up your storage location quickly. Not needed for most apps.</string>
|
||||
<string name="settings_expert_logcat_title">Save app log</string>
|
||||
<string name="settings_expert_logcat_summary">Developers can diagnose bugs with these logs.\n\nWarning: The log file might contain personally identifiable information. Review before and delete after sharing!</string>
|
||||
<string name="settings_expert_logcat_error">Error: Could not save app log</string>
|
||||
|
|
|
@ -3,12 +3,6 @@
|
|||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="false"
|
||||
android:key="unlimited_quota"
|
||||
android:summary="@string/settings_expert_quota_summary"
|
||||
android:title="@string/settings_expert_quota_title" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_apps"
|
||||
|
|
|
@ -80,7 +80,6 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
|||
private val snapshotManager = mockk<SnapshotManager>()
|
||||
private val backupReceiver = mockk<BackupReceiver>()
|
||||
private val kvBackup = KVBackup(
|
||||
settingsManager = settingsManager,
|
||||
backupReceiver = backupReceiver,
|
||||
inputFactory = inputFactory,
|
||||
dbManager = dbManager,
|
||||
|
@ -287,7 +286,7 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
|||
val bInputStream = ByteArrayInputStream(appData)
|
||||
|
||||
every { inputFactory.getInputStream(fileDescriptor) } returns bInputStream
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
coEvery { backupReceiver.addBytes(any(), capture(byteSlot)) } answers {
|
||||
bOutputStream.writeBytes(byteSlot.captured)
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ internal abstract class TransportTest {
|
|||
|
||||
protected val sigInfo: SigningInfo = mockk()
|
||||
protected val token = Random.nextLong()
|
||||
protected val quota = Random.nextLong(1, Long.MAX_VALUE)
|
||||
protected val applicationInfo = mockk<ApplicationInfo> {
|
||||
flags = FLAG_ALLOW_BACKUP or FLAG_INSTALLED
|
||||
}
|
||||
|
|
|
@ -87,11 +87,7 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
val isFullBackup = Random.nextBoolean()
|
||||
val quota = Random.nextLong()
|
||||
|
||||
if (isFullBackup) {
|
||||
every { full.quota } returns quota
|
||||
} else {
|
||||
every { kv.quota } returns quota
|
||||
}
|
||||
every { settingsManager.quota } returns quota
|
||||
assertEquals(quota, backup.getBackupQuota(packageInfo.packageName, isFullBackup))
|
||||
}
|
||||
|
||||
|
@ -182,9 +178,9 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
coEvery {
|
||||
full.performFullBackup(packageInfo, fileDescriptor, 0)
|
||||
} returns TRANSPORT_OK
|
||||
every { full.quota } returns DEFAULT_QUOTA_FULL_BACKUP
|
||||
every { settingsManager.quota } returns quota
|
||||
every {
|
||||
full.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1)
|
||||
full.checkFullBackupSize(quota + 1)
|
||||
} returns TRANSPORT_QUOTA_EXCEEDED
|
||||
every { full.currentPackageInfo } returns packageInfo
|
||||
every {
|
||||
|
@ -202,14 +198,8 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
TRANSPORT_OK,
|
||||
backup.performFullBackup(packageInfo, fileDescriptor, 0)
|
||||
)
|
||||
assertEquals(
|
||||
DEFAULT_QUOTA_FULL_BACKUP,
|
||||
backup.getBackupQuota(packageInfo.packageName, true)
|
||||
)
|
||||
assertEquals(
|
||||
TRANSPORT_QUOTA_EXCEEDED,
|
||||
backup.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1)
|
||||
)
|
||||
assertEquals(quota, backup.getBackupQuota(packageInfo.packageName, true))
|
||||
assertEquals(TRANSPORT_QUOTA_EXCEEDED, backup.checkFullBackupSize(quota + 1))
|
||||
backup.cancelFullBackup()
|
||||
assertEquals(0L, backup.requestFullBackupTime())
|
||||
|
||||
|
@ -227,7 +217,7 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
coEvery {
|
||||
full.performFullBackup(packageInfo, fileDescriptor, 0)
|
||||
} returns TRANSPORT_OK
|
||||
every { full.quota } returns DEFAULT_QUOTA_FULL_BACKUP
|
||||
every { settingsManager.quota } returns quota
|
||||
every { full.checkFullBackupSize(0) } returns TRANSPORT_PACKAGE_REJECTED
|
||||
every { full.currentPackageInfo } returns packageInfo
|
||||
every {
|
||||
|
@ -241,14 +231,8 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
every { backendManager.backendProperties } returns safProperties
|
||||
every { settingsManager.useMeteredNetwork } returns false
|
||||
|
||||
assertEquals(
|
||||
TRANSPORT_OK,
|
||||
backup.performFullBackup(packageInfo, fileDescriptor, 0)
|
||||
)
|
||||
assertEquals(
|
||||
DEFAULT_QUOTA_FULL_BACKUP,
|
||||
backup.getBackupQuota(packageInfo.packageName, true)
|
||||
)
|
||||
assertEquals(TRANSPORT_OK, backup.performFullBackup(packageInfo, fileDescriptor, 0))
|
||||
assertEquals(quota, backup.getBackupQuota(packageInfo.packageName, true))
|
||||
assertEquals(TRANSPORT_PACKAGE_REJECTED, backup.checkFullBackupSize(0))
|
||||
backup.cancelFullBackup()
|
||||
assertEquals(0L, backup.requestFullBackupTime())
|
||||
|
|
|
@ -17,6 +17,4 @@ internal abstract class BackupTest : TransportTest() {
|
|||
protected val outputStream = mockk<OutputStream>()
|
||||
protected val encryptedOutputStream = mockk<OutputStream>()
|
||||
|
||||
protected val quota = DEFAULT_QUOTA_FULL_BACKUP
|
||||
|
||||
}
|
||||
|
|
|
@ -49,21 +49,14 @@ internal class FullBackupTest : BackupTest() {
|
|||
|
||||
@Test
|
||||
fun `checkFullBackupSize exceeds quota`() {
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
|
||||
assertEquals(
|
||||
TRANSPORT_QUOTA_EXCEEDED,
|
||||
backup.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1)
|
||||
backup.checkFullBackupSize(quota + 1)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkFullBackupSize does not exceed quota when unlimited`() {
|
||||
every { settingsManager.isQuotaUnlimited() } returns true
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.checkFullBackupSize(quota + 1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkFullBackupSize for no data`() {
|
||||
assertEquals(TRANSPORT_PACKAGE_REJECTED, backup.checkFullBackupSize(0))
|
||||
|
@ -76,14 +69,14 @@ internal class FullBackupTest : BackupTest() {
|
|||
|
||||
@Test
|
||||
fun `checkFullBackupSize accepts min data`() {
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.checkFullBackupSize(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `checkFullBackupSize accepts max data`() {
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.checkFullBackupSize(quota))
|
||||
}
|
||||
|
@ -104,7 +97,8 @@ internal class FullBackupTest : BackupTest() {
|
|||
|
||||
@Test
|
||||
fun `sendBackupData first call over quota`() = runBlocking {
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
val quota = Random.nextInt(1, Int.MAX_VALUE).toLong()
|
||||
every { settingsManager.quota } returns quota
|
||||
every { inputFactory.getInputStream(data) } returns inputStream
|
||||
val numBytes = (quota + 1).toInt()
|
||||
expectSendData(numBytes)
|
||||
|
@ -123,7 +117,8 @@ internal class FullBackupTest : BackupTest() {
|
|||
|
||||
@Test
|
||||
fun `sendBackupData subsequent calls over quota`() = runBlocking {
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
val quota = (50 * 1024 * 1024).toLong()
|
||||
every { settingsManager.quota } returns quota
|
||||
every { inputFactory.getInputStream(data) } returns inputStream
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.performFullBackup(packageInfo, data, 0))
|
||||
|
@ -155,7 +150,7 @@ internal class FullBackupTest : BackupTest() {
|
|||
assertEquals(TRANSPORT_OK, backup.performFullBackup(packageInfo, data, 0))
|
||||
assertTrue(backup.hasState)
|
||||
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
every { inputStream.read(any(), any(), bytes.size) } throws IOException()
|
||||
|
||||
assertEquals(TRANSPORT_ERROR, backup.sendBackupData(bytes.size))
|
||||
|
@ -175,7 +170,7 @@ internal class FullBackupTest : BackupTest() {
|
|||
assertEquals(TRANSPORT_OK, backup.performFullBackup(packageInfo, data, 0))
|
||||
assertTrue(backup.hasState)
|
||||
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
every { inputStream.read(any(), 0, bytes.size) } returns bytes.size
|
||||
coEvery { backupReceiver.addBytes("FullBackup $packageName", any()) } throws IOException()
|
||||
|
||||
|
@ -196,7 +191,7 @@ internal class FullBackupTest : BackupTest() {
|
|||
assertEquals(TRANSPORT_OK, backup.performFullBackup(packageInfo, data, 0))
|
||||
assertTrue(backup.hasState)
|
||||
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
expectSendData(bytes.size)
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.sendBackupData(bytes.size))
|
||||
|
@ -215,7 +210,7 @@ internal class FullBackupTest : BackupTest() {
|
|||
|
||||
@Test
|
||||
fun `sendBackupData runs ok`() = runBlocking {
|
||||
every { settingsManager.isQuotaUnlimited() } returns false
|
||||
every { settingsManager.quota } returns quota
|
||||
every { inputFactory.getInputStream(data) } returns inputStream
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.performFullBackup(packageInfo, data, 0))
|
||||
|
|
|
@ -40,7 +40,6 @@ internal class KVBackupTest : BackupTest() {
|
|||
private val dbManager = mockk<KvDbManager>()
|
||||
|
||||
private val backup = KVBackup(
|
||||
settingsManager = settingsManager,
|
||||
backupReceiver = backupReceiver,
|
||||
inputFactory = inputFactory,
|
||||
dbManager = dbManager,
|
||||
|
|
Loading…
Reference in a new issue