Skip to content
Snippets Groups Projects
Unverified Commit 200a3ca2 authored by Jakob Möller's avatar Jakob Möller Committed by GitHub
Browse files

update to include exception for not enough storage space on main directory (#389)


* Update to include Exception for not enough space

Signed-off-by: default avatard067928 <jakob.moeller@sap.com>

* Update to include Exception for not enough space

Signed-off-by: default avatard067928 <jakob.moeller@sap.com>
parent 8a8f3f8c
No related branches found
No related tags found
No related merge requests found
package de.rki.coronawarnapp.exception
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.exception.reporting.ErrorCodes
import de.rki.coronawarnapp.exception.reporting.ReportedException
class NotEnoughSpaceOnDiskException(cause: Throwable? = null) : ReportedException(
ErrorCodes.NOT_ENOUGH_AVAILABLE_SPACE_ON_DISK.code,
"the app detected that not enough storage space is available for the required operation",
cause,
R.string.errors_not_enough_device_storage
)
...@@ -20,5 +20,6 @@ enum class ErrorCodes(val code: Int) { ...@@ -20,5 +20,6 @@ enum class ErrorCodes(val code: Int) {
// NONTECHNICAL // NONTECHNICAL
NO_NETWORK_CONNECTIVITY(1), NO_NETWORK_CONNECTIVITY(1),
NOT_ENOUGH_AVAILABLE_SPACE_ON_DISK(2),
EXTERNAL_NAVIGATION(10), EXTERNAL_NAVIGATION(10),
} }
package de.rki.coronawarnapp.storage package de.rki.coronawarnapp.storage
import android.content.Context
import android.os.Build
import android.os.storage.StorageManager
import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.CoronaWarnApplication
import de.rki.coronawarnapp.exception.NotEnoughSpaceOnDiskException
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import java.util.UUID
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/** /**
...@@ -38,34 +43,23 @@ object FileStorageHelper { ...@@ -38,34 +43,23 @@ object FileStorageHelper {
* Checks if internal store has free memory. * Checks if internal store has free memory.
* Threshold: FileStorageConstants.FREE_SPACE_THRESHOLD * Threshold: FileStorageConstants.FREE_SPACE_THRESHOLD
* Bound to .usableSpace due to API level restrictions (minimum required level - 23) * Bound to .usableSpace due to API level restrictions (minimum required level - 23)
*
* TODO Check with UX team to handle insufficient space flow
*/ */
fun checkFileStorageFreeSpace() { fun checkFileStorageFreeSpace() {
val availableSpace = (keyExportDirectory.usableSpace / BYTES) val availableSpace = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
.also { logAvailableSpace(it) } val storageManager = CoronaWarnApplication.getAppContext()
.getSystemService(Context.STORAGE_SERVICE) as StorageManager
val storageVolume = storageManager.primaryStorageVolume
val storageUUID =
UUID.fromString(storageVolume.uuid ?: StorageManager.UUID_DEFAULT.toString())
storageManager.getAllocatableBytes(storageUUID) / BYTES
} else {
keyExportDirectory.usableSpace / BYTES
}
if (availableSpace < FileStorageConstants.FREE_SPACE_THRESHOLD) { if (availableSpace < FileStorageConstants.FREE_SPACE_THRESHOLD) {
logInsufficientSpace(availableSpace) throw NotEnoughSpaceOnDiskException()
} }
} }
/**
* Remove outdated key files from internal storage.
* Threshold: FileStorageConstants.DAYS_TO_KEEP
*/
fun removeOutdatedFilesFromStorage() {
keyExportDirectory
.walk()
.filter(File::isDirectory)
.forEach { file: File ->
Unit
if (file != keyExportDirectory && file.isOutdated()) {
file.checkAndRemove().also { logFileRemovalResult(file.name, it) }
}
}
}
fun getAllFilesInKeyExportDirectory(): List<File> { fun getAllFilesInKeyExportDirectory(): List<File> {
return keyExportDirectory return keyExportDirectory
.walk(FileWalkDirection.BOTTOM_UP) .walk(FileWalkDirection.BOTTOM_UP)
......
...@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.storage ...@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.storage
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.ExceptionCategory
import de.rki.coronawarnapp.exception.TransactionException
import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.exception.reporting.report
import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
import de.rki.coronawarnapp.risk.TimeVariables.getActiveTracingDaysInRetentionPeriod import de.rki.coronawarnapp.risk.TimeVariables.getActiveTracingDaysInRetentionPeriod
...@@ -52,6 +53,8 @@ object TracingRepository { ...@@ -52,6 +53,8 @@ object TracingRepository {
try { try {
RetrieveDiagnosisKeysTransaction.start() RetrieveDiagnosisKeysTransaction.start()
RiskLevelTransaction.start() RiskLevelTransaction.start()
} catch (e: TransactionException) {
e.cause?.report(ExceptionCategory.EXPOSURENOTIFICATION)
} catch (e: Exception) { } catch (e: Exception) {
e.report(ExceptionCategory.EXPOSURENOTIFICATION) e.report(ExceptionCategory.EXPOSURENOTIFICATION)
} }
......
...@@ -23,6 +23,7 @@ import de.rki.coronawarnapp.BuildConfig ...@@ -23,6 +23,7 @@ import de.rki.coronawarnapp.BuildConfig
import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.CoronaWarnApplication
import de.rki.coronawarnapp.http.WebRequestBuilder import de.rki.coronawarnapp.http.WebRequestBuilder
import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants
import de.rki.coronawarnapp.storage.FileStorageHelper
import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.storage.keycache.KeyCacheEntity import de.rki.coronawarnapp.storage.keycache.KeyCacheEntity
import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository
...@@ -67,6 +68,7 @@ object CachedKeyFileHolder { ...@@ -67,6 +68,7 @@ object CachedKeyFileHolder {
* @return list of all files from both the cache and the diff query * @return list of all files from both the cache and the diff query
*/ */
suspend fun asyncFetchFiles(currentDate: Date): List<File> = withContext(Dispatchers.IO) { suspend fun asyncFetchFiles(currentDate: Date): List<File> = withContext(Dispatchers.IO) {
checkForFreeSpace()
val serverDates = getDatesFromServer() val serverDates = getDatesFromServer()
// TODO remove last3HourFetch before Release // TODO remove last3HourFetch before Release
if (BuildConfig.FLAVOR != "device" && isLast3HourFetchEnabled()) { if (BuildConfig.FLAVOR != "device" && isLast3HourFetchEnabled()) {
...@@ -114,6 +116,8 @@ object CachedKeyFileHolder { ...@@ -114,6 +116,8 @@ object CachedKeyFileHolder {
} }
} }
private fun checkForFreeSpace() = FileStorageHelper.checkFileStorageFreeSpace()
/** /**
* Calculates the missing days based on current missing entries in the cache * Calculates the missing days based on current missing entries in the cache
*/ */
......
...@@ -2,7 +2,6 @@ package de.rki.coronawarnapp.util ...@@ -2,7 +2,6 @@ package de.rki.coronawarnapp.util
import android.content.Context import android.content.Context
import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.CoronaWarnApplication
import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository
import io.mockk.MockKAnnotations import io.mockk.MockKAnnotations
import io.mockk.Runs import io.mockk.Runs
...@@ -51,6 +50,7 @@ class CachedKeyFileHolderTest { ...@@ -51,6 +50,7 @@ class CachedKeyFileHolderTest {
coEvery { keyCacheRepository.getDates() } returns listOf() coEvery { keyCacheRepository.getDates() } returns listOf()
coEvery { keyCacheRepository.getFilesFromEntries() } returns listOf() coEvery { keyCacheRepository.getFilesFromEntries() } returns listOf()
every { CachedKeyFileHolder["isLast3HourFetchEnabled"]() } returns false every { CachedKeyFileHolder["isLast3HourFetchEnabled"]() } returns false
every { CachedKeyFileHolder["checkForFreeSpace"]() } returns Unit
every { CachedKeyFileHolder["getDatesFromServer"]() } returns arrayListOf<String>() every { CachedKeyFileHolder["getDatesFromServer"]() } returns arrayListOf<String>()
runBlocking { runBlocking {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment