From 012110f00868c3f87e934397ceddbb6cc8b068f8 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 3 Oct 2023 18:54:51 +0200 Subject: [PATCH 1/5] perf: Do not load patches twice --- .../revanced/manager/flutter/MainActivity.kt | 35 +++++++++---------- lib/services/patcher_api.dart | 16 ++++----- .../views/installer/installer_viewmodel.dart | 2 ++ 3 files changed, 25 insertions(+), 28 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 691267b3..76ca3c66 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 @@ -8,6 +8,7 @@ import app.revanced.manager.flutter.utils.signing.Signer import app.revanced.manager.flutter.utils.zip.ZipFile import app.revanced.manager.flutter.utils.zip.structures.ZipEntry import app.revanced.patcher.PatchBundleLoader +import app.revanced.patcher.PatchSet import app.revanced.patcher.Patcher import app.revanced.patcher.PatcherOptions import app.revanced.patcher.patch.PatchResult @@ -31,6 +32,8 @@ class MainActivity : FlutterActivity() { private var cancel: Boolean = false private var stopResult: MethodChannel.Result? = null + private lateinit var patches: PatchSet + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) @@ -46,7 +49,6 @@ class MainActivity : FlutterActivity() { mainChannel.setMethodCallHandler { call, result -> when (call.method) { "runPatcher" -> { - val patchBundleFilePath = call.argument("patchBundleFilePath") val originalFilePath = call.argument("originalFilePath") val inputFilePath = call.argument("inputFilePath") val patchedFilePath = call.argument("patchedFilePath") @@ -57,7 +59,7 @@ class MainActivity : FlutterActivity() { val keyStoreFilePath = call.argument("keyStoreFilePath") val keystorePassword = call.argument("keystorePassword") - if (patchBundleFilePath != null && + if ( originalFilePath != null && inputFilePath != null && patchedFilePath != null && @@ -71,7 +73,6 @@ class MainActivity : FlutterActivity() { cancel = false runPatcher( result, - patchBundleFilePath, originalFilePath, inputFilePath, patchedFilePath, @@ -94,17 +95,19 @@ class MainActivity : FlutterActivity() { val patchBundleFilePath = call.argument("patchBundleFilePath")!! val cacheDirPath = call.argument("cacheDirPath")!! + try { + patches = PatchBundleLoader.Dex( + File(patchBundleFilePath), + optimizedDexDirectory = File(cacheDirPath) + ) + } catch (ex: Exception) { + return@setMethodCallHandler result.notImplemented() + } catch (err: Error) { + return@setMethodCallHandler result.notImplemented() + } + JSONArray().apply { - try { - PatchBundleLoader.Dex( - File(patchBundleFilePath), - optimizedDexDirectory = File(cacheDirPath) - ) - } catch (ex: Exception) { - return@setMethodCallHandler result.notImplemented() - } catch (err: Error) { - return@setMethodCallHandler result.notImplemented() - }.forEach { + patches.forEach { JSONObject().apply { put("name", it.name) put("description", it.description) @@ -136,7 +139,6 @@ class MainActivity : FlutterActivity() { private fun runPatcher( result: MethodChannel.Result, - patchBundleFilePath: String, originalFilePath: String, inputFilePath: String, patchedFilePath: String, @@ -223,10 +225,7 @@ class MainActivity : FlutterActivity() { updateProgress(0.1, "Loading patches...", "Loading patches") - val patches = PatchBundleLoader.Dex( - File(patchBundleFilePath), - optimizedDexDirectory = cacheDir - ).filter { patch -> + val patches = patches.filter { patch -> val isCompatible = patch.compatiblePackages?.any { it.name == patcher.context.packageMetadata.packageName } ?: false diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index 9a094bec..f6c8aa3e 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -59,9 +59,7 @@ class PatcherAPI { } List getUniversalPatches() { - return _patches - .where((patch) => patch.compatiblePackages.isEmpty) - .toList(); + return _patches.where((patch) => patch.compatiblePackages.isEmpty).toList(); } Future _loadPatches() async { @@ -85,15 +83,14 @@ class PatcherAPI { ) async { final List filteredApps = []; final bool allAppsIncluded = - _universalPatches.isNotEmpty && - showUniversalPatches; + _universalPatches.isNotEmpty && showUniversalPatches; if (allAppsIncluded) { final appList = await DeviceApps.getInstalledApplications( includeAppIcons: true, onlyAppsWithLaunchIntent: true, ); - for(final app in appList) { + for (final app in appList) { filteredApps.add(app as ApplicationWithIcon); } } @@ -154,9 +151,9 @@ class PatcherAPI { String apkFilePath, List selectedPatches, ) async { - final File? patchBundleFile = await _managerAPI.downloadPatches(); final File? integrationsFile = await _managerAPI.downloadIntegrations(); - if (patchBundleFile != null) { + + if (integrationsFile != null) { _dataDir.createSync(); _tmpDir.createSync(); final Directory workDir = _tmpDir.createTempSync('tmp-'); @@ -170,12 +167,11 @@ class PatcherAPI { await patcherChannel.invokeMethod( 'runPatcher', { - 'patchBundleFilePath': patchBundleFile.path, 'originalFilePath': originalFilePath, 'inputFilePath': inputFile.path, 'patchedFilePath': patchedFile.path, 'outFilePath': outFile!.path, - 'integrationsPath': integrationsFile!.path, + 'integrationsPath': integrationsFile.path, 'selectedPatches': selectedPatches.map((p) => p.name).toList(), 'cacheDirPath': cacheDir.path, 'keyStoreFilePath': _keyStoreFile.path, diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 137d2269..76a18f21 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -95,6 +95,8 @@ class InstallerViewModel extends BaseViewModel { isInstalled = false; hasErrors = false; } else if (value == 1.0) { + _managerAPI.patches.clear(); + isPatching = false; hasErrors = false; await _managerAPI.savePatches( From 3a88d4d3e69075adb6eedc4448476432cbb6a44b Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 4 Oct 2023 17:30:36 +0200 Subject: [PATCH 2/5] build: Bump dependencies --- android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7854f0c1..7f8b88f9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -85,7 +85,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" // ReVanced - implementation "app.revanced:revanced-patcher:15.0.3" + implementation "app.revanced:revanced-patcher:16.0.0" // Signing & aligning implementation("org.bouncycastle:bcpkix-jdk15on:1.70") From d8eadc2a2dcaaf958f79db4d236dacde787958fc Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 4 Oct 2023 18:45:13 +0200 Subject: [PATCH 3/5] feat: Use simpler wording --- .../revanced/manager/flutter/MainActivity.kt | 2 +- .../views/installer/installer_viewmodel.dart | 99 +++++++++---------- 2 files changed, 50 insertions(+), 51 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 76ca3c66..b88abb82 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 @@ -330,7 +330,7 @@ class MainActivity : FlutterActivity() { val stack = ex.stackTraceToString() updateProgress( -100.0, - "Aborted", + "Failed", "An error occurred:\n$stack" ) } diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 76a18f21..32bc245c 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -132,28 +132,24 @@ class InstallerViewModel extends BaseViewModel { Future runPatcher() async { try { - update(0.0, 'Initializing...', 'Initializing installer'); - if (_patches.isNotEmpty) { - try { - update(0.1, '', 'Creating working directory'); - await _patcherAPI.runPatcher( - _app.packageName, - _app.apkFilePath, - _patches, - ); - } on Exception catch (e) { - update( - -100.0, - 'Aborted...', - 'An error occurred! Aborted\nError:\n$e', - ); - if (kDebugMode) { - print(e); - } - } - } else { - update(-100.0, 'Aborted...', 'No app or patches selected! Aborted'); + update(0.1, '', 'Creating working directory'); + await _patcherAPI.runPatcher( + _app.packageName, + _app.apkFilePath, + _patches, + ); + } on Exception catch (e) { + update( + -100.0, + 'Failed...', + 'Something went wrong:\n$e', + ); + if (kDebugMode) { + print(e); } + } + + try { if (FlutterBackground.isBackgroundExecutionEnabled) { try { FlutterBackground.disableBackgroundExecution(); @@ -211,7 +207,8 @@ class InstallerViewModel extends BaseViewModel { ), RadioListTile( title: I18nText('installerView.installNonRootType'), - contentPadding: const EdgeInsets.symmetric(horizontal: 16), + contentPadding: + const EdgeInsets.symmetric(horizontal: 16), value: 0, groupValue: value, onChanged: (selected) { @@ -220,7 +217,8 @@ class InstallerViewModel extends BaseViewModel { ), RadioListTile( title: I18nText('installerView.installRootType'), - contentPadding: const EdgeInsets.symmetric(horizontal: 16), + contentPadding: + const EdgeInsets.symmetric(horizontal: 16), value: 1, groupValue: value, onChanged: (selected) { @@ -258,9 +256,9 @@ class InstallerViewModel extends BaseViewModel { Future stopPatcher() async { try { isCanceled = true; - update(0.5, 'Aborting...', 'Canceling patching process'); + update(0.5, 'Canceling...', 'Canceling patching process'); await _patcherAPI.stopPatcher(); - update(-100.0, 'Aborted...', 'Press back to exit'); + update(-100.0, 'Canceled...', 'Press back to exit'); } on Exception catch (e) { if (kDebugMode) { print(e); @@ -271,33 +269,34 @@ class InstallerViewModel extends BaseViewModel { Future installResult(BuildContext context, bool installAsRoot) async { try { _app.isRooted = installAsRoot; - update( - 1.0, - 'Installing...', - _app.isRooted - ? 'Installing patched file using root method' - : 'Installing patched file using nonroot method', - ); - isInstalled = await _patcherAPI.installPatchedFile(_app); - if (isInstalled) { - _app.isFromStorage = false; - _app.patchDate = DateTime.now(); - _app.appliedPatches = _patches.map((p) => p.name).toList(); + update( + 1.0, + 'Installing...', + _app.isRooted + ? 'Installing patched file using root method' + : 'Installing patched file using nonroot method', + ); + isInstalled = await _patcherAPI.installPatchedFile(_app); + if (isInstalled) { + _app.isFromStorage = false; + _app.patchDate = DateTime.now(); + _app.appliedPatches = _patches.map((p) => p.name).toList(); - // In case a patch changed the app name or package name, - // update the app info. - final app = await DeviceApps.getAppFromStorage(_patcherAPI.outFile!.path); - if (app != null) { - _app.name = app.appName; - _app.packageName = app.packageName; - } - - await _managerAPI.savePatchedApp(_app); - - update(1.0, 'Installed!', 'Installed!'); - } else { - // TODO(aabed): Show error message. + // In case a patch changed the app name or package name, + // update the app info. + final app = + await DeviceApps.getAppFromStorage(_patcherAPI.outFile!.path); + if (app != null) { + _app.name = app.appName; + _app.packageName = app.packageName; } + + await _managerAPI.savePatchedApp(_app); + + update(1.0, 'Installed!', 'Installed!'); + } else { + // TODO(aabed): Show error message. + } } on Exception catch (e) { if (kDebugMode) { print(e); From b07439d402edd392e39c2bc29b4dfbaec58fa7f6 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 4 Oct 2023 19:36:58 +0200 Subject: [PATCH 4/5] fix: Reload patches --- lib/ui/views/installer/installer_viewmodel.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 32bc245c..3bfa5d24 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -95,8 +95,6 @@ class InstallerViewModel extends BaseViewModel { isInstalled = false; hasErrors = false; } else if (value == 1.0) { - _managerAPI.patches.clear(); - isPatching = false; hasErrors = false; await _managerAPI.savePatches( @@ -132,7 +130,6 @@ class InstallerViewModel extends BaseViewModel { Future runPatcher() async { try { - update(0.1, '', 'Creating working directory'); await _patcherAPI.runPatcher( _app.packageName, _app.apkFilePath, @@ -149,6 +146,12 @@ class InstallerViewModel extends BaseViewModel { } } + // Necessary to reset the state of patches by reloading them + // in a later patching process. + // TODO(Benjamin): Fix this not working + _managerAPI.patches.clear(); + await _managerAPI.getPatches(); + try { if (FlutterBackground.isBackgroundExecutionEnabled) { try { From cd07f39b695b1eff73409992bf72c59b02227076 Mon Sep 17 00:00:00 2001 From: Benjamin Halko Date: Wed, 4 Oct 2023 12:16:56 -0700 Subject: [PATCH 5/5] fix: reset patches after patching --- lib/services/patcher_api.dart | 4 ++-- lib/ui/views/installer/installer_viewmodel.dart | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/services/patcher_api.dart b/lib/services/patcher_api.dart index f6c8aa3e..dc4ffabd 100644 --- a/lib/services/patcher_api.dart +++ b/lib/services/patcher_api.dart @@ -31,7 +31,7 @@ class PatcherAPI { File? outFile; Future initialize() async { - await _loadPatches(); + await loadPatches(); await _managerAPI.downloadIntegrations(); final Directory appCache = await getTemporaryDirectory(); _dataDir = await getExternalStorageDirectory() ?? appCache; @@ -62,7 +62,7 @@ class PatcherAPI { return _patches.where((patch) => patch.compatiblePackages.isEmpty).toList(); } - Future _loadPatches() async { + Future loadPatches() async { try { if (_patches.isEmpty) { _patches = await _managerAPI.getPatches(); diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 3bfa5d24..8d54987d 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -148,9 +148,8 @@ class InstallerViewModel extends BaseViewModel { // Necessary to reset the state of patches by reloading them // in a later patching process. - // TODO(Benjamin): Fix this not working _managerAPI.patches.clear(); - await _managerAPI.getPatches(); + await _patcherAPI.loadPatches(); try { if (FlutterBackground.isBackgroundExecutionEnabled) {