Merge branch 'dalvik-patches' into microg-dalvik-patch

# Conflicts:
#	src/main/kotlin/app/revanced/patches/Index.kt
#	src/main/kotlin/app/revanced/patches/youtube/misc/MicroGPatch.kt
This commit is contained in:
oSumAtrIX 2022-05-05 00:02:03 +02:00
commit aeacdf5bfb
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
20 changed files with 795 additions and 670 deletions

View File

@ -1,17 +1,20 @@
package app.revanced.patches
import app.revanced.patcher.patch.Patch
import app.revanced.patches.ad.HomeAdsPatch
import app.revanced.patches.ad.HomePromoPatch
import app.revanced.patches.ad.VideoAdsPatch
import app.revanced.patches.interaction.EnableSeekbarTappingPatch
import app.revanced.patches.layout.CreateButtonRemoverPatch
import app.revanced.patches.layout.ShortsButtonRemoverPatch
import app.revanced.patches.layout.HideReelsPatch
import app.revanced.patches.layout.MinimizedPlaybackPatch
import app.revanced.patches.layout.OldQualityLayoutPatch
import app.revanced.patches.misc.IntegrationsPatch
import app.revanced.patches.misc.MicroGPatch
import app.revanced.patcher.data.base.Data
import app.revanced.patcher.patch.base.Patch
import app.revanced.patches.music.audio.CodecsUnlockPatch
import app.revanced.patches.music.audio.EnableAudioOnlyPatch
import app.revanced.patches.music.layout.RemoveTasteBuilderPatch
import app.revanced.patches.music.layout.RemoveUpgradeTabPatch
import app.revanced.patches.music.premium.BackgroundPlayPatch
import app.revanced.patches.youtube.ad.HomeAdsPatch
import app.revanced.patches.youtube.ad.HomePromoPatch
import app.revanced.patches.youtube.ad.VideoAdsPatch
import app.revanced.patches.youtube.interaction.EnableSeekbarTappingPatch
import app.revanced.patches.youtube.layout.*
import app.revanced.patches.youtube.misc.FixLocaleConfigErrorPatch
import app.revanced.patches.youtube.misc.IntegrationsPatch
import app.revanced.patches.music.misc.MicroGPatch
/**
* Index contains all the patches.
@ -22,8 +25,9 @@ object Index {
* Array of patches.
* New patches should be added to the array.
*/
val patches: List<() -> Patch> = listOf(
val patches: List<() -> Patch<Data>> = listOf(
::IntegrationsPatch,
::FixLocaleConfigErrorPatch,
::MicroGPatch,
::HomeAdsPatch,
::VideoAdsPatch,
@ -33,6 +37,11 @@ object Index {
::ShortsButtonRemoverPatch,
::HideReelsPatch,
::OldQualityLayoutPatch,
::EnableSeekbarTappingPatch
::EnableSeekbarTappingPatch,
::EnableAudioOnlyPatch,
::RemoveUpgradeTabPatch,
::RemoveTasteBuilderPatch,
::BackgroundPlayPatch,
::CodecsUnlockPatch
)
}

View File

@ -1,598 +0,0 @@
package app.revanced.patches.misc
import app.revanced.extensions.startsWithAny
import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.proxy
import app.revanced.patcher.proxy.mutableTypes.MutableClass
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstruction
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.builder.instruction.BuilderInstruction21c
import org.jf.dexlib2.iface.instruction.formats.Instruction21c
import org.jf.dexlib2.iface.reference.StringReference
import org.jf.dexlib2.immutable.reference.ImmutableStringReference
private const val BASE_MICROG_PACKAGE_NAME = "com.mgoogle"
private const val BASE_REVANCED_PACKAGE_NAME = "app.revanced.android.youtube"
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.youtube", listOf("17.14.35")
)
)
private val metadata = PatchMetadata(
"microg",
"MicroG Patch",
"Patch to allow YouTube ReVanced to run without root and under a different package name.",
compatiblePackages,
"0.0.1"
)
private val description = "Signature required for ${metadata.name}."
enum class StringReplaceMode {
REPLACE_WITH_MICROG, REPLACE_WITH_REVANCED, DO_NOT_REPLACE
}
class MicroGPatch : Patch(
metadata, listOf(
MethodSignature(
MethodSignatureMetadata(
"google-play-sig-check-method",
MethodMetadata("Ldsf;", "d"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
description,
"0.0.1"
), "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf(
Opcode.MOVE_OBJECT_FROM16,
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.NEW_INSTANCE,
Opcode.MOVE_OBJECT_FROM16,
Opcode.INVOKE_DIRECT,
Opcode.CONST_4,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_EQ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.SGET,
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_WIDE,
Opcode.CONST_WIDE,
Opcode.CONST_STRING,
Opcode.CONST_4,
Opcode.CONST_STRING,
Opcode.CONST_4,
Opcode.CMP_LONG,
Opcode.IF_GEZ,
Opcode.CONST_16,
Opcode.GOTO_16,
Opcode.CONST_STRING,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.CONST_4,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.CONST,
Opcode.IF_NE,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.GOTO,
Opcode.NEW_ARRAY
), listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.")
), MethodSignature(
MethodSignatureMetadata(
"google-play-service-checker-method",
MethodMetadata("Llpe;", "d"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
description,
"0.0.1"
), "V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), listOf(
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.SGET_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.IF_NEZ,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.NEW_INSTANCE,
Opcode.CONST_STRING,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.RETURN_VOID
), listOf("Google Play Services not available")
), MethodSignature(
MethodSignatureMetadata(
"google-play-utility-method",
MethodMetadata("Llpe;", "b"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
description,
"0.0.1"
), "I", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.MONITOR_ENTER,
Opcode.SGET_BOOLEAN,
Opcode.IF_EQZ,
Opcode.MONITOR_EXIT,
Opcode.GOTO,
Opcode.SPUT_BOOLEAN,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.MONITOR_EXIT,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.SPUT,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.CONST_STRING,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MONITOR_EXIT,
Opcode.SGET,
Opcode.IF_EQZ,
Opcode.CONST,
Opcode.IF_NE,
Opcode.GOTO,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.THROW,
Opcode.MOVE_EXCEPTION,
Opcode.MONITOR_EXIT,
Opcode.THROW,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.CONST_4,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IF_NEZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.SPUT_OBJECT,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_16,
Opcode.IF_EQZ,
Opcode.CONST_STRING,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.CONST_16,
Opcode.GOTO_16,
Opcode.CONST_4,
Opcode.CONST_STRING,
Opcode.CONST_16,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IF_EQZ,
Opcode.INVOKE_STATIC,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.AGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.AGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IGET,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT,
Opcode.IF_GE,
Opcode.IGET,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.INVOKE_VIRTUAL,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.GOTO,
Opcode.IGET_BOOLEAN,
Opcode.IF_NEZ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.RETURN,
Opcode.CONST_STRING,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST_STRING,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.RETURN
), listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms")
), MethodSignature(
MethodSignatureMetadata(
"google-play-prime-method",
MethodMetadata("Louy;", "e"),
PatternScanMethod.Direct(),
compatiblePackages,
description,
"0.0.1"
), null, null, null, null, listOf("com.google.android.GoogleCamera", "com.android.vending")
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
// smali patches
disablePlayServiceChecks()
patcherData.classes.forEach { classDef ->
var proxiedClass: MutableClass? = null
classDef.methods.forEach methodLoop@{ method ->
val implementation = method.implementation ?: return@methodLoop
var proxiedImplementation: MutableMethodImplementation? = null
implementation.instructions.forEachIndexed { i, instruction ->
if (instruction.opcode == Opcode.CONST_STRING) {
val stringValue = ((instruction as Instruction21c).reference as StringReference).string
val replaceMode =
if (stringValue.startsWith("com.google.android.gms.chimera.container")) // https://github.com/TeamVanced/VancedMicroG/pull/139/file
StringReplaceMode.DO_NOT_REPLACE
else if (stringValue == "com.google" || stringValue.startsWithAny(
"com.google.android.gms.auth.accounts",
"com.google.android.gms.chimera",
"com.google.android.c2dm",
"com.google.android.c2dm",
"com.google.android.gsf",
"com.google.android.c2dm",
"com.google.iid",
"content://com.google.settings"
)
) {
StringReplaceMode.REPLACE_WITH_MICROG
} else if (stringValue.startsWithAny(
"com.google.android.youtube.SuggestionsProvider",
"com.google.android.youtube.fileprovider"
)
) {
StringReplaceMode.REPLACE_WITH_REVANCED
} else {
StringReplaceMode.DO_NOT_REPLACE
}
if (replaceMode != StringReplaceMode.DO_NOT_REPLACE) {
if (proxiedClass == null) {
proxiedClass = patcherData.proxy(classDef).resolve()
}
if (proxiedImplementation == null) {
proxiedImplementation =
proxiedClass!!.methods.first {
it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes)
}.implementation!!
}
val newString =
if (replaceMode == StringReplaceMode.REPLACE_WITH_REVANCED) stringValue.replace(
"com.google.android.youtube", BASE_REVANCED_PACKAGE_NAME
)
else stringValue.replace("com.google", BASE_MICROG_PACKAGE_NAME)
proxiedImplementation!!.replaceInstruction(
i, BuilderInstruction21c(
Opcode.CONST_STRING, instruction.registerA, ImmutableStringReference(newString)
)
)
}
// TODO: phenotype reference -> microg reference
//if (instruction is ReferenceInstruction) {
// val proxy = patcherData.proxy(classDef).resolve()
// val implementation = proxy.methods.first { it.name == method.name }.implementation!!
// when (instruction.referenceType) {
// ReferenceType.METHOD -> {
// val reference = instruction.reference as MethodReference
// if (!reference.name.startsWith("com.google.android.gms.phenotype")) return@forEachIndexed
// val modifiedReference = ImmutableMethodReference(
// reference.definingClass.replace("com.google", BASE_MICROG_PACKAGE_NAME),
// reference.name,
// reference.parameterTypes.map {
// it.toString().replace("com.google", BASE_MICROG_PACKAGE_NAME)
// },
// reference.returnType.replace("com.google", BASE_MICROG_PACKAGE_NAME),
// );
// val newInstruction = when (instruction.opcode.format) {
// Format.Format35c -> {
// val instruction35c = instruction as Instruction35c
// BuilderInstruction35c(
// instruction.opcode,
// instruction35c.registerCount,
// instruction35c.registerC,
// instruction35c.registerD,
// instruction35c.registerE,
// instruction35c.registerF,
// instruction35c.registerG,
// modifiedReference
// )
// }
// Format.Format3rc ->
// BuilderInstruction3rc(
// instruction.opcode,
// )
// Format.Format45cc ->
// BuilderInstruction45cc(
// instruction.opcode,
// )
// Format.Format4rcc ->
// BuilderInstruction4rcc(
// instruction.opcode,
// )
// }
// implementation.replaceInstruction(
// i,
// )
// }
// ReferenceType.METHOD_PROTO -> {
// }
// ReferenceType.TYPE -> {
// }
// ReferenceType.CALL_SITE -> {
// }
// ReferenceType.METHOD_HANDLE -> {
// }
// ReferenceType.FIELD -> {
// }
// ReferenceType.NONE -> {
// }
// }
//}
}
}
}
}
// replace string back
val implementation = signatures.elementAt(2).result!!.findParentMethod(
MethodSignature(
MethodSignatureMetadata(
"do-not-replace-method",
MethodMetadata("Llpe;", "c"),
PatternScanMethod.Direct(),
compatiblePackages,
description,
"0.0.1"
), "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), null, listOf("com.google.android.gms")
)
)!!.method.implementation!!
implementation.replaceInstruction(
implementation.instructions.indexOfFirst { it.opcode == Opcode.CONST_STRING },
"const-string v0, \"com.google.android.gms\"".toInstruction()
)
// allow GC to clean unused/ replaced immutable class definitions after this call
patcherData.classes.applyProxies()
// TODO: resource patches
return PatchResultSuccess()
}
private fun disablePlayServiceChecks() {
for (i in 0 until signatures.count() - 1) {
val result = signatures.elementAt(i).result!!
val stringInstructions = when (result.immutableMethod.returnType.first()) {
'L' -> """
const/4 v0, 0x0
return-object v0
"""
'V' -> "return-void"
'I' -> """
const/4 v0, 0x0
return v0
"""
else -> throw Exception("This case should never happen.")
}
result.method.implementation!!.addInstructions(
0, stringInstructions.trimIndent().toInstructions()
)
}
val implementation = signatures.last().result!!.method.implementation!!
var register = 2
val index = implementation.instructions.indexOfFirst {
if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false
val instructionString = ((it as Instruction21c).reference as StringReference).string
if (instructionString != "com.google.android.youtube") return@indexOfFirst false
register = it.registerA
return@indexOfFirst true
}
implementation.replaceInstruction(
index, "const-string v$register, \"$BASE_REVANCED_PACKAGE_NAME\"".toInstruction()
)
}
}

