diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/NotEnoughSpaceOnDiskException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/NotEnoughSpaceOnDiskException.kt new file mode 100644 index 0000000000000000000000000000000000000000..28ae9a03995cd9a844373458d43254ab757f5890 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/NotEnoughSpaceOnDiskException.kt @@ -0,0 +1,12 @@ +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 +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorCodes.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorCodes.kt index 9f62362d14ad8f93966559ef7518516ee75591ca..5b89a01d3dd66e1dcc6cea51c4df0631dc69b712 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorCodes.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/reporting/ErrorCodes.kt @@ -20,5 +20,6 @@ enum class ErrorCodes(val code: Int) { // NONTECHNICAL NO_NETWORK_CONNECTIVITY(1), + NOT_ENOUGH_AVAILABLE_SPACE_ON_DISK(2), EXTERNAL_NAVIGATION(10), } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/FileStorageHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/FileStorageHelper.kt index f1844b19fff95359a4ad40653863412d3905f21a..44442e9e61db22babad2aeb451523e1d5e897292 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/FileStorageHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/FileStorageHelper.kt @@ -1,8 +1,13 @@ 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.exception.NotEnoughSpaceOnDiskException import timber.log.Timber import java.io.File +import java.util.UUID import java.util.concurrent.TimeUnit /** @@ -38,34 +43,23 @@ object FileStorageHelper { * Checks if internal store has free memory. * Threshold: FileStorageConstants.FREE_SPACE_THRESHOLD * Bound to .usableSpace due to API level restrictions (minimum required level - 23) - * - * TODO Check with UX team to handle insufficient space flow */ fun checkFileStorageFreeSpace() { - val availableSpace = (keyExportDirectory.usableSpace / BYTES) - .also { logAvailableSpace(it) } - + val availableSpace = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + 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) { - 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> { return keyExportDirectory .walk(FileWalkDirection.BOTTOM_UP) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt index c94cc83476afb278ae5979c1a5a68f5d0ffe9109..c018540071a67b3cdae95a30ccf3f7aae6de0881 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt @@ -2,6 +2,7 @@ package de.rki.coronawarnapp.storage import androidx.lifecycle.MutableLiveData import de.rki.coronawarnapp.exception.ExceptionCategory +import de.rki.coronawarnapp.exception.TransactionException import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient import de.rki.coronawarnapp.risk.TimeVariables.getActiveTracingDaysInRetentionPeriod @@ -52,6 +53,8 @@ object TracingRepository { try { RetrieveDiagnosisKeysTransaction.start() RiskLevelTransaction.start() + } catch (e: TransactionException) { + e.cause?.report(ExceptionCategory.EXPOSURENOTIFICATION) } catch (e: Exception) { e.report(ExceptionCategory.EXPOSURENOTIFICATION) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt index 883d0d03e11cdd6bebb99e04a5707d344c4c0095..be5b2edf70b909a2fc43eacf02211adc088aea57 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt @@ -23,6 +23,7 @@ import de.rki.coronawarnapp.BuildConfig import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.http.WebRequestBuilder import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants +import de.rki.coronawarnapp.storage.FileStorageHelper import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.keycache.KeyCacheEntity import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository @@ -67,6 +68,7 @@ object CachedKeyFileHolder { * @return list of all files from both the cache and the diff query */ suspend fun asyncFetchFiles(currentDate: Date): List<File> = withContext(Dispatchers.IO) { + checkForFreeSpace() val serverDates = getDatesFromServer() // TODO remove last3HourFetch before Release if (BuildConfig.FLAVOR != "device" && isLast3HourFetchEnabled()) { @@ -114,6 +116,8 @@ object CachedKeyFileHolder { } } + private fun checkForFreeSpace() = FileStorageHelper.checkFileStorageFreeSpace() + /** * Calculates the missing days based on current missing entries in the cache */ diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt index a079159ca47c886f83183d12e8f96f805075e1bb..d796b4c7e66fb9a2ea3ae2f7edb924abe990bf06 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt @@ -2,7 +2,6 @@ package de.rki.coronawarnapp.util import android.content.Context import de.rki.coronawarnapp.CoronaWarnApplication - import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository import io.mockk.MockKAnnotations import io.mockk.Runs @@ -51,6 +50,7 @@ class CachedKeyFileHolderTest { coEvery { keyCacheRepository.getDates() } returns listOf() coEvery { keyCacheRepository.getFilesFromEntries() } returns listOf() every { CachedKeyFileHolder["isLast3HourFetchEnabled"]() } returns false + every { CachedKeyFileHolder["checkForFreeSpace"]() } returns Unit every { CachedKeyFileHolder["getDatesFromServer"]() } returns arrayListOf<String>() runBlocking {