feat: properly make use of logging facade

This deprecates the primary constructor of `PatcherOptions` with the `logger` parameter
This commit is contained in:
oSumAtrIX 2023-08-24 04:43:16 +02:00
parent ccccf5b1d2
commit ba56a6a2ee
No known key found for this signature in database
GPG key ID: A9B3094ACDB604B4
7 changed files with 72 additions and 43 deletions

View file

@ -15,6 +15,7 @@ import java.io.File
import java.util.function.Supplier
import java.util.logging.Level
import java.util.logging.LogManager
import java.util.logging.Logger
/**
* ReVanced Patcher.
@ -24,6 +25,8 @@ import java.util.logging.LogManager
class Patcher(
private val options: PatcherOptions
) : PatchExecutorFunction, PatchesConsumer, IntegrationsConsumer, Supplier<PatcherResult>, Closeable {
private val logger = Logger.getLogger(Patcher::class.java.name)
/**
* The context of ReVanced [Patcher].
* This holds the current state of the patcher.
@ -159,7 +162,7 @@ class Patcher(
if (options.resourceDecodingMode == ResourceContext.ResourceDecodingMode.FULL)
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.FULL)
options.logger.info("Executing patches")
logger.info("Executing patches")
val executedPatches = LinkedHashMap<String, ExecutedPatch>() // Key is name.

View file

@ -1,10 +1,10 @@
package app.revanced.patcher
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.logging.Logger
import app.revanced.patcher.logging.impl.NopLogger
import brut.androlib.Config
import java.io.File
import java.util.logging.Logger
/**
* Options for ReVanced [Patcher].
@ -12,15 +12,19 @@ import java.io.File
* @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 logger A [Logger].
* @param unusedLogger The logger to use for logging.
*/
data class PatcherOptions(
data class PatcherOptions
@Deprecated("Use the constructor without the logger parameter instead")
constructor(
internal val inputFile: File,
internal val resourceCachePath: File = File("revanced-resource-cache"),
internal val aaptBinaryPath: String? = null,
internal val frameworkFileDirectory: String? = null,
internal val logger: Logger = NopLogger
internal val unusedLogger: app.revanced.patcher.logging.Logger = NopLogger
) {
private val logger = Logger.getLogger(PatcherOptions::class.java.name)
/**
* The mode to use for resource decoding.
* @see ResourceContext.ResourceDecodingMode
@ -36,12 +40,32 @@ data class PatcherOptions(
frameworkDirectory = frameworkFileDirectory
}
/**
* Options for ReVanced [Patcher].
* @param inputFile The input file to patch.
* @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.
*/
constructor(
inputFile: File,
resourceCachePath: File = File("revanced-resource-cache"),
aaptBinaryPath: String? = null,
frameworkFileDirectory: String? = null,
) : this(
inputFile,
resourceCachePath,
aaptBinaryPath,
frameworkFileDirectory,
NopLogger
)
fun recreateResourceCacheDirectory() = resourceCachePath.also {
if (it.exists()) {
logger.info("Deleting existing resource cache directory")
if (!it.deleteRecursively())
logger.error("Failed to delete existing resource cache directory")
logger.severe("Failed to delete existing resource cache directory")
}
it.mkdirs()

View file

@ -1,8 +1,10 @@
package app.revanced.patcher.data
import app.revanced.patcher.PatcherContext
import app.revanced.patcher.PatcherOptions
import app.revanced.patcher.PatcherResult
import app.revanced.patcher.logging.Logger
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.annotations.RequiresIntegrations
import app.revanced.patcher.util.ClassMerger.merge
import app.revanced.patcher.util.ProxyClassList
import app.revanced.patcher.util.method.MethodWalker
@ -17,6 +19,7 @@ import lanchon.multidexlib2.DexIO
import lanchon.multidexlib2.MultiDexIO
import java.io.File
import java.io.Flushable
import java.util.logging.Logger
/**
* A context for bytecode.
@ -26,6 +29,8 @@ import java.io.Flushable
*/
class BytecodeContext internal constructor(private val options: PatcherOptions) :
Context<List<PatcherResult.PatchedDexFile>> {
private val logger = Logger.getLogger(BytecodeContext::class.java.name)
/**
* [Opcodes] of the supplied [PatcherOptions.inputFile].
*/
@ -45,7 +50,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
/**
* The [Integrations] of this [PatcherContext].
*/
internal val integrations = Integrations(options.logger)
internal val integrations = Integrations()
/**
* Find a class by a given class name.
@ -88,10 +93,8 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
/**
* The integrations of a [PatcherContext].
*
* @param logger The logger to use.
*/
internal inner class Integrations(private val logger: Logger) : MutableList<File> by mutableListOf(), Flushable {
internal inner class Integrations : MutableList<File> by mutableListOf(), Flushable {
/**
* Whether to merge integrations.
* True when any supplied [Patch] is annotated with [RequiresIntegrations].
@ -112,14 +115,14 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
null
).classes.forEach classDef@{ classDef ->
val existingClass = classes.find { it == classDef } ?: run {
logger.trace("Merging $classDef")
logger.fine("Merging $classDef")
classes.add(classDef)
return@classDef
}
logger.trace("$classDef exists. Adding missing methods and fields.")
logger.fine("$classDef exists. Adding missing methods and fields.")
existingClass.merge(classDef, this@BytecodeContext, logger).let { mergedClass ->
existingClass.merge(classDef, this@BytecodeContext).let { mergedClass ->
// If the class was merged, replace the original class with the merged class.
if (mergedClass === existingClass) return@let
classes.apply { remove(existingClass); add(mergedClass) }
@ -137,7 +140,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
* @return The compiled bytecode.
*/
override fun get(): List<PatcherResult.PatchedDexFile> {
options.logger.info("Compiling modified dex files")
logger.info("Compiling modified dex files")
return mutableMapOf<String, MemoryDataStore>().apply {
MultiDexIO.writeDexFile(

View file

@ -16,6 +16,7 @@ import java.io.File
import java.io.InputStream
import java.io.OutputStream
import java.nio.file.Files
import java.util.logging.Logger
/**
* A context for resources.
@ -27,6 +28,8 @@ class ResourceContext internal constructor(
private val context: PatcherContext,
private val options: PatcherOptions
) : Context<File?>, Iterable<File> {
private val logger = Logger.getLogger(ResourceContext::class.java.name)
val xmlEditor = XmlFileHolder()
/**
@ -42,7 +45,7 @@ class ResourceContext internal constructor(
ResourceDecodingMode.FULL -> {
val outDir = options.recreateResourceCacheDirectory()
options.logger.info("Decoding resources")
logger.info("Decoding resources")
resourcesDecoder.decodeResources(outDir)
resourcesDecoder.decodeManifest(outDir)
@ -57,7 +60,7 @@ class ResourceContext internal constructor(
}
ResourceDecodingMode.MANIFEST_ONLY -> {
options.logger.info("Decoding app manifest")
logger.info("Decoding app manifest")
// Decode manually instead of using resourceDecoder.decodeManifest
// because it does not support decoding to an OutputStream.
@ -100,7 +103,7 @@ class ResourceContext internal constructor(
var resourceFile: File? = null
if (options.resourceDecodingMode == ResourceDecodingMode.FULL) {
options.logger.info("Compiling modified resources")
logger.info("Compiling modified resources")
val cacheDirectory = ExtFile(options.resourceCachePath)
val aaptFile = cacheDirectory.resolve("aapt_temp_file").also {

View file

@ -1,5 +1,6 @@
package app.revanced.patcher.logging
@Deprecated("This will be removed in a future release")
interface Logger {
fun error(msg: String) {}
fun warn(msg: String) {}

View file

@ -2,4 +2,5 @@ package app.revanced.patcher.logging.impl
import app.revanced.patcher.logging.Logger
@Deprecated("This will be removed in a future release")
object NopLogger : Logger

View file

@ -2,7 +2,6 @@ package app.revanced.patcher.util
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.or
import app.revanced.patcher.logging.Logger
import app.revanced.patcher.util.ClassMerger.Utils.asMutableClass
import app.revanced.patcher.util.ClassMerger.Utils.filterAny
import app.revanced.patcher.util.ClassMerger.Utils.filterNotAny
@ -18,6 +17,7 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.logging.Logger
import kotlin.reflect.KFunction2
/**
@ -25,28 +25,28 @@ import kotlin.reflect.KFunction2
* Note: This will not consider method implementations or if the class is missing a superclass or interfaces.
*/
internal object ClassMerger {
private val logger = Logger.getLogger(ClassMerger::class.java.name)
/**
* Merge a class with [otherClass].
*
* @param otherClass The class to merge with
* @param context The context to traverse the class hierarchy in.
* @param logger A logger.
* @return The merged class or the original class if no merge was needed.
*/
fun ClassDef.merge(otherClass: ClassDef, context: BytecodeContext, logger: Logger? = null) = this
//.fixFieldAccess(otherClass, logger)
//.fixMethodAccess(otherClass, logger)
.addMissingFields(otherClass, logger)
.addMissingMethods(otherClass, logger)
.publicize(otherClass, context, logger)
fun ClassDef.merge(otherClass: ClassDef, context: BytecodeContext) = this
//.fixFieldAccess(otherClass)
//.fixMethodAccess(otherClass)
.addMissingFields(otherClass)
.addMissingMethods(otherClass)
.publicize(otherClass, context)
/**
* Add methods which are missing but existing in [fromClass].
*
* @param fromClass The class to add missing methods from.
* @param logger A logger.
*/
private fun ClassDef.addMissingMethods(fromClass: ClassDef, logger: Logger? = null): ClassDef {
private fun ClassDef.addMissingMethods(fromClass: ClassDef): ClassDef {
val missingMethods = fromClass.methods.let { fromMethods ->
methods.filterNot { method ->
fromMethods.any { fromMethod ->
@ -57,7 +57,7 @@ internal object ClassMerger {
if (missingMethods.isEmpty()) return this
logger?.trace("Found ${missingMethods.size} missing methods")
logger.fine("Found ${missingMethods.size} missing methods")
return asMutableClass().apply {
methods.addAll(missingMethods.map { it.toMutable() })
@ -68,16 +68,15 @@ internal object ClassMerger {
* Add fields which are missing but existing in [fromClass].
*
* @param fromClass The class to add missing fields from.
* @param logger A logger.
*/
private fun ClassDef.addMissingFields(fromClass: ClassDef, logger: Logger? = null): ClassDef {
private fun ClassDef.addMissingFields(fromClass: ClassDef): ClassDef {
val missingFields = fields.filterNotAny(fromClass.fields) { field, fromField ->
fromField.name == field.name
}
if (missingFields.isEmpty()) return this
logger?.trace("Found ${missingFields.size} missing fields")
logger.fine("Found ${missingFields.size} missing fields")
return asMutableClass().apply {
fields.addAll(missingFields.map { it.toMutable() })
@ -88,15 +87,14 @@ internal object ClassMerger {
* Make a class and its super class public recursively.
* @param reference The class to check the [AccessFlags] of.
* @param context The context to traverse the class hierarchy in.
* @param logger A logger.
*/
private fun ClassDef.publicize(reference: ClassDef, context: BytecodeContext, logger: Logger? = null) =
private fun ClassDef.publicize(reference: ClassDef, context: BytecodeContext) =
if (reference.accessFlags.isPublic() && !accessFlags.isPublic())
this.asMutableClass().apply {
context.traverseClassHierarchy(this) {
if (accessFlags.isPublic()) return@traverseClassHierarchy
logger?.trace("Publicizing ${this.type}")
logger.fine("Publicizing ${this.type}")
accessFlags = accessFlags.toPublic()
}
@ -107,9 +105,8 @@ internal object ClassMerger {
* Publicize fields if they are public in [reference].
*
* @param reference The class to check the [AccessFlags] of the fields in.
* @param logger A logger.
*/
private fun ClassDef.fixFieldAccess(reference: ClassDef, logger: Logger? = null): ClassDef {
private fun ClassDef.fixFieldAccess(reference: ClassDef): ClassDef {
val brokenFields = fields.filterAny(reference.fields) { field, referenceField ->
if (field.name != referenceField.name) return@filterAny false
@ -118,7 +115,7 @@ internal object ClassMerger {
if (brokenFields.isEmpty()) return this
logger?.trace("Found ${brokenFields.size} broken fields")
logger.fine("Found ${brokenFields.size} broken fields")
/**
* Make a field public.
@ -136,9 +133,8 @@ internal object ClassMerger {
* Publicize methods if they are public in [reference].
*
* @param reference The class to check the [AccessFlags] of the methods in.
* @param logger A logger.
*/
private fun ClassDef.fixMethodAccess(reference: ClassDef, logger: Logger? = null): ClassDef {
private fun ClassDef.fixMethodAccess(reference: ClassDef): ClassDef {
val brokenMethods = methods.filterAny(reference.methods) { method, referenceMethod ->
if (!MethodUtil.methodSignaturesMatch(method, referenceMethod)) return@filterAny false
@ -147,7 +143,7 @@ internal object ClassMerger {
if (brokenMethods.isEmpty()) return this
logger?.trace("Found ${brokenMethods.size} methods")
logger.fine("Found ${brokenMethods.size} methods")
/**
* Make a method public.
@ -194,7 +190,6 @@ internal object ClassMerger {
/**
* Filter [this] on [needles] matching the given [predicate].
*
* @param this The hay to filter for [needles].
* @param needles The needles to filter [this] with.
* @param predicate The filter.
* @return The [this] filtered on [needles] matching the given [predicate].
@ -206,7 +201,6 @@ internal object ClassMerger {
/**
* Filter [this] on [needles] not matching the given [predicate].
*
* @param this The hay to filter for [needles].
* @param needles The needles to filter [this] with.
* @param predicate The filter.
* @return The [this] filtered on [needles] not matching the given [predicate].