View File

@ -0,0 +1,157 @@
package app.revanced.patches.music.audio
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.data.implementation.toMethodWalker
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val packageMetadata = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("5.03.50")
)
)
private val patchMetadata = PatchMetadata(
"codecs-unlock",
"Audio codecs unlock patch",
"Enables more audio codecs. Usually results in better audio quality but may depend on song and device.",
packageMetadata,
"0.0.1"
)
class CodecsUnlockPatch : BytecodePatch(
patchMetadata,
listOf(
MethodSignature(
MethodSignatureMetadata(
"codec-lock-method",
MethodMetadata(
"Labwj;",
"a",
),
PatternScanMethod.Fuzzy(2),// FIXME: Test this threshold and find the best value.
packageMetadata,
"Required signature for ${patchMetadata.name}. Discovered in version 5.03.50.",
"0.0.1"
),
"L",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L", "L", "L", "L"),
listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.SGET,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_DIRECT,
Opcode.RETURN_OBJECT
)
),
MethodSignature(
MethodSignatureMetadata(
"all-codecs-reference-method",
MethodMetadata(
"Laari;",
"b",
),
PatternScanMethod.Fuzzy(2),// FIXME: Test this threshold and find the best value.
packageMetadata,
"Required signature for ${patchMetadata.name}. Discovered in version 5.03.50.",
"0.0.1"
),
"J",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L"),
listOf(
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_BOOLEAN,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.IGET_BOOLEAN,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.MOVE_EXCEPTION,
Opcode.INVOKE_SUPER,
Opcode.MOVE_RESULT_WIDE,
Opcode.RETURN_WIDE
),
listOf("itag")
)
)
) {
override fun execute(data: BytecodeData): PatchResult {
var result = signatures.first().result!!
val implementation = result.method.implementation!!
val instructionIndex = result.scanData.startIndex
result = signatures.last().result!!
val codecMethod = data
.toMethodWalker(result.immutableMethod)
.walk(result.scanData.startIndex)
.getMethod()
implementation.replaceInstruction(
instructionIndex,
"invoke-static {}, ${codecMethod.definingClass}->${codecMethod.name}()Ljava/util/Set;".toInstruction()
)
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,133 @@
package app.revanced.patches.music.audio
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("5.03.50")
)
)
class EnableAudioOnlyPatch : BytecodePatch(
PatchMetadata(
"audio-only-playback-patch",
"Audio Only Mode Patch",
"Add the option to play music without video.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"audio-only-method-signature",
MethodMetadata("Lgmd;", "c"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Signature for the method required to be patched.",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_EQ,
Opcode.CONST_4,
Opcode.GOTO,
Opcode.NOP,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_EQZ,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.RETURN_VOID
)
)
)
) {
override fun execute(data: BytecodeData): PatchResult {
val result = signatures.first().result!!.findParentMethod(
MethodSignature(
MethodSignatureMetadata(
"audio-only-enabler-method",
MethodMetadata("Lgmd;", "d"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Signature for the method required to be patched.",
"0.0.1"
),
"Z",
AccessFlags.PUBLIC or AccessFlags.FINAL,
listOf(),
listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IF_NEZ,
Opcode.IGET_OBJECT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.GOTO,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.RETURN
)
)
) ?: return PatchResultError("Required method for ${metadata.shortName} not found.")
val implementation = result.method.implementation!!
implementation.replaceInstruction(
implementation.instructions.count() - 1,
"const/4 v0, 0x1".toInstruction()
)
implementation.addInstruction(
"return v0".toInstruction()
)
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,94 @@
package app.revanced.patches.music.layout
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("5.03.50")
)
)
class RemoveTasteBuilderPatch : BytecodePatch(
PatchMetadata(
"tasteBuilder-remover",
"Remove TasteBuilder Patch",
"Removes the \"Tell us which artists you like\" card from the Home screen. The same functionality can be triggered from the settings anyway.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"taste-builder-constructor",
MethodMetadata("Lkyu;", "<init>"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Required signature for this patch.",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "L", "L", "L"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.INVOKE_VIRTUAL,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CONST,
Opcode.CONST_4,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IPUT_OBJECT,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IPUT_OBJECT
)
)
)
) {
override fun execute(data: BytecodeData): PatchResult {
val result = signatures.first().result!!
val implementation = result.method.implementation!!
val insertIndex = result.scanData.endIndex - 8
val register = (implementation.instructions[insertIndex] as Instruction22c).registerA
val instructionList =
"""
const/16 v1, 0x8
invoke-virtual {v${register}, v1}, Landroid/view/View;->setVisibility(I)V
""".trimIndent().toInstructions().toMutableList()
implementation.addInstructions(
insertIndex,
instructionList
)
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,151 @@
package app.revanced.patches.music.layout
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction22t
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("5.03.50")
)
)
class RemoveUpgradeTabPatch : BytecodePatch(
PatchMetadata(
"upgrade-tab-remover",
"Remove Upgrade Tab Patch",
"Remove the upgrade tab from t he pivot bar in YouTube music.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"pivot-bar-constructor",
MethodMetadata("Lhfu;", "<init2>"), // unknown
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Required signature for this patch.",
"0.0.1"
),
"V",
AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
listOf("L", "Z"),
listOf(
Opcode.INVOKE_DIRECT,
Opcode.CONST_4,
Opcode.IPUT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.IPUT_BOOLEAN,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.GOTO,
Opcode.NEW_INSTANCE,
Opcode.INVOKE_DIRECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.IGET_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT,
Opcode.IF_EQZ,
Opcode.INVOKE_INTERFACE,
Opcode.MOVE_RESULT_OBJECT,
Opcode.CHECK_CAST,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.INVOKE_INTERFACE,
Opcode.GOTO,
Opcode.NOP,
Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID
)
)
)
) {
override fun execute(data: BytecodeData): PatchResult {
val result = signatures.first().result!!
val implementation = result.method.implementation!!
val pivotBarElementFieldRef =
(implementation.instructions[result.scanData.endIndex - 1] as Instruction22c).reference
val register = (implementation.instructions.first() as Instruction35c).registerC
// first compile all the needed instructions
val instructionList =
"""
invoke-interface { v0 }, Ljava/util/List;->size()I
move-result v1
const/4 v2, 0x3
invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
iput-object v0, v$register, $pivotBarElementFieldRef
""".trimIndent().toInstructions().toMutableList()
// replace the instruction to retain the label at given index
implementation.replaceInstruction(
result.scanData.endIndex - 1,
instructionList[0] // invoke-interface
)
// do not forget to remove this instruction since we added it already
instructionList.removeFirst()
val exitInstruction = instructionList.last() // iput-object
implementation.addInstruction(
result.scanData.endIndex,
exitInstruction
)
// do not forget to remove this instruction since we added it already
instructionList.removeLast()
// add the necessary if statement to remove the upgrade tab button in case it exists
instructionList.add(
2, // if-le
BuilderInstruction22t(
Opcode.IF_LE,
1, 2,
implementation.newLabelForIndex(result.scanData.endIndex)
)
)
implementation.addInstructions(
result.scanData.endIndex,
instructionList
)
return PatchResultSuccess()
}
}

