Skip to content

Commit

Permalink
Try to recover data for force stopped apps from latest snapshot
Browse files Browse the repository at this point in the history
The system doesn't allow us to backup forced stopped apps, but if we had data for them once, we can at least carry it along.
  • Loading branch information
grote committed Oct 3, 2024
1 parent e1bd772 commit e0bcc1e
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ internal class SnapshotCreator(
* If we do *not* have data for the given [packageName],
* we try to extract data from the given [snapshot] (ideally we latest we have) and
* add it to the current snapshot under construction.
*
* @param warnNoData log a warning, if [snapshot] had no data for the given [packageName].
*/
fun onNoDataInCurrentRun(snapshot: Snapshot, packageName: String) {
fun onNoDataInCurrentRun(snapshot: Snapshot, packageName: String, warnNoData: Boolean = true) {
log.info { "onKvPackageNotChanged(${snapshot.token}, $packageName)" }

if (appBuilderMap.containsKey(packageName)) {
Expand All @@ -125,7 +127,9 @@ internal class SnapshotCreator(
}
val app = snapshot.appsMap[packageName]
if (app == null) {
log.error { " No changed data for $packageName, but we had no data for it" }
if (warnNoData) log.error {
" No changed data for $packageName, but we had no data for it"
}
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.util.Log
import com.stevesoltys.seedvault.metadata.MetadataManager
import com.stevesoltys.seedvault.metadata.PackageState.NOT_ALLOWED
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
import com.stevesoltys.seedvault.repo.AppBackupManager
import com.stevesoltys.seedvault.repo.SnapshotManager
import com.stevesoltys.seedvault.settings.SettingsManager
import com.stevesoltys.seedvault.transport.backup.PackageService
Expand All @@ -22,6 +23,7 @@ import java.io.IOException

internal class ApkBackupManager(
private val context: Context,
private val appBackupManager: AppBackupManager,
private val settingsManager: SettingsManager,
private val snapshotManager: SnapshotManager,
private val metadataManager: MetadataManager,
Expand Down Expand Up @@ -84,6 +86,15 @@ internal class ApkBackupManager(
} catch (e: IOException) {
Log.e(TAG, "Error storing new metadata for $packageName: ", e)
}
// see if there's data in latest snapshot for this app and re-use it
// this can be helpful for backing up recently STOPPED apps
snapshotManager.latestSnapshot?.let { snapshot ->
appBackupManager.snapshotCreator?.onNoDataInCurrentRun(
snapshot = snapshot,
packageName = packageName,
warnNoData = false,
)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ val workerModule = module {
single {
ApkBackupManager(
context = androidContext(),
appBackupManager = get(),
settingsManager = get(),
snapshotManager = get(),
metadataManager = get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import com.stevesoltys.seedvault.metadata.PackageMetadata
import com.stevesoltys.seedvault.metadata.PackageState.NOT_ALLOWED
import com.stevesoltys.seedvault.metadata.PackageState.UNKNOWN_ERROR
import com.stevesoltys.seedvault.metadata.PackageState.WAS_STOPPED
import com.stevesoltys.seedvault.repo.AppBackupManager
import com.stevesoltys.seedvault.repo.SnapshotCreator
import com.stevesoltys.seedvault.repo.SnapshotManager
import com.stevesoltys.seedvault.transport.TransportTest
import com.stevesoltys.seedvault.transport.backup.PackageService
Expand All @@ -33,6 +35,7 @@ import org.junit.jupiter.api.Test

internal class ApkBackupManagerTest : TransportTest() {

private val appBackupManager: AppBackupManager = mockk()
private val snapshotManager: SnapshotManager = mockk()
private val packageService: PackageService = mockk()
private val apkBackup: ApkBackup = mockk()
Expand All @@ -43,6 +46,7 @@ internal class ApkBackupManagerTest : TransportTest() {

private val apkBackupManager = ApkBackupManager(
context = context,
appBackupManager = appBackupManager,
settingsManager = settingsManager,
snapshotManager = snapshotManager,
metadataManager = metadataManager,
Expand All @@ -53,16 +57,20 @@ internal class ApkBackupManagerTest : TransportTest() {
)

private val packageMetadata: PackageMetadata = mockk()
private val snapshotCreator: SnapshotCreator = mockk()

init {
every { backendManager.backend } returns backend
every { appBackupManager.snapshotCreator } returns snapshotCreator
}

@Test
fun `Package state of app that is not stopped gets recorded as not-allowed`() = runBlocking {
every { nm.onAppsNotBackedUp() } just Runs
every { packageService.notBackedUpPackages } returns listOf(packageInfo)
every { settingsManager.isBackupEnabled(packageInfo.packageName) } returns true
every { snapshotManager.latestSnapshot } returns snapshot
every { snapshotCreator.onNoDataInCurrentRun(snapshot, packageName, false) } just Runs

expectUploadIcons()

Expand All @@ -87,6 +95,8 @@ internal class ApkBackupManagerTest : TransportTest() {
every { nm.onAppsNotBackedUp() } just Runs
every { packageService.notBackedUpPackages } returns listOf(packageInfo)
every { settingsManager.isBackupEnabled(packageInfo.packageName) } returns true
every { snapshotManager.latestSnapshot } returns snapshot
every { snapshotCreator.onNoDataInCurrentRun(snapshot, packageName, false) } just Runs

expectUploadIcons()

Expand Down Expand Up @@ -117,6 +127,8 @@ internal class ApkBackupManagerTest : TransportTest() {
every { nm.onAppsNotBackedUp() } just Runs
every { packageService.notBackedUpPackages } returns listOf(packageInfo)
every { settingsManager.isBackupEnabled(packageInfo.packageName) } returns true
every { snapshotManager.latestSnapshot } returns snapshot
every { snapshotCreator.onNoDataInCurrentRun(snapshot, packageName, false) } just Runs

expectUploadIcons()

Expand All @@ -141,6 +153,8 @@ internal class ApkBackupManagerTest : TransportTest() {
every { nm.onAppsNotBackedUp() } just Runs
every { packageService.notBackedUpPackages } returns listOf(packageInfo)
every { settingsManager.isBackupEnabled(packageInfo.packageName) } returns true
every { snapshotManager.latestSnapshot } returns snapshot
every { snapshotCreator.onNoDataInCurrentRun(snapshot, packageName, false) } just Runs

expectUploadIcons()

Expand Down Expand Up @@ -223,6 +237,8 @@ internal class ApkBackupManagerTest : TransportTest() {
every { nm.onAppsNotBackedUp() } just Runs
every { packageService.notBackedUpPackages } returns listOf(packageInfo)
every { settingsManager.isBackupEnabled(packageInfo.packageName) } returns true
every { snapshotManager.latestSnapshot } returns snapshot
every { snapshotCreator.onNoDataInCurrentRun(snapshot, packageName, false) } just Runs

expectUploadIcons()

Expand Down

0 comments on commit e0bcc1e

Please sign in to comment.