Always start a new RestoreSet when initializing the device
This avoids deleting the current backup when the user disables backups (or the system decides to do a random re-init).
This commit is contained in:
parent
bedba071df
commit
87a800438b
4 changed files with 19 additions and 37 deletions
|
@ -88,13 +88,16 @@ internal class BackupCoordinator(
|
|||
* Starts a new [RestoreSet] with a new token (the current unix epoch in milliseconds).
|
||||
* Call this at least once before calling [initializeDevice]
|
||||
* which must be called after this method to properly initialize the backup transport.
|
||||
*
|
||||
* @return the token of the new [RestoreSet].
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
suspend fun startNewRestoreSet() {
|
||||
private suspend fun startNewRestoreSet(): Long {
|
||||
val token = clock.time()
|
||||
Log.i(TAG, "Starting new RestoreSet with token $token...")
|
||||
settingsManager.setNewToken(token)
|
||||
plugin.startNewRestoreSet(token)
|
||||
return token
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,16 +119,14 @@ internal class BackupCoordinator(
|
|||
* [TRANSPORT_ERROR] (to retry following network error or other failure).
|
||||
*/
|
||||
suspend fun initializeDevice(): Int = try {
|
||||
val token = settingsManager.getToken()
|
||||
if (token == null) {
|
||||
Log.i(TAG, "No RestoreSet started, initialization is no-op.")
|
||||
} else {
|
||||
Log.i(TAG, "Initialize Device!")
|
||||
plugin.initializeDevice()
|
||||
Log.d(TAG, "Resetting backup metadata for token $token...")
|
||||
plugin.getMetadataOutputStream().use {
|
||||
metadataManager.onDeviceInitialization(token, it)
|
||||
}
|
||||
// we don't respect the intended system behavior here by always starting a new [RestoreSet]
|
||||
// instead of simply deleting the current one
|
||||
val token = startNewRestoreSet()
|
||||
Log.i(TAG, "Initialize Device!")
|
||||
plugin.initializeDevice()
|
||||
Log.d(TAG, "Resetting backup metadata for token $token...")
|
||||
plugin.getMetadataOutputStream(token).use {
|
||||
metadataManager.onDeviceInitialization(token, it)
|
||||
}
|
||||
// [finishBackup] will only be called when we return [TRANSPORT_OK] here
|
||||
// so we remember that we initialized successfully
|
||||
|
|
|
@ -107,9 +107,6 @@ internal class RecoveryCodeViewModel(
|
|||
storageBackup.deleteAllSnapshots()
|
||||
storageBackup.clearCache()
|
||||
try {
|
||||
// will also generate a new backup token for the new restore set
|
||||
backupCoordinator.startNewRestoreSet()
|
||||
|
||||
// initialize the new location
|
||||
if (backupManager.isBackupEnabled) backupManager.initializeTransportsForUser(
|
||||
UserHandle.myUserId(),
|
||||
|
|
|
@ -38,9 +38,6 @@ internal class BackupStorageViewModel(
|
|||
storageBackup.deleteAllSnapshots()
|
||||
storageBackup.clearCache()
|
||||
try {
|
||||
// will also generate a new backup token for the new restore set
|
||||
backupCoordinator.startNewRestoreSet()
|
||||
|
||||
// initialize the new location (if backups are enabled)
|
||||
if (backupManager.isBackupEnabled) backupManager.initializeTransportsForUser(
|
||||
UserHandle.myUserId(),
|
||||
|
|
|
@ -72,18 +72,9 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
requiresNetwork = false
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `starting a new restore set works as expected`() = runBlocking {
|
||||
every { clock.time() } returns token
|
||||
every { settingsManager.setNewToken(token) } just Runs
|
||||
coEvery { plugin.startNewRestoreSet(token) } just Runs
|
||||
|
||||
backup.startNewRestoreSet()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `device initialization succeeds and delegates to plugin`() = runBlocking {
|
||||
every { settingsManager.getToken() } returns token
|
||||
expectStartNewRestoreSet()
|
||||
coEvery { plugin.initializeDevice() } just Runs
|
||||
coEvery { plugin.getOutputStream(token, FILE_BACKUP_METADATA) } returns metadataOutputStream
|
||||
every { metadataManager.onDeviceInitialization(token, metadataOutputStream) } just Runs
|
||||
|
@ -97,21 +88,17 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
verify { metadataOutputStream.close() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `device initialization does no-op when no token available`() = runBlocking {
|
||||
every { settingsManager.getToken() } returns null
|
||||
every { kv.hasState() } returns false
|
||||
every { full.hasState() } returns false
|
||||
|
||||
assertEquals(TRANSPORT_OK, backup.initializeDevice())
|
||||
assertEquals(TRANSPORT_OK, backup.finishBackup())
|
||||
private suspend fun expectStartNewRestoreSet() {
|
||||
every { clock.time() } returns token
|
||||
every { settingsManager.setNewToken(token) } just Runs
|
||||
coEvery { plugin.startNewRestoreSet(token) } just Runs
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `error notification when device initialization fails`() = runBlocking {
|
||||
val maybeTrue = Random.nextBoolean()
|
||||
|
||||
every { settingsManager.getToken() } returns token
|
||||
expectStartNewRestoreSet()
|
||||
coEvery { plugin.initializeDevice() } throws IOException()
|
||||
every { metadataManager.requiresInit } returns maybeTrue
|
||||
every { settingsManager.canDoBackupNow() } returns !maybeTrue
|
||||
|
@ -130,7 +117,7 @@ internal class BackupCoordinatorTest : BackupTest() {
|
|||
@Test
|
||||
fun `no error notification when device initialization fails when no backup possible`() =
|
||||
runBlocking {
|
||||
every { settingsManager.getToken() } returns token
|
||||
expectStartNewRestoreSet()
|
||||
coEvery { plugin.initializeDevice() } throws IOException()
|
||||
every { metadataManager.requiresInit } returns false
|
||||
every { settingsManager.canDoBackupNow() } returns false
|
||||
|
|
Loading…
Reference in a new issue