View File

@ -0,0 +1,92 @@
package app.revanced.patches.music.premium
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.apps.youtube.music",
listOf("5.03.50")
)
)
class BackgroundPlayPatch : BytecodePatch(
PatchMetadata(
"background-play",
"Enable Background Playback Patch",
"Enable playing music in the background.",
compatiblePackages,
"0.0.1"
),
listOf(
MethodSignature(
MethodSignatureMetadata(
"background-playback-disabler-method",
MethodMetadata("Lafgf;", "e"),
PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages,
"Signature for the method required to be patched.",
"0.0.1"
),
"Z",
AccessFlags.PUBLIC or AccessFlags.STATIC,
listOf("L"),
listOf(
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET,
Opcode.AND_INT_LIT16,
Opcode.IF_EQZ,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.CONST,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.IF_NEZ,
Opcode.SGET_OBJECT,
Opcode.IGET,
Opcode.IF_NE,
Opcode.IGET_OBJECT,
Opcode.CHECK_CAST,
Opcode.GOTO,
Opcode.SGET_OBJECT,
Opcode.GOTO,
Opcode.CONST_4,
Opcode.IF_EQZ,
Opcode.IGET_BOOLEAN,
Opcode.IF_EQZ,
Opcode.CONST_4,
Opcode.RETURN,
Opcode.RETURN,
Opcode.RETURN
)
)
)
) {
override fun execute(data: BytecodeData): PatchResult {
signatures.first().result!!.method.implementation!!.addInstructions(
0,
"""
const/4 v0, 0x1
return v0
""".trimIndent().toInstructions()
)
return PatchResultSuccess()
}
}

