fix: delete temporary files (#1341)

This commit is contained in:
Ax333l 2023-10-07 16:09:02 +02:00 committed by GitHub
parent abf4d91703
commit 723f9cd98c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 66 additions and 33 deletions

View File

@ -9,9 +9,18 @@ import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts
import app.revanced.manager.util.RequestManageStorageContract
class FileSystem(private val app: Application) {
class Filesystem(private val app: Application) {
val contentResolver = app.contentResolver // TODO: move Content Resolver operations to here.
/**
* A directory that gets cleared when the app restarts.
* Do not store paths to this directory in a parcel.
*/
val tempDir = app.cacheDir.resolve("ephemeral").apply {
deleteRecursively()
mkdirs()
}
fun externalFilesDir() = Environment.getExternalStorageDirectory().toPath()
private fun usesManagePermission() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R

View File

@ -1,17 +1,20 @@
package app.revanced.manager.di
import app.revanced.manager.data.platform.FileSystem
import app.revanced.manager.data.platform.Filesystem
import app.revanced.manager.data.platform.NetworkInfo
import app.revanced.manager.domain.repository.*
import app.revanced.manager.domain.worker.WorkerRepository
import app.revanced.manager.network.api.ReVancedAPI
import org.koin.core.module.dsl.createdAtStart
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
val repositoryModule = module {
singleOf(::ReVancedAPI)
singleOf(::GithubRepository)
singleOf(::FileSystem)
singleOf(::Filesystem) {
createdAtStart()
}
singleOf(::NetworkInfo)
singleOf(::PatchBundlePersistenceRepository)
singleOf(::PatchSelectionRepository)

View File

@ -24,16 +24,17 @@ class Session(
private val input: File,
private val onStepSucceeded: suspend () -> Unit
) : Closeable {
private val temporary = File(cacheDir).resolve("manager").also { it.mkdirs() }
private val tempDir = File(cacheDir).resolve("patcher").also { it.mkdirs() }
private val patcher = Patcher(
PatcherOptions(
inputFile = input,
resourceCachePath = temporary.resolve("aapt-resources"),
resourceCachePath = tempDir.resolve("aapt-resources"),
frameworkFileDirectory = frameworkDir,
aaptBinaryPath = aaptPath
)
)
private suspend fun Patcher.applyPatchesVerbose() {
this.apply(true).collect { (patch, exception) ->
if (exception == null) {
@ -70,7 +71,7 @@ class Session(
logger.info("Writing patched files...")
val result = patcher.get()
val aligned = temporary.resolve("aligned.apk")
val aligned = tempDir.resolve("aligned.apk")
ApkUtils.copyAligned(input, aligned, result)
logger.info("Patched apk saved to $aligned")
@ -82,7 +83,7 @@ class Session(
}
override fun close() {
temporary.delete()
tempDir.deleteRecursively()
patcher.close()
}

View File

@ -14,6 +14,7 @@ import androidx.core.content.ContextCompat
import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
import app.revanced.manager.R
import app.revanced.manager.data.platform.Filesystem
import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.domain.installer.RootInstaller
import app.revanced.manager.domain.manager.PreferencesManager
@ -49,6 +50,7 @@ class PatcherWorker(
private val prefs: PreferencesManager by inject()
private val downloadedAppRepository: DownloadedAppRepository by inject()
private val pm: PM by inject()
private val fs: Filesystem by inject()
private val installedAppRepository: InstalledAppRepository by inject()
private val rootInstaller: RootInstaller by inject()
@ -57,13 +59,12 @@ class PatcherWorker(
val output: String,
val selectedPatches: PatchesSelection,
val options: Options,
val packageName: String,
val packageVersion: String,
val progress: MutableStateFlow<ImmutableList<Step>>,
val logger: ManagerLogger,
val selectedApp: SelectedApp,
val setInputFile: (File) -> Unit
)
) {
val packageName get() = input.packageName
}
companion object {
private const val logPrefix = "[Worker]:"
@ -153,7 +154,7 @@ class PatcherWorker(
return try {
if (args.selectedApp is SelectedApp.Installed) {
if (args.input is SelectedApp.Installed) {
installedAppRepository.get(args.packageName)?.let {
if (it.installType == InstallType.ROOT) {
rootInstaller.unmount(args.packageName)
@ -212,7 +213,7 @@ class PatcherWorker(
}
Session(
applicationContext.cacheDir.absolutePath,
fs.tempDir.absolutePath,
frameworkPath,
aaptPath,
args.logger,

View File

@ -26,7 +26,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.data.platform.FileSystem
import app.revanced.manager.data.platform.Filesystem
import app.revanced.manager.patcher.patch.Option
import app.revanced.manager.util.toast
import app.revanced.patcher.patch.options.types.*
@ -61,7 +61,7 @@ private fun StringOptionDialog(
mutableStateOf(value.orEmpty())
}
val fs: FileSystem = rememberKoinInject()
val fs: Filesystem = rememberKoinInject()
val (contract, permissionName) = fs.permissionContract()
val permissionLauncher = rememberLauncherForActivityResult(contract = contract) {
showFileDialog = it

View File

@ -13,7 +13,7 @@ sealed class SelectedApp : Parcelable {
data class Download(override val packageName: String, override val version: String, val app: AppDownloader.App) : SelectedApp()
@Parcelize
data class Local(override val packageName: String, override val version: String, val file: File) : SelectedApp()
data class Local(override val packageName: String, override val version: String, val file: File, val shouldDelete: Boolean) : SelectedApp()
@Parcelize
data class Installed(override val packageName: String, override val version: String) : SelectedApp()

View File

@ -13,20 +13,27 @@ class AppSelectorViewModel(
private val app: Application,
private val pm: PM
) : ViewModel() {
private val inputFile = File(app.cacheDir, "input.apk").also {
it.delete()
}
val appList = pm.appList
fun loadLabel(app: PackageInfo?) = with(pm) { app?.label() ?: "Not installed" }
fun loadSelectedFile(uri: Uri) =
app.contentResolver.openInputStream(uri)?.use { stream ->
File(app.cacheDir, "input.apk").also {
it.delete()
Files.copy(stream, it.toPath())
}.let { file ->
pm.getPackageInfo(file)
?.let { packageInfo ->
SelectedApp.Local(packageName = packageInfo.packageName, version = packageInfo.versionName, file = file)
}
with(inputFile) {
delete()
Files.copy(stream, toPath())
pm.getPackageInfo(this)?.let { packageInfo ->
SelectedApp.Local(
packageName = packageInfo.packageName,
version = packageInfo.versionName,
file = this,
shouldDelete = true
)
}
}
}
}

View File

@ -19,6 +19,7 @@ import androidx.lifecycle.viewModelScope
import androidx.work.WorkInfo
import androidx.work.WorkManager
import app.revanced.manager.R
import app.revanced.manager.data.platform.Filesystem
import app.revanced.manager.data.room.apps.installed.InstallType
import app.revanced.manager.data.room.apps.installed.InstalledApp
import app.revanced.manager.domain.installer.RootInstaller
@ -57,16 +58,22 @@ class InstallerViewModel(
) : ViewModel(), KoinComponent {
private val keystoreManager: KeystoreManager by inject()
private val app: Application by inject()
private val fs: Filesystem by inject()
private val pm: PM by inject()
private val workerRepository: WorkerRepository by inject()
private val installedAppRepository: InstalledAppRepository by inject()
private val rootInstaller: RootInstaller by inject()
val packageName: String = input.selectedApp.packageName
private val outputFile = File(app.cacheDir, "output.apk")
private val signedFile = File(app.cacheDir, "signed.apk").also { if (it.exists()) it.delete() }
private val tempDir = fs.tempDir.resolve("installer").also {
it.deleteRecursively()
it.mkdirs()
}
private val outputFile = tempDir.resolve("output.apk")
private val signedFile = tempDir.resolve("signed.apk")
private var hasSigned = false
var inputFile: File? = null
private var inputFile: File? = null
private var installedApp: InstalledApp? = null
var isInstalling by mutableStateOf(false)
@ -82,6 +89,8 @@ class InstallerViewModel(
private val logger = ManagerLogger()
init {
// TODO: navigate away when system-initiated process death is detected because it is not possible to recover from it.
viewModelScope.launch {
installedApp = installedAppRepository.get(packageName)
}
@ -101,11 +110,8 @@ class InstallerViewModel(
outputFile.path,
patches,
options,
packageName,
selectedApp.version,
_progress,
logger,
selectedApp,
setInputFile = { inputFile = it }
)
)
@ -176,8 +182,14 @@ class InstallerViewModel(
app.unregisterReceiver(installBroadcastReceiver)
workManager.cancelWorkById(patcherWorkerId)
outputFile.delete()
signedFile.delete()
when (val selectedApp = input.selectedApp) {
is SelectedApp.Local -> {
if (selectedApp.shouldDelete) selectedApp.file.delete()
}
else -> {}
}
tempDir.deleteRecursively()
try {
if (input.selectedApp is SelectedApp.Installed) {

View File

@ -68,7 +68,7 @@ class VersionSelectorViewModel(
}
val downloadedVersions = downloadedAppRepository.getAll().map { downloadedApps ->
downloadedApps.filter { it.packageName == packageName }.map { SelectedApp.Local(it.packageName, it.version, it.file) }
downloadedApps.filter { it.packageName == packageName }.map { SelectedApp.Local(it.packageName, it.version, it.file, false) }
}
init {