mirror of
https://github.com/revanced/revanced-patcher.git
synced 2025-05-01 05:44:24 +02:00
docs: Document important parts of the code
This commit is contained in:
parent
1dd3394ea3
commit
650bf71124
@ -5,17 +5,24 @@ import app.revanced.patcher.patch.Patch
|
|||||||
import app.revanced.patcher.resolver.SignatureResolver
|
import app.revanced.patcher.resolver.SignatureResolver
|
||||||
import app.revanced.patcher.signature.MethodSignature
|
import app.revanced.patcher.signature.MethodSignature
|
||||||
import lanchon.multidexlib2.BasicDexFileNamer
|
import lanchon.multidexlib2.BasicDexFileNamer
|
||||||
|
import lanchon.multidexlib2.DexIO
|
||||||
import lanchon.multidexlib2.MultiDexIO
|
import lanchon.multidexlib2.MultiDexIO
|
||||||
import org.jf.dexlib2.Opcodes
|
import org.jf.dexlib2.Opcodes
|
||||||
import org.jf.dexlib2.iface.ClassDef
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
import org.jf.dexlib2.iface.DexFile
|
import org.jf.dexlib2.iface.DexFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ReVanced Patcher.
|
||||||
|
* @param input The input file (an apk or any other multi dex container).
|
||||||
|
* @param output The output folder.
|
||||||
|
* @param signatures An array of method signatures for the patches
|
||||||
|
*
|
||||||
|
*/
|
||||||
class Patcher(
|
class Patcher(
|
||||||
input: File,
|
input: File,
|
||||||
private val output: File,
|
private val output: File,
|
||||||
signatures: Array<MethodSignature>,
|
signatures: Array<MethodSignature>,
|
||||||
|
|
||||||
) {
|
) {
|
||||||
private val cache: Cache
|
private val cache: Cache
|
||||||
private val patches = mutableSetOf<Patch>()
|
private val patches = mutableSetOf<Patch>()
|
||||||
@ -25,6 +32,9 @@ class Patcher(
|
|||||||
cache = Cache(dexFile.classes, SignatureResolver(dexFile.classes, signatures).resolve())
|
cache = Cache(dexFile.classes, SignatureResolver(dexFile.classes, signatures).resolve())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the patched dex file.
|
||||||
|
*/
|
||||||
fun save() {
|
fun save() {
|
||||||
val newDexFile = object : DexFile {
|
val newDexFile = object : DexFile {
|
||||||
override fun getClasses(): Set<ClassDef> {
|
override fun getClasses(): Set<ClassDef> {
|
||||||
@ -45,13 +55,21 @@ class Patcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should use the multithreading capable overload for writeDexFile
|
// TODO: we should use the multithreading capable overload for writeDexFile
|
||||||
MultiDexIO.writeDexFile(true, output, BasicDexFileNamer(), newDexFile, 50000, null)
|
MultiDexIO.writeDexFile(true, output, BasicDexFileNamer(), newDexFile, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a patch to the patcher.
|
||||||
|
* @param patches The patches to add.
|
||||||
|
*/
|
||||||
fun addPatches(vararg patches: Patch) {
|
fun addPatches(vararg patches: Patch) {
|
||||||
this.patches.addAll(patches)
|
this.patches.addAll(patches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply patches loaded into the patcher.
|
||||||
|
* @param stopOnError If true, the patches will stop on the first error.
|
||||||
|
*/
|
||||||
fun applyPatches(stopOnError: Boolean = false): Map<String, Result<Nothing?>> {
|
fun applyPatches(stopOnError: Boolean = false): Map<String, Result<Nothing?>> {
|
||||||
return buildMap {
|
return buildMap {
|
||||||
// TODO: after each patch execution we could clear left overs like proxied classes to safe memory
|
// TODO: after each patch execution we could clear left overs like proxied classes to safe memory
|
||||||
|
@ -13,6 +13,10 @@ class Cache(
|
|||||||
// if the class proxy already exists in the cached proxy list below
|
// if the class proxy already exists in the cached proxy list below
|
||||||
internal val classProxy = mutableSetOf<ClassProxy>()
|
internal val classProxy = mutableSetOf<ClassProxy>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a class by a given predicate
|
||||||
|
* @return A proxy for the first class that matches the predicate
|
||||||
|
*/
|
||||||
fun findClass(predicate: (ClassDef) -> Boolean): ClassProxy? {
|
fun findClass(predicate: (ClassDef) -> Boolean): ClassProxy? {
|
||||||
// if we already proxied the class matching the predicate,
|
// if we already proxied the class matching the predicate,
|
||||||
val proxiedClass = classProxy.singleOrNull { classProxy -> predicate(classProxy.immutableClass) }
|
val proxiedClass = classProxy.singleOrNull { classProxy -> predicate(classProxy.immutableClass) }
|
||||||
|
@ -3,6 +3,13 @@ package app.revanced.patcher.proxy
|
|||||||
import app.revanced.patcher.proxy.mutableTypes.MutableClass
|
import app.revanced.patcher.proxy.mutableTypes.MutableClass
|
||||||
import org.jf.dexlib2.iface.ClassDef
|
import org.jf.dexlib2.iface.ClassDef
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A proxy class for a [ClassDef]
|
||||||
|
* A class proxy simply holds a reference to the original class
|
||||||
|
* and creates a mutable clone for the original class if needed.
|
||||||
|
* @param immutableClass The class to proxy
|
||||||
|
* @param originalIndex The original index of the class in the list of classes
|
||||||
|
*/
|
||||||
class ClassProxy(
|
class ClassProxy(
|
||||||
val immutableClass: ClassDef,
|
val immutableClass: ClassDef,
|
||||||
val originalIndex: Int,
|
val originalIndex: Int,
|
||||||
@ -10,6 +17,10 @@ class ClassProxy(
|
|||||||
internal var proxyUsed = false
|
internal var proxyUsed = false
|
||||||
internal lateinit var mutatedClass: MutableClass
|
internal lateinit var mutatedClass: MutableClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a mutable clone of the original class
|
||||||
|
* A patch should always use the original immutable class reference to avoid unnucessary allocations for the mutable class
|
||||||
|
*/
|
||||||
fun resolve(): MutableClass {
|
fun resolve(): MutableClass {
|
||||||
if (!proxyUsed) {
|
if (!proxyUsed) {
|
||||||
proxyUsed = true
|
proxyUsed = true
|
||||||
|
@ -2,6 +2,14 @@ package app.revanced.patcher.signature
|
|||||||
|
|
||||||
import org.jf.dexlib2.Opcode
|
import org.jf.dexlib2.Opcode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a method signature.
|
||||||
|
* @param name A suggestive name for the method which the signature was created for.
|
||||||
|
* @param returnType The return type of the method.
|
||||||
|
* @param methodParameters The parameters of the method.
|
||||||
|
* @param opcodes A list of opcodes of the method.
|
||||||
|
* @param accessFlags The access flags of the method.
|
||||||
|
*/
|
||||||
@Suppress("ArrayInDataClass")
|
@Suppress("ArrayInDataClass")
|
||||||
data class MethodSignature(
|
data class MethodSignature(
|
||||||
val name: String,
|
val name: String,
|
||||||
|
@ -3,6 +3,12 @@ package app.revanced.patcher.signature
|
|||||||
import app.revanced.patcher.proxy.ClassProxy
|
import app.revanced.patcher.proxy.ClassProxy
|
||||||
import app.revanced.patcher.resolver.SignatureResolver
|
import app.revanced.patcher.resolver.SignatureResolver
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the result of a [SignatureResolver].
|
||||||
|
* @param definingClassProxy The [ClassProxy] that the matching method was found in.
|
||||||
|
* @param resolvedMethodName The name of the actual matching method.
|
||||||
|
* @param scanData OpCodes pattern scan result.
|
||||||
|
*/
|
||||||
data class SignatureResolverResult(
|
data class SignatureResolverResult(
|
||||||
val definingClassProxy: ClassProxy,
|
val definingClassProxy: ClassProxy,
|
||||||
val resolvedMethodName: String,
|
val resolvedMethodName: String,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user