View File

@ -1,9 +1,13 @@
package app.revanced.patches.ad
package app.revanced.patches.youtube.ad
import app.revanced.extensions.injectHideCall
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -30,7 +34,7 @@ private val patchMetadata = PatchMetadata(
private val signatureDescription = "Required signature for ${patchMetadata.name}. Discovered in version 17.03.38."
class HomeAdsPatch : Patch(
class HomeAdsPatch : BytecodePatch(
patchMetadata,
listOf(
MethodSignature(
@ -1685,7 +1689,7 @@ class HomeAdsPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
for (i in 0 until signatures.count()) {
val signature = signatures.elementAt(i)
val result = signature.result!!

View File

@ -1,15 +1,20 @@
package app.revanced.patches.ad
package app.revanced.patches.youtube.ad
import app.revanced.extensions.injectHideCall
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.data.implementation.toMethodWalker
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.toMethodWalker
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction11x
@ -31,7 +36,7 @@ private val patchMetadata = PatchMetadata(
private val signatureDescription = "Required signature for ${patchMetadata.name}. Discovered in version 17.03.38."
class HomePromoPatch : Patch(
class HomePromoPatch : BytecodePatch(
patchMetadata,
listOf(
MethodSignature(
@ -137,7 +142,7 @@ class HomePromoPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
for (signature in signatures) {
val result = signature.result!!
@ -162,7 +167,7 @@ class HomePromoPatch : Patch(
val toBePatchedInvokeOffset =
requiredMethod.immutableMethod.implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_DIRECT }
val toBePatchedMethod = patcherData
val toBePatchedMethod = data
.toMethodWalker(requiredMethod.immutableMethod)
.walk(toBePatchedInvokeOffset, true)
.getMethod() as MutableMethod

View File

@ -1,9 +1,14 @@
package app.revanced.patches.ad
package app.revanced.patches.youtube.ad
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -27,7 +32,7 @@ private val patchMetadata = PatchMetadata(
"0.0.1"
)
class VideoAdsPatch : Patch(
class VideoAdsPatch : BytecodePatch(
patchMetadata,
listOf(
MethodSignature(
@ -66,7 +71,7 @@ class VideoAdsPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
var result = signatures.first().result!!
val responsibleMethodSignature = MethodSignature(
@ -104,5 +109,4 @@ class VideoAdsPatch : Patch(
return PatchResultSuccess()
}
}
}

View File

@ -1,9 +1,14 @@
package app.revanced.patches.interaction
package app.revanced.patches.youtube.interaction
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -23,7 +28,7 @@ private val compatiblePackages = listOf(
)
)
class EnableSeekbarTappingPatch : Patch(
class EnableSeekbarTappingPatch : BytecodePatch(
PatchMetadata(
"seekbar-tapping",
"Enable seekbar tapping patch",
@ -124,7 +129,7 @@ class EnableSeekbarTappingPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
var result = signatures.first().result!!
val tapSeekMethods = mutableMapOf<String, Method>()

View File

@ -1,8 +1,13 @@
package app.revanced.patches.layout
package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -19,7 +24,7 @@ private val compatiblePackages = listOf(
)
)
class CreateButtonRemoverPatch : Patch(
class CreateButtonRemoverPatch : BytecodePatch(
PatchMetadata(
"create-button",
"Create button patch",
@ -76,7 +81,7 @@ class CreateButtonRemoverPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
val result = signatures.first().result!!
// Get the required register which holds the view object we need to pass to the method hideCreateButton

View File

@ -1,8 +1,12 @@
package app.revanced.patches.layout
package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -18,7 +22,7 @@ private val compatiblePackages = listOf(
)
)
class HideReelsPatch : Patch(
class HideReelsPatch : BytecodePatch(
PatchMetadata(
"hide-reels",
"Hide reels patch",
@ -96,7 +100,7 @@ class HideReelsPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
val result = signatures.first().result!!
val implementation = result.method.implementation!!

View File

@ -1,9 +1,13 @@
package app.revanced.patches.layout
package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -19,7 +23,7 @@ private val compatiblePackages = listOf(
)
)
class MinimizedPlaybackPatch : Patch(
class MinimizedPlaybackPatch : BytecodePatch(
PatchMetadata(
"minimized-playback",
"Minimized Playback Patch",
@ -70,7 +74,7 @@ class MinimizedPlaybackPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
// Instead of removing all instructions like Vanced,
// we return the method at the beginning instead
signatures.first().result!!.method.implementation!!.addInstructions(

View File

@ -1,9 +1,14 @@
package app.revanced.patches.layout
package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultError
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -20,7 +25,7 @@ private val compatiblePackages = listOf(
)
)
class OldQualityLayoutPatch : Patch(
class OldQualityLayoutPatch : BytecodePatch(
PatchMetadata(
"old-quality-layout",
"Old Quality Layout Patch",
@ -70,7 +75,7 @@ class OldQualityLayoutPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
var result = signatures.first().result!!
result = result.findParentMethod(

View File

@ -1,8 +1,12 @@
package app.revanced.patches.layout
package app.revanced.patches.youtube.layout
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
@ -10,10 +14,7 @@ import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.toInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.iface.instruction.formats.Instruction3rc
import org.jf.dexlib2.iface.instruction.formats.Instruction11x
import org.jf.dexlib2.builder.instruction.BuilderInstruction32x
private val compatiblePackages = listOf(
PackageMetadata(
@ -22,7 +23,7 @@ private val compatiblePackages = listOf(
)
)
class ShortsButtonRemoverPatch : Patch(
class ShortsButtonRemoverPatch : BytecodePatch(
PatchMetadata(
"shorts-button",
"Shorts button patch",
@ -105,7 +106,7 @@ class ShortsButtonRemoverPatch : Patch(
),
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
val result1 = signatures.first().result!!
val implementation1 = result1.method.implementation!!
val moveEnumInstruction = implementation1.instructions[result1.scanData.endIndex]

View File

@ -0,0 +1,46 @@
package app.revanced.patches.youtube.misc
import app.revanced.patcher.data.implementation.ResourceData
import app.revanced.patcher.patch.implementation.ResourcePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import com.sun.org.apache.xerces.internal.dom.ElementImpl
private val compatiblePackages = listOf(
PackageMetadata(
"com.google.android.youtube",
listOf("17.14.35")
)
)
class FixLocaleConfigErrorPatch : ResourcePatch(
PatchMetadata(
"locale-config-fix",
"Manifest attribute fix patch",
"Fix an error when building the resources by patching the manifest file.",
compatiblePackages,
"0.0.1"
),
) {
override fun execute(data: ResourceData): PatchResult {
// create an xml editor instance
val editor = data.getXmlEditor("AndroidManifest.xml")
// edit the application nodes attribute...
val applicationNode = editor
.file
.getElementsByTagName("application")
.item(0) as ElementImpl
// by replacing the attributes name
val attribute = "android:localeConfig"
applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute))
applicationNode.removeAttribute("android:localeConfig")
// close & save the modified file
editor.close()
return PatchResultSuccess()
}
}

View File

@ -1,9 +1,13 @@
package app.revanced.patches.misc
package app.revanced.patches.youtube.misc
import app.revanced.patcher.PatcherData
import app.revanced.patcher.data.implementation.BytecodeData
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.implementation.BytecodePatch
import app.revanced.patcher.patch.implementation.metadata.PackageMetadata
import app.revanced.patcher.patch.implementation.metadata.PatchMetadata
import app.revanced.patcher.patch.implementation.misc.PatchResult
import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess
import app.revanced.patcher.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature
@ -22,7 +26,7 @@ private val compatiblePackages = listOf(
)
)
class IntegrationsPatch : Patch(
class IntegrationsPatch : BytecodePatch(
PatchMetadata(
"integrations",
"Inject Integrations Patch",
@ -80,7 +84,7 @@ class IntegrationsPatch : Patch(
)
)
) {
override fun execute(patcherData: PatcherData): PatchResult {
override fun execute(data: BytecodeData): PatchResult {
val result = signatures.first().result!!
val implementation = result.method.implementation!!

View File

@ -15,7 +15,7 @@ internal class SignatureChecker {
if (!file.exists()) {
throw IllegalStateException("Missing $file! To run this test, please place stock.apk here: ${file.absolutePath}")
}
val patcher = Patcher(file)
val patcher = Patcher(file, "signatureCheckerCache", false)
patcher.addPatches(Index.patches.map { it() })
val unresolved = mutableListOf<MethodSignature>()
for (signature in patcher.resolveSignatures()) {