Catch out of space exception during FullBackup

This commit is contained in:
Torsten Grote 2024-05-09 14:13:05 -03:00 committed by Chirayu Desai
parent 860733d238
commit 066b147315
8 changed files with 31 additions and 10 deletions

View file

@ -31,7 +31,7 @@ class KoinInstrumentationTestApp : App() {
single { spyk(SettingsManager(context)) } single { spyk(SettingsManager(context)) }
single { spyk(BackupNotificationManager(context)) } single { spyk(BackupNotificationManager(context)) }
single { spyk(FullBackup(get(), get(), get(), get())) } single { spyk(FullBackup(get(), get(), get(), get(), get())) }
single { spyk(KVBackup(get(), get(), get(), get(), get())) } single { spyk(KVBackup(get(), get(), get(), get(), get())) }
single { spyk(InputFactory()) } single { spyk(InputFactory()) }

View file

@ -9,6 +9,7 @@ import android.content.Context
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import androidx.annotation.WorkerThread import androidx.annotation.WorkerThread
import java.io.IOException
abstract class StorageProperties<T> { abstract class StorageProperties<T> {
abstract val config: T abstract val config: T
@ -34,3 +35,7 @@ abstract class StorageProperties<T> {
return capabilities.hasCapability(NET_CAPABILITY_INTERNET) && (allowMetered || !isMetered) return capabilities.hasCapability(NET_CAPABILITY_INTERNET) && (allowMetered || !isMetered)
} }
} }
fun Exception.isOutOfSpace(): Boolean {
return this is IOException && message?.contains("No space left on device") == true
}

View file

@ -26,6 +26,7 @@ import com.stevesoltys.seedvault.metadata.PackageState.QUOTA_EXCEEDED
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
import com.stevesoltys.seedvault.plugins.StoragePlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePluginManager import com.stevesoltys.seedvault.plugins.StoragePluginManager
import com.stevesoltys.seedvault.plugins.isOutOfSpace
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
@ -360,9 +361,7 @@ internal class BackupCoordinator(
onPackageBackedUp(packageInfo, BackupType.KV, size) onPackageBackedUp(packageInfo, BackupType.KV, size)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Error calling onPackageBackedUp for $packageName", e) Log.e(TAG, "Error calling onPackageBackedUp for $packageName", e)
if (e is IOException && if (e.isOutOfSpace()) nm.onInsufficientSpaceError()
e.message?.contains("No space left on device") == true
) nm.onInsufficientSpaceError()
result = TRANSPORT_PACKAGE_REJECTED result = TRANSPORT_PACKAGE_REJECTED
} }
} }

View file

@ -28,6 +28,7 @@ val backupModule = module {
FullBackup( FullBackup(
pluginManager = get(), pluginManager = get(),
settingsManager = get(), settingsManager = get(),
nm = get(),
inputFactory = get(), inputFactory = get(),
crypto = get(), crypto = get(),
) )

View file

@ -12,7 +12,9 @@ import com.stevesoltys.seedvault.crypto.Crypto
import com.stevesoltys.seedvault.header.VERSION import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForFull import com.stevesoltys.seedvault.header.getADForFull
import com.stevesoltys.seedvault.plugins.StoragePluginManager import com.stevesoltys.seedvault.plugins.StoragePluginManager
import com.stevesoltys.seedvault.plugins.isOutOfSpace
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import libcore.io.IoUtils.closeQuietly import libcore.io.IoUtils.closeQuietly
import java.io.EOFException import java.io.EOFException
import java.io.IOException import java.io.IOException
@ -41,6 +43,7 @@ private val TAG = FullBackup::class.java.simpleName
internal class FullBackup( internal class FullBackup(
private val pluginManager: StoragePluginManager, private val pluginManager: StoragePluginManager,
private val settingsManager: SettingsManager, private val settingsManager: SettingsManager,
private val nm: BackupNotificationManager,
private val inputFactory: InputFactory, private val inputFactory: InputFactory,
private val crypto: Crypto, private val crypto: Crypto,
) { ) {
@ -170,6 +173,7 @@ internal class FullBackup(
TRANSPORT_OK TRANSPORT_OK
} catch (e: IOException) { } catch (e: IOException) {
Log.e(TAG, "Error handling backup data for ${state.packageName}: ", e) Log.e(TAG, "Error handling backup data for ${state.packageName}: ", e)
if (e.isOutOfSpace()) nm.onInsufficientSpaceError()
TRANSPORT_ERROR TRANSPORT_ERROR
} }
} }

