feat(installer): sign apk in patcher worker

This commit is contained in:
Ax333l 2023-10-27 23:30:45 +02:00
parent 7d887c73e8
commit 172604fcdb
No known key found for this signature in database
GPG Key ID: D2B4D85271127D23
4 changed files with 36 additions and 35 deletions

View File

@ -26,7 +26,12 @@ class Step(
val state: State = State.WAITING
)
class PatcherProgressManager(context: Context, selectedPatches: List<String>, selectedApp: SelectedApp, downloadProgress: StateFlow<Pair<Float, Float>?>) {
class PatcherProgressManager(
context: Context,
selectedPatches: List<String>,
selectedApp: SelectedApp,
downloadProgress: StateFlow<Pair<Float, Float>?>
) {
val steps = generateSteps(context, selectedPatches, selectedApp, downloadProgress)
private var currentStep: StepKey? = StepKey(0, 0)
@ -87,12 +92,20 @@ class PatcherProgressManager(context: Context, selectedPatches: List<String>, se
selectedPatches.map { SubStep(it) }.toImmutableList()
)
fun generateSteps(context: Context, selectedPatches: List<String>, selectedApp: SelectedApp, downloadProgress: StateFlow<Pair<Float, Float>?>? = null) = mutableListOf(
fun generateSteps(
context: Context,
selectedPatches: List<String>,
selectedApp: SelectedApp,
downloadProgress: StateFlow<Pair<Float, Float>?>? = null
) = mutableListOf(
Step(
R.string.patcher_step_group_prepare,
listOfNotNull(
SubStep(context.getString(R.string.patcher_step_load_patches)),
SubStep("Download apk", progress = downloadProgress).takeIf { selectedApp is SelectedApp.Download },
SubStep(
"Download apk",
progress = downloadProgress
).takeIf { selectedApp is SelectedApp.Download },
SubStep(context.getString(R.string.patcher_step_unpack)),
SubStep(context.getString(R.string.patcher_step_integrations))
).toImmutableList()
@ -100,7 +113,10 @@ class PatcherProgressManager(context: Context, selectedPatches: List<String>, se
generatePatchesStep(selectedPatches),
Step(
R.string.patcher_step_group_saving,
persistentListOf(SubStep(context.getString(R.string.patcher_step_write_patched)))
persistentListOf(
SubStep(context.getString(R.string.patcher_step_write_patched)),
SubStep(context.getString(R.string.patcher_step_sign_apk))
)
)
)
}

View File

@ -19,6 +19,7 @@ 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.KeystoreManager
import app.revanced.manager.domain.manager.PreferencesManager
import app.revanced.manager.domain.repository.DownloadedAppRepository
import app.revanced.manager.domain.repository.InstalledAppRepository
@ -50,6 +51,7 @@ class PatcherWorker(
private val patchBundleRepository: PatchBundleRepository by inject()
private val workerRepository: WorkerRepository by inject()
private val prefs: PreferencesManager by inject()
private val keystoreManager: KeystoreManager by inject()
private val downloadedAppRepository: DownloadedAppRepository by inject()
private val pm: PM by inject()
private val fs: Filesystem by inject()
@ -159,6 +161,8 @@ class PatcherWorker(
progressFlow.value = progressManager.getProgress().toImmutableList()
}
val patchedApk = fs.tempDir.resolve("patched.apk")
return try {
if (args.input is SelectedApp.Installed) {
@ -219,9 +223,12 @@ class PatcherWorker(
inputFile,
onStepSucceeded = ::updateProgress
).use { session ->
session.run(File(args.output), patches, integrations)
session.run(patchedApk, patches, integrations)
}
keystoreManager.sign(patchedApk, File(args.output))
updateProgress() // Signing
Log.i(tag, "Patching succeeded".logFmt())
progressManager.success()
Result.success()
@ -231,6 +238,7 @@ class PatcherWorker(
Result.failure()
} finally {
updateProgress(false)
patchedApk.delete()
}
}
}

View File

@ -24,7 +24,6 @@ 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
import app.revanced.manager.domain.manager.KeystoreManager
import app.revanced.manager.domain.repository.InstalledAppRepository
import app.revanced.manager.domain.worker.WorkerRepository
import app.revanced.manager.patcher.worker.PatcherProgressManager
@ -57,7 +56,6 @@ import java.util.logging.LogRecord
class InstallerViewModel(
private val input: Destination.Installer
) : 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()
@ -72,8 +70,6 @@ class InstallerViewModel(
}
private val outputFile = tempDir.resolve("output.apk")
private val signedFile = tempDir.resolve("signed.apk")
private var hasSigned = false
private var inputFile: File? = null
private var installedApp: InstalledApp? = null
@ -209,42 +205,22 @@ class InstallerViewModel(
tempDir.deleteRecursively()
}
private suspend fun signApk(): Boolean {
if (!hasSigned) {
try {
withContext(Dispatchers.Default) {
keystoreManager.sign(outputFile, signedFile)
}
} catch (e: Exception) {
Log.e(tag, "Got exception while signing", e)
app.toast(app.getString(R.string.sign_fail, e::class.simpleName))
return false
}
}
return true
}
fun export(uri: Uri?) = viewModelScope.launch {
uri?.let {
if (signApk()) {
withContext(Dispatchers.IO) {
app.contentResolver.openOutputStream(it)
.use { stream -> Files.copy(signedFile.toPath(), stream) }
}
app.toast(app.getString(R.string.export_app_success))
withContext(Dispatchers.IO) {
app.contentResolver.openOutputStream(it)
.use { stream -> Files.copy(outputFile.toPath(), stream) }
}
app.toast(app.getString(R.string.export_app_success))
}
}
fun install(installType: InstallType) = viewModelScope.launch {
isInstalling = true
try {
if (!signApk()) return@launch
when (installType) {
InstallType.DEFAULT -> {
pm.installApp(listOf(signedFile))
pm.installApp(listOf(outputFile))
}
InstallType.ROOT -> {
@ -262,7 +238,7 @@ class InstallerViewModel(
private suspend fun installAsRoot() {
try {
val label = with(pm) {
getPackageInfo(signedFile)?.label()
getPackageInfo(outputFile)?.label()
?: throw Exception("Failed to load application info")
}

View File

@ -235,6 +235,7 @@
<string name="patcher_step_group_patching">Patching</string>
<string name="patcher_step_group_saving">Saving</string>
<string name="patcher_step_write_patched">Write patched Apk</string>
<string name="patcher_step_sign_apk">Sign Apk</string>
<string name="patcher_notification_message">Patching in progress…</string>
<string name="step_completed">completed</string>