Clean up code after refactorings
This commit is contained in:
parent
5c75574f65
commit
7b0e02c451
59 changed files with 84 additions and 240 deletions
|
@ -10,7 +10,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||
import androidx.test.filters.MediumTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.stevesoltys.seedvault.backend.LegacyStoragePlugin
|
||||
import com.stevesoltys.seedvault.backend.getAvailableBackupFileHandles
|
||||
import com.stevesoltys.seedvault.backend.saf.DocumentsProviderLegacyPlugin
|
||||
import com.stevesoltys.seedvault.backend.saf.DocumentsStorage
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
|
|
|
@ -13,7 +13,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||
import androidx.test.filters.MediumTest
|
||||
import com.stevesoltys.seedvault.repo.BackupData
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import io.mockk.CapturingSlot
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
|
@ -34,7 +33,6 @@ import kotlin.test.assertEquals
|
|||
@MediumTest
|
||||
class KvBackupInstrumentationTest : KoinComponent {
|
||||
|
||||
private val settingsManager: SettingsManager by inject()
|
||||
private val backupReceiver: BackupReceiver = mockk()
|
||||
private val inputFactory: InputFactory = mockk()
|
||||
private val dbManager: KvDbManager by inject()
|
||||
|
|
|
@ -13,9 +13,9 @@ import com.stevesoltys.seedvault.proto.SnapshotKt.blob
|
|||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.repo.BackupData
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import com.stevesoltys.seedvault.repo.SnapshotCreatorFactory
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.repo.SnapshotCreatorFactory
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
|
|
|
@ -86,11 +86,9 @@ open class App : Application() {
|
|||
settingsManager = get(),
|
||||
keyManager = get(),
|
||||
backendManager = get(),
|
||||
metadataManager = get(),
|
||||
appListRetriever = get(),
|
||||
storageBackup = get(),
|
||||
backupManager = get(),
|
||||
backupInitializer = get(),
|
||||
backupStateManager = get(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ import android.util.Log
|
|||
import androidx.annotation.WorkerThread
|
||||
import com.stevesoltys.seedvault.getStorageContext
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.repo.BlobCache
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.settings.StoragePluginType
|
||||
import com.stevesoltys.seedvault.repo.BlobCache
|
||||
import org.calyxos.seedvault.core.backends.Backend
|
||||
import org.calyxos.seedvault.core.backends.BackendFactory
|
||||
import org.calyxos.seedvault.core.backends.BackendProperties
|
||||
|
@ -89,6 +89,7 @@ class BackendManager(
|
|||
mBackend = backend
|
||||
mBackendProperties = storageProperties
|
||||
blobCache.clearLocalCache()
|
||||
// TODO not critical, but nice to have: clear also local snapshot cache
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,6 @@ import org.calyxos.seedvault.core.backends.saf.SafProperties
|
|||
import org.calyxos.seedvault.core.backends.saf.getTreeDocumentFile
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
@Deprecated("")
|
||||
|
@ -51,7 +50,7 @@ internal class DocumentsStorage(
|
|||
private val context: Context get() = appContext.getStorageContext { safStorage.isUsb }
|
||||
private val contentResolver: ContentResolver get() = context.contentResolver
|
||||
|
||||
internal var rootBackupDir: DocumentFile? = null
|
||||
private var rootBackupDir: DocumentFile? = null
|
||||
get() = runBlocking {
|
||||
if (field == null) {
|
||||
val parent = safStorage.getDocumentFile(context)
|
||||
|
@ -94,16 +93,6 @@ internal class DocumentsStorage(
|
|||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun getOutputStream(file: DocumentFile): OutputStream {
|
||||
return try {
|
||||
contentResolver.openOutputStream(file.uri, "wt") ?: throw IOException()
|
||||
} catch (e: Exception) {
|
||||
// SAF can throw all sorts of exceptions, so wrap it in IOException
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,7 +181,7 @@ suspend fun DocumentFile.findFileBlocking(context: Context, displayName: String)
|
|||
@Throws(IOException::class, TimeoutCancellationException::class)
|
||||
internal suspend fun getLoadedCursor(timeout: Long = 15_000, query: () -> Cursor?) =
|
||||
withTimeout(timeout) {
|
||||
suspendCancellableCoroutine<Cursor> { cont ->
|
||||
suspendCancellableCoroutine { cont ->
|
||||
val cursor = query() ?: throw IOException()
|
||||
cont.invokeOnCancellation { cursor.close() }
|
||||
val loading = cursor.extras.getBoolean(EXTRA_LOADING, false)
|
||||
|
|
|
@ -139,17 +139,6 @@ internal object StorageRootResolver {
|
|||
return if (index != -1) getInt(index) else 0
|
||||
}
|
||||
|
||||
private fun Cursor.getLong(columnName: String): Long? {
|
||||
val index = getColumnIndex(columnName)
|
||||
if (index == -1) return null
|
||||
val value = getString(index) ?: return null
|
||||
return try {
|
||||
java.lang.Long.parseLong(value)
|
||||
} catch (e: NumberFormatException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun getIcon(context: Context, authority: String, rootId: String, icon: Int): Drawable? {
|
||||
return getPackageIcon(context, authority, icon) ?: when {
|
||||
authority == AUTHORITY_STORAGE && rootId == ROOT_ID_DEVICE -> {
|
||||
|
|
|
@ -102,17 +102,6 @@ internal interface Crypto {
|
|||
@Deprecated("only for v1")
|
||||
fun getNameForApk(salt: String, packageName: String, suffix: String = ""): String
|
||||
|
||||
/**
|
||||
* Returns a [AesGcmHkdfStreaming] encrypting stream
|
||||
* that gets encrypted and authenticated the given associated data.
|
||||
*/
|
||||
@Deprecated("only for v1")
|
||||
@Throws(IOException::class, GeneralSecurityException::class)
|
||||
fun newEncryptingStreamV1(
|
||||
outputStream: OutputStream,
|
||||
associatedData: ByteArray,
|
||||
): OutputStream
|
||||
|
||||
/**
|
||||
* Returns a [AesGcmHkdfStreaming] decrypting stream
|
||||
* that gets decrypted and authenticated the given associated data.
|
||||
|
@ -245,13 +234,6 @@ internal class CryptoImpl(
|
|||
return messageDigest.digest()
|
||||
}
|
||||
|
||||
@Deprecated("only for v1")
|
||||
@Throws(IOException::class, GeneralSecurityException::class)
|
||||
override fun newEncryptingStreamV1(
|
||||
outputStream: OutputStream,
|
||||
associatedData: ByteArray,
|
||||
): OutputStream = CoreCrypto.newEncryptingStream(keyV1, outputStream, associatedData)
|
||||
|
||||
@Deprecated("only for v1")
|
||||
@Throws(IOException::class, GeneralSecurityException::class)
|
||||
override fun newDecryptingStreamV1(
|
||||
|
|
|
@ -33,12 +33,6 @@ internal class MetadataWriterImpl : MetadataWriter {
|
|||
if (packageMetadata.size != null) {
|
||||
put(JSON_PACKAGE_SIZE, packageMetadata.size)
|
||||
}
|
||||
if (packageMetadata.system) {
|
||||
put(JSON_PACKAGE_SYSTEM, true)
|
||||
}
|
||||
if (packageMetadata.isLaunchableSystemApp) {
|
||||
put(JSON_PACKAGE_SYSTEM_LAUNCHER, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
return json.toString().toByteArray(Utf8)
|
||||
|
|
|
@ -144,6 +144,7 @@ internal class AppBackupManager(
|
|||
@Throws(IOException::class)
|
||||
suspend fun removeBackupRepo() {
|
||||
blobCache.clearLocalCache()
|
||||
// TODO not critical, but nice to have: clear also local snapshot cache
|
||||
backendManager.backend.remove(TopLevelFolder(crypto.repoId))
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@ val repoModule = module {
|
|||
val snapshotFolder = File(androidContext().filesDir, FOLDER_SNAPSHOTS)
|
||||
SnapshotManager(snapshotFolder, get(), get(), get())
|
||||
}
|
||||
factory { SnapshotCreatorFactory(androidContext(), get(), get(), get(), get()) }
|
||||
factory { SnapshotCreatorFactory(androidContext(), get(), get(), get()) }
|
||||
factory { Pruner(get(), get(), get()) }
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ import com.stevesoltys.seedvault.proto.Snapshot
|
|||
import com.stevesoltys.seedvault.proto.Snapshot.Apk
|
||||
import com.stevesoltys.seedvault.proto.Snapshot.App
|
||||
import com.stevesoltys.seedvault.proto.Snapshot.Blob
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import com.stevesoltys.seedvault.transport.backup.isSystemApp
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
|
@ -38,7 +37,6 @@ internal class SnapshotCreator(
|
|||
private val context: Context,
|
||||
private val clock: Clock,
|
||||
private val packageService: PackageService,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val metadataManager: MetadataManager,
|
||||
) {
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ package com.stevesoltys.seedvault.repo
|
|||
import android.content.Context
|
||||
import com.stevesoltys.seedvault.Clock
|
||||
import com.stevesoltys.seedvault.metadata.MetadataManager
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
|
||||
/**
|
||||
|
@ -18,9 +17,8 @@ internal class SnapshotCreatorFactory(
|
|||
private val context: Context,
|
||||
private val clock: Clock,
|
||||
private val packageService: PackageService,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val metadataManager: MetadataManager,
|
||||
) {
|
||||
fun createSnapshotCreator() =
|
||||
SnapshotCreator(context, clock, packageService, settingsManager, metadataManager)
|
||||
SnapshotCreator(context, clock, packageService, metadataManager)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import com.stevesoltys.seedvault.backend.BackendManager
|
|||
import com.stevesoltys.seedvault.metadata.PackageMetadataMap
|
||||
import com.stevesoltys.seedvault.metadata.PackageState
|
||||
import com.stevesoltys.seedvault.restore.install.isInstalled
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.transport.TRANSPORT_ID
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import com.stevesoltys.seedvault.transport.restore.RestoreCoordinator
|
||||
|
@ -55,7 +54,6 @@ internal data class AppRestoreResult(
|
|||
internal class AppDataRestoreManager(
|
||||
private val context: Context,
|
||||
private val backupManager: IBackupManager,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val restoreCoordinator: RestoreCoordinator,
|
||||
private val backendManager: BackendManager,
|
||||
) {
|
||||
|
|
|
@ -96,7 +96,7 @@ internal class AppSelectionManager(
|
|||
val backend = backendManager.backend
|
||||
val token = restorableBackup.token
|
||||
backend.load(LegacyAppBackupFile.IconsFile(token)).use {
|
||||
iconManager.downloadIconsV1(restorableBackup.version, token, it)
|
||||
iconManager.downloadIconsV1(token, it)
|
||||
}
|
||||
} else if (restorableBackup.version >= 2) {
|
||||
val repoId = restorableBackup.repoId ?: error("No repoId in v2 backup")
|
||||
|
|
|
@ -83,7 +83,7 @@ internal class RestoreViewModel(
|
|||
private val appSelectionManager =
|
||||
AppSelectionManager(app, backendManager, iconManager, viewModelScope)
|
||||
private val appDataRestoreManager = AppDataRestoreManager(
|
||||
app, backupManager, settingsManager, restoreCoordinator, backendManager
|
||||
app, backupManager, restoreCoordinator, backendManager
|
||||
)
|
||||
|
||||
private val mDisplayFragment = MutableLiveEvent<DisplayFragment>()
|
||||
|
|
|
@ -21,15 +21,15 @@ import com.stevesoltys.seedvault.crypto.Crypto
|
|||
import com.stevesoltys.seedvault.encodeBase64
|
||||
import com.stevesoltys.seedvault.metadata.ApkSplit
|
||||
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.repo.getBlobHandles
|
||||
import com.stevesoltys.seedvault.restore.RestoreService
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED
|
||||
import com.stevesoltys.seedvault.repo.getBlobHandles
|
||||
import com.stevesoltys.seedvault.transport.backup.isSystemApp
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import com.stevesoltys.seedvault.worker.hashSignature
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
|
|
|
@ -84,7 +84,7 @@ internal class InstallProgressAdapter(
|
|||
if (item.icon == null) iconJob = scope.launch {
|
||||
iconLoader(item, appIcon::setImageDrawable)
|
||||
} else appIcon.setImageDrawable(item.icon)
|
||||
appName.text = item.name ?: getAppName(v.context, item.packageName.toString())
|
||||
appName.text = item.name ?: getAppName(v.context, item.packageName)
|
||||
appInfo.visibility = GONE
|
||||
when (item.state) {
|
||||
IN_PROGRESS -> {
|
||||
|
|
|
@ -80,8 +80,7 @@ internal class AppListRetriever(
|
|||
AppStatus(
|
||||
packageName = packageName,
|
||||
enabled = settingsManager.isBackupEnabled(packageName),
|
||||
icon = data.iconRes?.let { getDrawable(context, it) }
|
||||
?: getIconFromPackageManager(packageName),
|
||||
icon = getDrawable(context, data.iconRes) ?: getIconFromPackageManager(packageName),
|
||||
name = context.getString(data.nameRes),
|
||||
time = metadata?.time ?: 0,
|
||||
size = metadata?.size,
|
||||
|
|
|
@ -16,8 +16,8 @@ import androidx.preference.PreferenceManager
|
|||
import androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE
|
||||
import androidx.work.ExistingPeriodicWorkPolicy.UPDATE
|
||||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.settings.preference.M3ListPreference
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||
|
|
|
@ -35,12 +35,10 @@ import androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE
|
|||
import androidx.work.WorkManager
|
||||
import com.stevesoltys.seedvault.BackupStateManager
|
||||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.crypto.KeyManager
|
||||
import com.stevesoltys.seedvault.metadata.MetadataManager
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.crypto.KeyManager
|
||||
import com.stevesoltys.seedvault.permitDiskReads
|
||||
import com.stevesoltys.seedvault.storage.StorageBackupJobService
|
||||
import com.stevesoltys.seedvault.transport.backup.BackupInitializer
|
||||
import com.stevesoltys.seedvault.ui.LiveEvent
|
||||
import com.stevesoltys.seedvault.ui.MutableLiveEvent
|
||||
import com.stevesoltys.seedvault.ui.RequireProvisioningViewModel
|
||||
|
@ -68,11 +66,9 @@ internal class SettingsViewModel(
|
|||
settingsManager: SettingsManager,
|
||||
keyManager: KeyManager,
|
||||
backendManager: BackendManager,
|
||||
private val metadataManager: MetadataManager,
|
||||
private val appListRetriever: AppListRetriever,
|
||||
private val storageBackup: StorageBackup,
|
||||
private val backupManager: IBackupManager,
|
||||
private val backupInitializer: BackupInitializer,
|
||||
backupStateManager: BackupStateManager,
|
||||
) : RequireProvisioningViewModel(app, settingsManager, keyManager, backendManager) {
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
package com.stevesoltys.seedvault.storage
|
||||
|
||||
import com.stevesoltys.seedvault.crypto.KeyManager
|
||||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.crypto.KeyManager
|
||||
import org.calyxos.backup.storage.api.StorageBackup
|
||||
import org.koin.dsl.module
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.os.ParcelFileDescriptor
|
|||
import android.util.Log
|
||||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.settings.SettingsActivity
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.transport.backup.BackupCoordinator
|
||||
import com.stevesoltys.seedvault.transport.restore.RestoreCoordinator
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -43,7 +42,6 @@ class ConfigurableBackupTransport internal constructor(private val context: Cont
|
|||
|
||||
private val backupCoordinator by inject<BackupCoordinator>()
|
||||
private val restoreCoordinator by inject<RestoreCoordinator>()
|
||||
private val settingsManager by inject<SettingsManager>()
|
||||
|
||||
override fun transportDirName(): String {
|
||||
return TRANSPORT_DIRECTORY_NAME
|
||||
|
|
|
@ -20,7 +20,6 @@ import android.content.pm.PackageInfo
|
|||
import android.os.ParcelFileDescriptor
|
||||
import android.util.Log
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.stevesoltys.seedvault.Clock
|
||||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.metadata.BackupType
|
||||
import com.stevesoltys.seedvault.metadata.MetadataManager
|
||||
|
@ -64,14 +63,12 @@ internal class BackupCoordinator(
|
|||
private val appBackupManager: AppBackupManager,
|
||||
private val kv: KVBackup,
|
||||
private val full: FullBackup,
|
||||
private val clock: Clock,
|
||||
private val packageService: PackageService,
|
||||
private val metadataManager: MetadataManager,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val nm: BackupNotificationManager,
|
||||
) {
|
||||
|
||||
private val backend get() = backendManager.backend
|
||||
private val snapshotCreator
|
||||
get() = appBackupManager.snapshotCreator ?: error("No SnapshotCreator")
|
||||
private val state = CoordinatorState(
|
||||
|
@ -92,6 +89,8 @@ internal class BackupCoordinator(
|
|||
*
|
||||
* If the transport returns anything other than [TRANSPORT_OK] from this method,
|
||||
* the OS will halt the current initialize operation and schedule a retry in the near future.
|
||||
* Attention: [finishBackup] will not be called in this case.
|
||||
*
|
||||
* Even if the transport is in a state
|
||||
* such that attempting to "initialize" the backend storage is meaningless -
|
||||
* for example, if there is no current live data-set at all,
|
||||
|
@ -103,12 +102,8 @@ internal class BackupCoordinator(
|
|||
* [TRANSPORT_ERROR] (to retry following network error or other failure).
|
||||
*/
|
||||
fun initializeDevice(): Int {
|
||||
// we don't respect the intended system behavior here by always starting a new [RestoreSet]
|
||||
// instead of simply deleting the current one
|
||||
Log.i(TAG, "Initialize Device!")
|
||||
|
||||
// [finishBackup] will only be called when we return [TRANSPORT_OK] here
|
||||
// so we remember that we initialized successfully
|
||||
// we don't respect the intended system behavior of erasing all stored data
|
||||
state.calledInitialize = true
|
||||
return TRANSPORT_OK
|
||||
}
|
||||
|
|
|
@ -41,7 +41,6 @@ val backupModule = module {
|
|||
appBackupManager = get(),
|
||||
kv = get(),
|
||||
full = get(),
|
||||
clock = get(),
|
||||
packageService = get(),
|
||||
metadataManager = get(),
|
||||
settingsManager = get(),
|
||||
|
|
|
@ -138,14 +138,15 @@ internal class FullBackup(
|
|||
suspend fun cancelFullBackup() {
|
||||
val state = this.state ?: error("No state when canceling")
|
||||
Log.i(TAG, "Cancel full backup for ${state.packageName}")
|
||||
// TODO check if worth keeping the blobs. they've been uploaded already and may be re-usable
|
||||
// so we could add them to the snapshot's blobMap or just let prune remove them at the end
|
||||
// finalize the receiver
|
||||
try {
|
||||
backupReceiver.finalize(getOwner(state.packageName))
|
||||
} catch (e: Exception) {
|
||||
// as the backup was cancelled anyway, we don't care if finalizing had an error
|
||||
Log.e(TAG, "Error finalizing backup in cancelFullBackup().", e)
|
||||
}
|
||||
// If the transport receives this callback, it will *not* receive a call to [finishBackup].
|
||||
// It needs to tear down any ongoing backup state here.
|
||||
clearState()
|
||||
}
|
||||
|
||||
|
|
|
@ -125,11 +125,6 @@ internal class PackageService(
|
|||
packageInfo.allowsBackup()
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of apps that do not allow backup.
|
||||
*/
|
||||
val userNotAllowedApps: List<PackageInfo> = emptyList()
|
||||
|
||||
val launchableSystemApps: List<ResolveInfo>
|
||||
@WorkerThread
|
||||
get() {
|
||||
|
|
|
@ -18,11 +18,10 @@ import android.util.Log.isLoggable
|
|||
import com.stevesoltys.seedvault.ERROR_BACKUP_CANCELLED
|
||||
import com.stevesoltys.seedvault.MAGIC_PACKAGE_MANAGER
|
||||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.metadata.MetadataManager
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import com.stevesoltys.seedvault.repo.hexFromProto
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import com.stevesoltys.seedvault.worker.AppBackupPruneWorker
|
||||
import com.stevesoltys.seedvault.worker.BackupRequester
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -38,7 +37,6 @@ internal class NotificationBackupObserver(
|
|||
) : IBackupObserver.Stub(), KoinComponent {
|
||||
|
||||
private val nm: BackupNotificationManager by inject()
|
||||
private val metadataManager: MetadataManager by inject()
|
||||
private val packageService: PackageService by inject()
|
||||
private val settingsManager: SettingsManager by inject()
|
||||
private val appBackupManager: AppBackupManager by inject()
|
||||
|
@ -153,7 +151,7 @@ internal class NotificationBackupObserver(
|
|||
success = snapshot != null
|
||||
snapshot
|
||||
}
|
||||
val size = if (snapshot != null) { // TODO count size of APKs separately
|
||||
val size = if (snapshot != null) { // TODO for later: count size of APKs separately
|
||||
val chunkIds = snapshot.appsMap.values.flatMap { it.chunkIdsList }
|
||||
chunkIds.sumOf {
|
||||
snapshot.blobsMap[it.hexFromProto()]?.uncompressedLength?.toLong() ?: 0L
|
||||
|
|
|
@ -16,7 +16,6 @@ import com.stevesoltys.seedvault.R
|
|||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.backend.saf.SafHandler
|
||||
import com.stevesoltys.seedvault.backend.webdav.WebDavHandler
|
||||
import org.calyxos.seedvault.core.backends.webdav.WebDavProperties
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.storage.StorageBackupJobService
|
||||
import com.stevesoltys.seedvault.transport.backup.BackupInitializer
|
||||
|
@ -28,6 +27,7 @@ import org.calyxos.backup.storage.api.StorageBackup
|
|||
import org.calyxos.backup.storage.backup.BackupJobService
|
||||
import org.calyxos.seedvault.core.backends.Backend
|
||||
import org.calyxos.seedvault.core.backends.saf.SafProperties
|
||||
import org.calyxos.seedvault.core.backends.webdav.WebDavProperties
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
|
|
@ -24,8 +24,6 @@ import com.stevesoltys.seedvault.ui.INTENT_EXTRA_IS_RESTORE
|
|||
import com.stevesoltys.seedvault.ui.INTENT_EXTRA_IS_SETUP_WIZARD
|
||||
import org.koin.androidx.viewmodel.ext.android.getViewModel
|
||||
|
||||
private val TAG = StorageActivity::class.java.name
|
||||
|
||||
class StorageActivity : BackupActivity() {
|
||||
|
||||
private lateinit var viewModel: StorageViewModel
|
||||
|
|
|
@ -16,7 +16,6 @@ import com.stevesoltys.seedvault.R
|
|||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.backend.saf.SafHandler
|
||||
import com.stevesoltys.seedvault.backend.webdav.WebDavHandler
|
||||
import org.calyxos.seedvault.core.backends.webdav.WebDavProperties
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.ui.LiveEvent
|
||||
import com.stevesoltys.seedvault.ui.MutableLiveEvent
|
||||
|
@ -26,6 +25,7 @@ import kotlinx.coroutines.launch
|
|||
import org.calyxos.seedvault.core.backends.Backend
|
||||
import org.calyxos.seedvault.core.backends.saf.SafProperties
|
||||
import org.calyxos.seedvault.core.backends.webdav.WebDavConfig
|
||||
import org.calyxos.seedvault.core.backends.webdav.WebDavProperties
|
||||
|
||||
internal abstract class StorageViewModel(
|
||||
private val app: Application,
|
||||
|
@ -48,8 +48,6 @@ internal abstract class StorageViewModel(
|
|||
private var safOption: SafOption? = null
|
||||
|
||||
internal var isSetupWizard: Boolean = false
|
||||
internal val hasStorageSet: Boolean
|
||||
get() = backendManager.backendProperties != null
|
||||
abstract val isRestoreOperation: Boolean
|
||||
|
||||
internal fun loadStorageRoots() {
|
||||
|
|
|
@ -17,11 +17,11 @@ import com.stevesoltys.seedvault.proto.Snapshot
|
|||
import com.stevesoltys.seedvault.proto.Snapshot.Apk
|
||||
import com.stevesoltys.seedvault.proto.Snapshot.Blob
|
||||
import com.stevesoltys.seedvault.proto.SnapshotKt.split
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.repo.forProto
|
||||
import com.stevesoltys.seedvault.repo.hexFromProto
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.transport.backup.isNotUpdatedSystemApp
|
||||
import com.stevesoltys.seedvault.transport.backup.isTestOnly
|
||||
import org.calyxos.seedvault.core.toHexString
|
||||
|
|
|
@ -8,7 +8,7 @@ package com.stevesoltys.seedvault.worker
|
|||
import android.content.Context
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
import android.util.Log
|
||||
import androidx.work.BackoffPolicy
|
||||
import androidx.work.BackoffPolicy.EXPONENTIAL
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.ExistingWorkPolicy.REPLACE
|
||||
import androidx.work.ForegroundInfo
|
||||
|
@ -36,7 +36,7 @@ class AppBackupPruneWorker(
|
|||
fun scheduleNow(context: Context) {
|
||||
val workRequest = OneTimeWorkRequestBuilder<AppBackupPruneWorker>()
|
||||
.setExpedited(RUN_AS_NON_EXPEDITED_WORK_REQUEST)
|
||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(10))
|
||||
.setBackoffCriteria(EXPONENTIAL, Duration.ofSeconds(10))
|
||||
.build()
|
||||
val workManager = WorkManager.getInstance(context)
|
||||
Log.i(TAG, "Asking to prune app backups now...")
|
||||
|
|
|
@ -24,8 +24,8 @@ import androidx.work.WorkManager
|
|||
import androidx.work.WorkerParameters
|
||||
import com.stevesoltys.seedvault.R
|
||||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
|
||||
import com.stevesoltys.seedvault.ui.notification.NOTIFICATION_ID_OBSERVER
|
||||
import org.koin.core.component.KoinComponent
|
||||
|
|
|
@ -20,8 +20,8 @@ import com.stevesoltys.seedvault.crypto.TYPE_ICONS
|
|||
import com.stevesoltys.seedvault.proto.Snapshot
|
||||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.transport.backup.PackageService
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.calyxos.backup.storage.crypto.StreamCrypto.toByteArray
|
||||
|
@ -150,13 +150,13 @@ internal class IconManager(
|
|||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@Throws(IOException::class, SecurityException::class, GeneralSecurityException::class)
|
||||
fun downloadIconsV1(version: Byte, token: Long, inputStream: InputStream): Set<String> {
|
||||
fun downloadIconsV1(token: Long, inputStream: InputStream): Set<String> {
|
||||
Log.d(TAG, "Start downloading icons")
|
||||
val folder = File(context.cacheDir, CACHE_FOLDER)
|
||||
if (!folder.isDirectory && !folder.mkdirs())
|
||||
throw IOException("Can't create cache folder for icons")
|
||||
val set = mutableSetOf<String>()
|
||||
crypto.newDecryptingStreamV1(inputStream, getAD(version, token)).use { cryptoStream ->
|
||||
crypto.newDecryptingStreamV1(inputStream, getAD(1.toByte(), token)).use { cryptoStream ->
|
||||
ZipInputStream(cryptoStream).use { zip ->
|
||||
var entry = zip.nextEntry
|
||||
while (entry != null) {
|
||||
|
|
|
@ -21,7 +21,6 @@ import java.io.ByteArrayOutputStream
|
|||
import java.io.IOException
|
||||
import kotlin.random.Random
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@TestInstance(PER_METHOD)
|
||||
class CryptoIntegrationTest {
|
||||
|
||||
|
@ -41,17 +40,6 @@ class CryptoIntegrationTest {
|
|||
assertThat(crypto.getRandomBytes(42), not(equalTo(crypto.getRandomBytes(42))))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decrypting encrypted cleartext works v1`() {
|
||||
val ad = Random.nextBytes(42)
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
crypto.newEncryptingStreamV1(outputStream, ad).use { it.write(cleartext) }
|
||||
val inputStream = ByteArrayInputStream(outputStream.toByteArray())
|
||||
crypto.newDecryptingStreamV1(inputStream, ad).use {
|
||||
assertReadEquals(cleartext, it)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decrypting encrypted cleartext works v2`() {
|
||||
val ad = Random.nextBytes(42)
|
||||
|
@ -63,18 +51,6 @@ class CryptoIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decrypting encrypted cleartext fails with different AD v1`() {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
crypto.newEncryptingStreamV1(outputStream, Random.nextBytes(42)).use { it.write(cleartext) }
|
||||
val inputStream = ByteArrayInputStream(outputStream.toByteArray())
|
||||
assertThrows(IOException::class.java) {
|
||||
crypto.newDecryptingStreamV1(inputStream, Random.nextBytes(41)).use {
|
||||
it.read()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `decrypting encrypted cleartext fails with different AD v2`() {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
|
|
|
@ -11,8 +11,8 @@ import io.mockk.every
|
|||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.slot
|
||||
import junit.framework.Assert.assertTrue
|
||||
import org.junit.Assert.assertArrayEquals
|
||||
import org.junit.jupiter.api.Assertions.assertArrayEquals
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD
|
||||
|
|
|
@ -21,7 +21,6 @@ import com.stevesoltys.seedvault.metadata.PackageState.APK_AND_DATA
|
|||
import com.stevesoltys.seedvault.metadata.PackageState.NOT_ALLOWED
|
||||
import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
|
||||
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
|
||||
import com.stevesoltys.seedvault.settings.SettingsManager
|
||||
import io.mockk.Runs
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
|
@ -49,7 +48,6 @@ class MetadataManagerTest {
|
|||
private val clock: Clock = mockk()
|
||||
private val metadataWriter: MetadataWriter = mockk()
|
||||
private val metadataReader: MetadataReader = mockk()
|
||||
private val settingsManager: SettingsManager = mockk()
|
||||
|
||||
private val manager = MetadataManager(
|
||||
context = context,
|
||||
|
|
|
@ -86,7 +86,7 @@ internal class BackupReceiverTest : TransportTest() {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `readFromStream`() = runBlocking {
|
||||
fun readFromStream() = runBlocking {
|
||||
val bytes = getRandomByteArray()
|
||||
val chunkBytes1 = getRandomByteArray()
|
||||
val chunkBytes2 = getRandomByteArray()
|
||||
|
|
|
@ -38,8 +38,7 @@ internal class SnapshotCreatorTest : TransportTest() {
|
|||
|
||||
private val ctx: Context = ApplicationProvider.getApplicationContext()
|
||||
private val packageService: PackageService = mockk()
|
||||
private val snapshotCreator =
|
||||
SnapshotCreator(ctx, clock, packageService, settingsManager, metadataManager)
|
||||
private val snapshotCreator = SnapshotCreator(ctx, clock, packageService, metadataManager)
|
||||
|
||||
@Test
|
||||
fun `test onApkBackedUp`() {
|
||||
|
|
|
@ -22,16 +22,16 @@ import com.stevesoltys.seedvault.getRandomString
|
|||
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||
import com.stevesoltys.seedvault.metadata.PackageMetadataMap
|
||||
import com.stevesoltys.seedvault.proto.Snapshot
|
||||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.repo.SnapshotCreator
|
||||
import com.stevesoltys.seedvault.repo.SnapshotManager
|
||||
import com.stevesoltys.seedvault.repo.hexFromProto
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED
|
||||
import com.stevesoltys.seedvault.repo.SnapshotManager
|
||||
import com.stevesoltys.seedvault.transport.TransportTest
|
||||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.repo.SnapshotCreator
|
||||
import com.stevesoltys.seedvault.repo.hexFromProto
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import com.stevesoltys.seedvault.worker.ApkBackup
|
||||
import io.mockk.Runs
|
||||
|
@ -41,7 +41,6 @@ import io.mockk.just
|
|||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.slot
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.calyxos.seedvault.core.backends.AppBackupFileType
|
||||
import org.calyxos.seedvault.core.backends.Backend
|
||||
|
|
|
@ -29,15 +29,15 @@ import com.stevesoltys.seedvault.metadata.PackageMetadataMap
|
|||
import com.stevesoltys.seedvault.proto.SnapshotKt.blob
|
||||
import com.stevesoltys.seedvault.proto.SnapshotKt.split
|
||||
import com.stevesoltys.seedvault.proto.copy
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.repo.hexFromProto
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED
|
||||
import com.stevesoltys.seedvault.transport.TransportTest
|
||||
import com.stevesoltys.seedvault.repo.hexFromProto
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
|
|
|
@ -26,14 +26,14 @@ import com.stevesoltys.seedvault.getRandomString
|
|||
import com.stevesoltys.seedvault.metadata.ApkSplit
|
||||
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||
import com.stevesoltys.seedvault.metadata.PackageMetadataMap
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.FAILED_SYSTEM_APP
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED
|
||||
import com.stevesoltys.seedvault.restore.install.ApkInstallState.SUCCEEDED
|
||||
import com.stevesoltys.seedvault.transport.TransportTest
|
||||
import com.stevesoltys.seedvault.repo.Loader
|
||||
import com.stevesoltys.seedvault.transport.restore.RestorableBackup
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.every
|
||||
|
|
|
@ -9,9 +9,9 @@ import com.stevesoltys.seedvault.getRandomString
|
|||
import com.stevesoltys.seedvault.transport.TransportTest
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.random.Random
|
||||
|
||||
|
|
|
@ -93,16 +93,15 @@ internal class CoordinatorIntegrationTest : TransportTest() {
|
|||
)
|
||||
private val packageService: PackageService = mockk()
|
||||
private val backup = BackupCoordinator(
|
||||
context,
|
||||
backendManager,
|
||||
appBackupManager,
|
||||
kvBackup,
|
||||
fullBackup,
|
||||
clock,
|
||||
packageService,
|
||||
metadataManager,
|
||||
settingsManager,
|
||||
notificationManager
|
||||
context = context,
|
||||
backendManager = backendManager,
|
||||
appBackupManager = appBackupManager,
|
||||
kv = kvBackup,
|
||||
full = fullBackup,
|
||||
packageService = packageService,
|
||||
metadataManager = metadataManager,
|
||||
settingsManager = settingsManager,
|
||||
nm = notificationManager,
|
||||
)
|
||||
|
||||
private val kvRestore = KVRestore(
|
||||
|
|
|
@ -13,7 +13,6 @@ import android.os.ParcelFileDescriptor
|
|||
import com.stevesoltys.seedvault.backend.BackendManager
|
||||
import com.stevesoltys.seedvault.getRandomString
|
||||
import com.stevesoltys.seedvault.metadata.BackupType
|
||||
import com.stevesoltys.seedvault.metadata.PackageMetadata
|
||||
import com.stevesoltys.seedvault.metadata.PackageState.NO_DATA
|
||||
import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
|
||||
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
|
||||
|
@ -51,7 +50,6 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
appBackupManager = appBackupManager,
|
||||
kv = kv,
|
||||
full = full,
|
||||
clock = clock,
|
||||
packageService = packageService,
|
||||
metadataManager = metadataManager,
|
||||
settingsManager = settingsManager,
|
||||
|
@ -60,7 +58,6 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
|
||||
private val backend = mockk<Backend>()
|
||||
private val fileDescriptor: ParcelFileDescriptor = mockk()
|
||||
private val packageMetadata: PackageMetadata = mockk()
|
||||
private val safProperties = SafProperties(
|
||||
config = Uri.EMPTY,
|
||||
name = getRandomString(),
|
||||
|
|
|
@ -66,7 +66,7 @@ internal class BackupCreationTest : BackupTest() {
|
|||
private val appBackupManager = mockk<AppBackupManager>()
|
||||
private val packageService = mockk<PackageService>()
|
||||
private val snapshotCreator =
|
||||
SnapshotCreator(context, clock, packageService, settingsManager, mockk(relaxed = true))
|
||||
SnapshotCreator(context, clock, packageService, mockk(relaxed = true))
|
||||
private val notificationManager = mockk<BackupNotificationManager>()
|
||||
private val db = TestKvDbManager()
|
||||
|
||||
|
@ -80,7 +80,6 @@ internal class BackupCreationTest : BackupTest() {
|
|||
appBackupManager = appBackupManager,
|
||||
kv = kvBackup,
|
||||
full = fullBackup,
|
||||
clock = clock,
|
||||
packageService = packageService,
|
||||
metadataManager = metadataManager,
|
||||
settingsManager = settingsManager,
|
||||
|
|
|
@ -31,7 +31,6 @@ import io.mockk.coVerify
|
|||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.calyxos.seedvault.core.backends.AppBackupFileType
|
||||
|
@ -90,28 +89,17 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
chunkIds = listOf(chunkId2),
|
||||
)
|
||||
|
||||
mockkStatic("com.stevesoltys.seedvault.backend.BackendExtKt")
|
||||
every { backendManager.backend } returns backend
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getAvailableRestoreSets() builds set from plugin response`() = runBlocking {
|
||||
val info1 = FileInfo(LegacyAppBackupFile.Metadata(token), 1)
|
||||
val info2 = FileInfo(LegacyAppBackupFile.Metadata(token + 1), 2)
|
||||
val handle1 = LegacyAppBackupFile.Metadata(token)
|
||||
val handle2 = LegacyAppBackupFile.Metadata(token + 1)
|
||||
|
||||
coEvery {
|
||||
backend.list(
|
||||
topLevelFolder = null,
|
||||
AppBackupFileType.Snapshot::class, LegacyAppBackupFile.Metadata::class,
|
||||
callback = captureLambda<(FileInfo) -> Unit>()
|
||||
)
|
||||
} answers {
|
||||
val callback = lambda<(FileInfo) -> Unit>().captured
|
||||
callback(info1)
|
||||
callback(info2)
|
||||
}
|
||||
coEvery { backend.load(info1.fileHandle) } returns inputStream
|
||||
coEvery { backend.load(info2.fileHandle) } returns inputStream
|
||||
coEvery { backend.getAvailableBackupFileHandles() } returns listOf(handle1, handle2)
|
||||
coEvery { backend.load(handle1) } returns inputStream
|
||||
coEvery { backend.load(handle2) } returns inputStream
|
||||
every { metadataReader.readMetadata(inputStream, token) } returns metadata
|
||||
every { metadataReader.readMetadata(inputStream, token + 1) } returns metadata
|
||||
every { inputStream.close() } just Runs
|
||||
|
@ -146,22 +134,12 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
|
||||
@Test
|
||||
fun `startRestore() fetches metadata if missing`() = runBlocking {
|
||||
val info1 = FileInfo(LegacyAppBackupFile.Metadata(token), 1)
|
||||
val info2 = FileInfo(LegacyAppBackupFile.Metadata(token + 1), 2)
|
||||
val handle1 = LegacyAppBackupFile.Metadata(token)
|
||||
val handle2 = LegacyAppBackupFile.Metadata(token + 1)
|
||||
|
||||
coEvery {
|
||||
backend.list(
|
||||
topLevelFolder = null,
|
||||
AppBackupFileType.Snapshot::class, LegacyAppBackupFile.Metadata::class,
|
||||
callback = captureLambda<(FileInfo) -> Unit>()
|
||||
)
|
||||
} answers {
|
||||
val callback = lambda<(FileInfo) -> Unit>().captured
|
||||
callback(info1)
|
||||
callback(info2)
|
||||
}
|
||||
coEvery { backend.load(info1.fileHandle) } returns inputStream
|
||||
coEvery { backend.load(info2.fileHandle) } returns inputStream
|
||||
coEvery { backend.getAvailableBackupFileHandles() } returns listOf(handle1, handle2)
|
||||
coEvery { backend.load(handle1) } returns inputStream
|
||||
coEvery { backend.load(handle2) } returns inputStream
|
||||
every { metadataReader.readMetadata(inputStream, token) } returns metadata
|
||||
every { metadataReader.readMetadata(inputStream, token + 1) } returns metadata
|
||||
every { inputStream.close() } just Runs
|
||||
|
@ -273,21 +251,10 @@ internal class RestoreCoordinatorTest : TransportTest() {
|
|||
@Test
|
||||
fun `startRestore() errors when it can't find snapshots`() = runBlocking {
|
||||
val handle = AppBackupFileType.Snapshot(repoId, getRandomByteArray(32).toHexString())
|
||||
val info = FileInfo(handle, 1)
|
||||
|
||||
every { backendManager.backendProperties } returns safStorage
|
||||
every { safStorage.isUnavailableUsb(context) } returns false
|
||||
|
||||
coEvery {
|
||||
backend.list(
|
||||
topLevelFolder = null,
|
||||
AppBackupFileType.Snapshot::class, LegacyAppBackupFile.Metadata::class,
|
||||
callback = captureLambda<(FileInfo) -> Unit>()
|
||||
)
|
||||
} answers {
|
||||
val callback = lambda<(FileInfo) -> Unit>().captured
|
||||
callback(info)
|
||||
}
|
||||
coEvery { backend.getAvailableBackupFileHandles() } returns listOf(handle)
|
||||
coEvery { snapshotManager.loadSnapshot(handle) } returns snapshot.copy {
|
||||
token = this@RestoreCoordinatorTest.token - 1 // unexpected token
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ import com.stevesoltys.seedvault.proto.copy
|
|||
import com.stevesoltys.seedvault.repo.AppBackupManager
|
||||
import com.stevesoltys.seedvault.repo.BackupData
|
||||
import com.stevesoltys.seedvault.repo.BackupReceiver
|
||||
import com.stevesoltys.seedvault.transport.backup.BackupTest
|
||||
import com.stevesoltys.seedvault.repo.SnapshotCreator
|
||||
import com.stevesoltys.seedvault.transport.backup.BackupTest
|
||||
import io.mockk.Runs
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
|
|
|
@ -23,6 +23,5 @@ public object Constants {
|
|||
public val appSnapshotRegex: Regex = Regex("(^[a-f0-9]{64})\\.snapshot$")
|
||||
public val fileSnapshotRegex: Regex = Regex("(^[0-9]{13})\\.SeedSnap$") // good until year 2286
|
||||
public const val MIME_TYPE: String = "application/octet-stream"
|
||||
public const val CHUNK_FOLDER_COUNT: Int = 256
|
||||
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.calyxos.backup.storage.api.BackupFile
|
|||
import org.calyxos.backup.storage.api.StorageBackup
|
||||
import org.calyxos.backup.storage.backup.NotificationBackupObserver
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.toDuration
|
||||
|
||||
data class BackupProgress(
|
||||
|
@ -91,7 +90,6 @@ internal class BackupStats(
|
|||
liveData.postValue(BackupProgress(filesProcessed, totalFiles, null))
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
override suspend fun onBackupComplete(backupDuration: Long?) {
|
||||
super.onBackupComplete(backupDuration)
|
||||
|
||||
|
@ -162,7 +160,6 @@ internal class BackupStats(
|
|||
liveData.postValue(BackupProgress(filesProcessed, totalFiles, text))
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
override suspend fun onPruneComplete(pruneDuration: Long) {
|
||||
super.onPruneComplete(pruneDuration)
|
||||
|
||||
|
|
|
@ -10,17 +10,17 @@ import android.security.keystore.KeyProperties.PURPOSE_ENCRYPT
|
|||
import android.security.keystore.KeyProperties.PURPOSE_SIGN
|
||||
import android.security.keystore.KeyProperties.PURPOSE_VERIFY
|
||||
import android.security.keystore.KeyProtection
|
||||
import org.calyxos.seedvault.core.crypto.CoreCrypto.ALGORITHM_HMAC
|
||||
import java.security.KeyStore
|
||||
import javax.crypto.SecretKey
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
object KeyManager: org.calyxos.seedvault.core.crypto.KeyManager {
|
||||
object KeyManager : org.calyxos.seedvault.core.crypto.KeyManager {
|
||||
|
||||
private const val KEY_SIZE = 256
|
||||
internal const val KEY_SIZE_BYTES = KEY_SIZE / 8
|
||||
private const val KEY_SIZE_BYTES = KEY_SIZE / 8
|
||||
private const val KEY_ALIAS_MASTER = "com.stevesoltys.seedvault.master"
|
||||
private const val ANDROID_KEY_STORE = "AndroidKeyStore"
|
||||
private const val ALGORITHM_HMAC = "HmacSHA256"
|
||||
|
||||
private const val FAKE_SEED = "This is a legacy backup key 1234"
|
||||
|
||||
|
|
|
@ -14,10 +14,8 @@ import org.calyxos.backup.storage.api.BackupFile
|
|||
import org.calyxos.backup.storage.scanner.DocumentScanner
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.measureTimedValue
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
fun scanTree(context: Context, documentScanner: DocumentScanner, treeUri: Uri): String {
|
||||
val sb = StringBuilder()
|
||||
val timedResult = measureTimedValue {
|
||||
|
|
|
@ -13,7 +13,6 @@ import org.calyxos.backup.storage.api.BackupFile
|
|||
import org.calyxos.backup.storage.scanner.MediaScanner
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.TimedValue
|
||||
import kotlin.time.measureTimedValue
|
||||
|
||||
|
@ -27,7 +26,6 @@ data class ScanResult(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
fun scanUri(context: Context, mediaScanner: MediaScanner, uri: Uri): String {
|
||||
val sb = StringBuilder()
|
||||
val timedResult = measureTimedValue {
|
||||
|
@ -57,7 +55,6 @@ fun dump(context: Context, mediaFiles: List<BackupFile>, sb: StringBuilder? = nu
|
|||
return ScanResult(itemsFound, totalSize)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
fun appendStats(
|
||||
context: Context,
|
||||
sb: StringBuilder,
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import android.widget.Toast.LENGTH_SHORT
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import de.grobox.storagebackuptester.MainViewModel
|
||||
|
|
|
@ -6,4 +6,5 @@
|
|||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<item name="colorSecondaryVariant">@color/teal_200</item>
|
||||
<item name="colorOnSecondary">@color/black</item>
|
||||
<!-- Status bar color. -->
|
||||
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
|
||||
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorAccent">@color/matrix</item>
|
||||
</style>
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
<color name="purple_200">#FFBB86FC</color>
|
||||
<color name="purple_500">#FF6200EE</color>
|
||||
<color name="purple_700">#FF3700B3</color>
|
||||
<color name="teal_200">#FF03DAC5</color>
|
||||
<color name="teal_700">#FF018786</color>
|
||||
|
|
|
@ -11,7 +11,6 @@ import kotlin.contracts.InvocationKind
|
|||
import kotlin.contracts.contract
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.toDuration
|
||||
|
||||
/**
|
||||
|
@ -20,7 +19,7 @@ import kotlin.time.toDuration
|
|||
* So when building with AOSP 11, things will blow up.
|
||||
*/
|
||||
|
||||
@OptIn(ExperimentalContracts::class, ExperimentalTime::class)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal inline fun measure(block: () -> Unit): Duration {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
|
@ -30,7 +29,7 @@ internal inline fun measure(block: () -> Unit): Duration {
|
|||
return (System.currentTimeMillis() - start).toDuration(DurationUnit.MILLISECONDS)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class, ExperimentalTime::class)
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
internal inline fun <T> measure(text: String, block: () -> T): T {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
|
|
Loading…
Reference in a new issue