View file

@ -13,6 +13,7 @@ import com.stevesoltys.seedvault.metadata.PackageState.NOT_ALLOWED
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
import com.stevesoltys.seedvault.plugins.StoragePlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePluginManager import com.stevesoltys.seedvault.plugins.StoragePluginManager
import com.stevesoltys.seedvault.plugins.isOutOfSpace
import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA import com.stevesoltys.seedvault.plugins.saf.FILE_BACKUP_METADATA
import com.stevesoltys.seedvault.settings.SettingsManager import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.transport.backup.PackageService import com.stevesoltys.seedvault.transport.backup.PackageService
@ -110,9 +111,7 @@ internal class ApkBackupManager(
} ?: false } ?: false
} catch (e: IOException) { } catch (e: IOException) {
Log.e(TAG, "Error while writing APK for $packageName", e) Log.e(TAG, "Error while writing APK for $packageName", e)
if (e.message?.contains("No space left on device") == true) { if (e.isOutOfSpace()) nm.onInsufficientSpaceError()
nm.onInsufficientSpaceError()
}
false false
} }
} }

View file

@ -65,8 +65,13 @@ internal class CoordinatorIntegrationTest : TransportTest() {
private val backupPlugin = mockk<StoragePlugin<*>>() private val backupPlugin = mockk<StoragePlugin<*>>()
private val kvBackup = private val kvBackup =
KVBackup(storagePluginManager, settingsManager, inputFactory, cryptoImpl, dbManager) KVBackup(storagePluginManager, settingsManager, inputFactory, cryptoImpl, dbManager)
private val fullBackup = private val fullBackup = FullBackup(
FullBackup(storagePluginManager, settingsManager, inputFactory, cryptoImpl) pluginManager = storagePluginManager,
settingsManager = settingsManager,
nm = notificationManager,
inputFactory = inputFactory,
crypto = cryptoImpl,
)
private val apkBackup = mockk<ApkBackup>() private val apkBackup = mockk<ApkBackup>()
private val packageService: PackageService = mockk() private val packageService: PackageService = mockk()
private val backup = BackupCoordinator( private val backup = BackupCoordinator(

View file

@ -8,6 +8,7 @@ import com.stevesoltys.seedvault.header.VERSION
import com.stevesoltys.seedvault.header.getADForFull import com.stevesoltys.seedvault.header.getADForFull
import com.stevesoltys.seedvault.plugins.StoragePlugin import com.stevesoltys.seedvault.plugins.StoragePlugin
import com.stevesoltys.seedvault.plugins.StoragePluginManager import com.stevesoltys.seedvault.plugins.StoragePluginManager
import com.stevesoltys.seedvault.ui.notification.BackupNotificationManager
import io.mockk.Runs import io.mockk.Runs
import io.mockk.coEvery import io.mockk.coEvery
import io.mockk.every import io.mockk.every
@ -26,7 +27,14 @@ internal class FullBackupTest : BackupTest() {
private val storagePluginManager: StoragePluginManager = mockk() private val storagePluginManager: StoragePluginManager = mockk()
private val plugin = mockk<StoragePlugin<*>>() private val plugin = mockk<StoragePlugin<*>>()
private val backup = FullBackup(storagePluginManager, settingsManager, inputFactory, crypto) private val notificationManager = mockk<BackupNotificationManager>()
private val backup = FullBackup(
pluginManager = storagePluginManager,
settingsManager = settingsManager,
nm = notificationManager,
inputFactory = inputFactory,
crypto = crypto,
)
private val bytes = ByteArray(23).apply { Random.nextBytes(this) } private val bytes = ByteArray(23).apply { Random.nextBytes(this) }
private val inputStream = mockk<FileInputStream>() private val inputStream = mockk<FileInputStream>()