Rename Storage to SafStorage
in preparation for generalization
This commit is contained in:
parent
6788d0d25a
commit
2489190824
19 changed files with 117 additions and 68 deletions
|
@ -49,7 +49,7 @@ class PluginTest : KoinComponent {
|
|||
|
||||
@Before
|
||||
fun setup() = runBlocking {
|
||||
every { mockedSettingsManager.getStorage() } returns settingsManager.getStorage()
|
||||
every { mockedSettingsManager.getSafStorage() } returns settingsManager.getSafStorage()
|
||||
storage.rootBackupDir?.deleteContents(context)
|
||||
?: error("Select a storage location in the app first!")
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ class PluginTest : KoinComponent {
|
|||
fun testInitializationAndRestoreSets() = runBlocking(Dispatchers.IO) {
|
||||
// no backups available initially
|
||||
assertEquals(0, storagePlugin.getAvailableBackups()?.toList()?.size)
|
||||
val s = settingsManager.getStorage() ?: error("no storage")
|
||||
val s = settingsManager.getSafStorage() ?: error("no storage")
|
||||
assertFalse(storagePlugin.hasBackup(s))
|
||||
|
||||
// prepare returned tokens requested when initializing device
|
||||
|
|
|
@ -17,7 +17,7 @@ internal class BackupRestoreTest : SeedvaultLargeTest() {
|
|||
confirmCode()
|
||||
}
|
||||
|
||||
if (settingsManager.getStorage() == null) {
|
||||
if (settingsManager.getSafStorage() == null) {
|
||||
chooseStorageLocation()
|
||||
} else {
|
||||
changeBackupLocation()
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.stevesoltys.seedvault.plugins
|
|||
|
||||
import android.app.backup.RestoreSet
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
@ -59,7 +59,7 @@ interface StoragePlugin {
|
|||
*/
|
||||
@WorkerThread
|
||||
@Throws(IOException::class)
|
||||
suspend fun hasBackup(storage: Storage): Boolean
|
||||
suspend fun hasBackup(safStorage: SafStorage): Boolean
|
||||
|
||||
/**
|
||||
* Get the set of all backups currently available for restore.
|
||||
|
|
|
@ -9,7 +9,6 @@ import com.stevesoltys.seedvault.plugins.EncryptedMetadata
|
|||
import com.stevesoltys.seedvault.plugins.StoragePlugin
|
||||
import com.stevesoltys.seedvault.plugins.chunkFolderRegex
|
||||
import com.stevesoltys.seedvault.plugins.tokenRegex
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
@ -28,7 +27,7 @@ internal class DocumentsProviderStoragePlugin(
|
|||
*/
|
||||
private val context: Context
|
||||
get() = appContext.getStorageContext {
|
||||
storage.storage?.isUsb == true
|
||||
storage.safStorage?.isUsb == true
|
||||
}
|
||||
|
||||
private val packageManager: PackageManager = appContext.packageManager
|
||||
|
@ -79,10 +78,10 @@ internal class DocumentsProviderStoragePlugin(
|
|||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override suspend fun hasBackup(storage: Storage): Boolean {
|
||||
override suspend fun hasBackup(safStorage: SafStorage): Boolean {
|
||||
// potentially get system user context if needed here
|
||||
val c = appContext.getStorageContext { storage.isUsb }
|
||||
val parent = DocumentFile.fromTreeUri(c, storage.uri) ?: throw AssertionError()
|
||||
val c = appContext.getStorageContext { safStorage.isUsb }
|
||||
val parent = DocumentFile.fromTreeUri(c, safStorage.uri) ?: throw AssertionError()
|
||||
val rootDir = parent.findFileBlocking(c, DIRECTORY_ROOT) ?: return false
|
||||
val backupSets = getBackups(c, rootDir)
|
||||
return backupSets.isNotEmpty()
|
||||
|
|
|
@ -18,7 +18,6 @@ import androidx.annotation.VisibleForTesting
|
|||
import androidx.documentfile.provider.DocumentFile
|
||||
import com.stevesoltys.seedvault.getStorageContext
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
@ -45,9 +44,9 @@ internal class DocumentsStorage(
|
|||
private val appContext: Context,
|
||||
private val settingsManager: SettingsManager,
|
||||
) {
|
||||
internal var storage: Storage? = null
|
||||
internal var safStorage: SafStorage? = null
|
||||
get() {
|
||||
if (field == null) field = settingsManager.getStorage()
|
||||
if (field == null) field = settingsManager.getSafStorage()
|
||||
return field
|
||||
}
|
||||
|
||||
|
@ -56,14 +55,14 @@ internal class DocumentsStorage(
|
|||
*/
|
||||
private val context: Context
|
||||
get() = appContext.getStorageContext {
|
||||
storage?.isUsb == true
|
||||
safStorage?.isUsb == true
|
||||
}
|
||||
private val contentResolver: ContentResolver get() = context.contentResolver
|
||||
|
||||
internal var rootBackupDir: DocumentFile? = null
|
||||
get() = runBlocking {
|
||||
if (field == null) {
|
||||
val parent = storage?.getDocumentFile(context)
|
||||
val parent = safStorage?.getDocumentFile(context)
|
||||
?: return@runBlocking null
|
||||
field = try {
|
||||
parent.createOrGetDirectory(context, DIRECTORY_ROOT).apply {
|
||||
|
@ -104,13 +103,13 @@ internal class DocumentsStorage(
|
|||
* Resets this storage abstraction, forcing it to re-fetch cached values on next access.
|
||||
*/
|
||||
fun reset(newToken: Long?) {
|
||||
storage = null
|
||||
safStorage = null
|
||||
currentToken = newToken
|
||||
rootBackupDir = null
|
||||
currentSetDir = null
|
||||
}
|
||||
|
||||
fun getAuthority(): String? = storage?.uri?.authority
|
||||
fun getAuthority(): String? = safStorage?.uri?.authority
|
||||
|
||||
@Throws(IOException::class)
|
||||
suspend fun getSetDir(token: Long = currentToken ?: error("no token")): DocumentFile? {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2024 The Calyx Institute
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package com.stevesoltys.seedvault.plugins.saf
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.Uri
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
|
||||
data class SafStorage(
|
||||
val uri: Uri,
|
||||
val name: String,
|
||||
val isUsb: Boolean,
|
||||
val requiresNetwork: Boolean,
|
||||
) {
|
||||
fun getDocumentFile(context: Context) = DocumentFile.fromTreeUri(context, uri)
|
||||
?: throw AssertionError("Should only happen on API < 21.")
|
||||
|
||||
/**
|
||||
* Returns true if this is USB storage that is not available, false otherwise.
|
||||
*
|
||||
* Must be run off UI thread (ideally I/O).
|
||||
*/
|
||||
@WorkerThread
|
||||
fun isUnavailableUsb(context: Context): Boolean {
|
||||
return isUsb && !getDocumentFile(context).isDirectory
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is storage that requires network access,
|
||||
* but it isn't available right now.
|
||||
*/
|
||||
fun isUnavailableNetwork(context: Context, allowMetered: Boolean): Boolean {
|
||||
return requiresNetwork && !hasUnmeteredInternet(context, allowMetered)
|
||||
}
|
||||
|
||||
private fun hasUnmeteredInternet(context: Context, allowMetered: Boolean): Boolean {
|
||||
val cm = context.getSystemService(ConnectivityManager::class.java) ?: return false
|
||||
val isMetered = cm.isActiveNetworkMetered
|
||||
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) ?: return false
|
||||
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
|
||||
(allowMetered || !isMetered)
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import com.stevesoltys.seedvault.plugins.chunkFolderRegex
|
|||
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
|
||||
import com.stevesoltys.seedvault.plugins.saf.FILE_NO_MEDIA
|
||||
import com.stevesoltys.seedvault.plugins.tokenRegex
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
|
@ -135,7 +135,7 @@ internal class WebDavStoragePlugin(
|
|||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
override suspend fun hasBackup(storage: Storage): Boolean {
|
||||
override suspend fun hasBackup(safStorage: SafStorage): Boolean {
|
||||
// TODO this requires refactoring
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class SchedulingFragment : PreferenceFragmentCompat(),
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val storage = settingsManager.getStorage()
|
||||
val storage = settingsManager.getSafStorage()
|
||||
if (storage?.isUsb == true) {
|
||||
findPreference<PreferenceCategory>("scheduling_category_conditions")?.isEnabled = false
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import androidx.preference.TwoStatePreference
|
|||
import androidx.work.WorkInfo
|
||||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import com.stevesoltys.seedvault.restore.RestoreActivity
|
||||
import com.stevesoltys.seedvault.ui.toRelativeTime
|
||||
import org.koin.android.ext.android.inject
|
||||
|
@ -48,7 +49,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
private var menuBackupNow: MenuItem? = null
|
||||
private var menuRestore: MenuItem? = null
|
||||
|
||||
private var storage: Storage? = null
|
||||
private var safStorage: SafStorage? = null
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
permitDiskReads {
|
||||
|
@ -164,7 +165,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
// we need to re-set the title when returning to this fragment
|
||||
activity?.setTitle(R.string.backup)
|
||||
|
||||
storage = settingsManager.getStorage()
|
||||
safStorage = settingsManager.getSafStorage()
|
||||
setBackupEnabledState()
|
||||
setBackupLocationSummary()
|
||||
setAutoRestoreState()
|
||||
|
@ -241,7 +242,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
activity?.contentResolver?.let {
|
||||
autoRestore.isChecked = Settings.Secure.getInt(it, BACKUP_AUTO_RESTORE, 1) == 1
|
||||
}
|
||||
val storage = this.storage
|
||||
val storage = this.safStorage
|
||||
if (storage?.isUsb == true) {
|
||||
autoRestore.summary = getString(R.string.settings_auto_restore_summary) + "\n\n" +
|
||||
getString(R.string.settings_auto_restore_summary_usb, storage.name)
|
||||
|
@ -252,7 +253,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
|
||||
private fun setBackupLocationSummary() {
|
||||
// get name of storage location
|
||||
backupLocation.summary = storage?.name ?: getString(R.string.settings_backup_location_none)
|
||||
backupLocation.summary = safStorage?.name ?: getString(R.string.settings_backup_location_none)
|
||||
}
|
||||
|
||||
private fun setAppBackupStatusSummary(lastBackupInMillis: Long?) {
|
||||
|
@ -271,7 +272,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
* says that nothing is scheduled which can happen when backup destination is on flash drive.
|
||||
*/
|
||||
private fun setAppBackupSchedulingSummary(workInfo: WorkInfo?) {
|
||||
if (storage?.isUsb == true) {
|
||||
if (safStorage?.isUsb == true) {
|
||||
backupScheduling.summary = getString(R.string.settings_backup_status_next_backup_usb)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.documentfile.provider.DocumentFile
|
|||
import androidx.preference.PreferenceManager
|
||||
import com.stevesoltys.seedvault.getStorageContext
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import com.stevesoltys.seedvault.transport.backup.BackupCoordinator
|
||||
import java.util.concurrent.ConcurrentSkipListSet
|
||||
|
||||
|
@ -88,24 +89,24 @@ class SettingsManager(private val context: Context) {
|
|||
token = newToken
|
||||
}
|
||||
|
||||
// FIXME Storage is currently plugin specific and not generic
|
||||
fun setStorage(storage: Storage) {
|
||||
// FIXME SafStorage is currently plugin specific and not generic
|
||||
fun setSafStorage(safStorage: SafStorage) {
|
||||
prefs.edit()
|
||||
.putString(PREF_KEY_STORAGE_URI, storage.uri.toString())
|
||||
.putString(PREF_KEY_STORAGE_NAME, storage.name)
|
||||
.putBoolean(PREF_KEY_STORAGE_IS_USB, storage.isUsb)
|
||||
.putBoolean(PREF_KEY_STORAGE_REQUIRES_NETWORK, storage.requiresNetwork)
|
||||
.putString(PREF_KEY_STORAGE_URI, safStorage.uri.toString())
|
||||
.putString(PREF_KEY_STORAGE_NAME, safStorage.name)
|
||||
.putBoolean(PREF_KEY_STORAGE_IS_USB, safStorage.isUsb)
|
||||
.putBoolean(PREF_KEY_STORAGE_REQUIRES_NETWORK, safStorage.requiresNetwork)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun getStorage(): Storage? {
|
||||
fun getSafStorage(): SafStorage? {
|
||||
val uriStr = prefs.getString(PREF_KEY_STORAGE_URI, null) ?: return null
|
||||
val uri = Uri.parse(uriStr)
|
||||
val name = prefs.getString(PREF_KEY_STORAGE_NAME, null)
|
||||
?: throw IllegalStateException("no storage name")
|
||||
val isUsb = prefs.getBoolean(PREF_KEY_STORAGE_IS_USB, false)
|
||||
val requiresNetwork = prefs.getBoolean(PREF_KEY_STORAGE_REQUIRES_NETWORK, false)
|
||||
return Storage(uri, name, isUsb, requiresNetwork)
|
||||
return SafStorage(uri, name, isUsb, requiresNetwork)
|
||||
}
|
||||
|
||||
fun setFlashDrive(usb: FlashDrive?) {
|
||||
|
@ -144,7 +145,7 @@ class SettingsManager(private val context: Context) {
|
|||
*/
|
||||
@WorkerThread
|
||||
fun canDoBackupNow(): Boolean {
|
||||
val storage = getStorage() ?: return false
|
||||
val storage = getSafStorage() ?: return false
|
||||
val systemContext = context.getStorageContext { storage.isUsb }
|
||||
return !storage.isUnavailableUsb(systemContext) &&
|
||||
!storage.isUnavailableNetwork(context, useMeteredNetwork)
|
||||
|
|
|
@ -131,7 +131,7 @@ internal class SettingsViewModel(
|
|||
}
|
||||
|
||||
override fun onStorageLocationChanged() {
|
||||
val storage = settingsManager.getStorage() ?: return
|
||||
val storage = settingsManager.getSafStorage() ?: return
|
||||
|
||||
Log.i(TAG, "onStorageLocationChanged (isUsb: ${storage.isUsb}")
|
||||
if (storage.isUsb) {
|
||||
|
@ -156,7 +156,7 @@ internal class SettingsViewModel(
|
|||
}
|
||||
|
||||
private fun onStoragePropertiesChanged() {
|
||||
val storage = settingsManager.getStorage() ?: return
|
||||
val storage = settingsManager.getSafStorage() ?: return
|
||||
|
||||
Log.d(TAG, "onStoragePropertiesChanged")
|
||||
// register storage observer
|
||||
|
@ -200,7 +200,7 @@ internal class SettingsViewModel(
|
|||
i.putExtra(EXTRA_START_APP_BACKUP, true)
|
||||
startForegroundService(app, i)
|
||||
} else {
|
||||
val isUsb = settingsManager.getStorage()?.isUsb ?: false
|
||||
val isUsb = settingsManager.getSafStorage()?.isUsb ?: false
|
||||
AppBackupWorker.scheduleNow(app, reschedule = !isUsb)
|
||||
}
|
||||
}
|
||||
|
@ -280,14 +280,14 @@ internal class SettingsViewModel(
|
|||
}
|
||||
|
||||
fun scheduleAppBackup(existingWorkPolicy: ExistingPeriodicWorkPolicy) {
|
||||
val storage = settingsManager.getStorage() ?: error("no storage available")
|
||||
val storage = settingsManager.getSafStorage() ?: error("no storage available")
|
||||
if (!storage.isUsb && backupManager.isBackupEnabled) {
|
||||
AppBackupWorker.schedule(app, settingsManager, existingWorkPolicy)
|
||||
}
|
||||
}
|
||||
|
||||
fun scheduleFilesBackup() {
|
||||
val storage = settingsManager.getStorage() ?: error("no storage available")
|
||||
val storage = settingsManager.getSafStorage() ?: error("no storage available")
|
||||
if (!storage.isUsb && settingsManager.isStorageBackupEnabled()) {
|
||||
BackupJobService.scheduleJob(
|
||||
context = app,
|
||||
|
|
|
@ -18,7 +18,7 @@ internal class SeedvaultSafStoragePlugin(
|
|||
*/
|
||||
override val context: Context
|
||||
get() = appContext.getStorageContext {
|
||||
storage.storage?.isUsb == true
|
||||
storage.safStorage?.isUsb == true
|
||||
}
|
||||
override val root: DocumentFile
|
||||
get() = storage.rootBackupDir ?: error("No storage set")
|
||||
|
|
|
@ -43,7 +43,7 @@ internal class StorageBackupService : BackupService() {
|
|||
|
||||
override fun onBackupFinished(intent: Intent, success: Boolean) {
|
||||
if (intent.getBooleanExtra(EXTRA_START_APP_BACKUP, false)) {
|
||||
val isUsb = settingsManager.getStorage()?.isUsb ?: false
|
||||
val isUsb = settingsManager.getSafStorage()?.isUsb ?: false
|
||||
AppBackupWorker.scheduleNow(applicationContext, reschedule = !isUsb)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -411,7 +411,7 @@ internal class BackupCoordinator(
|
|||
val longBackoff = DAYS.toMillis(30)
|
||||
|
||||
// back off if there's no storage set
|
||||
val storage = settingsManager.getStorage() ?: return longBackoff
|
||||
val storage = settingsManager.getSafStorage() ?: return longBackoff
|
||||
return when {
|
||||
// back off if storage is removable and not available right now
|
||||
storage.isUnavailableUsb(context) -> longBackoff
|
||||
|
|
|
@ -169,7 +169,7 @@ internal class RestoreCoordinator(
|
|||
// check if we even have a backup of that app
|
||||
if (metadataManager.getPackageMetadata(pmPackageName) != null) {
|
||||
// remind user to plug in storage device
|
||||
val storageName = settingsManager.getStorage()?.name
|
||||
val storageName = settingsManager.getSafStorage()?.name
|
||||
?: context.getString(R.string.settings_backup_location_none)
|
||||
notificationManager.onRemovableStorageNotAvailableForRestore(
|
||||
pmPackageName,
|
||||
|
@ -365,7 +365,7 @@ internal class RestoreCoordinator(
|
|||
|
||||
// TODO this is plugin specific, needs to be factored out when supporting different plugins
|
||||
private fun isStorageRemovableAndNotAvailable(): Boolean {
|
||||
val storage = settingsManager.getStorage() ?: return false
|
||||
val storage = settingsManager.getSafStorage() ?: return false
|
||||
return storage.isUnavailableUsb(context)
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ internal class BackupStorageViewModel(
|
|||
}
|
||||
|
||||
private fun scheduleBackupWorkers() {
|
||||
val storage = settingsManager.getStorage() ?: error("no storage available")
|
||||
val storage = settingsManager.getSafStorage() ?: error("no storage available")
|
||||
if (!storage.isUsb) {
|
||||
if (backupManager.isBackupEnabled) {
|
||||
AppBackupWorker.schedule(app, settingsManager, CANCEL_AND_REENQUEUE)
|
||||
|
|
|
@ -16,10 +16,10 @@ import androidx.lifecycle.viewModelScope
|
|||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.isMassStorage
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import com.stevesoltys.seedvault.settings.BackupManagerSettings
|
||||
import com.stevesoltys.seedvault.settings.FlashDrive
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import com.stevesoltys.seedvault.ui.LiveEvent
|
||||
import com.stevesoltys.seedvault.ui.MutableLiveEvent
|
||||
import com.stevesoltys.seedvault.ui.storage.StorageOption.SafOption
|
||||
|
@ -47,7 +47,7 @@ internal abstract class StorageViewModel(
|
|||
|
||||
internal var isSetupWizard: Boolean = false
|
||||
internal val hasStorageSet: Boolean
|
||||
get() = settingsManager.getStorage() != null
|
||||
get() = settingsManager.getSafStorage() != null
|
||||
abstract val isRestoreOperation: Boolean
|
||||
|
||||
companion object {
|
||||
|
@ -55,7 +55,7 @@ internal abstract class StorageViewModel(
|
|||
context: Context,
|
||||
settingsManager: SettingsManager,
|
||||
): Boolean {
|
||||
val storage = settingsManager.getStorage() ?: return false
|
||||
val storage = settingsManager.getSafStorage() ?: return false
|
||||
if (storage.isUsb) return true
|
||||
return permitDiskReads {
|
||||
storage.getDocumentFile(context).isDirectory
|
||||
|
@ -106,20 +106,20 @@ internal abstract class StorageViewModel(
|
|||
return saveStorage(storage)
|
||||
}
|
||||
|
||||
protected fun createStorage(uri: Uri): Storage {
|
||||
protected fun createStorage(uri: Uri): SafStorage {
|
||||
val root = safOption ?: throw IllegalStateException("no storage root")
|
||||
val name = if (root.isInternal()) {
|
||||
"${root.title} (${app.getString(R.string.settings_backup_location_internal)})"
|
||||
} else {
|
||||
root.title
|
||||
}
|
||||
return Storage(uri, name, root.isUsb, root.requiresNetwork)
|
||||
return SafStorage(uri, name, root.isUsb, root.requiresNetwork)
|
||||
}
|
||||
|
||||
protected fun saveStorage(storage: Storage): Boolean {
|
||||
settingsManager.setStorage(storage)
|
||||
protected fun saveStorage(safStorage: SafStorage): Boolean {
|
||||
settingsManager.setSafStorage(safStorage)
|
||||
|
||||
if (storage.isUsb) {
|
||||
if (safStorage.isUsb) {
|
||||
Log.d(TAG, "Selected storage is a removable USB device.")
|
||||
val wasSaved = saveUsbDevice()
|
||||
// reset stored flash drive, if we did not update it
|
||||
|
@ -129,9 +129,9 @@ internal abstract class StorageViewModel(
|
|||
}
|
||||
BackupManagerSettings.resetDefaults(app.contentResolver)
|
||||
|
||||
Log.d(TAG, "New storage location saved: ${storage.uri}")
|
||||
Log.d(TAG, "New storage location saved: ${safStorage.uri}")
|
||||
|
||||
return storage.isUsb
|
||||
return safStorage.isUsb
|
||||
}
|
||||
|
||||
private fun saveUsbDevice(): Boolean {
|
||||
|
|
|
@ -17,7 +17,7 @@ import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
|
|||
import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
|
||||
import com.stevesoltys.seedvault.plugins.StoragePlugin
|
||||
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
||||
import com.stevesoltys.seedvault.worker.ApkBackup
|
||||
import io.mockk.Runs
|
||||
|
@ -58,7 +58,7 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
private val metadataOutputStream = mockk<OutputStream>()
|
||||
private val fileDescriptor: ParcelFileDescriptor = mockk()
|
||||
private val packageMetadata: PackageMetadata = mockk()
|
||||
private val storage = Storage(
|
||||
private val safStorage = SafStorage(
|
||||
uri = Uri.EMPTY,
|
||||
name = getRandomString(),
|
||||
isUsb = false,
|
||||
|
@ -290,7 +290,7 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
)
|
||||
} just Runs
|
||||
coEvery { full.cancelFullBackup(token, metadata.salt, false) } just Runs
|
||||
every { settingsManager.getStorage() } returns storage
|
||||
every { settingsManager.getSafStorage() } returns safStorage
|
||||
every { settingsManager.useMeteredNetwork } returns false
|
||||
every { metadataOutputStream.close() } just Runs
|
||||
|
||||
|
@ -340,7 +340,7 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
)
|
||||
} just Runs
|
||||
coEvery { full.cancelFullBackup(token, metadata.salt, false) } just Runs
|
||||
every { settingsManager.getStorage() } returns storage
|
||||
every { settingsManager.getSafStorage() } returns safStorage
|
||||
every { settingsManager.useMeteredNetwork } returns false
|
||||
every { metadataOutputStream.close() } just Runs
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import com.stevesoltys.seedvault.metadata.MetadataReader
|
|||
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||
import com.stevesoltys.seedvault.plugins.EncryptedMetadata
|
||||
import com.stevesoltys.seedvault.plugins.StoragePlugin
|
||||
import com.stevesoltys.seedvault.settings.Storage
|
||||
import com.stevesoltys.seedvault.plugins.saf.SafStorage
|
||||
import com.stevesoltys.seedvault.transport.TransportTest
|
||||
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
||||
import io.mockk.Runs
|
||||
|
@ -57,7 +57,7 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
)
|
||||
|
||||
private val inputStream = mockk<InputStream>()
|
||||
private val storage: Storage = mockk()
|
||||
private val safStorage: SafStorage = mockk()
|
||||
private val packageInfo2 = PackageInfo().apply { packageName = "org.example2" }
|
||||
private val packageInfoArray = arrayOf(packageInfo)
|
||||
private val packageInfoArray2 = arrayOf(packageInfo, packageInfo2)
|
||||
|
@ -164,10 +164,10 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
@Test
|
||||
fun `startRestore() optimized auto-restore with removed storage shows notification`() =
|
||||
runBlocking {
|
||||
every { settingsManager.getStorage() } returns storage
|
||||
every { storage.isUnavailableUsb(context) } returns true
|
||||
every { settingsManager.getSafStorage() } returns safStorage
|
||||
every { safStorage.isUnavailableUsb(context) } returns true
|
||||
every { metadataManager.getPackageMetadata(packageName) } returns PackageMetadata(42L)
|
||||
every { storage.name } returns storageName
|
||||
every { safStorage.name } returns storageName
|
||||
every {
|
||||
notificationManager.onRemovableStorageNotAvailableForRestore(
|
||||
packageName,
|
||||
|
@ -188,8 +188,8 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
@Test
|
||||
fun `startRestore() optimized auto-restore with available storage shows no notification`() =
|
||||
runBlocking {
|
||||
every { settingsManager.getStorage() } returns storage
|
||||
every { storage.isUnavailableUsb(context) } returns false
|
||||
every { settingsManager.getSafStorage() } returns safStorage
|
||||
every { safStorage.isUnavailableUsb(context) } returns false
|
||||
|
||||
restore.beforeStartRestore(metadata)
|
||||
assertEquals(TRANSPORT_OK, restore.startRestore(token, pmPackageInfoArray))
|
||||
|
@ -204,8 +204,8 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
|
||||
@Test
|
||||
fun `startRestore() with removed storage shows no notification`() = runBlocking {
|
||||
every { settingsManager.getStorage() } returns storage
|
||||
every { storage.isUnavailableUsb(context) } returns true
|
||||
every { settingsManager.getSafStorage() } returns safStorage
|
||||
every { safStorage.isUnavailableUsb(context) } returns true
|
||||
every { metadataManager.getPackageMetadata(packageName) } returns null
|
||||
|
||||
assertEquals(TRANSPORT_ERROR, restore.startRestore(token, pmPackageInfoArray))
|
||||
|
|
Loading…
Reference in a new issue