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