Re-initialize backup location when changing recovery code

* delete all storage backups for current user
* clears the storage backup cache
* start a new app data restore set and initializes it

The reason is that old backups won't be readable anymore with the new key. We also can't delete other backups safely as we did before, because we can't be sure that they don't belong to a different device or user.
diff --git a/app/src/main/java/com/stevesoltys/seedvault/App.kt b/app/src/main/java/com/stevesoltys/seedvault/App.kt
index 6aaeeb2..a443b3b 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/App.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/App.kt
@@ -46,7 +46,7 @@
         factory { AppListRetriever(this@App, get(), get(), get()) }
 
         viewModel { SettingsViewModel(this@App, get(), get(), get(), get(), get(), get()) }
-        viewModel { RecoveryCodeViewModel(this@App, get(), get(), get()) }
+        viewModel { RecoveryCodeViewModel(this@App, get(), get(), get(), get(), get()) }
         viewModel { BackupStorageViewModel(this@App, get(), get(), get(), get()) }
         viewModel { RestoreStorageViewModel(this@App, get(), get()) }
         viewModel { RestoreViewModel(this@App, get(), get(), get(), get(), get(), get()) }
diff --git a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt
index 9789b43..c71d450 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/plugins/saf/DocumentsProviderBackupPlugin.kt
@@ -45,11 +45,6 @@
     }
 
     @Throws(IOException::class)
-    override suspend fun deleteAllBackups() {
-        storage.rootBackupDir?.deleteContents(context)
-    }
-
-    @Throws(IOException::class)
     override suspend fun getMetadataOutputStream(): OutputStream {
         val setDir = storage.getSetDir() ?: throw IOException()
         val metadataFile = setDir.createOrGetFile(context, FILE_BACKUP_METADATA)
diff --git a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt
index 5a08a63..f867250 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/transport/backup/BackupPlugin.kt
@@ -26,12 +26,6 @@
     suspend fun initializeDevice()
 
     /**
-     * Delete all existing [RestoreSet]s from the storage medium.
-     */
-    @Throws(IOException::class)
-    suspend fun deleteAllBackups()
-
-    /**
      * Returns an [OutputStream] for writing backup metadata.
      */
     @Throws(IOException::class)
diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt
index 1bde12c..4b707b8 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeInputFragment.kt
@@ -192,7 +192,7 @@
 
     private val regenRequest = registerForActivityResult(StartActivityForResult()) {
         if (it.resultCode == RESULT_OK) {
-            viewModel.deleteAllBackup()
+            viewModel.reinitializeBackupLocation()
             parentFragmentManager.popBackStack()
             Snackbar.make(requireView(), R.string.recovery_code_recreated, Snackbar.LENGTH_LONG)
                 .show()
diff --git a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt
index c306947..3b8c617 100644
--- a/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt
+++ b/app/src/main/java/com/stevesoltys/seedvault/ui/recoverycode/RecoveryCodeViewModel.kt
@@ -1,11 +1,14 @@
 package com.stevesoltys.seedvault.ui.recoverycode
 
+import android.app.backup.IBackupManager
+import android.os.UserHandle
 import android.util.Log
 import androidx.lifecycle.AndroidViewModel
 import com.stevesoltys.seedvault.App
 import com.stevesoltys.seedvault.crypto.Crypto
 import com.stevesoltys.seedvault.crypto.KeyManager
-import com.stevesoltys.seedvault.transport.backup.BackupPlugin
+import com.stevesoltys.seedvault.transport.TRANSPORT_ID
+import com.stevesoltys.seedvault.transport.backup.BackupCoordinator
 import com.stevesoltys.seedvault.ui.LiveEvent
 import com.stevesoltys.seedvault.ui.MutableLiveEvent
 import io.github.novacrypto.bip39.JavaxPBKDF2WithHmacSHA512
@@ -21,6 +24,7 @@
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.launch
+import org.calyxos.backup.storage.api.StorageBackup
 import java.io.IOException
 import java.security.SecureRandom
 import java.util.ArrayList
@@ -28,11 +32,15 @@
 internal const val WORD_NUM = 12
 internal const val WORD_LIST_SIZE = 2048
 
-class RecoveryCodeViewModel(
+private val TAG = RecoveryCodeViewModel::class.java.simpleName
+
+internal class RecoveryCodeViewModel(
     app: App,
     private val crypto: Crypto,
     private val keyManager: KeyManager,
-    private val backupPlugin: BackupPlugin
+    private val backupManager: IBackupManager,
+    private val backupCoordinator: BackupCoordinator,
+    private val storageBackup: StorageBackup
 ) : AndroidViewModel(app) {
 
     internal val wordList: List<CharSequence> by lazy {
@@ -79,12 +87,32 @@
         }
     }
 
-    fun deleteAllBackup() {
+    /**
+     * Deletes all storage backups for current user and clears the storage backup cache.
+     * Also starts a new app data restore set and initializes it.
+     *
+     * The reason is that old backups won't be readable anymore with the new key.
+     * We can't delete other backups safely, because we can't be sure
+     * that they don't belong to a different device or user.
+     */
+    fun reinitializeBackupLocation() {
+        Log.d(TAG, "Re-initializing backup location...")
         GlobalScope.launch(Dispatchers.IO) {
+            // remove old storage snapshots and clear cache
+            storageBackup.deleteAllSnapshots()
+            storageBackup.clearCache()
             try {
-                backupPlugin.deleteAllBackups()
+                // will also generate a new backup token for the new restore set
+                backupCoordinator.startNewRestoreSet()
+
+                // initialize the new location
+                backupManager.initializeTransportsForUser(
+                    UserHandle.myUserId(),
+                    arrayOf(TRANSPORT_ID),
+                    null
+                )
             } catch (e: IOException) {
-                Log.e("RecoveryCodeViewModel", "Error deleting backups", e)
+                Log.e(TAG, "Error starting new RestoreSet", e)
             }
         }
     }