From 77dbee3d6ae7b8dc77543e036624daa68ae63504 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 9 Oct 2023 04:10:20 +0200 Subject: [PATCH] feat: Add option to use single threaded writer for dex files BREAKING CHANGE: This commit gets rid of deprecated constructors. --- revanced-patcher/api/revanced-patcher.api | 8 +++--- .../app/revanced/patcher/PatcherOptions.kt | 13 +++++----- .../revanced/patcher/data/BytecodeContext.kt | 25 +++++++++++++------ 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/revanced-patcher/api/revanced-patcher.api b/revanced-patcher/api/revanced-patcher.api index 4cb39241..8c467230 100644 --- a/revanced-patcher/api/revanced-patcher.api +++ b/revanced-patcher/api/revanced-patcher.api @@ -67,10 +67,10 @@ public final class app/revanced/patcher/PatcherException$CircularDependencyExcep public final class app/revanced/patcher/PatcherOptions { public fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;)V public synthetic fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;)V - public synthetic fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun copy (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;)Lapp/revanced/patcher/PatcherOptions; - public static synthetic fun copy$default (Lapp/revanced/patcher/PatcherOptions;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;ILjava/lang/Object;)Lapp/revanced/patcher/PatcherOptions; + public fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Z)V + public synthetic fun (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun copy (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Z)Lapp/revanced/patcher/PatcherOptions; + public static synthetic fun copy$default (Lapp/revanced/patcher/PatcherOptions;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lapp/revanced/patcher/PatcherOptions; public fun equals (Ljava/lang/Object;)Z public fun hashCode ()I public final fun recreateResourceCacheDirectory ()Ljava/io/File; diff --git a/revanced-patcher/src/main/kotlin/app/revanced/patcher/PatcherOptions.kt b/revanced-patcher/src/main/kotlin/app/revanced/patcher/PatcherOptions.kt index 1dfbdaa7..1bed3582 100644 --- a/revanced-patcher/src/main/kotlin/app/revanced/patcher/PatcherOptions.kt +++ b/revanced-patcher/src/main/kotlin/app/revanced/patcher/PatcherOptions.kt @@ -1,7 +1,6 @@ package app.revanced.patcher import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.logging.impl.NopLogger import brut.androlib.Config import java.io.File import java.util.logging.Logger @@ -12,16 +11,15 @@ import java.util.logging.Logger * @param resourceCachePath The path to the directory to use for caching resources. * @param aaptBinaryPath The path to a custom aapt binary. * @param frameworkFileDirectory The path to the directory to cache the framework file in. - * @param unusedLogger The logger to use for logging. + * @param multithreadingDexFileWriter Whether to use multiple threads for writing dex files. + * This can impact memory usage. */ -data class PatcherOptions -@Deprecated("Use the constructor without the logger parameter instead") -constructor( +data class PatcherOptions( internal val inputFile: File, internal val resourceCachePath: File = File("revanced-resource-cache"), internal val aaptBinaryPath: String? = null, internal val frameworkFileDirectory: String? = null, - internal val unusedLogger: app.revanced.patcher.logging.Logger = NopLogger + internal val multithreadingDexFileWriter: Boolean = false, ) { private val logger = Logger.getLogger(PatcherOptions::class.java.name) @@ -47,6 +45,7 @@ constructor( * @param aaptBinaryPath The path to a custom aapt binary. * @param frameworkFileDirectory The path to the directory to cache the framework file in. */ + @Deprecated("Use the constructor with the multithreadingDexFileWriter parameter instead") constructor( inputFile: File, resourceCachePath: File = File("revanced-resource-cache"), @@ -57,7 +56,7 @@ constructor( resourceCachePath, aaptBinaryPath, frameworkFileDirectory, - NopLogger + false, ) fun recreateResourceCacheDirectory() = resourceCachePath.also { diff --git a/revanced-patcher/src/main/kotlin/app/revanced/patcher/data/BytecodeContext.kt b/revanced-patcher/src/main/kotlin/app/revanced/patcher/data/BytecodeContext.kt index fd6a131f..0dee449f 100644 --- a/revanced-patcher/src/main/kotlin/app/revanced/patcher/data/BytecodeContext.kt +++ b/revanced-patcher/src/main/kotlin/app/revanced/patcher/data/BytecodeContext.kt @@ -12,11 +12,11 @@ import com.android.tools.smali.dexlib2.Opcodes import com.android.tools.smali.dexlib2.iface.ClassDef import com.android.tools.smali.dexlib2.iface.DexFile import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.writer.io.MemoryDataStore import lanchon.multidexlib2.BasicDexFileNamer import lanchon.multidexlib2.DexIO import lanchon.multidexlib2.MultiDexIO import java.io.File +import java.io.FileFilter import java.io.Flushable import java.util.logging.Logger @@ -142,16 +142,25 @@ class BytecodeContext internal constructor(private val options: PatcherOptions) * @return The compiled bytecode. */ override fun get(): List { - logger.info("Compiling modified dex files") + logger.info("Compiling patched dex files") - return mutableMapOf().apply { + val patchedDexFileResults = options.resourceCachePath.resolve("dex").also { + it.deleteRecursively() // Make sure the directory is empty. + it.mkdirs() + }.apply { MultiDexIO.writeDexFile( - true, -1, // Defaults to amount of available cores. - this, BasicDexFileNamer(), object : DexFile { + true, + if (options.multithreadingDexFileWriter) -1 else 1, + this, + BasicDexFileNamer(), + object : DexFile { override fun getClasses() = this@BytecodeContext.classes.also(ProxyClassList::replaceClasses) override fun getOpcodes() = this@BytecodeContext.opcodes - }, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null - ) - }.map { PatcherResult.PatchedDexFile(it.key, it.value.readAt(0)) } + }, + DexIO.DEFAULT_MAX_DEX_POOL_SIZE + ) { _, entryName, _ -> logger.info("Compiled $entryName") } + }.listFiles(FileFilter { it.isFile })!!.map { PatcherResult.PatchedDexFile(it.name, it.inputStream()) } + + return patchedDexFileResults } } \ No newline at end of file