chore: Changes from gradle `ktlintformat` task

This commit is contained in:
LisoUseInAIKyrios 2024-03-31 23:43:13 +04:00
parent 57012c0e58
commit e925ed6eb3
616 changed files with 3063 additions and 2614 deletions

View File

@ -68,8 +68,9 @@ tasks {
dependsOn(build) dependsOn(build)
doLast { doLast {
val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools") val d8 =
.listFilesOrdered().last().resolve("d8").absolutePath File(System.getenv("ANDROID_HOME")).resolve("build-tools")
.listFilesOrdered().last().resolve("d8").absolutePath
val patchesJar = configurations.archives.get().allArtifacts.files.files.first().absolutePath val patchesJar = configurations.archives.get().allArtifacts.files.files.first().absolutePath
val workingDirectory = layout.buildDirectory.dir("libs").get().asFile val workingDirectory = layout.buildDirectory.dir("libs").get().asFile

View File

@ -6,27 +6,28 @@ import com.google.gson.GsonBuilder
import java.io.File import java.io.File
internal class JsonPatchesFileGenerator : PatchesFileGenerator { internal class JsonPatchesFileGenerator : PatchesFileGenerator {
override fun generate(patches: PatchSet) = patches.map { override fun generate(patches: PatchSet) =
JsonPatch( patches.map {
it.name!!, JsonPatch(
it.description, it.name!!,
it.compatiblePackages, it.description,
it.use, it.compatiblePackages,
it.requiresIntegrations, it.use,
it.options.values.map { option -> it.requiresIntegrations,
JsonPatch.Option( it.options.values.map { option ->
option.key, JsonPatch.Option(
option.default, option.key,
option.values, option.default,
option.title, option.values,
option.description, option.title,
option.required, option.description,
) option.required
}, )
) }
}.let { )
File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it)) }.let {
} File("patches.json").writeText(GsonBuilder().serializeNulls().create().toJson(it))
}
@Suppress("unused") @Suppress("unused")
private class JsonPatch( private class JsonPatch(
@ -35,7 +36,7 @@ internal class JsonPatchesFileGenerator : PatchesFileGenerator {
val compatiblePackages: Set<Patch.CompatiblePackage>? = null, val compatiblePackages: Set<Patch.CompatiblePackage>? = null,
val use: Boolean = true, val use: Boolean = true,
val requiresIntegrations: Boolean = false, val requiresIntegrations: Boolean = false,
val options: List<Option>, val options: List<Option>
) { ) {
class Option( class Option(
val key: String, val key: String,
@ -43,7 +44,7 @@ internal class JsonPatchesFileGenerator : PatchesFileGenerator {
val values: Map<String, Any?>?, val values: Map<String, Any?>?,
val title: String?, val title: String?,
val description: String?, val description: String?,
val required: Boolean, val required: Boolean
) )
} }
} }

View File

@ -3,10 +3,11 @@ package app.revanced.generator
import app.revanced.patcher.PatchBundleLoader import app.revanced.patcher.PatchBundleLoader
import java.io.File import java.io.File
internal fun main() = PatchBundleLoader.Jar( internal fun main() =
File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first(), PatchBundleLoader.Jar(
).also { loader -> File("build/libs/").listFiles { it -> it.name.endsWith(".jar") }!!.first()
if (loader.isEmpty()) throw IllegalStateException("No patches found") ).also { loader ->
}.let { bundle -> if (loader.isEmpty()) throw IllegalStateException("No patches found")
arrayOf(JsonPatchesFileGenerator()).forEach { generator -> generator.generate(bundle) } }.let { bundle ->
} arrayOf(JsonPatchesFileGenerator()).forEach { generator -> generator.generate(bundle) }
}

View File

@ -7,7 +7,7 @@ import app.revanced.patcher.patch.annotation.Patch
@Patch( @Patch(
name = "Export all activities", name = "Export all activities",
description = "Makes all app activities exportable.", description = "Makes all app activities exportable.",
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object ExportAllActivitiesPatch : ResourcePatch() { object ExportAllActivitiesPatch : ResourcePatch() {

View File

@ -14,7 +14,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
name = "Spoof Wi-Fi connection", name = "Spoof Wi-Fi connection",
description = "Spoofs an existing Wi-Fi connection.", description = "Spoofs an existing Wi-Fi connection.",
use = false, use = false,
requiresIntegrations = true, requiresIntegrations = true
) )
@Suppress("unused") @Suppress("unused")
object SpoofWifiPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() { object SpoofWifiPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() {
@ -25,15 +25,18 @@ object SpoofWifiPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() {
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
) = filterMapInstruction35c<MethodCall>( ) = filterMapInstruction35c<MethodCall>(
INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX, INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
classDef, classDef,
instruction, instruction,
instructionIndex, instructionIndex
) )
override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) { override fun transform(
mutableMethod: MutableMethod,
entry: Instruction35cInfo
) {
val (methodType, instruction, instructionIndex) = entry val (methodType, instruction, instructionIndex) = entry
methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex) methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
} }
@ -43,163 +46,163 @@ object SpoofWifiPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() {
override val definedClassName: String, override val definedClassName: String,
override val methodName: String, override val methodName: String,
override val methodParams: Array<String>, override val methodParams: Array<String>,
override val returnType: String, override val returnType: String
) : IMethodCall { ) : IMethodCall {
GetSystemService1( GetSystemService1(
"Landroid/content/Context;", "Landroid/content/Context;",
"getSystemService", "getSystemService",
arrayOf("Ljava/lang/String;"), arrayOf("Ljava/lang/String;"),
"Ljava/lang/Object;", "Ljava/lang/Object;"
), ),
GetSystemService2( GetSystemService2(
"Landroid/content/Context;", "Landroid/content/Context;",
"getSystemService", "getSystemService",
arrayOf("Ljava/lang/Class;"), arrayOf("Ljava/lang/Class;"),
"Ljava/lang/Object;", "Ljava/lang/Object;"
), ),
GetActiveNetworkInfo( GetActiveNetworkInfo(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"getActiveNetworkInfo", "getActiveNetworkInfo",
arrayOf(), arrayOf(),
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;"
), ),
IsConnected( IsConnected(
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;",
"isConnected", "isConnected",
arrayOf(), arrayOf(),
"Z", "Z"
), ),
IsConnectedOrConnecting( IsConnectedOrConnecting(
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;",
"isConnectedOrConnecting", "isConnectedOrConnecting",
arrayOf(), arrayOf(),
"Z", "Z"
), ),
IsAvailable( IsAvailable(
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;",
"isAvailable", "isAvailable",
arrayOf(), arrayOf(),
"Z", "Z"
), ),
GetState( GetState(
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;",
"getState", "getState",
arrayOf(), arrayOf(),
"Landroid/net/NetworkInfo\$State;", "Landroid/net/NetworkInfo\$State;"
), ),
GetDetailedState( GetDetailedState(
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;",
"getDetailedState", "getDetailedState",
arrayOf(), arrayOf(),
"Landroid/net/NetworkInfo\$DetailedState;", "Landroid/net/NetworkInfo\$DetailedState;"
), ),
IsActiveNetworkMetered( IsActiveNetworkMetered(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"isActiveNetworkMetered", "isActiveNetworkMetered",
arrayOf(), arrayOf(),
"Z", "Z"
), ),
GetActiveNetwork( GetActiveNetwork(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"getActiveNetwork", "getActiveNetwork",
arrayOf(), arrayOf(),
"Landroid/net/Network;", "Landroid/net/Network;"
), ),
GetNetworkInfo( GetNetworkInfo(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"getNetworkInfo", "getNetworkInfo",
arrayOf("Landroid/net/Network;"), arrayOf("Landroid/net/Network;"),
"Landroid/net/NetworkInfo;", "Landroid/net/NetworkInfo;"
), ),
HasTransport( HasTransport(
"Landroid/net/NetworkCapabilities;", "Landroid/net/NetworkCapabilities;",
"hasTransport", "hasTransport",
arrayOf("I"), arrayOf("I"),
"Z", "Z"
), ),
HasCapability( HasCapability(
"Landroid/net/NetworkCapabilities;", "Landroid/net/NetworkCapabilities;",
"hasCapability", "hasCapability",
arrayOf("I"), arrayOf("I"),
"Z", "Z"
), ),
RegisterBestMatchingNetworkCallback( RegisterBestMatchingNetworkCallback(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"registerBestMatchingNetworkCallback", "registerBestMatchingNetworkCallback",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"),
"V", "V"
), ),
RegisterDefaultNetworkCallback1( RegisterDefaultNetworkCallback1(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"registerDefaultNetworkCallback", "registerDefaultNetworkCallback",
arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"), arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V", "V"
), ),
RegisterDefaultNetworkCallback2( RegisterDefaultNetworkCallback2(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"registerDefaultNetworkCallback", "registerDefaultNetworkCallback",
arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"),
"V", "V"
), ),
RegisterNetworkCallback1( RegisterNetworkCallback1(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"registerNetworkCallback", "registerNetworkCallback",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V", "V"
), ),
RegisterNetworkCallback2( RegisterNetworkCallback2(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"registerNetworkCallback", "registerNetworkCallback",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/app/PendingIntent;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/app/PendingIntent;"),
"V", "V"
), ),
RegisterNetworkCallback3( RegisterNetworkCallback3(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"registerNetworkCallback", "registerNetworkCallback",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"),
"V", "V"
), ),
RequestNetwork1( RequestNetwork1(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"requestNetwork", "requestNetwork",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V", "V"
), ),
RequestNetwork2( RequestNetwork2(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"requestNetwork", "requestNetwork",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "I"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "I"),
"V", "V"
), ),
RequestNetwork3( RequestNetwork3(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"requestNetwork", "requestNetwork",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;"),
"V", "V"
), ),
RequestNetwork4( RequestNetwork4(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"requestNetwork", "requestNetwork",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/app/PendingIntent;"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/app/PendingIntent;"),
"V", "V"
), ),
RequestNetwork5( RequestNetwork5(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"requestNetwork", "requestNetwork",
arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;", "I"), arrayOf("Landroid/net/NetworkRequest;", "Landroid/net/ConnectivityManager\$NetworkCallback;", "Landroid/os/Handler;", "I"),
"V", "V"
), ),
UnregisterNetworkCallback1( UnregisterNetworkCallback1(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"unregisterNetworkCallback", "unregisterNetworkCallback",
arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"), arrayOf("Landroid/net/ConnectivityManager\$NetworkCallback;"),
"V", "V"
), ),
UnregisterNetworkCallback2( UnregisterNetworkCallback2(
"Landroid/net/ConnectivityManager;", "Landroid/net/ConnectivityManager;",
"unregisterNetworkCallback", "unregisterNetworkCallback",
arrayOf("Landroid/app/PendingIntent;"), arrayOf("Landroid/app/PendingIntent;"),
"V", "V"
), )
} }
} }

View File

