From 1028ec8e2abc7367d10753f1a0471aa2ee622611 Mon Sep 17 00:00:00 2001 From: Alberto Ponces Date: Fri, 23 Sep 2022 00:38:42 +0100 Subject: [PATCH] fix: Prevent Manager from crashing when a patcher exception occurs and print its stack trace on installer's log --- .../revanced/manager/flutter/MainActivity.kt | 250 +++++++++--------- .../views/installer/installer_viewmodel.dart | 26 +- 2 files changed, 149 insertions(+), 127 deletions(-) diff --git a/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt b/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt index f7c6cc72..307170ba 100644 --- a/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt +++ b/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt @@ -74,7 +74,6 @@ class MainActivity : FlutterActivity() { result.notImplemented() } } - else -> result.notImplemented() } } @@ -101,161 +100,174 @@ class MainActivity : FlutterActivity() { val integrations = File(integrationsPath) val keyStoreFile = File(keyStoreFilePath) - val patches = DexPatchBundle( - patchBundleFilePath, - DexClassLoader( - patchBundleFilePath, - cacheDirPath, - null, - javaClass.classLoader - ) - ).loadPatches().filter { patch -> selectedPatches.any { it == patch.patchName } } - Thread { - handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.1, - "header" to "", - "log" to "Copying original apk" - ) - ) - } - originalFile.copyTo(inputFile, true) - - handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.2, - "header" to "Unpacking apk...", - "log" to "Unpacking input apk" - ) - ) - } - val patcher = - Patcher( - PatcherOptions( - inputFile, + try { + val patches = DexPatchBundle( + patchBundleFilePath, + DexClassLoader( + patchBundleFilePath, cacheDirPath, - resourcePatching, - Aapt.binary(applicationContext).absolutePath, - cacheDirPath, - logger = ManagerLogger() + null, + javaClass.classLoader ) - ) - - handler.post { - installerChannel.invokeMethod( - "update", - mapOf("progress" to 0.3, "header" to "", "log" to "") - ) - } - if (mergeIntegrations) { + ).loadPatches().filter { patch -> selectedPatches.any { it == patch.patchName } } + handler.post { installerChannel.invokeMethod( "update", mapOf( - "progress" to 0.4, - "header" to "Merging integrations...", - "log" to "Merging integrations" + "progress" to 0.1, + "header" to "", + "log" to "Copying original apk" ) ) } - patcher.addFiles(listOf(integrations)) {} - } + originalFile.copyTo(inputFile, true) - handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.5, - "header" to "Applying patches...", - "log" to "" + handler.post { + installerChannel.invokeMethod( + "update", + mapOf( + "progress" to 0.2, + "header" to "Unpacking apk...", + "log" to "Unpacking input apk" + ) ) - ) - } - patcher.addPatches(patches) - patcher.applyPatches().forEach { (patch, res) -> - if (res.isSuccess) { - val msg = "[success] $patch" + } + val patcher = + Patcher( + PatcherOptions( + inputFile, + cacheDirPath, + resourcePatching, + Aapt.binary(applicationContext).absolutePath, + cacheDirPath, + logger = ManagerLogger() + ) + ) + + handler.post { + installerChannel.invokeMethod( + "update", + mapOf("progress" to 0.3, "header" to "", "log" to "") + ) + } + if (mergeIntegrations) { handler.post { installerChannel.invokeMethod( "update", mapOf( - "progress" to 0.5, - "header" to "", - "log" to msg + "progress" to 0.4, + "header" to "Merging integrations...", + "log" to "Merging integrations" ) ) } - return@forEach + patcher.addFiles(listOf(integrations)) {} } - val msg = "[error] $patch:" + res.exceptionOrNull()!! + handler.post { installerChannel.invokeMethod( "update", - mapOf("progress" to 0.5, "header" to "", "log" to msg) + mapOf( + "progress" to 0.5, + "header" to "Applying patches...", + "log" to "" + ) ) } - } - handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.7, - "header" to "Repacking apk...", - "log" to "Repacking patched apk" - ) - ) - } - val res = patcher.save() - ZipFile(patchedFile).use { file -> - res.dexFiles.forEach { - file.addEntryCompressData( - ZipEntry.createWithName(it.name), - it.stream.readBytes() + patcher.addPatches(patches) + patcher.applyPatches().forEach { (patch, res) -> + if (res.isSuccess) { + val msg = "[success] $patch" + handler.post { + installerChannel.invokeMethod( + "update", + mapOf( + "progress" to 0.5, + "header" to "", + "log" to msg + ) + ) + } + return@forEach + } + val msg = "[error] $patch:" + res.exceptionOrNull()!! + handler.post { + installerChannel.invokeMethod( + "update", + mapOf("progress" to 0.5, "header" to "", "log" to msg) + ) + } + } + + handler.post { + installerChannel.invokeMethod( + "update", + mapOf( + "progress" to 0.7, + "header" to "Repacking apk...", + "log" to "Repacking patched apk" + ) ) } - res.resourceFile?.let { + val res = patcher.save() + ZipFile(patchedFile).use { file -> + res.dexFiles.forEach { + file.addEntryCompressData( + ZipEntry.createWithName(it.name), + it.stream.readBytes() + ) + } + res.resourceFile?.let { + file.copyEntriesFromFileAligned( + ZipFile(it), + ZipAligner::getEntryAlignment + ) + } file.copyEntriesFromFileAligned( - ZipFile(it), + ZipFile(inputFile), ZipAligner::getEntryAlignment ) } - file.copyEntriesFromFileAligned( - ZipFile(inputFile), - ZipAligner::getEntryAlignment - ) - } - handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 0.9, - "header" to "Signing apk...", - "log" to "" + handler.post { + installerChannel.invokeMethod( + "update", + mapOf( + "progress" to 0.9, + "header" to "Signing apk...", + "log" to "" + ) ) - ) - } - Signer("ReVanced", "s3cur3p@ssw0rd").signApk(patchedFile, outFile, keyStoreFile) + } + Signer("ReVanced", "s3cur3p@ssw0rd").signApk(patchedFile, outFile, keyStoreFile) - handler.post { - installerChannel.invokeMethod( - "update", - mapOf( - "progress" to 1.0, - "header" to "Finished!", - "log" to "Finished!" + handler.post { + installerChannel.invokeMethod( + "update", + mapOf( + "progress" to 1.0, + "header" to "Finished!", + "log" to "Finished!" + ) ) - ) + } + } catch (ex: Throwable) { + val stack = ex.stackTraceToString() + handler.post { + installerChannel.invokeMethod( + "update", + mapOf( + "progress" to -100.0, + "header" to "Aborting...", + "log" to "An error occurred! Aborting\nError:\n$stack" + ) + ) + } } - handler.post { result.success(null) } - } - .start() + }.start() } inner class ManagerLogger : Logger { diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index ede88df1..10a90a17 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -78,14 +78,20 @@ class InstallerViewModel extends BaseViewModel { } void update(double value, String header, String log) { - if (value > 0) { + if (value >= 0.0) { progress = value; } - isPatching = progress == 1.0 ? false : true; - if (progress == 0.0) { + if (value == 0.0) { logs = ''; + isPatching = true; isInstalled = false; hasErrors = false; + } else if (value == 1.0) { + isPatching = false; + hasErrors = false; + } else if (value == -100.0) { + isPatching = false; + hasErrors = true; } if (header.isNotEmpty) { headerLogs = header; @@ -95,6 +101,9 @@ class InstallerViewModel extends BaseViewModel { logs += '\n'; } logs += log; + if (logs[logs.length - 1] == '\n') { + logs = logs.substring(0, logs.length - 1); + } Future.delayed(const Duration(milliseconds: 500)).then((value) { scrollController.animateTo( scrollController.position.maxScrollExtent, @@ -117,12 +126,14 @@ class InstallerViewModel extends BaseViewModel { _patches, ); } catch (e) { - hasErrors = true; - update(-1.0, 'Aborting...', 'An error occurred! Aborting\nError: $e'); + update( + -100.0, + 'Aborting...', + 'An error occurred! Aborting\nError:\n$e', + ); } } else { - hasErrors = true; - update(-1.0, 'Aborting...', 'No app or patches selected! Aborting'); + update(-100.0, 'Aborting...', 'No app or patches selected! Aborting'); } if (FlutterBackground.isBackgroundExecutionEnabled) { try { @@ -132,7 +143,6 @@ class InstallerViewModel extends BaseViewModel { } } await Wakelock.disable(); - isPatching = false; } void installResult(BuildContext context, bool installAsRoot) async {