Exclude storage provider from restore and update affected unit tests,

additionally adding a test to ensure the storage provider is excluded.

Otherwise, when the storage provider (i.e. DAVx5 or Nextcloud) is installed,
it will be terminated, and the restoration process will be interrupted.

Change-Id: Ic1be201b673d718b416009ff61f5d975c89b6a62
This commit is contained in:
t-m-w 2022-06-30 22:48:14 +00:00
parent 976e898656
commit 7901aec408
4 changed files with 39 additions and 1 deletions

View file

@ -41,7 +41,12 @@ internal class ApkRestore(
@Suppress("BlockingMethodInNonBlockingContext")
fun restore(backup: RestorableBackup) = flow {
// filter out packages without APK and get total
val packages = backup.packageMetadataMap.filter { it.value.hasApk() }
val packages = backup.packageMetadataMap.filter {
// We also need to exclude the DocumentsProvider used to retrieve backup data.
// Otherwise, it gets killed when we install it, terminating our restoration.
val isStorageProvider = it.key == storagePlugin.providerPackageName
it.value.hasApk() && !isStorageProvider
}
val total = packages.size
var progress = 0

View file

@ -118,6 +118,7 @@ internal class ApkBackupRestoreTest : TransportTest() {
every { metadataManager.salt } returns salt
every { crypto.getNameForApk(salt, packageName) } returns name
every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkBackup.backupApkIfNecessary(packageInfo, PackageState.APK_AND_DATA, outputStreamGetter)

View file

@ -97,6 +97,7 @@ internal class ApkRestoreTest : TransportTest() {
every { strictContext.cacheDir } returns File(tmpDir.toString())
every { crypto.getNameForApk(salt, packageName, "") } returns name
coEvery { storagePlugin.getInputStream(token, name) } returns apkInputStream
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedFailFinished(i, value)
@ -112,6 +113,7 @@ internal class ApkRestoreTest : TransportTest() {
every { crypto.getNameForApk(salt, packageName, "") } returns name
coEvery { storagePlugin.getInputStream(token, name) } returns apkInputStream
every { pm.getPackageArchiveInfo(any(), any()) } returns packageInfo
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedFailFinished(i, value)
@ -124,6 +126,7 @@ internal class ApkRestoreTest : TransportTest() {
coEvery {
apkInstaller.install(match { it.size == 1 }, packageName, installerName, any())
} throws SecurityException()
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressFailFinished(i, value)
@ -146,6 +149,7 @@ internal class ApkRestoreTest : TransportTest() {
coEvery {
apkInstaller.install(match { it.size == 1 }, packageName, installerName, any())
} returns installResult
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressSuccessFinished(i, value)
@ -184,6 +188,7 @@ internal class ApkRestoreTest : TransportTest() {
coEvery {
apkInstaller.install(match { it.size == 1 }, packageName, installerName, any())
} returns installResult
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressSuccessFinished(i, value)
@ -202,6 +207,7 @@ internal class ApkRestoreTest : TransportTest() {
cacheBaseApkAndGetInfo(tmpDir)
every { packageInfo.applicationInfo.loadIcon(pm) } returns icon
every { storagePlugin.providerPackageName } returns storageProviderPackageName
if (willFail) {
every {
@ -281,6 +287,7 @@ internal class ApkRestoreTest : TransportTest() {
every {
splitCompatChecker.isCompatible(deviceName, listOf(split1Name, split2Name))
} returns false
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressFailFinished(i, value)
@ -303,6 +310,7 @@ internal class ApkRestoreTest : TransportTest() {
coEvery {
storagePlugin.getInputStream(token, suffixName)
} returns ByteArrayInputStream(getRandomByteArray())
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressFailFinished(i, value)
@ -325,6 +333,7 @@ internal class ApkRestoreTest : TransportTest() {
every { splitCompatChecker.isCompatible(deviceName, listOf(splitName)) } returns true
every { crypto.getNameForApk(salt, packageName, splitName) } returns suffixName
coEvery { storagePlugin.getInputStream(token, suffixName) } throws IOException()
every { storagePlugin.providerPackageName } returns storageProviderPackageName
apkRestore.restore(backup).collectIndexed { i, value ->
assertQueuedProgressFailFinished(i, value)
@ -363,6 +372,7 @@ internal class ApkRestoreTest : TransportTest() {
coEvery { storagePlugin.getInputStream(token, suffixName1) } returns split1InputStream
every { crypto.getNameForApk(salt, packageName, split2Name) } returns suffixName2
coEvery { storagePlugin.getInputStream(token, suffixName2) } returns split2InputStream
every { storagePlugin.providerPackageName } returns storageProviderPackageName
coEvery {
apkInstaller.install(match { it.size == 3 }, packageName, installerName, any())
@ -381,6 +391,27 @@ internal class ApkRestoreTest : TransportTest() {
}
}
@Test
fun `storage provider app does not get reinstalled`(@TempDir tmpDir: Path) = runBlocking {
// set the storage provider package name to match our current package name,
// and ensure that the current package is therefore skipped.
every { storagePlugin.providerPackageName } returns packageName
apkRestore.restore(backup).collectIndexed { i, value ->
when (i) {
0 -> {
assertFalse(value.isFinished)
}
1 -> {
// the only package provided should have been filtered, leaving 0 packages.
assertEquals(0, value.total)
assertTrue(value.isFinished)
}
else -> fail("more values emitted")
}
}
}
private fun swapPackages(packageMetadataMap: PackageMetadataMap): RestorableBackup {
val metadata = metadata.copy(packageMetadataMap = packageMetadataMap)
return backup.copy(backupMetadata = metadata)

View file

@ -61,6 +61,7 @@ internal abstract class TransportTest {
protected val salt = metadata.salt
protected val name = getRandomString(12)
protected val name2 = getRandomString(23)
protected val storageProviderPackageName = getRandomString(23)
init {
mockkStatic(Log::class)