@ -7,7 +7,7 @@ import app.revanced.patcher.patch.annotation.Patch
@Patch( @Patch(
name = "Predictive back gesture", name = "Predictive back gesture",
description = "Enables the predictive back gesture introduced on Android 13.", description = "Enables the predictive back gesture introduced on Android 13.",
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object PredictiveBackGesturePatch : ResourcePatch() { object PredictiveBackGesturePatch : ResourcePatch() {

View File

@ -8,7 +8,7 @@ import org.w3c.dom.Element
@Patch( @Patch(
name = "Enable Android debugging", name = "Enable Android debugging",
description = "Enables Android debugging capabilities. This can slow down the app.", description = "Enables Android debugging capabilities. This can slow down the app.",
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object EnableAndroidDebuggingPatch : ResourcePatch() { object EnableAndroidDebuggingPatch : ResourcePatch() {

View File

@ -5,14 +5,14 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch import app.revanced.patches.all.misc.debugging.EnableAndroidDebuggingPatch
import app.revanced.util.Utils.trimIndentMultiline import app.revanced.util.Utils.trimIndentMultiline
import org.w3c.dom.Element
import java.io.File import java.io.File
import org.w3c.dom.Element
@Patch( @Patch(
name = "Override certificate pinning", name = "Override certificate pinning",
description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.", description = "Overrides certificate pinning, allowing to inspect traffic via a proxy.",
dependencies = [EnableAndroidDebuggingPatch::class], dependencies = [EnableAndroidDebuggingPatch::class],
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object OverrideCertificatePinningPatch : ResourcePatch() { object OverrideCertificatePinningPatch : ResourcePatch() {
@ -54,7 +54,7 @@ object OverrideCertificatePinningPatch : ResourcePatch() {
</trust-anchors> </trust-anchors>
</debug-overrides> </debug-overrides>
</network-security-config> </network-security-config>
""".trimIndentMultiline(), """.trimIndentMultiline()
) )
} }
} }

View File

@ -5,13 +5,13 @@ import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption import app.revanced.patcher.patch.options.PatchOption.PatchExtensions.stringPatchOption
import app.revanced.patcher.patch.options.PatchOptionException import app.revanced.patcher.patch.options.PatchOptionException
import org.w3c.dom.Element
import java.io.Closeable import java.io.Closeable
import org.w3c.dom.Element
@Patch( @Patch(
name = "Change package name", name = "Change package name",
description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.", description = "Appends \".revanced\" to the package name by default. Changing the package name of the app can lead to unexpected issues.",
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object ChangePackageNamePatch : ResourcePatch(), Closeable { object ChangePackageNamePatch : ResourcePatch(), Closeable {
@ -22,7 +22,7 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
values = mapOf("Default" to "Default"), values = mapOf("Default" to "Default"),
title = "Package name", title = "Package name",
description = "The name of the package to rename the app to.", description = "The name of the package to rename the app to.",
required = true, required = true
) { ) {
it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$")) it == "Default" || it!!.matches(Regex("^[a-z]\\w*(\\.[a-z]\\w*)+\$"))
} }
@ -64,7 +64,7 @@ object ChangePackageNamePatch : ResourcePatch(), Closeable {
replacementPackageName replacementPackageName
} else { } else {
"${manifest.getAttribute("package")}.revanced" "${manifest.getAttribute("package")}.revanced"
}, }
) )
} }
} }

View File

@ -11,9 +11,9 @@ import app.revanced.util.*
import app.revanced.util.resource.ArrayResource import app.revanced.util.resource.ArrayResource
import app.revanced.util.resource.BaseResource import app.revanced.util.resource.BaseResource
import app.revanced.util.resource.StringResource import app.revanced.util.resource.StringResource
import org.w3c.dom.Node
import java.io.Closeable import java.io.Closeable
import java.util.* import java.util.*
import org.w3c.dom.Node
/** /**
* An identifier of an app. For example, `youtube`. * An identifier of an app. For example, `youtube`.
@ -82,11 +82,11 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
fun addResources( fun addResources(
value: Value, value: Value,
resourceKind: String, resourceKind: String,
transform: (Node) -> BaseResource, transform: (Node) -> BaseResource
) { ) {
inputStreamFromBundledResource( inputStreamFromBundledResource(
"addresources", "addresources",
"$value/$resourceKind.xml", "$value/$resourceKind.xml"
)?.let { stream -> )?.let { stream ->
// Add the resources associated with the given value to the map, // Add the resources associated with the given value to the map,
// instead of overwriting it. // instead of overwriting it.
@ -144,7 +144,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
*/ */
operator fun invoke( operator fun invoke(
value: Value, value: Value,
resource: BaseResource, resource: BaseResource
) = getOrPut(value, ::mutableSetOf).add(resource) ) = getOrPut(value, ::mutableSetOf).add(resource)
/** /**
@ -157,7 +157,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
*/ */
operator fun invoke( operator fun invoke(
value: Value, value: Value,
resources: Iterable<BaseResource>, resources: Iterable<BaseResource>
) = getOrPut(value, ::mutableSetOf).addAll(resources) ) = getOrPut(value, ::mutableSetOf).addAll(resources)
/** /**
@ -174,7 +174,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
name: String, name: String,
value: String, value: String,
formatted: Boolean = true, formatted: Boolean = true,
resourceValue: Value = "values", resourceValue: Value = "values"
) = invoke(resourceValue, StringResource(name, value, formatted)) ) = invoke(resourceValue, StringResource(name, value, formatted))
/** /**
@ -187,7 +187,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
*/ */
operator fun invoke( operator fun invoke(
name: String, name: String,
items: List<String>, items: List<String>
) = invoke("values", ArrayResource(name, items)) ) = invoke("values", ArrayResource(name, items))
/** /**
@ -218,7 +218,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
appId to patchId appId to patchId
} }
}, }
): Boolean { ): Boolean {
val (appId, patchId) = patch.parseIds() val (appId, patchId) = patch.parseIds()
@ -241,7 +241,7 @@ object AddResourcesPatch : ResourcePatch(), MutableMap<Value, MutableSet<BaseRes
override fun close() { override fun close() {
operator fun MutableMap<String, Pair<DomFileEditor, Node>>.invoke( operator fun MutableMap<String, Pair<DomFileEditor, Node>>.invoke(
value: Value, value: Value,
resource: BaseResource, resource: BaseResource
) { ) {
// TODO: Fix open-closed principle violation by modifying BaseResource#serialize so that it accepts // TODO: Fix open-closed principle violation by modifying BaseResource#serialize so that it accepts
// a Value and the map of documents. It will then get or put the document suitable for its resource type // a Value and the map of documents. It will then get or put the document suitable for its resource type

View File

@ -14,13 +14,19 @@ abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
): T? ): T?
abstract fun transform(mutableMethod: MutableMethod, entry: T) abstract fun transform(
mutableMethod: MutableMethod,
entry: T
)
// Returns the patch indices as a Sequence, which will execute lazily. // Returns the patch indices as a Sequence, which will execute lazily.
fun findPatchIndices(classDef: ClassDef, method: Method): Sequence<T>? { fun findPatchIndices(
classDef: ClassDef,
method: Method
): Sequence<T>? {
return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) -> return method.implementation?.instructions?.asSequence()?.withIndex()?.mapNotNull { (index, instruction) ->
filterMap(classDef, method, instruction, index) filterMap(classDef, method, instruction, index)
} }
@ -30,14 +36,15 @@ abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
// Find all methods to patch // Find all methods to patch
buildMap { buildMap {
context.classes.forEach { classDef -> context.classes.forEach { classDef ->
val methods = buildList { val methods =
classDef.methods.forEach { method -> buildList {
// Since the Sequence executes lazily, classDef.methods.forEach { method ->
// using any() results in only calling // Since the Sequence executes lazily,
// filterMap until the first index has been found. // using any() results in only calling
if (findPatchIndices(classDef, method)?.any() == true) add(method) // filterMap until the first index has been found.
if (findPatchIndices(classDef, method)?.any() == true) add(method)
}
} }
}
if (methods.isNotEmpty()) { if (methods.isNotEmpty()) {
put(classDef, methods) put(classDef, methods)
@ -48,8 +55,9 @@ abstract class BaseTransformInstructionsPatch<T> : BytecodePatch(emptySet()) {
val mutableClass = context.proxy(classDef).mutableClass val mutableClass = context.proxy(classDef).mutableClass
methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod -> methods.map(mutableClass::findMutableMethodOf).forEach methods@{ mutableMethod ->
val patchIndices = findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque()) val patchIndices =
?: return@methods findPatchIndices(mutableClass, mutableMethod)?.toCollection(ArrayDeque())
?: return@methods
while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast()) while (!patchIndices.isEmpty()) transform(mutableMethod, patchIndices.removeLast())
} }

View File

@ -33,21 +33,22 @@ interface IMethodCall {
definingClassDescriptor: String, definingClassDescriptor: String,
method: MutableMethod, method: MutableMethod,
instruction: Instruction35c, instruction: Instruction35c,
instructionIndex: Int, instructionIndex: Int
) { ) {
val registers = arrayOf( val registers =
instruction.registerC, arrayOf(
instruction.registerD, instruction.registerC,
instruction.registerE, instruction.registerD,
instruction.registerF, instruction.registerE,
instruction.registerG, instruction.registerF,
) instruction.registerG
)
val argsNum = methodParams.size + 1 // + 1 for instance of definedClassName val argsNum = methodParams.size + 1 // + 1 for instance of definedClassName
if (argsNum > registers.size) { if (argsNum > registers.size) {
// should never happen, but just to be sure (also for the future) a safety check // should never happen, but just to be sure (also for the future) a safety check
throw RuntimeException( throw RuntimeException(
"Not enough registers for $definedClassName#$methodName: " + "Not enough registers for $definedClassName#$methodName: " +
"Required $argsNum registers, but only got ${registers.size}.", "Required $argsNum registers, but only got ${registers.size}."
) )
} }
@ -57,26 +58,27 @@ interface IMethodCall {
method.replaceInstruction( method.replaceInstruction(
instructionIndex, instructionIndex,
"invoke-static { $args }, $definingClassDescriptor->$replacementMethodDefinition", "invoke-static { $args }, $definingClassDescriptor->$replacementMethodDefinition"
) )
} }
} }
inline fun <reified E> fromMethodReference( inline fun <reified E> fromMethodReference(
methodReference: MethodReference, methodReference: MethodReference
) )
where E : Enum<E>, E : IMethodCall = enumValues<E>().firstOrNull { search -> where E : Enum<E>, E : IMethodCall =
search.definedClassName == methodReference.definingClass && enumValues<E>().firstOrNull { search ->
search.methodName == methodReference.name && search.definedClassName == methodReference.definingClass &&
methodReference.parameterTypes.toTypedArray().contentEquals(search.methodParams) && search.methodName == methodReference.name &&
search.returnType == methodReference.returnType methodReference.parameterTypes.toTypedArray().contentEquals(search.methodParams) &&
} search.returnType == methodReference.returnType
}
inline fun <reified E> filterMapInstruction35c( inline fun <reified E> filterMapInstruction35c(
integrationsClassDescriptorPrefix: String, integrationsClassDescriptorPrefix: String,
classDef: ClassDef, classDef: ClassDef,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
): Instruction35cInfo? where E : Enum<E>, E : IMethodCall { ): Instruction35cInfo? where E : Enum<E>, E : IMethodCall {
if (classDef.type.startsWith(integrationsClassDescriptorPrefix)) { if (classDef.type.startsWith(integrationsClassDescriptorPrefix)) {
// avoid infinite recursion // avoid infinite recursion

View File

@ -15,7 +15,7 @@ import com.android.tools.smali.dexlib2.iface.instruction.Instruction
description = "Removes the restriction of capturing audio from apps that normally wouldn't allow it.", description = "Removes the restriction of capturing audio from apps that normally wouldn't allow it.",
dependencies = [RemoveCaptureRestrictionResourcePatch::class], dependencies = [RemoveCaptureRestrictionResourcePatch::class],
use = false, use = false,
requiresIntegrations = true, requiresIntegrations = true
) )
@Suppress("unused") @Suppress("unused")
object RemoveCaptureRestrictionPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() { object RemoveCaptureRestrictionPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() {
@ -28,35 +28,38 @@ object RemoveCaptureRestrictionPatch : BaseTransformInstructionsPatch<Instructio
override val definedClassName: String, override val definedClassName: String,
override val methodName: String, override val methodName: String,
override val methodParams: Array<String>, override val methodParams: Array<String>,
override val returnType: String, override val returnType: String
) : IMethodCall { ) : IMethodCall {
SetAllowedCapturePolicySingle( SetAllowedCapturePolicySingle(
"Landroid/media/AudioAttributes\$Builder;", "Landroid/media/AudioAttributes\$Builder;",
"setAllowedCapturePolicy", "setAllowedCapturePolicy",
arrayOf("I"), arrayOf("I"),
"Landroid/media/AudioAttributes\$Builder;", "Landroid/media/AudioAttributes\$Builder;"
), ),
SetAllowedCapturePolicyGlobal( SetAllowedCapturePolicyGlobal(
"Landroid/media/AudioManager;", "Landroid/media/AudioManager;",
"setAllowedCapturePolicy", "setAllowedCapturePolicy",
arrayOf("I"), arrayOf("I"),
"V", "V"
), )
} }
override fun filterMap( override fun filterMap(
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
) = filterMapInstruction35c<MethodCall>( ) = filterMapInstruction35c<MethodCall>(
INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX, INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
classDef, classDef,
instruction, instruction,
instructionIndex, instructionIndex
) )
override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) { override fun transform(
mutableMethod: MutableMethod,
entry: Instruction35cInfo
) {
val (methodType, instruction, instructionIndex) = entry val (methodType, instruction, instructionIndex) = entry
methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex) methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
} }

View File

@ -19,7 +19,7 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
name = "Remove screenshot restriction", name = "Remove screenshot restriction",
description = "Removes the restriction of taking screenshots in apps that normally wouldn't allow it.", description = "Removes the restriction of taking screenshots in apps that normally wouldn't allow it.",
use = false, use = false,
requiresIntegrations = true, requiresIntegrations = true
) )
@Suppress("unused") @Suppress("unused")
object RemoveScreenshotRestrictionPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() { object RemoveScreenshotRestrictionPatch : BaseTransformInstructionsPatch<Instruction35cInfo>() {
@ -36,15 +36,18 @@ object RemoveScreenshotRestrictionPatch : BaseTransformInstructionsPatch<Instruc
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
) = filterMapInstruction35c<MethodCall>( ) = filterMapInstruction35c<MethodCall>(
INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX, INTEGRATIONS_CLASS_DESCRIPTOR_PREFIX,
classDef, classDef,
instruction, instruction,
instructionIndex, instructionIndex
) )
override fun transform(mutableMethod: MutableMethod, entry: Instruction35cInfo) { override fun transform(
mutableMethod: MutableMethod,
entry: Instruction35cInfo
) {
val (methodType, instruction, instructionIndex) = entry val (methodType, instruction, instructionIndex) = entry
methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex) methodType.replaceInvokeVirtualWithIntegrations(INTEGRATIONS_CLASS_DESCRIPTOR, mutableMethod, instruction, instructionIndex)
} }
@ -54,20 +57,20 @@ object RemoveScreenshotRestrictionPatch : BaseTransformInstructionsPatch<Instruc
override val definedClassName: String, override val definedClassName: String,
override val methodName: String, override val methodName: String,
override val methodParams: Array<String>, override val methodParams: Array<String>,
override val returnType: String, override val returnType: String
) : IMethodCall { ) : IMethodCall {
AddFlags( AddFlags(
"Landroid/view/Window;", "Landroid/view/Window;",
"addFlags", "addFlags",
arrayOf("I"), arrayOf("I"),
"V", "V"
), ),
SetFlags( SetFlags(
"Landroid/view/Window;", "Landroid/view/Window;",
"setFlags", "setFlags",
arrayOf("I", "I"), arrayOf("I", "I"),
"V", "V"
), )
} }
} }
@ -76,7 +79,7 @@ private class ModifyLayoutParamsFlags : BaseTransformInstructionsPatch<Pair<Inst
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
): Pair<Instruction22c, Int>? { ): Pair<Instruction22c, Int>? {
if (instruction.opcode != Opcode.IPUT) { if (instruction.opcode != Opcode.IPUT) {
return null return null
@ -95,13 +98,16 @@ private class ModifyLayoutParamsFlags : BaseTransformInstructionsPatch<Pair<Inst
return Pair(instruction22c, instructionIndex) return Pair(instruction22c, instructionIndex)
} }
override fun transform(mutableMethod: MutableMethod, entry: Pair<Instruction22c, Int>) { override fun transform(
mutableMethod: MutableMethod,
entry: Pair<Instruction22c, Int>
) {
val (instruction, index) = entry val (instruction, index) = entry
val register = instruction.registerA val register = instruction.registerA
mutableMethod.addInstructions( mutableMethod.addInstructions(
index, index,
"and-int/lit16 v$register, v$register, -0x2001", "and-int/lit16 v$register, v$register, -0x2001"
) )
} }
} }

View File

@ -19,7 +19,7 @@ import java.util.*
@Patch( @Patch(
name = "Spoof SIM country", name = "Spoof SIM country",
description = "Spoofs country information returned by the SIM card provider.", description = "Spoofs country information returned by the SIM card provider.",
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object SpoofSimCountryPatch : BaseTransformInstructionsPatch<Pair<Int, String>>() { object SpoofSimCountryPatch : BaseTransformInstructionsPatch<Pair<Int, String>>() {
@ -27,17 +27,17 @@ object SpoofSimCountryPatch : BaseTransformInstructionsPatch<Pair<Int, String>>(
private val networkCountryIso by isoCountryPatchOption( private val networkCountryIso by isoCountryPatchOption(
"networkCountryIso", "networkCountryIso",
"Network ISO Country Code", "Network ISO Country Code"
) )
private val simCountryIso by isoCountryPatchOption( private val simCountryIso by isoCountryPatchOption(
"simCountryIso", "simCountryIso",
"Sim ISO Country Code", "Sim ISO Country Code"
) )
private fun isoCountryPatchOption( private fun isoCountryPatchOption(
key: String, key: String,
title: String, title: String
) = stringPatchOption( ) = stringPatchOption(
key, key,
null, null,
@ -45,39 +45,41 @@ object SpoofSimCountryPatch : BaseTransformInstructionsPatch<Pair<Int, String>>(
title, title,
"ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.", "ISO-3166-1 alpha-2 country code equivalent for the SIM provider's country code.",
false, false,
validator = { it: String? -> it == null || it.uppercase() in countries.values }, validator = { it: String? -> it == null || it.uppercase() in countries.values }
) )
override fun filterMap( override fun filterMap(
classDef: ClassDef, classDef: ClassDef,
method: Method, method: Method,
instruction: Instruction, instruction: Instruction,
instructionIndex: Int, instructionIndex: Int
): Pair<Int, String>? { ): Pair<Int, String>? {
if (instruction !is ReferenceInstruction) return null if (instruction !is ReferenceInstruction) return null
val reference = instruction.reference as? MethodReference ?: return null val reference = instruction.reference as? MethodReference ?: return null
val match = MethodCall.entries.firstOrNull { search -> val match =
MethodUtil.methodSignaturesMatch(reference, search.reference) MethodCall.entries.firstOrNull { search ->
} ?: return null MethodUtil.methodSignaturesMatch(reference, search.reference)
} ?: return null
val iso = when (match) { val iso =
MethodCall.NetworkCountryIso -> networkCountryIso when (match) {
MethodCall.SimCountryIso -> simCountryIso MethodCall.NetworkCountryIso -> networkCountryIso
}?.lowercase() MethodCall.SimCountryIso -> simCountryIso
}?.lowercase()
return iso?.let { instructionIndex to it } return iso?.let { instructionIndex to it }
} }
override fun transform( override fun transform(
mutableMethod: MutableMethod, mutableMethod: MutableMethod,
entry: Pair<Int, String>, entry: Pair<Int, String>
) = transformMethodCall(entry, mutableMethod) ) = transformMethodCall(entry, mutableMethod)
private fun transformMethodCall( private fun transformMethodCall(
entry: Pair<Int, String>, entry: Pair<Int, String>,
mutableMethod: MutableMethod, mutableMethod: MutableMethod
) { ) {
val (instructionIndex, methodCallValue) = entry val (instructionIndex, methodCallValue) = entry
@ -85,28 +87,28 @@ object SpoofSimCountryPatch : BaseTransformInstructionsPatch<Pair<Int, String>>(
mutableMethod.replaceInstruction( mutableMethod.replaceInstruction(
instructionIndex + 1, instructionIndex + 1,
"const-string v$register, \"$methodCallValue\"", "const-string v$register, \"$methodCallValue\""
) )
} }
private enum class MethodCall( private enum class MethodCall(
val reference: MethodReference, val reference: MethodReference
) { ) {
NetworkCountryIso( NetworkCountryIso(
ImmutableMethodReference( ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;", "Landroid/telephony/TelephonyManager;",
"getNetworkCountryIso", "getNetworkCountryIso",
emptyList(), emptyList(),
"Ljava/lang/String;", "Ljava/lang/String;"
), )
), ),
SimCountryIso( SimCountryIso(
ImmutableMethodReference( ImmutableMethodReference(
"Landroid/telephony/TelephonyManager;", "Landroid/telephony/TelephonyManager;",
"getSimCountryIso", "getSimCountryIso",
emptyList(), emptyList(),
"Ljava/lang/String;", "Ljava/lang/String;"
), )
), )
} }
} }

View File

@ -12,11 +12,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch( @Patch(
name = "Pro unlock", name = "Pro unlock",
compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers", ["4.52"])], compatiblePackages = [CompatiblePackage("com.backdrops.wallpapers", ["4.52"])]
) )
@Suppress("unused") @Suppress("unused")
object ProUnlockPatch : BytecodePatch( object ProUnlockPatch : BytecodePatch(
setOf(ProUnlockFingerprint), setOf(ProUnlockFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
ProUnlockFingerprint.result?.let { result -> ProUnlockFingerprint.result?.let { result ->
@ -28,7 +28,7 @@ object ProUnlockPatch : BytecodePatch(
result.scanResult.patternScanResult!!.endIndex, result.scanResult.patternScanResult!!.endIndex,
""" """
const/4 v$register, 0x1 const/4 v$register, 0x1
""", """
) )
} }
} ?: throw ProUnlockFingerprint.exception } ?: throw ProUnlockFingerprint.exception

View File

@ -4,15 +4,16 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal object ProUnlockFingerprint : MethodFingerprint( internal object ProUnlockFingerprint : MethodFingerprint(
opcodes = listOf( opcodes =
listOf(
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_EQZ, Opcode.IF_EQZ
), ),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;" && methodDef.definingClass == "Lcom/backdrops/wallpapers/data/local/DatabaseHandlerIAB;" &&
methodDef.name == "lambda\$existPurchase\$0" methodDef.name == "lambda\$existPurchase\$0"
}, }
) )

View File

@ -10,11 +10,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Unlock pro", name = "Unlock pro",
compatiblePackages = [CompatiblePackage("com.candylink.openvpn")], compatiblePackages = [CompatiblePackage("com.candylink.openvpn")]
) )
@Suppress("unused") @Suppress("unused")
object UnlockProPatch : BytecodePatch( object UnlockProPatch : BytecodePatch(
setOf(IsPremiumPurchasedFingerprint), setOf(IsPremiumPurchasedFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
IsPremiumPurchasedFingerprint.result?.mutableMethod?.addInstructions( IsPremiumPurchasedFingerprint.result?.mutableMethod?.addInstructions(
@ -22,7 +22,7 @@ object UnlockProPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) ?: throw IsPremiumPurchasedFingerprint.exception ) ?: throw IsPremiumPurchasedFingerprint.exception
} }
} }

View File

@ -6,5 +6,5 @@ internal object IsPremiumPurchasedFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("PreferenceProvider;") && methodDef.definingClass.endsWith("PreferenceProvider;") &&
methodDef.name == "isPremiumPurchased" methodDef.name == "isPremiumPurchased"
}, }
) )

View File

@ -11,11 +11,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Bypass root checks", name = "Bypass root checks",
description = "Removes the restriction to use the app with root permissions or on a custom ROM.", description = "Removes the restriction to use the app with root permissions or on a custom ROM.",
compatiblePackages = [CompatiblePackage("it.ipzs.cieid")], compatiblePackages = [CompatiblePackage("it.ipzs.cieid")]
) )
@Suppress("unused") @Suppress("unused")
object BypassRootChecksPatch : BytecodePatch( object BypassRootChecksPatch : BytecodePatch(
setOf(CheckRootFingerprint), setOf(CheckRootFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
CheckRootFingerprint.result?.mutableMethod?.addInstruction(1, "return-void") CheckRootFingerprint.result?.mutableMethod?.addInstruction(1, "return-void")

View File

@ -5,5 +5,5 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object CheckRootFingerprint : MethodFingerprint( internal object CheckRootFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lit/ipzs/cieid/BaseActivity;" && methodDef.name == "onResume" methodDef.definingClass == "Lit/ipzs/cieid/BaseActivity;" && methodDef.name == "onResume"
}, }
) )

View File

@ -12,11 +12,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Hide story ads", name = "Hide story ads",
description = "Hides the ads in the Facebook app stories.", description = "Hides the ads in the Facebook app stories.",
compatiblePackages = [CompatiblePackage("com.facebook.katana")], compatiblePackages = [CompatiblePackage("com.facebook.katana")]
) )
@Suppress("unused") @Suppress("unused")
object HideStoryAdsPatch : BytecodePatch( object HideStoryAdsPatch : BytecodePatch(
setOf(FetchMoreAdsFingerprint, AdsInsertionFingerprint), setOf(FetchMoreAdsFingerprint, AdsInsertionFingerprint)
) { ) {
override fun execute(context: BytecodeContext) = override fun execute(context: BytecodeContext) =
setOf(FetchMoreAdsFingerprint, AdsInsertionFingerprint).forEach { fingerprint -> setOf(FetchMoreAdsFingerprint, AdsInsertionFingerprint).forEach { fingerprint ->

View File

@ -7,9 +7,10 @@ internal abstract class FieldMethodFingerprint(fieldValue: String) : MethodFinge
returnType = "V", returnType = "V",
parameters = listOf(), parameters = listOf(),
customFingerprint = { methodDef, classDef -> customFingerprint = { methodDef, classDef ->
methodDef.name == "run" && classDef.fields.any any@{ field -> methodDef.name == "run" &&
if (field.name != "__redex_internal_original_name") return@any false classDef.fields.any any@{ field ->
(field.initialValue as? StringEncodedValue)?.value == fieldValue if (field.name != "__redex_internal_original_name") return@any false
} (field.initialValue as? StringEncodedValue)?.value == fieldValue
}, }
}
) )

View File

@ -12,11 +12,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Remove bootloader detection", name = "Remove bootloader detection",
description = "Removes the check for an unlocked bootloader.", description = "Removes the check for an unlocked bootloader.",
compatiblePackages = [CompatiblePackage("at.gv.bmf.bmf2go")], compatiblePackages = [CompatiblePackage("at.gv.bmf.bmf2go")]
) )
@Suppress("unused") @Suppress("unused")
object BootloaderDetectionPatch : BytecodePatch( object BootloaderDetectionPatch : BytecodePatch(
setOf(CreateKeyFingerprint, BootStateFingerprint), setOf(CreateKeyFingerprint, BootStateFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
arrayOf(CreateKeyFingerprint, BootStateFingerprint).forEach { fingerprint -> arrayOf(CreateKeyFingerprint, BootStateFingerprint).forEach { fingerprint ->
@ -25,7 +25,7 @@ object BootloaderDetectionPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) ?: throw fingerprint.exception ) ?: throw fingerprint.exception
} }
} }

View File

@ -8,7 +8,8 @@ import com.android.tools.smali.dexlib2.Opcode
internal object BootStateFingerprint : MethodFingerprint( internal object BootStateFingerprint : MethodFingerprint(
"Z", "Z",
accessFlags = AccessFlags.PUBLIC.value, accessFlags = AccessFlags.PUBLIC.value,
opcodes = listOf( opcodes =
listOf(
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_4, Opcode.CONST_4,
@ -25,6 +26,6 @@ internal object BootStateFingerprint : MethodFingerprint(
Opcode.IF_NE, Opcode.IF_NE,
Opcode.GOTO, Opcode.GOTO,
Opcode.MOVE, Opcode.MOVE,
Opcode.RETURN, Opcode.RETURN
), )
) )

View File

@ -7,5 +7,5 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object CreateKeyFingerprint : MethodFingerprint( internal object CreateKeyFingerprint : MethodFingerprint(
"Z", "Z",
accessFlags = AccessFlags.PUBLIC.value, accessFlags = AccessFlags.PUBLIC.value,
strings = listOf("attestation", "SHA-256", "random", "EC", "AndroidKeyStore"), strings = listOf("attestation", "SHA-256", "random", "EC", "AndroidKeyStore")
) )

View File

@ -11,11 +11,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Remove root detection", name = "Remove root detection",
description = "Removes the check for root permissions.", description = "Removes the check for root permissions.",
compatiblePackages = [CompatiblePackage("at.gv.bmf.bmf2go")], compatiblePackages = [CompatiblePackage("at.gv.bmf.bmf2go")]
) )
@Suppress("unused") @Suppress("unused")
object RootDetectionPatch : BytecodePatch( object RootDetectionPatch : BytecodePatch(
setOf(RootDetectionFingerprint), setOf(RootDetectionFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
RootDetectionFingerprint.result?.mutableMethod?.addInstructions( RootDetectionFingerprint.result?.mutableMethod?.addInstructions(
@ -23,7 +23,7 @@ object RootDetectionPatch : BytecodePatch(
""" """
sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; sget-object v0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
return-object v0 return-object v0
""", """
) ?: throw RootDetectionFingerprint.exception ) ?: throw RootDetectionFingerprint.exception
} }
} }

View File

@ -10,13 +10,14 @@ internal object RootDetectionFingerprint : MethodFingerprint(
"L", "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes =
listOf(
Opcode.NEW_INSTANCE, Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.RETURN_OBJECT, Opcode.RETURN_OBJECT
), )
) )

View File

@ -14,11 +14,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch( @Patch(
name = "Remove device restrictions", name = "Remove device restrictions",
description = "Removes restrictions from using the app on any device. Requires mounting patched app over original.", description = "Removes restrictions from using the app on any device. Requires mounting patched app over original.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.recorder")], compatiblePackages = [CompatiblePackage("com.google.android.apps.recorder")]
) )
@Suppress("unused") @Suppress("unused")
object RemoveDeviceRestrictions : BytecodePatch( object RemoveDeviceRestrictions : BytecodePatch(
setOf(OnApplicationCreateFingerprint), setOf(OnApplicationCreateFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
OnApplicationCreateFingerprint.result?.let { OnApplicationCreateFingerprint.result?.let {

View File

@ -8,5 +8,5 @@ internal object OnApplicationCreateFingerprint : MethodFingerprint(
if (methodDef.name != "onCreate") return@custom false if (methodDef.name != "onCreate") return@custom false
classDef.type.endsWith("RecorderApplication;") classDef.type.endsWith("RecorderApplication;")
}, }
) )

View File

@ -10,17 +10,18 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Disable ads", name = "Disable ads",
compatiblePackages = [CompatiblePackage("com.myprog.hexedit")], compatiblePackages = [CompatiblePackage("com.myprog.hexedit")]
) )
@Suppress("unused") @Suppress("unused")
object DisableAdsPatch : BytecodePatch( object DisableAdsPatch : BytecodePatch(
setOf(PrimaryAdsFingerprint), setOf(PrimaryAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) = PrimaryAdsFingerprint.result?.mutableMethod?.replaceInstructions( override fun execute(context: BytecodeContext) =
0, PrimaryAdsFingerprint.result?.mutableMethod?.replaceInstructions(
""" 0,
"""
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) ?: throw PrimaryAdsFingerprint.exception ) ?: throw PrimaryAdsFingerprint.exception
} }

View File

@ -5,5 +5,5 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object PrimaryAdsFingerprint : MethodFingerprint( internal object PrimaryAdsFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled" methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled"
}, }
) )

View File

@ -9,11 +9,11 @@ import app.revanced.patches.iconpackstudio.misc.pro.fingerprints.CheckProFingerp
@Patch( @Patch(
name = "Unlock pro", name = "Unlock pro",
compatiblePackages = [CompatiblePackage("ginlemon.iconpackstudio", ["2.2 build 016"])], compatiblePackages = [CompatiblePackage("ginlemon.iconpackstudio", ["2.2 build 016"])]
) )
@Suppress("unused") @Suppress("unused")
object UnlockProPatch : BytecodePatch( object UnlockProPatch : BytecodePatch(
setOf(CheckProFingerprint), setOf(CheckProFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val method = CheckProFingerprint.result!!.mutableMethod val method = CheckProFingerprint.result!!.mutableMethod
@ -22,7 +22,7 @@ object UnlockProPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) )
} }
} }

View File

@ -4,5 +4,5 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object CheckProFingerprint : MethodFingerprint( internal object CheckProFingerprint : MethodFingerprint(
"Z", "Z",
customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("IPSPurchaseRepository;") }, customFingerprint = { methodDef, _ -> methodDef.definingClass.endsWith("IPSPurchaseRepository;") }
) )

View File

@ -12,15 +12,16 @@ import app.revanced.util.returnEarly
@Patch( @Patch(
name = "Remove root detection", name = "Remove root detection",
description = "Removes the check for root permissions and unlocked bootloader.", description = "Removes the check for root permissions and unlocked bootloader.",
compatiblePackages = [CompatiblePackage("at.gv.oe.app")], compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
) )
@Suppress("unused") @Suppress("unused")
object RootDetectionPatch : BytecodePatch( object RootDetectionPatch : BytecodePatch(
setOf(AttestationSupportedCheckFingerprint, BootloaderCheckFingerprint, RootCheckFingerprint), setOf(AttestationSupportedCheckFingerprint, BootloaderCheckFingerprint, RootCheckFingerprint)
) { ) {
override fun execute(context: BytecodeContext) = listOf( override fun execute(context: BytecodeContext) =
AttestationSupportedCheckFingerprint, listOf(
BootloaderCheckFingerprint, AttestationSupportedCheckFingerprint,
RootCheckFingerprint, BootloaderCheckFingerprint,
).returnEarly(true) RootCheckFingerprint
).returnEarly(true)
} }

View File

@ -9,5 +9,5 @@ internal object AttestationSupportedCheckFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.name == "attestationSupportCheck" && methodDef.name == "attestationSupportCheck" &&
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;") methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
}, }
) )

View File

@ -9,5 +9,5 @@ internal object BootloaderCheckFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.name == "bootloaderCheck" && methodDef.name == "bootloaderCheck" &&
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;") methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
}, }
) )

View File

@ -9,5 +9,5 @@ internal object RootCheckFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.name == "rootCheck" && methodDef.name == "rootCheck" &&
methodDef.definingClass.endsWith("/DeviceIntegrityCheck;") methodDef.definingClass.endsWith("/DeviceIntegrityCheck;")
}, }
) )

View File

@ -10,11 +10,11 @@ import app.revanced.patches.idaustria.detection.signature.fingerprints.SpoofSign
@Patch( @Patch(
name = "Spoof signature", name = "Spoof signature",
description = "Spoofs the signature of the app.", description = "Spoofs the signature of the app.",
compatiblePackages = [CompatiblePackage("at.gv.oe.app")], compatiblePackages = [CompatiblePackage("at.gv.oe.app")]
) )
@Suppress("unused") @Suppress("unused")
object SpoofSignaturePatch : BytecodePatch( object SpoofSignaturePatch : BytecodePatch(
setOf(SpoofSignatureFingerprint), setOf(SpoofSignatureFingerprint)
) { ) {
private const val EXPECTED_SIGNATURE = private const val EXPECTED_SIGNATURE =
"OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" + "OpenSSLRSAPublicKey{modulus=ac3e6fd6050aa7e0d6010ae58190404cd89a56935b44f6fee" +
@ -35,7 +35,7 @@ object SpoofSignaturePatch : BytecodePatch(
""" """
const-string v0, "$EXPECTED_SIGNATURE" const-string v0, "$EXPECTED_SIGNATURE"
return-object v0 return-object v0
""", """
) )
} }
} }

View File

@ -9,5 +9,5 @@ internal object SpoofSignatureFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PRIVATE.value, accessFlags = AccessFlags.PRIVATE.value,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey" methodDef.definingClass.endsWith("/SL2Step1Task;") && methodDef.name == "getPubKey"
}, }
) )

View File

@ -10,11 +10,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Hide ads", name = "Hide ads",
compatiblePackages = [CompatiblePackage("com.nis.app")], compatiblePackages = [CompatiblePackage("com.nis.app")]
) )
@Suppress("unused") @Suppress("unused")
object HideAdsPatch : BytecodePatch( object HideAdsPatch : BytecodePatch(
setOf(InshortsAdsFingerprint), setOf(InshortsAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
InshortsAdsFingerprint.result?.let { result -> InshortsAdsFingerprint.result?.let { result ->
@ -23,7 +23,7 @@ object HideAdsPatch : BytecodePatch(
0, 0,
""" """
return-void return-void
""", """
) )
} }
} ?: throw InshortsAdsFingerprint.exception } ?: throw InshortsAdsFingerprint.exception

View File

@ -4,5 +4,5 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
internal object InshortsAdsFingerprint : MethodFingerprint( internal object InshortsAdsFingerprint : MethodFingerprint(
"V", "V",
strings = listOf("GoogleAdLoader", "exception in requestAd"), strings = listOf("GoogleAdLoader", "exception in requestAd")
) )

View File

@ -15,15 +15,15 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch( @Patch(
name = "Hide timeline ads", name = "Hide timeline ads",
compatiblePackages = [CompatiblePackage("com.instagram.android")], compatiblePackages = [CompatiblePackage("com.instagram.android")]
) )
@Suppress("unused") @Suppress("unused")
object HideTimelineAdsPatch : BytecodePatch( object HideTimelineAdsPatch : BytecodePatch(
setOf( setOf(
ShowAdFingerprint, ShowAdFingerprint,
IsAdCheckOneFingerprint, IsAdCheckOneFingerprint,
IsAdCheckTwoFingerprint, IsAdCheckTwoFingerprint
), )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// The exact function of the following methods is unknown. // The exact function of the following methods is unknown.
@ -55,7 +55,7 @@ object HideTimelineAdsPatch : BytecodePatch(
const/4 v0, 0x0 # Returning false to hide the ad. const/4 v0, 0x0 # Returning false to hide the ad.
return v0 return v0
""", """,
ExternalLabel("not_an_ad", getInstruction(checkIndex)), ExternalLabel("not_an_ad", getInstruction(checkIndex))
) )
} }
} ?: throw ShowAdFingerprint.exception } ?: throw ShowAdFingerprint.exception

View File

@ -9,10 +9,11 @@ internal object IsAdCheckOneFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = listOf(), parameters = listOf(),
opcodes = listOf( opcodes =
listOf(
Opcode.XOR_INT_LIT8, Opcode.XOR_INT_LIT8,
Opcode.IF_NE, Opcode.IF_NE,
Opcode.RETURN, Opcode.RETURN,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL
), )
) )

View File

@ -9,7 +9,8 @@ internal object IsAdCheckTwoFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes =
listOf(
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
@ -17,6 +18,6 @@ internal object IsAdCheckTwoFingerprint : MethodFingerprint(
Opcode.CONST_4, Opcode.CONST_4,
Opcode.IF_EQZ, Opcode.IF_EQZ,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.RETURN, Opcode.RETURN
), )
) )

View File

@ -9,13 +9,14 @@ internal object ShowAdFingerprint : MethodFingerprint(
"Z", "Z",
AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL, AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
listOf("L", "L", "Z", "Z"), listOf("L", "L", "Z", "Z"),
opcodes = listOf( opcodes =
listOf(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.IF_NE, Opcode.IF_NE,
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.RETURN, Opcode.RETURN
), )
) )

View File

@ -9,11 +9,11 @@ import app.revanced.patches.irplus.ad.fingerprints.IrplusAdsFingerprint
@Patch( @Patch(
name = "Remove ads", name = "Remove ads",
compatiblePackages = [CompatiblePackage("net.binarymode.android.irplus")], compatiblePackages = [CompatiblePackage("net.binarymode.android.irplus")]
) )
@Suppress("unused") @Suppress("unused")
object RemoveAdsPatch : BytecodePatch( object RemoveAdsPatch : BytecodePatch(
setOf(IrplusAdsFingerprint), setOf(IrplusAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val method = IrplusAdsFingerprint.result!!.mutableMethod val method = IrplusAdsFingerprint.result!!.mutableMethod

View File

@ -8,5 +8,5 @@ internal object IrplusAdsFingerprint : MethodFingerprint(
"V", "V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "Z"), listOf("L", "Z"),
strings = listOf("TAGGED"), strings = listOf("TAGGED")
) )

View File

@ -10,11 +10,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Disable mandatory login", name = "Disable mandatory login",
compatiblePackages = [CompatiblePackage("com.adobe.lrmobile")], compatiblePackages = [CompatiblePackage("com.adobe.lrmobile")]
) )
@Suppress("unused") @Suppress("unused")
object DisableMandatoryLoginPatch : BytecodePatch( object DisableMandatoryLoginPatch : BytecodePatch(
setOf(IsLoggedInFingerprint), setOf(IsLoggedInFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
IsLoggedInFingerprint.result?.mutableMethod?.apply { IsLoggedInFingerprint.result?.mutableMethod?.apply {

View File

@ -8,12 +8,13 @@ import com.android.tools.smali.dexlib2.Opcode
internal object IsLoggedInFingerprint : MethodFingerprint( internal object IsLoggedInFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL,
opcodes = listOf( opcodes =
listOf(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.IF_NE, Opcode.IF_NE,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.GOTO, Opcode.GOTO
), )
) )

View File

@ -10,11 +10,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Unlock premium", name = "Unlock premium",
compatiblePackages = [CompatiblePackage("com.adobe.lrmobile")], compatiblePackages = [CompatiblePackage("com.adobe.lrmobile")]
) )
@Suppress("unused") @Suppress("unused")
object UnlockPremiumPatch : BytecodePatch( object UnlockPremiumPatch : BytecodePatch(
setOf(HasPurchasedFingerprint), setOf(HasPurchasedFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
// Set hasPremium = true. // Set hasPremium = true.

View File

@ -9,10 +9,11 @@ internal object HasPurchasedFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL, accessFlags = AccessFlags.PRIVATE or AccessFlags.FINAL,
strings = listOf("isPurchaseDoneRecently = true, access platform profile present? = "), strings = listOf("isPurchaseDoneRecently = true, access platform profile present? = "),
opcodes = listOf( opcodes =
listOf(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.CONST_4, Opcode.CONST_4
), )
) )

View File

@ -9,7 +9,7 @@ import app.revanced.util.exception
@Patch(description = "Disables Firebase license validation.") @Patch(description = "Disables Firebase license validation.")
object LicenseValidationPatch : BytecodePatch( object LicenseValidationPatch : BytecodePatch(
setOf(LicenseValidationFingerprint), setOf(LicenseValidationFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
LicenseValidationFingerprint.result?.apply { LicenseValidationFingerprint.result?.apply {
@ -18,7 +18,7 @@ object LicenseValidationPatch : BytecodePatch(
""" """
const/4 p0, 0x1 const/4 p0, 0x1
return p0 return p0
""", """
) )
} ?: throw LicenseValidationFingerprint.exception } ?: throw LicenseValidationFingerprint.exception
} }

View File

@ -9,7 +9,8 @@ internal object LicenseValidationFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
opcodes = listOf( opcodes =
listOf(
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_WIDE, Opcode.MOVE_RESULT_WIDE,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
@ -19,6 +20,6 @@ internal object LicenseValidationFingerprint : MethodFingerprint(
Opcode.CONST_4, Opcode.CONST_4,
Opcode.RETURN, Opcode.RETURN,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.RETURN, Opcode.RETURN
), )
) )

View File

@ -9,7 +9,7 @@ import app.revanced.util.exception
@Patch(description = "Disables detection of incorrect signature.") @Patch(description = "Disables detection of incorrect signature.")
object SignatureVerificationPatch : BytecodePatch( object SignatureVerificationPatch : BytecodePatch(
setOf(VerifySignatureFingerprint), setOf(VerifySignatureFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
VerifySignatureFingerprint.result?.apply { VerifySignatureFingerprint.result?.apply {
@ -18,7 +18,7 @@ object SignatureVerificationPatch : BytecodePatch(
""" """
const/4 p0, 0x1 const/4 p0, 0x1
return p0 return p0
""", """
) )
} ?: throw VerifySignatureFingerprint.exception } ?: throw VerifySignatureFingerprint.exception
} }

View File

@ -11,7 +11,8 @@ internal object VerifySignatureFingerprint : MethodFingerprint(
returnType = "Z", returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
parameters = listOf("Landroid/app/Activity;"), parameters = listOf("Landroid/app/Activity;"),
opcodes = listOf( opcodes =
listOf(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.INVOKE_STATIC, Opcode.INVOKE_STATIC,
@ -30,6 +31,6 @@ internal object VerifySignatureFingerprint : MethodFingerprint(
Opcode.IF_EQZ, Opcode.IF_EQZ,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.RETURN, Opcode.RETURN,
Opcode.ADD_INT_LIT8, Opcode.ADD_INT_LIT8
), )
) )

View File

@ -14,7 +14,7 @@ import app.revanced.util.exception
name = "Unlock pro", name = "Unlock pro",
dependencies = [ dependencies = [
SignatureVerificationPatch::class, SignatureVerificationPatch::class,
LicenseValidationPatch::class, LicenseValidationPatch::class
], ],
compatiblePackages = [ compatiblePackages = [
CompatiblePackage( CompatiblePackage(
@ -23,14 +23,14 @@ import app.revanced.util.exception
"4.6364", "4.6364",
"4.6370", "4.6370",
"4.6375", "4.6375",
"4.6377", "4.6377"
], ]
), )
], ]
) )
@Suppress("unused") @Suppress("unused")
object UnlockProVersionPatch : BytecodePatch( object UnlockProVersionPatch : BytecodePatch(
setOf(IsFreeVersionFingerprint), setOf(IsFreeVersionFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
IsFreeVersionFingerprint.result?.apply { IsFreeVersionFingerprint.result?.apply {
@ -39,7 +39,7 @@ object UnlockProVersionPatch : BytecodePatch(
""" """
sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean; sget-object p0, Ljava/lang/Boolean;->FALSE:Ljava/lang/Boolean;
return-object p0 return-object p0
""", """
) )
} ?: throw IsFreeVersionFingerprint.exception } ?: throw IsFreeVersionFingerprint.exception
} }

View File

@ -10,13 +10,14 @@ internal object IsFreeVersionFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
strings = listOf("free"), strings = listOf("free"),
parameters = listOf("Landroid/content/Context;"), parameters = listOf("Landroid/content/Context;"),
opcodes = listOf( opcodes =
listOf(
Opcode.SGET, Opcode.SGET,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING, Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_EQZ, Opcode.IF_EQZ
), )
) )

View File

@ -6,12 +6,13 @@ import com.android.tools.smali.dexlib2.AccessFlags
internal object LoadInboxAdsFingerprint : MethodFingerprint( internal object LoadInboxAdsFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
strings = listOf( strings =
listOf(
"ads_load_begin", "ads_load_begin",
"inbox_ads_fetch_start", "inbox_ads_fetch_start"
), ),
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC, accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;" methodDef.definingClass == "Lcom/facebook/messaging/business/inboxads/plugins/inboxads/itemsupplier/InboxAdsItemSupplierImplementation;"
}, }
) )

View File

@ -11,11 +11,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Hide inbox ads", name = "Hide inbox ads",
description = "Hides ads in inbox.", description = "Hides ads in inbox.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")], compatiblePackages = [CompatiblePackage("com.facebook.orca")]
) )
@Suppress("unused") @Suppress("unused")
object HideInboxAdsPatch : BytecodePatch( object HideInboxAdsPatch : BytecodePatch(
setOf(LoadInboxAdsFingerprint), setOf(LoadInboxAdsFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
LoadInboxAdsFingerprint.result?.mutableMethod?.apply { LoadInboxAdsFingerprint.result?.mutableMethod?.apply {

View File

@ -7,9 +7,10 @@ internal object SendTypingIndicatorFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
parameters = listOf(), parameters = listOf(),
customFingerprint = { methodDef, classDef -> customFingerprint = { methodDef, classDef ->
methodDef.name == "run" && classDef.fields.any { methodDef.name == "run" &&
it.name == "__redex_internal_original_name" && classDef.fields.any {
(it.initialValue as? DexBackedStringEncodedValue)?.value == "ConversationTypingContext\$sendActiveStateRunnable\$1" it.name == "__redex_internal_original_name" &&
} (it.initialValue as? DexBackedStringEncodedValue)?.value == "ConversationTypingContext\$sendActiveStateRunnable\$1"
}, }
}
) )

View File

@ -7,12 +7,13 @@ internal object SwitchMessangeInputEmojiButtonFingerprint : MethodFingerprint(
returnType = "V", returnType = "V",
parameters = listOf("L", "Z"), parameters = listOf("L", "Z"),
strings = listOf("afterTextChanged", "expression_search"), strings = listOf("afterTextChanged", "expression_search"),
opcodes = listOf( opcodes =
listOf(
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IF_EQZ, Opcode.IF_EQZ,
Opcode.CONST_STRING, Opcode.CONST_STRING,
Opcode.GOTO, Opcode.GOTO,
Opcode.CONST_STRING, Opcode.CONST_STRING,
Opcode.GOTO, Opcode.GOTO
), )
) )

View File

@ -13,11 +13,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
@Patch( @Patch(
name = "Disable switching emoji to sticker", name = "Disable switching emoji to sticker",
description = "Disables switching from emoji to sticker search mode in message input field.", description = "Disables switching from emoji to sticker search mode in message input field.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")], compatiblePackages = [CompatiblePackage("com.facebook.orca")]
) )
@Suppress("unused") @Suppress("unused")
object DisableSwitchingEmojiToStickerPatch : BytecodePatch( object DisableSwitchingEmojiToStickerPatch : BytecodePatch(
setOf(SwitchMessangeInputEmojiButtonFingerprint), setOf(SwitchMessangeInputEmojiButtonFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SwitchMessangeInputEmojiButtonFingerprint.result?.let { SwitchMessangeInputEmojiButtonFingerprint.result?.let {
@ -28,7 +28,7 @@ object DisableSwitchingEmojiToStickerPatch : BytecodePatch(
replaceInstruction( replaceInstruction(
setStringIndex, setStringIndex,
"const-string v$targetRegister, \"expression\"", "const-string v$targetRegister, \"expression\""
) )
} }
} ?: throw SwitchMessangeInputEmojiButtonFingerprint.exception } ?: throw SwitchMessangeInputEmojiButtonFingerprint.exception

View File

@ -11,11 +11,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Disable typing indicator", name = "Disable typing indicator",
description = "Disables the indicator while typing a message.", description = "Disables the indicator while typing a message.",
compatiblePackages = [CompatiblePackage("com.facebook.orca")], compatiblePackages = [CompatiblePackage("com.facebook.orca")]
) )
@Suppress("unused") @Suppress("unused")
object DisableTypingIndicatorPatch : BytecodePatch( object DisableTypingIndicatorPatch : BytecodePatch(
setOf(SendTypingIndicatorFingerprint), setOf(SendTypingIndicatorFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SendTypingIndicatorFingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void") SendTypingIndicatorFingerprint.result?.mutableMethod?.replaceInstruction(0, "return-void")

View File

@ -15,11 +15,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
name = "Force English locale", name = "Force English locale",
description = "Forces wearable devices to use the English locale.", description = "Forces wearable devices to use the English locale.",
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")], compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")],
dependencies = [FixLoginPatch::class], dependencies = [FixLoginPatch::class]
) )
@Suppress("unused") @Suppress("unused")
object ForceEnglishLocalePatch : BytecodePatch( object ForceEnglishLocalePatch : BytecodePatch(
setOf(SyncBluetoothLanguageFingerprint), setOf(SyncBluetoothLanguageFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
SyncBluetoothLanguageFingerprint.result?.let { SyncBluetoothLanguageFingerprint.result?.let {
@ -31,7 +31,7 @@ object ForceEnglishLocalePatch : BytecodePatch(
replaceInstruction( replaceInstruction(
resolvePhoneLocaleInstruction, resolvePhoneLocaleInstruction,
"const-string v$registerIndexToUpdate, \"en_gb\"", "const-string v$registerIndexToUpdate, \"en_gb\""
) )
} }
} ?: throw SyncBluetoothLanguageFingerprint.exception } ?: throw SyncBluetoothLanguageFingerprint.exception

View File

@ -8,5 +8,5 @@ internal object SyncBluetoothLanguageFingerprint : MethodFingerprint(
methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" && methodDef.definingClass == "Lcom/xiaomi/fitness/devicesettings/DeviceSettingsSyncer;" &&
methodDef.name == "syncBluetoothLanguage" methodDef.name == "syncBluetoothLanguage"
}, },
opcodes = listOf(Opcode.MOVE_RESULT_OBJECT), opcodes = listOf(Opcode.MOVE_RESULT_OBJECT)
) )

View File

@ -11,16 +11,16 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Fix login", name = "Fix login",
description = "Fixes login for uncertified Mi Fitness app", description = "Fixes login for uncertified Mi Fitness app",
compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")], compatiblePackages = [CompatiblePackage("com.xiaomi.wearable")]
) )
@Suppress("unused") @Suppress("unused")
object FixLoginPatch : BytecodePatch( object FixLoginPatch : BytecodePatch(
setOf(XiaomiAccountManagerConstructorFingerprint), setOf(XiaomiAccountManagerConstructorFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
XiaomiAccountManagerConstructorFingerprint.result?.mutableMethod?.addInstruction( XiaomiAccountManagerConstructorFingerprint.result?.mutableMethod?.addInstruction(
0, 0,
"const/16 p2, 0x0", "const/16 p2, 0x0"
) ?: throw XiaomiAccountManagerConstructorFingerprint.exception ) ?: throw XiaomiAccountManagerConstructorFingerprint.exception
} }
} }

View File

@ -9,8 +9,9 @@ internal object XiaomiAccountManagerConstructorFingerprint : MethodFingerprint(
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;" methodDef.definingClass == "Lcom/xiaomi/passport/accountmanager/XiaomiAccountManager;"
}, },
parameters = listOf( parameters =
listOf(
"Landroid/content/Context;", "Landroid/content/Context;",
"Z", "Z"
), )
) )

View File

@ -9,11 +9,11 @@ import app.revanced.patches.moneymanager.fingerprints.UnlockProFingerprint
@Patch( @Patch(
name = "Unlock pro", name = "Unlock pro",
compatiblePackages = [CompatiblePackage("com.ithebk.expensemanager")], compatiblePackages = [CompatiblePackage("com.ithebk.expensemanager")]
) )
@Suppress("unused") @Suppress("unused")
object UnlockProPatch : BytecodePatch( object UnlockProPatch : BytecodePatch(
setOf(UnlockProFingerprint), setOf(UnlockProFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
UnlockProFingerprint.result!!.mutableMethod.addInstructions( UnlockProFingerprint.result!!.mutableMethod.addInstructions(
@ -21,7 +21,7 @@ object UnlockProPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) )
} }
} }

View File

@ -9,11 +9,12 @@ internal object UnlockProFingerprint : MethodFingerprint(
"Z", "Z",
AccessFlags.STATIC or AccessFlags.SYNTHETIC, AccessFlags.STATIC or AccessFlags.SYNTHETIC,
parameters = listOf("L"), parameters = listOf("L"),
opcodes = listOf( opcodes =
listOf(
Opcode.IGET_BOOLEAN, Opcode.IGET_BOOLEAN,
Opcode.RETURN, Opcode.RETURN
), ),
customFingerprint = { methodDef, _ -> customFingerprint = { methodDef, _ ->
methodDef.definingClass.endsWith("MainActivity;") methodDef.definingClass.endsWith("MainActivity;")
}, }
) )

View File

@ -11,17 +11,18 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Hide music video ads", name = "Hide music video ads",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Suppress("unused") @Suppress("unused")
object HideMusicVideoAds : BytecodePatch( object HideMusicVideoAds : BytecodePatch(
setOf(ShowMusicVideoAdsParentFingerprint), setOf(ShowMusicVideoAdsParentFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
ShowMusicVideoAdsParentFingerprint.result?.let { ShowMusicVideoAdsParentFingerprint.result?.let {
val showMusicVideoAdsMethod = context val showMusicVideoAdsMethod =
.toMethodWalker(it.mutableMethod) context
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod .toMethodWalker(it.mutableMethod)
.nextMethod(it.scanResult.patternScanResult!!.startIndex + 1, true).getMethod() as MutableMethod
showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0") showMusicVideoAdsMethod.addInstruction(0, "const/4 p1, 0x0")
} ?: throw ShowMusicVideoAdsParentFingerprint.exception } ?: throw ShowMusicVideoAdsParentFingerprint.exception
@ -30,7 +31,7 @@ object HideMusicVideoAds : BytecodePatch(
@Deprecated("This patch class has been renamed to HideMusicVideoAds.") @Deprecated("This patch class has been renamed to HideMusicVideoAds.")
object MusicVideoAdsPatch : BytecodePatch( object MusicVideoAdsPatch : BytecodePatch(
dependencies = setOf(HideMusicVideoAds::class), dependencies = setOf(HideMusicVideoAds::class)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
} }

View File

@ -4,10 +4,11 @@ import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.Opcode
internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint( internal object ShowMusicVideoAdsParentFingerprint : MethodFingerprint(
opcodes = listOf( opcodes =
listOf(
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT
), ),
strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error."), strings = listOf("maybeRegenerateCpnAndStatsClient called unexpectedly, but no error.")
) )

View File

@ -11,11 +11,11 @@ import com.android.tools.smali.dexlib2.Opcode
@Patch( @Patch(
description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.", description = "Adds more audio codec options. The new audio codecs usually result in better audio quality.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Deprecated("This patch is no longer needed as the feature is now enabled by default.") @Deprecated("This patch is no longer needed as the feature is now enabled by default.")
object CodecsUnlockPatch : BytecodePatch( object CodecsUnlockPatch : BytecodePatch(
setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint), setOf(CodecsLockFingerprint, AllCodecsReferenceFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
val codecsLockResult = CodecsLockFingerprint.result!! val codecsLockResult = CodecsLockFingerprint.result!!
@ -23,14 +23,15 @@ object CodecsUnlockPatch : BytecodePatch(
val implementation = codecsLockResult.mutableMethod.implementation!! val implementation = codecsLockResult.mutableMethod.implementation!!
val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex
val instructionIndex = scanResultStartIndex + val instructionIndex =
if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) { scanResultStartIndex +
// for 5.16.xx and lower if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) {
-3 // for 5.16.xx and lower
} else { -3
// since 5.17.xx } else {
-2 // since 5.17.xx
} -2
}
val allCodecsResult = AllCodecsReferenceFingerprint.result!! val allCodecsResult = AllCodecsReferenceFingerprint.result!!
val allCodecsMethod = val allCodecsMethod =
@ -40,7 +41,7 @@ object CodecsUnlockPatch : BytecodePatch(
implementation.replaceInstruction( implementation.replaceInstruction(
instructionIndex, instructionIndex,
"invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction(), "invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction()
) )
} }
} }

View File

@ -49,7 +49,7 @@ internal object AllCodecsReferenceFingerprint : MethodFingerprint(
Opcode.MOVE_EXCEPTION, Opcode.MOVE_EXCEPTION,
Opcode.INVOKE_SUPER, Opcode.INVOKE_SUPER,
Opcode.MOVE_RESULT_WIDE, Opcode.MOVE_RESULT_WIDE,
Opcode.RETURN_WIDE, Opcode.RETURN_WIDE
), ),
listOf("itag"), listOf("itag")
) )

View File

@ -10,7 +10,8 @@ import com.android.tools.smali.dexlib2.Opcode
internal object CodecsLockFingerprint : MethodFingerprint( internal object CodecsLockFingerprint : MethodFingerprint(
"L", "L",
AccessFlags.PUBLIC or AccessFlags.STATIC, AccessFlags.PUBLIC or AccessFlags.STATIC,
opcodes = listOf( opcodes =
listOf(
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
@ -24,7 +25,7 @@ internal object CodecsLockFingerprint : MethodFingerprint(
Opcode.MOVE_RESULT_OBJECT, Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.RETURN_OBJECT, Opcode.RETURN_OBJECT
), ),
strings = listOf("eac3_supported"), strings = listOf("eac3_supported")
) )

View File

@ -11,11 +11,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Enable exclusive audio playback", name = "Enable exclusive audio playback",
description = "Enables the option to play audio without video.", description = "Enables the option to play audio without video.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Suppress("unused") @Suppress("unused")
object EnableExclusiveAudioPlayback : BytecodePatch( object EnableExclusiveAudioPlayback : BytecodePatch(
setOf(AllowExclusiveAudioPlaybackFingerprint), setOf(AllowExclusiveAudioPlaybackFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
AllowExclusiveAudioPlaybackFingerprint.result?.mutableMethod?.apply { AllowExclusiveAudioPlaybackFingerprint.result?.mutableMethod?.apply {
@ -24,7 +24,7 @@ object EnableExclusiveAudioPlayback : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) )
} ?: throw AllowExclusiveAudioPlaybackFingerprint.exception } ?: throw AllowExclusiveAudioPlaybackFingerprint.exception
} }

View File

@ -20,6 +20,6 @@ internal object AllowExclusiveAudioPlaybackFingerprint : MethodFingerprint(
Opcode.GOTO, Opcode.GOTO,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.RETURN, Opcode.RETURN
), )
) )

View File

@ -14,11 +14,11 @@ import app.revanced.util.exception
name = "Permanent repeat", name = "Permanent repeat",
description = "Permanently remember your repeating preference even if the playlist ends or another track is played.", description = "Permanently remember your repeating preference even if the playlist ends or another track is played.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object PermanentRepeatPatch : BytecodePatch( object PermanentRepeatPatch : BytecodePatch(
setOf(RepeatTrackFingerprint), setOf(RepeatTrackFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
RepeatTrackFingerprint.result?.let { RepeatTrackFingerprint.result?.let {
@ -29,7 +29,7 @@ object PermanentRepeatPatch : BytecodePatch(
addInstructionsWithLabels( addInstructionsWithLabels(
startIndex, startIndex,
"goto :repeat", "goto :repeat",
ExternalLabel("repeat", getInstruction(repeatIndex)), ExternalLabel("repeat", getInstruction(repeatIndex))
) )
} }
} ?: throw RepeatTrackFingerprint.exception } ?: throw RepeatTrackFingerprint.exception

View File

@ -17,6 +17,6 @@ internal object RepeatTrackFingerprint : MethodFingerprint(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT, Opcode.MOVE_RESULT,
Opcode.IF_NEZ, Opcode.IF_NEZ
), )
) )

View File

@ -10,10 +10,11 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Permanent shuffle", name = "Permanent shuffle",
description = "Permanently remember your shuffle preference " + description =
"Permanently remember your shuffle preference " +
"even if the playlist ends or another track is played.", "even if the playlist ends or another track is played.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) { object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
@ -25,7 +26,7 @@ object PermanentShufflePatch : BytecodePatch(setOf(DisableShuffleFingerprint)) {
@Deprecated("This patch class has been renamed to PermanentShufflePatch.") @Deprecated("This patch class has been renamed to PermanentShufflePatch.")
object PermanentShuffleTogglePatch : BytecodePatch( object PermanentShuffleTogglePatch : BytecodePatch(
dependencies = setOf(PermanentShufflePatch::class), dependencies = setOf(PermanentShufflePatch::class)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
} }

View File

@ -15,6 +15,6 @@ internal object DisableShuffleFingerprint : MethodFingerprint(
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.IPUT_OBJECT, Opcode.IPUT_OBJECT,
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL
), )
) )

View File

@ -14,11 +14,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
name = "Hide category bar", name = "Hide category bar",
description = "Hides the category bar at the top of the homepage.", description = "Hides the category bar at the top of the homepage.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")],
use = false, use = false
) )
@Suppress("unused") @Suppress("unused")
object HideCategoryBar : BytecodePatch( object HideCategoryBar : BytecodePatch(
setOf(ConstructCategoryBarFingerprint), setOf(ConstructCategoryBarFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
ConstructCategoryBarFingerprint.result?.let { ConstructCategoryBarFingerprint.result?.let {
@ -31,7 +31,7 @@ object HideCategoryBar : BytecodePatch(
""" """
const/16 v2, 0x8 const/16 v2, 0x8
invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V invoke-virtual {v$register, v2}, Landroid/view/View;->setVisibility(I)V
""", """
) )
} }
} ?: throw ConstructCategoryBarFingerprint.exception } ?: throw ConstructCategoryBarFingerprint.exception
@ -40,7 +40,7 @@ object HideCategoryBar : BytecodePatch(
@Deprecated("This patch class has been renamed to HideCategoryBar.") @Deprecated("This patch class has been renamed to HideCategoryBar.")
object CompactHeaderPatch : BytecodePatch( object CompactHeaderPatch : BytecodePatch(
dependencies = setOf(HideCategoryBar::class), dependencies = setOf(HideCategoryBar::class)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
} }

View File

@ -18,6 +18,6 @@ internal object ConstructCategoryBarFingerprint : MethodFingerprint(
Opcode.CONST, Opcode.CONST,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL,
Opcode.NEW_INSTANCE, Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT, Opcode.INVOKE_DIRECT
), )
) )

View File

@ -13,19 +13,19 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Minimized playback", name = "Minimized playback",
description = "Unlocks options for picture-in-picture and background playback.", description = "Unlocks options for picture-in-picture and background playback.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Suppress("unused") @Suppress("unused")
object MinimizedPlaybackPatch : BytecodePatch( object MinimizedPlaybackPatch : BytecodePatch(
setOf( setOf(
KidsMinimizedPlaybackPolicyControllerFingerprint, KidsMinimizedPlaybackPolicyControllerFingerprint,
BackgroundPlaybackDisableFingerprint, BackgroundPlaybackDisableFingerprint
), )
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction( KidsMinimizedPlaybackPolicyControllerFingerprint.result?.mutableMethod?.addInstruction(
0, 0,
"return-void", "return-void"
) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception ) ?: throw KidsMinimizedPlaybackPolicyControllerFingerprint.exception
BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions( BackgroundPlaybackDisableFingerprint.result?.mutableMethod?.addInstructions(
@ -33,7 +33,7 @@ object MinimizedPlaybackPatch : BytecodePatch(
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) ?: throw BackgroundPlaybackDisableFingerprint.exception ) ?: throw BackgroundPlaybackDisableFingerprint.exception
} }
} }

View File

@ -18,6 +18,6 @@ internal object BackgroundPlaybackDisableFingerprint : MethodFingerprint(
Opcode.IGET_OBJECT, Opcode.IGET_OBJECT,
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.IGET, Opcode.IGET
), )
) )

View File

@ -21,6 +21,6 @@ internal object KidsMinimizedPlaybackPolicyControllerFingerprint : MethodFingerp
Opcode.SGET_OBJECT, Opcode.SGET_OBJECT,
Opcode.CONST_4, Opcode.CONST_4,
Opcode.IF_NE, Opcode.IF_NE,
Opcode.IPUT_BOOLEAN, Opcode.IPUT_BOOLEAN
), )
) )

View File

@ -14,11 +14,11 @@ import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
@Patch( @Patch(
name = "Hide 'Get Music Premium' label", name = "Hide 'Get Music Premium' label",
description = "Hides the red \"Get Music Premium\" label from the account menu.", description = "Hides the red \"Get Music Premium\" label from the account menu.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Suppress("unused") @Suppress("unused")
object HideGetPremiumPatch : BytecodePatch( object HideGetPremiumPatch : BytecodePatch(
setOf(HideGetPremiumFingerprint), setOf(HideGetPremiumFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
HideGetPremiumFingerprint.result?.let { HideGetPremiumFingerprint.result?.let {
@ -31,13 +31,13 @@ object HideGetPremiumPatch : BytecodePatch(
replaceInstruction( replaceInstruction(
insertIndex, insertIndex,
"const/16 v$visibilityRegister, 0x8", "const/16 v$visibilityRegister, 0x8"
) )
addInstruction( addInstruction(
insertIndex + 1, insertIndex + 1,
"invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " + "invoke-virtual {v$getPremiumViewRegister, v$visibilityRegister}, " +
"Landroid/view/View;->setVisibility(I)V", "Landroid/view/View;->setVisibility(I)V"
) )
} }
} ?: throw HideGetPremiumFingerprint.exception } ?: throw HideGetPremiumFingerprint.exception

View File

@ -12,7 +12,7 @@ internal object HideGetPremiumFingerprint : MethodFingerprint(
listOf( listOf(
Opcode.IF_NEZ, Opcode.IF_NEZ,
Opcode.CONST_16, Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL, Opcode.INVOKE_VIRTUAL
), ),
listOf("FEmusic_history", "FEmusic_offline"), listOf("FEmusic_history", "FEmusic_offline")
) )

View File

@ -22,22 +22,24 @@ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
@Patch( @Patch(
name = "Remove upgrade button", name = "Remove upgrade button",
description = "Removes the upgrade tab from the pivot bar.", description = "Removes the upgrade tab from the pivot bar.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Suppress("unused") @Suppress("unused")
object RemoveUpgradeButtonPatch : BytecodePatch( object RemoveUpgradeButtonPatch : BytecodePatch(
setOf(PivotBarConstructorFingerprint), setOf(PivotBarConstructorFingerprint)
) { ) {
override fun execute(context: BytecodeContext) { override fun execute(context: BytecodeContext) {
PivotBarConstructorFingerprint.result?.let { PivotBarConstructorFingerprint.result?.let {
it.mutableMethod.apply { it.mutableMethod.apply {
val pivotBarElementFieldReference = getInstruction(it.scanResult.patternScanResult!!.endIndex - 1) val pivotBarElementFieldReference =
.getReference<FieldReference>() getInstruction(it.scanResult.patternScanResult!!.endIndex - 1)
.getReference<FieldReference>()
val register = (getInstructions().first() as Instruction35c).registerC val register = (getInstructions().first() as Instruction35c).registerC
// First compile all the needed instructions. // First compile all the needed instructions.
val instructionList = """ val instructionList =
"""
invoke-interface { v0 }, Ljava/util/List;->size()I invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1 move-result v1
const/4 v2, 0x4 const/4 v2, 0x4
@ -50,7 +52,7 @@ object RemoveUpgradeButtonPatch : BytecodePatch(
// Replace the instruction to retain the label at given index. // Replace the instruction to retain the label at given index.
replaceInstruction( replaceInstruction(
endIndex - 1, endIndex - 1,
instructionList[0], // invoke-interface. instructionList[0] // invoke-interface.
) )
// Do not forget to remove this instruction since we added it already. // Do not forget to remove this instruction since we added it already.
instructionList.removeFirst() instructionList.removeFirst()
@ -58,7 +60,7 @@ object RemoveUpgradeButtonPatch : BytecodePatch(
val exitInstruction = instructionList.last() // iput-object val exitInstruction = instructionList.last() // iput-object
addInstruction( addInstruction(
endIndex, endIndex,
exitInstruction, exitInstruction
) )
// Do not forget to remove this instruction since we added it already. // Do not forget to remove this instruction since we added it already.
instructionList.removeLast() instructionList.removeLast()
@ -70,13 +72,13 @@ object RemoveUpgradeButtonPatch : BytecodePatch(
Opcode.IF_LE, Opcode.IF_LE,
1, 1,
2, 2,
newLabel(endIndex), newLabel(endIndex)
), )
) )
addInstructions( addInstructions(
endIndex, endIndex,
instructionList, instructionList
) )
} }
} ?: throw PivotBarConstructorFingerprint.exception } ?: throw PivotBarConstructorFingerprint.exception

View File

@ -14,6 +14,6 @@ internal object PivotBarConstructorFingerprint : MethodFingerprint(
Opcode.INVOKE_INTERFACE, Opcode.INVOKE_INTERFACE,
Opcode.GOTO, Opcode.GOTO,
Opcode.IPUT_OBJECT, Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID, Opcode.RETURN_VOID
), )
) )

View File

@ -11,7 +11,7 @@ import app.revanced.util.exception
@Patch( @Patch(
name = "Bypass certificate checks", name = "Bypass certificate checks",
description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.", description = "Bypasses certificate checks which prevent YouTube Music from working on Android Auto.",
compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")], compatiblePackages = [CompatiblePackage("com.google.android.apps.youtube.music")]
) )
@Suppress("unused") @Suppress("unused")
object BypassCertificateChecksPatch : BytecodePatch(setOf(CheckCertificateFingerprint)) { object BypassCertificateChecksPatch : BytecodePatch(setOf(CheckCertificateFingerprint)) {
@ -22,7 +22,7 @@ object BypassCertificateChecksPatch : BytecodePatch(setOf(CheckCertificateFinger
""" """
const/4 v0, 0x1 const/4 v0, 0x1
return v0 return v0
""", """
) )
} ?: throw CheckCertificateFingerprint.exception } ?: throw CheckCertificateFingerprint.exception
} }

View File

@ -8,5 +8,5 @@ internal object CheckCertificateFingerprint : MethodFingerprint(
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
returnType = "Z", returnType = "Z",
parameters = listOf("Ljava/lang/String;"), parameters = listOf("Ljava/lang/String;"),
strings = listOf("X509", "Failed to get certificate."), strings = listOf("X509", "Failed to get certificate.")
) )

View File

@ -14,25 +14,27 @@ object GmsCoreSupportPatch : BaseGmsCoreSupportPatch(
fromPackageName = MUSIC_PACKAGE_NAME, fromPackageName = MUSIC_PACKAGE_NAME,
toPackageName = REVANCED_MUSIC_PACKAGE_NAME, toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
primeMethodFingerprint = PrimeMethodFingerprint, primeMethodFingerprint = PrimeMethodFingerprint,
earlyReturnFingerprints = setOf( earlyReturnFingerprints =
setOf(
ServiceCheckFingerprint, ServiceCheckFingerprint,
GooglePlayUtilityFingerprint, GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint, CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint, CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint, CastContextFetchFingerprint
), ),
mainActivityOnCreateFingerprint = ApplicationInitFingerprint, mainActivityOnCreateFingerprint = ApplicationInitFingerprint,
integrationsPatchDependency = IntegrationsPatch::class, integrationsPatchDependency = IntegrationsPatch::class,
gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch, gmsCoreSupportResourcePatch = GmsCoreSupportResourcePatch,
compatiblePackages = setOf(CompatiblePackage("com.google.android.apps.youtube.music")), compatiblePackages = setOf(CompatiblePackage("com.google.android.apps.youtube.music")),
fingerprints = setOf( fingerprints =
setOf(
ServiceCheckFingerprint, ServiceCheckFingerprint,
GooglePlayUtilityFingerprint, GooglePlayUtilityFingerprint,
CastDynamiteModuleFingerprint, CastDynamiteModuleFingerprint,
CastDynamiteModuleV2Fingerprint, CastDynamiteModuleV2Fingerprint,
CastContextFetchFingerprint, CastContextFetchFingerprint,
PrimeMethodFingerprint, PrimeMethodFingerprint
), )
) { ) {
override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption override val gmsCoreVendorGroupId by gmsCoreVendorGroupIdOption
} }

View File

@ -7,5 +7,5 @@ import app.revanced.patches.shared.misc.gms.BaseGmsCoreSupportResourcePatch
object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch( object GmsCoreSupportResourcePatch : BaseGmsCoreSupportResourcePatch(
fromPackageName = MUSIC_PACKAGE_NAME, fromPackageName = MUSIC_PACKAGE_NAME,
toPackageName = REVANCED_MUSIC_PACKAGE_NAME, toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
spoofedPackageSignature = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875", spoofedPackageSignature = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875"
) )

View File

@ -3,5 +3,5 @@ package app.revanced.patches.music.misc.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
internal object CastDynamiteModuleFingerprint : MethodFingerprint( internal object CastDynamiteModuleFingerprint : MethodFingerprint(
strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl"), strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl")
) )

View File

@ -3,5 +3,5 @@ package app.revanced.patches.music.misc.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
internal object CastDynamiteModuleV2Fingerprint : MethodFingerprint( internal object CastDynamiteModuleV2Fingerprint : MethodFingerprint(
strings = listOf("Failed to load module via V2: "), strings = listOf("Failed to load module via V2: ")
) )

View File

@ -8,11 +8,12 @@ internal object GooglePlayUtilityFingerprint : MethodFingerprint(
"I", "I",
AccessFlags.PUBLIC or AccessFlags.STATIC, AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L", "I"), listOf("L", "I"),
strings = listOf( strings =
listOf(
"This should never happen.", "This should never happen.",
"MetadataValueReader", "MetadataValueReader",
"GooglePlayServicesUtil", "GooglePlayServicesUtil",
"com.android.vending", "com.android.vending",
"android.hardware.type.embedded", "android.hardware.type.embedded"
), )
) )

View File

@ -3,5 +3,5 @@ package app.revanced.patches.music.misc.gms.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint import app.revanced.patcher.fingerprint.MethodFingerprint
internal object PrimeMethodFingerprint : MethodFingerprint( internal object PrimeMethodFingerprint : MethodFingerprint(
strings = listOf("com.google.android.GoogleCamera", "com.android.vending"), strings = listOf("com.google.android.GoogleCamera", "com.android.vending")
) )

View File

@ -8,5 +8,5 @@ internal object ServiceCheckFingerprint : MethodFingerprint(
"V", "V",
AccessFlags.PUBLIC or AccessFlags.STATIC, AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L", "I"), listOf("L", "I"),
strings = listOf("Google Play Services not available"), strings = listOf("Google Play Services not available")
) )

View File

@ -6,5 +6,5 @@ import app.revanced.patches.shared.misc.integrations.BaseIntegrationsPatch
@Patch(requiresIntegrations = true) @Patch(requiresIntegrations = true)
object IntegrationsPatch : BaseIntegrationsPatch( object IntegrationsPatch : BaseIntegrationsPatch(
setOf(ApplicationInitFingerprint), setOf(ApplicationInitFingerprint)
) )

Some files were not shown because too many files have changed in this diff Show More