diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d2aef5ea --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +[*.{kt,kts}] +indent_size=4 +insert_final_newline=true +max_line_length=100 diff --git a/.gitignore b/.gitignore index 89216d50..ec605697 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ out/ lib/ .idea/* !.idea/runConfigurations* +!.idea/inspectionProfiles* !.idea/codeStyles* *.ipr *.iws diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index e122e4f9..35a40e4e 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -131,6 +131,16 @@ </codeStyleSettings> <codeStyleSettings language="kotlin"> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> + <option name="RIGHT_MARGIN" value="100" /> + <option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" /> + <option name="LINE_COMMENT_ADD_SPACE" value="true" /> + <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" /> + <option name="KEEP_BLANK_LINES_IN_CODE" value="1" /> + <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" /> + <option name="ALIGN_MULTILINE_PARAMETERS" value="false" /> + <option name="PARAMETER_ANNOTATION_WRAP" value="1" /> + <option name="VARIABLE_ANNOTATION_WRAP" value="1" /> + <option name="ENUM_CONSTANTS_WRAP" value="1" /> <indentOptions> <option name="CONTINUATION_INDENT_SIZE" value="4" /> </indentOptions> diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..d467c379 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ +<component name="InspectionProjectProfileManager"> + <profile version="1.0"> + <option name="myName" value="Project Default" /> + <inspection_tool class="AndroidLintMangledCRLF" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" /> + <inspection_tool class="KotlinUnusedImport" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="LongLine" enabled="true" level="ERROR" enabled_by_default="true" /> + <inspection_tool class="RedundantSemicolon" enabled="true" level="ERROR" enabled_by_default="true" /> + </profile> +</component> \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 82ab682e..9414cabf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -script: ./gradlew check assemble +script: ./gradlew check assemble ktlintCheck cache: directories: diff --git a/app/build.gradle b/app/build.gradle index c3e034b4..f7418a95 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,10 @@ import groovy.xml.XmlUtil -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' +plugins { + id "com.android.application" + id "kotlin-android" + id "org.jlleitschuh.gradle.ktlint" version "9.4.0" +} android { @@ -74,6 +77,17 @@ android { apply from: '../gradle/dependencies.gradle' +ktlint { + version = "0.36.0" // https://github.com/pinterest/ktlint/issues/764 + android = true + enableExperimentalRules = false + verbose = true + disabledRules = [ + "import-ordering", + "no-blank-line-before-rbrace", + ] +} + gradle.projectsEvaluated { tasks.withType(JavaCompile) { if (JavaVersion.current() >= JavaVersion.VERSION_1_9) { @@ -92,9 +106,14 @@ preBuild.doLast { def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' } parsedXml.component[1].remove(jdkNode) - def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform" + def apiString = android.compileSdkVersion.substring("android-".length()) + def sdkString = "Android API " + apiString + " Platform" //noinspection GroovyResultOfObjectAllocationIgnored // the note gets inserted - new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK']) + new Node(parsedXml.component[1], 'orderEntry', [ + 'type' : 'jdk', + 'jdkName': sdkString, + 'jdkType': 'Android SDK' + ]) XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile)) } catch (NullPointerException | FileNotFoundException ex) { diff --git a/app/src/main/java/com/stevesoltys/seedvault/App.kt b/app/src/main/java/com/stevesoltys/seedvault/App.kt index 5b56a661..47a279a1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/App.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/App.kt @@ -56,7 +56,7 @@ class App : Application() { cryptoModule, headerModule, metadataModule, - documentsProviderModule, // storage plugin + documentsProviderModule, // storage plugin backupModule, restoreModule, appModule diff --git a/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt b/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt index d5dd5084..c225ac6e 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/UsbIntentReceiver.kt @@ -69,7 +69,9 @@ abstract class UsbMonitor : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action = intent.action ?: return - if (intent.action == ACTION_USB_DEVICE_ATTACHED || intent.action == ACTION_USB_DEVICE_DETACHED) { + if (intent.action == ACTION_USB_DEVICE_ATTACHED || + intent.action == ACTION_USB_DEVICE_DETACHED + ) { val device = intent.extras?.getParcelable<UsbDevice>(EXTRA_DEVICE) ?: return Log.d(TAG, "New USB mass-storage device attached.") device.log() diff --git a/app/src/main/java/com/stevesoltys/seedvault/crypto/Crypto.kt b/app/src/main/java/com/stevesoltys/seedvault/crypto/Crypto.kt index 9165a8d7..8b6a6960 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/crypto/Crypto.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/crypto/Crypto.kt @@ -115,7 +115,8 @@ internal class CryptoImpl( val cipher = cipherFactory.createEncryptionCipher() check(cipher.getOutputSize(cleartext.size) <= MAX_SEGMENT_LENGTH) { - "Cipher's output size ${cipher.getOutputSize(cleartext.size)} is larger than maximum segment length ($MAX_SEGMENT_LENGTH)" + "Cipher's output size ${cipher.getOutputSize(cleartext.size)} is larger" + + "than maximum segment length ($MAX_SEGMENT_LENGTH)" } encryptSegment(cipher, outputStream, cleartext) } @@ -162,9 +163,9 @@ internal class CryptoImpl( "expected '$expectedPackageName'." ) } - if (header.key != expectedKey) { - throw SecurityException("Invalid key '${header.key}' in header, expected '$expectedKey'.") - } + if (header.key != expectedKey) throw SecurityException( + "Invalid key '${header.key}' in header, expected '$expectedKey'." + ) return header } @@ -190,9 +191,9 @@ internal class CryptoImpl( @Throws(EOFException::class, IOException::class, SecurityException::class) private fun decryptSegment(inputStream: InputStream, maxSegmentLength: Int): ByteArray { val segmentHeader = headerReader.readSegmentHeader(inputStream) - if (segmentHeader.segmentLength > maxSegmentLength) { - throw SecurityException("Segment length too long: ${segmentHeader.segmentLength} > $maxSegmentLength") - } + if (segmentHeader.segmentLength > maxSegmentLength) throw SecurityException( + "Segment length too long: ${segmentHeader.segmentLength} > $maxSegmentLength" + ) val buffer = ByteArray(segmentHeader.segmentLength.toInt()) val bytesRead = inputStream.read(buffer) diff --git a/app/src/main/java/com/stevesoltys/seedvault/header/Header.kt b/app/src/main/java/com/stevesoltys/seedvault/header/Header.kt index 6017d4f9..248cd8c9 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/header/Header.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/header/Header.kt @@ -22,7 +22,9 @@ data class VersionHeader( "Package $packageName has name longer than $MAX_PACKAGE_LENGTH_SIZE" } key?.let { - check(key.length <= MAX_KEY_LENGTH_SIZE) { "Key $key is longer than $MAX_KEY_LENGTH_SIZE" } + check(key.length <= MAX_KEY_LENGTH_SIZE) { + "Key $key is longer than $MAX_KEY_LENGTH_SIZE" + } } } } diff --git a/app/src/main/java/com/stevesoltys/seedvault/header/HeaderReader.kt b/app/src/main/java/com/stevesoltys/seedvault/header/HeaderReader.kt index 419f551d..e29b9494 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/header/HeaderReader.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/header/HeaderReader.kt @@ -33,15 +33,21 @@ internal class HeaderReaderImpl : HeaderReader { val packageLength = buffer.short.toInt() if (packageLength <= 0) throw SecurityException("Invalid package length: $packageLength") - if (packageLength > MAX_PACKAGE_LENGTH_SIZE) throw SecurityException("Too large package length: $packageLength") - if (packageLength > buffer.remaining()) throw SecurityException("Not enough bytes for package name") + if (packageLength > MAX_PACKAGE_LENGTH_SIZE) throw SecurityException( + "Too large package length: $packageLength" + ) + if (packageLength > buffer.remaining()) throw SecurityException( + "Not enough bytes for package name" + ) val packageName = ByteArray(packageLength) .apply { buffer.get(this) } .toString(Utf8) val keyLength = buffer.short.toInt() if (keyLength < 0) throw SecurityException("Invalid key length: $keyLength") - if (keyLength > MAX_KEY_LENGTH_SIZE) throw SecurityException("Too large key length: $keyLength") + if (keyLength > MAX_KEY_LENGTH_SIZE) throw SecurityException( + "Too large key length: $keyLength" + ) if (keyLength > buffer.remaining()) throw SecurityException("Not enough bytes for key") val key = if (keyLength == 0) null else ByteArray(keyLength) .apply { buffer.get(this) } diff --git a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt index dc10762f..830c4e8f 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataManager.kt @@ -80,7 +80,8 @@ class MetadataManager( "APK backup returned version null" } check(it.version == null || it.version < packageMetadata.version) { - "APK backup backed up the same or a smaller version: was ${it.version} is ${packageMetadata.version}" + "APK backup backed up the same or a smaller version:" + + "was ${it.version} is ${packageMetadata.version}" } } val oldPackageMetadata = metadata.packageMetadataMap[packageName] diff --git a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataReader.kt b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataReader.kt index 7c840c30..860d99e4 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataReader.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/metadata/MetadataReader.kt @@ -78,9 +78,9 @@ internal class MetadataReaderImpl(private val crypto: Crypto) : MetadataReader { ) } val token = meta.getLong(JSON_METADATA_TOKEN) - if (expectedToken != null && token != expectedToken) { - throw SecurityException("Invalid token '$token' in metadata, expected '$expectedToken'.") - } + if (expectedToken != null && token != expectedToken) throw SecurityException( + "Invalid token '$token' in metadata, expected '$expectedToken'." + ) // get package metadata val packageMetadataMap = PackageMetadataMap() for (packageName in json.keys()) { diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreErrorBroadcastReceiver.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreErrorBroadcastReceiver.kt index 40d88041..d8e3ed38 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreErrorBroadcastReceiver.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreErrorBroadcastReceiver.kt @@ -15,7 +15,9 @@ internal const val REQUEST_CODE_UNINSTALL = 4576841 class RestoreErrorBroadcastReceiver : BroadcastReceiver() { // using KoinComponent would crash robolectric tests :( - private val notificationManager: BackupNotificationManager by lazy { get().get<BackupNotificationManager>() } + private val notificationManager: BackupNotificationManager by lazy { + get().get<BackupNotificationManager>() + } override fun onReceive(context: Context, intent: Intent) { if (intent.action != ACTION_RESTORE_ERROR_UNINSTALL) return @@ -24,7 +26,7 @@ class RestoreErrorBroadcastReceiver : BroadcastReceiver() { val packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME)!! - @Suppress("DEPRECATION") // the alternative doesn't work for us + @Suppress("DEPRECATION") // the alternative doesn't work for us val i = Intent(Intent.ACTION_UNINSTALL_PACKAGE).apply { data = "package:$packageName".toUri() flags = FLAG_ACTIVITY_NEW_TASK diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreViewModel.kt index 2114ec37..b97b48c1 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreViewModel.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/RestoreViewModel.kt @@ -186,7 +186,9 @@ internal class RestoreViewModel( // we need to start a new session and retrieve the restore sets before starting the restore val restoreSetResult = getAvailableRestoreSets() if (restoreSetResult.hasError()) { - mRestoreBackupResult.postValue(RestoreBackupResult(app.getString(R.string.restore_finished_error))) + mRestoreBackupResult.postValue( + RestoreBackupResult(app.getString(R.string.restore_finished_error)) + ) return } @@ -196,7 +198,9 @@ internal class RestoreViewModel( if (restoreAllResult != 0) { if (session == null) Log.e(TAG, "session was null") else Log.e(TAG, "restoreAll() returned non-zero value") - mRestoreBackupResult.postValue(RestoreBackupResult(app.getString(R.string.restore_finished_error))) + mRestoreBackupResult.postValue( + RestoreBackupResult(app.getString(R.string.restore_finished_error)) + ) return } } @@ -306,8 +310,9 @@ internal class RestoreViewModel( val restorableBackups = restoreSets.mapNotNull { set -> getRestorableBackup(set, backupMetadata[set.token]) } - if (restorableBackups.isEmpty()) RestoreSetResult(app.getString(R.string.restore_set_empty_result)) - else RestoreSetResult(restorableBackups) + if (restorableBackups.isEmpty()) { + RestoreSetResult(app.getString(R.string.restore_set_empty_result)) + } else RestoreSetResult(restorableBackups) } } continuation.resume(result) diff --git a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt index 393d08a8..cded2c24 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/settings/SettingsFragment.kt @@ -2,7 +2,7 @@ package com.stevesoltys.seedvault.settings import android.app.backup.IBackupManager import android.content.Context -import android.content.Context.BACKUP_SERVICE +import android.content.Context.BACKUP_SERVICE // ktlint-disable no-unused-imports import android.content.Intent import android.content.IntentFilter import android.hardware.usb.UsbDevice @@ -11,7 +11,7 @@ import android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED import android.os.Bundle import android.os.RemoteException import android.provider.Settings -import android.provider.Settings.Secure.BACKUP_AUTO_RESTORE +import android.provider.Settings.Secure.BACKUP_AUTO_RESTORE // ktlint-disable no-unused-imports import android.util.Log import android.view.Menu import android.view.MenuInflater diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/ConfigurableBackupTransportService.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/ConfigurableBackupTransportService.kt index 9ac50ac9..328ff1bd 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/ConfigurableBackupTransportService.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/ConfigurableBackupTransportService.kt @@ -2,10 +2,10 @@ package com.stevesoltys.seedvault.transport import android.app.Service import android.app.backup.BackupManager -import android.app.backup.BackupManager.FLAG_NON_INCREMENTAL_BACKUP +import android.app.backup.BackupManager.FLAG_NON_INCREMENTAL_BACKUP // ktlint-disable no-unused-imports import android.app.backup.IBackupManager import android.content.Context -import android.content.Context.BACKUP_SERVICE +import android.content.Context.BACKUP_SERVICE // ktlint-disable no-unused-imports import android.content.Intent import android.os.IBinder import android.os.RemoteException diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt index e54e3209..92ed5e38 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/ApkBackup.kt @@ -79,8 +79,8 @@ class ApkBackup( // do not backup if we have the version already and signatures did not change if (version <= backedUpVersion && !signaturesChanged(packageMetadata, signatures)) { Log.d( - TAG, - "Package $packageName with version $version already has a backup ($backedUpVersion)" + + TAG, "Package $packageName with version $version" + + " already has a backup ($backedUpVersion)" + " with the same signature. Not backing it up." ) return null diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt index f509fc90..d15cc8bc 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinator.kt @@ -327,12 +327,16 @@ internal class BackupCoordinator( */ suspend fun finishBackup(): Int = when { kv.hasState() -> { - check(!full.hasState()) { "K/V backup has state, but full backup has dangling state as well" } + check(!full.hasState()) { + "K/V backup has state, but full backup has dangling state as well" + } onPackageBackedUp(kv.getCurrentPackage()!!) // not-null because we have state kv.finishBackup() } full.hasState() -> { - check(!kv.hasState()) { "Full backup has state, but K/V backup has dangling state as well" } + check(!kv.hasState()) { + "Full backup has state, but K/V backup has dangling state as well" + } onPackageBackedUp(full.getCurrentPackage()!!) // not-null because we have state full.finishBackup() } @@ -352,15 +356,17 @@ internal class BackupCoordinator( val packageName = packageInfo.packageName try { nm.onOptOutAppBackup(packageName, i + 1, notAllowedPackages.size) - val packageState = if (packageInfo.isStopped()) WAS_STOPPED else NOT_ALLOWED + val packageState = + if (packageInfo.isStopped()) WAS_STOPPED else NOT_ALLOWED val wasBackedUp = backUpApk(packageInfo, packageState) if (!wasBackedUp) { - val packageMetadata = metadataManager.getPackageMetadata(packageName) + val packageMetadata = + metadataManager.getPackageMetadata(packageName) val oldPackageState = packageMetadata?.state if (oldPackageState != null && oldPackageState != packageState) { Log.e( - TAG, - "Package $packageName was in $oldPackageState, update to $packageState" + TAG, "Package $packageName was in $oldPackageState" + + ", update to $packageState" ) plugin.getMetadataOutputStream().use { metadataManager.onPackageBackupError(packageInfo, packageState, it) diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkInstaller.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkInstaller.kt index c0844505..ec31fd48 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkInstaller.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkInstaller.kt @@ -62,7 +62,7 @@ internal class ApkInstaller(private val context: Context) { } // Don't set more sessionParams intentionally here. // We saw strange permission issues when doing setInstallReason() or setting installFlags. - @Suppress("BlockingMethodInNonBlockingContext") // flows on Dispatcher.IO + @Suppress("BlockingMethodInNonBlockingContext") // flows on Dispatcher.IO val session = installer.openSession(installer.createSession(sessionParams)) val sizeBytes = cachedApk.length() session.use { s -> @@ -96,7 +96,9 @@ internal class ApkInstaller(private val context: Context) { val success = i.getIntExtra(EXTRA_STATUS, -1) == STATUS_SUCCESS val statusMsg = i.getStringExtra(EXTRA_STATUS_MESSAGE)!! - check(packageName == expectedPackageName) { "Expected $expectedPackageName, but got $packageName." } + check(packageName == expectedPackageName) { + "Expected $expectedPackageName, but got $packageName." + } Log.d(TAG, "Received result for $packageName: success=$success $statusMsg") // delete cached APK file diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkRestore.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkRestore.kt index 545e6d53..a55eb28f 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkRestore.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/transport/restore/ApkRestore.kt @@ -95,9 +95,9 @@ internal class ApkRestore( // check APK's SHA-256 hash val sha256 = messageDigest.digest().encodeBase64() - if (metadata.sha256 != sha256) { - throw SecurityException("Package $packageName has sha256 '$sha256', but '${metadata.sha256}' expected.") - } + if (metadata.sha256 != sha256) throw SecurityException( + "Package $packageName has sha256 '$sha256', but '${metadata.sha256}' expected." + ) // parse APK (GET_SIGNATURES is needed even though deprecated) @Suppress("DEPRECATION") val flags = GET_SIGNING_CERTIFICATES or GET_SIGNATURES @@ -105,9 +105,9 @@ internal class ApkRestore( ?: throw IOException("getPackageArchiveInfo returned null") // check APK package name - if (packageName != packageInfo.packageName) { - throw SecurityException("Package $packageName expected, but ${packageInfo.packageName} found.") - } + if (packageName != packageInfo.packageName) throw SecurityException( + "Package $packageName expected, but ${packageInfo.packageName} found." + ) // check APK version code if (metadata.version != packageInfo.longVersionCode) { diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootAdapter.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootAdapter.kt index b4fbf3d8..0ec955cf 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootAdapter.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootAdapter.kt @@ -1,6 +1,5 @@ package com.stevesoltys.seedvault.ui.storage - import android.content.Context import android.text.format.Formatter import android.view.LayoutInflater diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt index c8936e12..c9815651 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/ui/storage/StorageRootFetcher.kt @@ -277,9 +277,15 @@ internal class StorageRootFetcher(private val context: Context, private val isRe private fun getIcon(context: Context, authority: String, rootId: String, icon: Int): Drawable? { return getPackageIcon(context, authority, icon) ?: when { - authority == AUTHORITY_STORAGE && rootId == ROOT_ID_DEVICE -> context.getDrawable(R.drawable.ic_phone_android) - authority == AUTHORITY_STORAGE && rootId != ROOT_ID_HOME -> context.getDrawable(R.drawable.ic_usb) - authority == AUTHORITY_NEXTCLOUD -> context.getDrawable(R.drawable.nextcloud) + authority == AUTHORITY_STORAGE && rootId == ROOT_ID_DEVICE -> { + context.getDrawable(R.drawable.ic_phone_android) + } + authority == AUTHORITY_STORAGE && rootId != ROOT_ID_HOME -> { + context.getDrawable(R.drawable.ic_usb) + } + authority == AUTHORITY_NEXTCLOUD -> { + context.getDrawable(R.drawable.nextcloud) + } else -> null } } diff --git a/app/src/sharedTest/java/com/stevesoltys/seedvault/crypto/KeyManagerTestImpl.kt b/app/src/sharedTest/java/com/stevesoltys/seedvault/crypto/KeyManagerTestImpl.kt index e787f543..bce7f8a4 100644 --- a/app/src/sharedTest/java/com/stevesoltys/seedvault/crypto/KeyManagerTestImpl.kt +++ b/app/src/sharedTest/java/com/stevesoltys/seedvault/crypto/KeyManagerTestImpl.kt @@ -23,4 +23,4 @@ class KeyManagerTestImpl : KeyManager { return key } -} \ No newline at end of file +} diff --git a/app/src/test/java/com/stevesoltys/seedvault/crypto/WordListTest.kt b/app/src/test/java/com/stevesoltys/seedvault/crypto/WordListTest.kt index 7e835eab..58c771d3 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/crypto/WordListTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/crypto/WordListTest.kt @@ -2090,31 +2090,36 @@ class WordListTest { @Suppress("MaxLineLength") fun `12 words generate expected seed`() { assertEquals( - "64AA8C388EC0F3A13C7E51653BC766E30668D30952AB34381C4B174BF3278774B4EE43D0BA08BCBCE0D0B806DEB7AA364A83525C34847078B2A8002A3E116066", + "64AA8C388EC0F3A13C7E51653BC766E30668D30952AB34381C4B174BF3278774" + + "B4EE43D0BA08BCBCE0D0B806DEB7AA364A83525C34847078B2A8002A3E116066", SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed( "write wrong yard year yellow you young youth zebra zero zone zoo", "" ).toHexString("") ) assertEquals( - "E911FAA42F389AA9F6D5A40B2ECB876B06D6D1FFBD5885C54720398EB11918CAB8F7BAD70FD5BE39BEB4EB065610700D1CFF1D4BFAA26F998357E15E79002779", + "E911FAA42F389AA9F6D5A40B2ECB876B06D6D1FFBD5885C54720398EB11918CA" + + "B8F7BAD70FD5BE39BEB4EB065610700D1CFF1D4BFAA26F998357E15E79002779", SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed( "matrix lava they brand negative spray floor gym purity picture ritual disorder", "" ).toHexString("") ) assertEquals( - "DDB26091680CF30D0DC615546E4612327DB287B6B2B8B8947A3E12580315D38C3BF7DD0EB4E9E50B10A41925332E0C8ED43C80DBA29281EF331A1DFA858BF1C9", + "DDB26091680CF30D0DC615546E4612327DB287B6B2B8B8947A3E12580315D38C" + + "3BF7DD0EB4E9E50B10A41925332E0C8ED43C80DBA29281EF331A1DFA858BF1C9", SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed( "middle rack south alert ribbon tube hope involve defy oxygen gloom rabbit", "" ).toHexString("") ) assertEquals( - "4815B580D0DCDA08334C92B3CB9A8436CD581C55841FB2794FB1E3D6E389F447C8C6520B2FE567720950F5B39BE7EC42C0BC98D3C63F8FEF642B5BD3EE4CDD7B", + "4815B580D0DCDA08334C92B3CB9A8436CD581C55841FB2794FB1E3D6E389F447" + + "C8C6520B2FE567720950F5B39BE7EC42C0BC98D3C63F8FEF642B5BD3EE4CDD7B", SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed( "interest mask trial hold foot segment fade page monitor apple garden shuffle", "" ).toHexString("") ) assertEquals( - "FF462543D8FB9DAE6C17FA7BA047238664207FCC797D6688E10DD1B3CFD183D4928AD088E8287B69BABCAEB0F87A2DFF2ADD49A7FDB7EB2554D7344F09C41A76", + "FF462543D8FB9DAE6C17FA7BA047238664207FCC797D6688E10DD1B3CFD183D4" + + "928AD088E8287B69BABCAEB0F87A2DFF2ADD49A7FDB7EB2554D7344F09C41A76", SeedCalculator(JavaxPBKDF2WithHmacSHA512.INSTANCE).calculateSeed( "palace glory gospel garment obscure person edge total hunt fix setup uphold\n", "" ).toHexString("") diff --git a/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataReaderTest.kt b/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataReaderTest.kt index 990a0a67..a49e9f0d 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataReaderTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataReaderTest.kt @@ -160,7 +160,9 @@ class MetadataReaderTest { assertNull(packageMetadata.signatures) } - private fun getMetadata(packageMetadata: PackageMetadataMap = PackageMetadataMap()): BackupMetadata { + private fun getMetadata( + packageMetadata: PackageMetadataMap = PackageMetadataMap() + ): BackupMetadata { return BackupMetadata( version = 1.toByte(), token = Random.nextLong(), diff --git a/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataWriterDecoderTest.kt b/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataWriterDecoderTest.kt index 813832b0..865249e7 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataWriterDecoderTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/metadata/MetadataWriterDecoderTest.kt @@ -110,7 +110,9 @@ internal class MetadataWriterDecoderTest { ) } - private fun getMetadata(packageMetadata: HashMap<String, PackageMetadata> = HashMap()): BackupMetadata { + private fun getMetadata( + packageMetadata: HashMap<String, PackageMetadata> = HashMap() + ): BackupMetadata { return BackupMetadata( version = Random.nextBytes(1)[0], token = Random.nextLong(), diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/ApkBackupTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/ApkBackupTest.kt index d34bbaa0..96ffce05 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/ApkBackupTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/ApkBackupTest.kt @@ -32,7 +32,6 @@ import java.io.OutputStream import java.nio.file.Path import kotlin.random.Random - @Suppress("BlockingMethodInNonBlockingContext") internal class ApkBackupTest : BackupTest() { @@ -104,7 +103,9 @@ internal class ApkBackupTest : BackupTest() { @Test fun `do not accept empty signature`() = runBlocking { every { settingsManager.backupApks() } returns true - every { metadataManager.getPackageMetadata(packageInfo.packageName) } returns packageMetadata + every { + metadataManager.getPackageMetadata(packageInfo.packageName) + } returns packageMetadata every { sigInfo.hasMultipleSigners() } returns false every { sigInfo.signingCertificateHistory } returns emptyArray() @@ -151,7 +152,9 @@ internal class ApkBackupTest : BackupTest() { private fun expectChecks(packageMetadata: PackageMetadata = this.packageMetadata) { every { settingsManager.backupApks() } returns true - every { metadataManager.getPackageMetadata(packageInfo.packageName) } returns packageMetadata + every { + metadataManager.getPackageMetadata(packageInfo.packageName) + } returns packageMetadata every { PackageUtils.computeSha256DigestBytes(signatureBytes) } returns signatureHash every { sigInfo.hasMultipleSigners() } returns false every { sigInfo.signingCertificateHistory } returns sigs diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt index b59000b2..fcf8a4af 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/backup/BackupCoordinatorTest.kt @@ -246,7 +246,9 @@ internal class BackupCoordinatorTest : BackupTest() { coEvery { full.performFullBackup(packageInfo, fileDescriptor, 0) } returns TRANSPORT_OK expectApkBackupAndMetadataWrite() every { full.getQuota() } returns DEFAULT_QUOTA_FULL_BACKUP - every { full.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1) } returns TRANSPORT_QUOTA_EXCEEDED + every { + full.checkFullBackupSize(DEFAULT_QUOTA_FULL_BACKUP + 1) + } returns TRANSPORT_QUOTA_EXCEEDED every { full.getCurrentPackage() } returns packageInfo every { metadataManager.onPackageBackupError( @@ -347,7 +349,9 @@ internal class BackupCoordinatorTest : BackupTest() { apkBackup.backupApkIfNecessary(notAllowedPackages[0], NOT_ALLOWED, any()) } returns null // check old metadata for state changes, because we won't update it otherwise - every { metadataManager.getPackageMetadata(notAllowedPackages[0].packageName) } returns packageMetadata + every { + metadataManager.getPackageMetadata(notAllowedPackages[0].packageName) + } returns packageMetadata every { packageMetadata.state } returns NOT_ALLOWED // no change // update notification for second package @@ -386,10 +390,15 @@ internal class BackupCoordinatorTest : BackupTest() { val oldPackageMetadata: PackageMetadata = mockk() every { packageService.notAllowedPackages } returns listOf(packageInfo) - every { notificationManager.onOptOutAppBackup(packageInfo.packageName, 1, 1) } just Runs + every { + notificationManager.onOptOutAppBackup(packageInfo.packageName, 1, 1) + } just Runs coEvery { apkBackup.backupApkIfNecessary(packageInfo, NOT_ALLOWED, any()) } returns null - every { metadataManager.getPackageMetadata(packageInfo.packageName) } returns oldPackageMetadata - every { oldPackageMetadata.state } returns WAS_STOPPED // state differs now, was stopped before + every { + metadataManager.getPackageMetadata(packageInfo.packageName) + } returns oldPackageMetadata + // state differs now, was stopped before + every { oldPackageMetadata.state } returns WAS_STOPPED coEvery { plugin.getMetadataOutputStream() } returns metadataOutputStream every { metadataManager.onPackageBackupError( diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/restore/ApkRestoreTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/restore/ApkRestoreTest.kt index 69d03b85..29b5b6db 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/restore/ApkRestoreTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/restore/ApkRestoreTest.kt @@ -215,7 +215,7 @@ internal class ApkRestoreTest : RestoreTest() { } @Test - fun `test system apps only get reinstalled when older system apps exist`(@TempDir tmpDir: Path) = + fun `test system apps only reinstalled when older system apps exist`(@TempDir tmpDir: Path) = runBlocking { val packageMetadata = this@ApkRestoreTest.packageMetadata.copy(system = true) packageMetadataMap[packageName] = packageMetadata diff --git a/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt b/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt index 6647994a..5270794b 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/transport/restore/RestoreCoordinatorTest.kt @@ -165,7 +165,7 @@ internal class RestoreCoordinatorTest : TransportTest() { } @Test - fun `startRestore() optimized auto-restore with removed storage but no backup shows no notification`() { + fun `startRestore() with removed storage shows no notification`() { every { settingsManager.getStorage() } returns storage every { storage.isUsb } returns true every { storage.getDocumentFile(context) } returns documentFile