diff --git a/build.gradle.kts b/build.gradle.kts index 4fbc0499a..c26f10b76 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -27,6 +27,7 @@ dependencies { testImplementation(kotlin("test")) implementation("app.revanced:revanced-patcher:1.+") + implementation(kotlin("reflect")) } java { diff --git a/src/main/kotlin/app/revanced/extensions/Extensions.kt b/src/main/kotlin/app/revanced/extensions/Extensions.kt index 16242c940..8162d7afd 100644 --- a/src/main/kotlin/app/revanced/extensions/Extensions.kt +++ b/src/main/kotlin/app/revanced/extensions/Extensions.kt @@ -1,6 +1,6 @@ package app.revanced.extensions -import app.revanced.patcher.smali.toInstruction +import app.revanced.patcher.util.smali.toInstruction import org.jf.dexlib2.builder.MutableMethodImplementation internal fun MutableMethodImplementation.injectHideCall( diff --git a/src/main/kotlin/app/revanced/patches/Index.kt b/src/main/kotlin/app/revanced/patches/Index.kt deleted file mode 100644 index 8c45945d6..000000000 --- a/src/main/kotlin/app/revanced/patches/Index.kt +++ /dev/null @@ -1,44 +0,0 @@ -package app.revanced.patches - -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.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 - -/** - * Index contains all the patches. - */ -@Suppress("Unused") -object Index { - /** - * Array of patches. - * New patches should be added to the array. - */ - val patches: List<() -> Patch> = listOf( - ::IntegrationsPatch, - ::FixLocaleConfigErrorPatch, - //::HomeAdsPatch, - ::VideoAdsPatch, - ::HomePromoPatch, - ::MinimizedPlaybackPatch, - ::CreateButtonRemoverPatch, - ::ShortsButtonRemoverPatch, - ::HideReelsPatch, - ::OldQualityLayoutPatch, - ::EnableSeekbarTappingPatch, - ::EnableAudioOnlyPatch, - ::RemoveUpgradeTabPatch, - ::RemoveTasteBuilderPatch, - ::BackgroundPlayPatch, - ::CodecsUnlockPatch - ) -} diff --git a/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt deleted file mode 100644 index 03c2264ff..000000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/CodecsUnlockPatch.kt +++ /dev/null @@ -1,157 +0,0 @@ -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() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt deleted file mode 100644 index e1186acb0..000000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/EnableAudioOnlyPatch.kt +++ /dev/null @@ -1,133 +0,0 @@ -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() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt new file mode 100644 index 000000000..e1404585b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.music.audio.codecs.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.apps.youtube.music", arrayOf("5.03.50") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class CodecsUnlockCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt new file mode 100644 index 000000000..4f178a6e9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt @@ -0,0 +1,44 @@ +package app.revanced.patches.music.audio.codecs.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.data.implementation.toMethodWalker +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstruction +import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility +import app.revanced.patches.music.audio.codecs.signatures.AllCodecsReferenceSignature +import app.revanced.patches.music.audio.codecs.signatures.CodecsLockSignature + +@Patch +@Name("codecs-unlock") +@Description("Enables more audio codecs. Usually results in better audio quality but may depend on song and device.") +@CodecsUnlockCompatibility +@Version("0.0.1") +class CodecsUnlockPatch : BytecodePatch( + listOf( + CodecsLockSignature, AllCodecsReferenceSignature + ) +) { + 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() + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/signatures/AllCodecsReferenceSignature.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/signatures/AllCodecsReferenceSignature.kt new file mode 100644 index 000000000..2ff563ad9 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/signatures/AllCodecsReferenceSignature.kt @@ -0,0 +1,62 @@ +package app.revanced.patches.music.audio.codecs.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("all-codecs-reference-signature") +@MatchingMethod( + "Laari;", + "b", +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@CodecsUnlockCompatibility +@Version("0.0.1") +object AllCodecsReferenceSignature : MethodSignature( + "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") +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/signatures/CodecsLockSignature.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/signatures/CodecsLockSignature.kt new file mode 100644 index 000000000..ff3f56de7 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/codecs/signatures/CodecsLockSignature.kt @@ -0,0 +1,47 @@ +package app.revanced.patches.music.audio.codecs.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("codec-lock-signature") +@MatchingMethod( + "Labwj;", + "a", +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@CodecsUnlockCompatibility +@Version("0.0.1") +object CodecsLockSignature : MethodSignature( + "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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt new file mode 100644 index 000000000..6b9b022e8 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.music.audio.exclusiveaudio.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.apps.youtube.music", arrayOf("5.03.50") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class ExclusiveAudioCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt new file mode 100644 index 000000000..e1e67f521 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt @@ -0,0 +1,70 @@ +package app.revanced.patches.music.audio.exclusiveaudio.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.or +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +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.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patcher.util.smali.toInstruction +import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility +import app.revanced.patches.music.audio.exclusiveaudio.signatures.ExclusiveAudioSignature +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Patch +@Name("exclusive-audio-playback") +@Description("Add the option to play music without video.") +@ExclusiveAudioCompatibility +@Version("0.0.1") +class ExclusiveAudioPatch : BytecodePatch( + listOf( + ExclusiveAudioSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val result = signatures.first().result!!.findParentMethod(@Name("audio-only-enabler-method") @MatchingMethod( + "Lgmd;", + "d" + ) @DirectPatternScanMethod @ExclusiveAudioCompatibility @Version( + "0.0.1" + ) object : MethodSignature( + "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 parent method could not be found.") + + val implementation = result.method.implementation!! + implementation.replaceInstruction( + implementation.instructions.count() - 1, "const/4 v0, 0x1".toInstruction() + ) + implementation.addInstruction( + "return v0".toInstruction() + ) + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/signatures/ExclusiveAudioSignature.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/signatures/ExclusiveAudioSignature.kt new file mode 100644 index 000000000..4e384c0ae --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/signatures/ExclusiveAudioSignature.kt @@ -0,0 +1,60 @@ +package app.revanced.patches.music.audio.exclusiveaudio.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("exclusive-audio-signature") +@MatchingMethod( + "Lgmd;", "c" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@ExclusiveAudioCompatibility +@Version("0.0.1") +object ExclusiveAudioSignature : MethodSignature( + "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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveTasteBuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveTasteBuilderPatch.kt deleted file mode 100644 index 904c16e5d..000000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/RemoveTasteBuilderPatch.kt +++ /dev/null @@ -1,94 +0,0 @@ -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;", ""), - 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() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt deleted file mode 100644 index b55c28008..000000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/RemoveUpgradeTabPatch.kt +++ /dev/null @@ -1,151 +0,0 @@ -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;", ""), // 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() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt new file mode 100644 index 000000000..fb2c0e383 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.music.layout.tastebuilder.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.apps.youtube.music", arrayOf("5.03.50") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class RemoveTasteBuilderCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt new file mode 100644 index 000000000..81dac406f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt @@ -0,0 +1,46 @@ +package app.revanced.patches.music.layout.tastebuilder.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility +import app.revanced.patches.music.layout.tastebuilder.signatures.TasteBuilderConstructorSignature +import org.jf.dexlib2.iface.instruction.formats.Instruction22c + +@Patch +@Name("tasteBuilder-remover") +@Description("Removes the \"Tell us which artists you like\" card from the Home screen. The same functionality can be triggered from the settings anyway.") +@RemoveTasteBuilderCompatibility +@Version("0.0.1") +class RemoveTasteBuilderPatch : BytecodePatch( + listOf( + TasteBuilderConstructorSignature + ) +) { + 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() + } +} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/signatures/TasteBuilderConstructorSignature.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/signatures/TasteBuilderConstructorSignature.kt new file mode 100644 index 000000000..f00284b07 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/signatures/TasteBuilderConstructorSignature.kt @@ -0,0 +1,43 @@ +package app.revanced.patches.music.layout.tastebuilder.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("taste-builder-constructor") +@MatchingMethod( + "Lkyu;", "" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@RemoveTasteBuilderCompatibility +@Version("0.0.1") +object TasteBuilderConstructorSignature : MethodSignature( + "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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt new file mode 100644 index 000000000..9125b39b2 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.music.layout.upgradebutton.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.apps.youtube.music", arrayOf("5.03.50") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class RemoveUpgradeButtonCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt new file mode 100644 index 000000000..9a2813d6d --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt @@ -0,0 +1,76 @@ +package app.revanced.patches.music.layout.upgradebutton.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility +import app.revanced.patches.music.layout.upgradebutton.signatures.PivotBarConstructorSignature +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 + + +@Patch +@Name("upgrade-button-remover") +@Description("Remove the upgrade tab from t he pivot bar in YouTube music.") +@RemoveUpgradeButtonCompatibility +@Version("0.0.1") +class RemoveUpgradeButtonPatch : BytecodePatch( + listOf( + PivotBarConstructorSignature + ) +) { + 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() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/signatures/PivotBarConstructorSignature.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/signatures/PivotBarConstructorSignature.kt new file mode 100644 index 000000000..238340d50 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/signatures/PivotBarConstructorSignature.kt @@ -0,0 +1,71 @@ +package app.revanced.patches.music.layout.upgradebutton.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("pivot-bar-constructor") +@MatchingMethod( + "Lhfu;", "" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@RemoveUpgradeButtonCompatibility +@Version("0.0.1") +object PivotBarConstructorSignature : MethodSignature( + "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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt deleted file mode 100644 index f84aec6fb..000000000 --- a/src/main/kotlin/app/revanced/patches/music/premium/BackgroundPlayPatch.kt +++ /dev/null @@ -1,92 +0,0 @@ -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() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt new file mode 100644 index 000000000..26af8716f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.music.premium.backgroundplay.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.apps.youtube.music", arrayOf("5.03.50") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class BackgroundPlayCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt new file mode 100644 index 000000000..84fe9a09f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt @@ -0,0 +1,37 @@ +package app.revanced.patches.music.premium.backgroundplay.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility +import app.revanced.patches.music.premium.backgroundplay.signatures.BackgroundPlaybackDisableSignature + +@Patch +@Name("background-play") +@Description("Enable playing music in the background.") +@BackgroundPlayCompatibility +@Version("0.0.1") +class BackgroundPlayPatch : BytecodePatch( + listOf( + BackgroundPlaybackDisableSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + signatures.first().result!!.method.implementation!!.addInstructions( + 0, + """ + const/4 v0, 0x1 + return v0 + """.trimIndent().toInstructions() + ) + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/signatures/BackgroundPlaybackDisableSignature.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/signatures/BackgroundPlaybackDisableSignature.kt new file mode 100644 index 000000000..98ed88508 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/signatures/BackgroundPlaybackDisableSignature.kt @@ -0,0 +1,52 @@ +package app.revanced.patches.music.premium.backgroundplay.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("background-playback-disabler-signature") +@MatchingMethod( + "Lafgf;", "e" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@BackgroundPlayCompatibility +@Version("0.0.1") +object BackgroundPlaybackDisableSignature : MethodSignature( + "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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/HomeAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/HomeAdsPatch.kt deleted file mode 100644 index fda073ee8..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/HomeAdsPatch.kt +++ /dev/null @@ -1,1706 +0,0 @@ -package app.revanced.patches.youtube.ad - -import app.revanced.extensions.injectHideCall -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.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 org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.Instruction11x - - -private val packageMetadata = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.03.38") - ), -) - -private val patchMetadata = PatchMetadata( - "home-ads", - "Home Ads Patch", - "Patch to remove ads in YouTube", - packageMetadata, - "0.0.1" -) - -private val signatureDescription = "Required signature for ${patchMetadata.name}. Discovered in version 17.03.38." - -class HomeAdsPatch : BytecodePatch( - patchMetadata, - listOf( - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-1", - MethodMetadata( - "Ljke;", - "k", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "Z", - AccessFlags.PRIVATE or AccessFlags.FINAL, - listOf("L"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.GOTO, - Opcode.IGET_OBJECT, - Opcode.IF_EQ, - Opcode.CONST, - Opcode.GOTO, - Opcode.CONST, - Opcode.INVOKE_DIRECT, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_DIRECT, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.IGET_OBJECT, - Opcode.GOTO, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.IF_EQ, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-2", - MethodMetadata( - "Ljsi;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "I" - ), - listOf( - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - 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.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - 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, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IPUT_BOOLEAN, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-3", - MethodMetadata( - "Ljrh;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_16, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.CONST_4, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.MOVE_OBJECT_FROM16 - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-4", - MethodMetadata( - "Ljrk;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "I"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-5", - MethodMetadata( - "Ljrn;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "I"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-6", - MethodMetadata( - "Ljrq;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-7", - MethodMetadata( - "Ljrr;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "I", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-8", - MethodMetadata( - "Ljrt;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-9", - MethodMetadata( - "Ljru;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-10", - MethodMetadata( - "Ljrv;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_16, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-11", - MethodMetadata( - "Ljpm;", - "lX", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, - listOf("L", "L"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-12", - MethodMetadata( - "Ljpr;", - "b", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PRIVATE or AccessFlags.FINAL, - listOf(), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-13", - MethodMetadata( - "Ljqk;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-14", - MethodMetadata( - "Ljqa;", - "b", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PRIVATE or AccessFlags.FINAL, - listOf(), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.RETURN_VOID - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-15", - MethodMetadata( - "Ljra;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "I"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.CONST_16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.NEW_INSTANCE, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.CONST_4, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-16", - MethodMetadata( - "Ljrd;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.CONST_4, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.CONST_16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.NEW_INSTANCE, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) - ), - MethodSignature( - MethodSignatureMetadata( - "home-ads-method-17", - MethodMetadata( - "Ljre;", - "", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - packageMetadata, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.IF_NEZ, - Opcode.MOVE_OBJECT_FROM16, - Opcode.GOTO, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_4, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CONST_16, - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.CONST_16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.NEW_INSTANCE, - Opcode.CONST_16, - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IF_EQZ, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - for (i in 0 until signatures.count()) { - val signature = signatures.elementAt(i) - val result = signature.result!! - val implementation = result.method.implementation!! - val index = result.scanData.startIndex - val instructions = implementation.instructions - - val register = (instructions[index + (if (i < 2) -1 else 1)] as Instruction11x).registerA - implementation.injectHideCall(index + 2, register) - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/HomePromoPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/HomePromoPatch.kt deleted file mode 100644 index f92d16738..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/HomePromoPatch.kt +++ /dev/null @@ -1,188 +0,0 @@ -package app.revanced.patches.youtube.ad - -import app.revanced.extensions.injectHideCall -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.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 org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.formats.Instruction11x - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.03.38", "17.14.35", "17.17.34") - ) -) - -private val patchMetadata = PatchMetadata( - "home-promo-ads", - "Home Promo Ads Patch", - "Patch to remove promoted ads in YouTube", - compatiblePackages, - "0.0.1" -) - -private val signatureDescription = "Required signature for ${patchMetadata.name}. Discovered in version 17.03.38." - -class HomePromoPatch : BytecodePatch( - patchMetadata, - listOf( - MethodSignature( - MethodSignatureMetadata( - "promoted-discovery-app-parent-method", - MethodMetadata( - "Ljre;", - "lP", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, - listOf("L", "L"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.IGET_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.NEW_ARRAY, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_GE, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.APUT_OBJECT, - Opcode.ADD_INT_LIT8, - Opcode.GOTO - ) - ), - MethodSignature( - MethodSignatureMetadata( - "promoted-discovery-action-parent-method", - MethodMetadata( - "Ljqv;", - "lP", - ), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, - listOf("L", "L"), - listOf( - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL_RANGE, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.XOR_INT_2ADDR, - Opcode.IGET_BOOLEAN, - Opcode.INVOKE_DIRECT, - Opcode.IGET_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - for (signature in signatures) { - val result = signature.result!! - - val methodMetadata = MethodMetadata(signature.metadata.methodMetadata!!.definingClass, "d") - val requiredMethod = result.findParentMethod( - MethodSignature( - MethodSignatureMetadata( - "promoted-discovery-action-method", - methodMetadata, - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - signatureDescription, - "0.0.1" - ), - "V", - AccessFlags.PRIVATE or AccessFlags.FINAL, - listOf("Z", "Z"), - null - ) - ) - ?: return PatchResultError("Required parent method ${methodMetadata.name} could not be found in ${methodMetadata.definingClass}") - - val toBePatchedInvokeOffset = - requiredMethod.immutableMethod.implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_DIRECT } - val toBePatchedMethod = data - .toMethodWalker(requiredMethod.immutableMethod) - .walk(toBePatchedInvokeOffset, true) - .getMethod() as MutableMethod - - val implementation = toBePatchedMethod.implementation!! - val invokeVirtualOffset = implementation.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_VIRTUAL } - - val moveResultInstruction = implementation.instructions[invokeVirtualOffset + 1] - if (moveResultInstruction.opcode != Opcode.MOVE_RESULT_OBJECT) - return PatchResultError("The toBePatchedInvokeOffset offset was wrong in ${metadata.name}") - - val register = (moveResultInstruction as Instruction11x).registerA - implementation.injectHideCall(invokeVirtualOffset + 2, register) - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/VideoAdsPatch.kt deleted file mode 100644 index 0f8396bb5..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/VideoAdsPatch.kt +++ /dev/null @@ -1,112 +0,0 @@ -package app.revanced.patches.youtube.ad - -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.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.toInstructions -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -private val packageMetadata = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.14.35", "17.17.34") - ) -) - -private val patchMetadata = PatchMetadata( - "video-ads", - "YouTube Video Ads Patch", - "Patch to remove ads in the YouTube video player.", - packageMetadata, - "0.0.1" -) - -class VideoAdsPatch : BytecodePatch( - patchMetadata, - listOf( - MethodSignature( - MethodSignatureMetadata( - "show-video-ads-constructor", - MethodMetadata( - "Laadb", - "", - ), - PatternScanMethod.Fuzzy(2),// FIXME: Test this threshold and find the best value. - packageMetadata, - "Required signature for ${patchMetadata.name}. Discovered in version 17.14.35.", - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "L", "L"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - null, // either CONST_4 or CONST_16 - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.IPUT_BOOLEAN, - Opcode.RETURN_VOID - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - var result = signatures.first().result!! - - val responsibleMethodSignature = MethodSignature( - MethodSignatureMetadata( - "show-video-ads-method", - MethodMetadata( - "zai", - null // unknown - ), - PatternScanMethod.Direct(), - packageMetadata, - "Signature to find the method, which is responsible for showing the video ads. Discovered in version 17.14.35", - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("Z"), - null - ) - - result = result.findParentMethod( - responsibleMethodSignature - ) ?: return PatchResultError( - "Could not find parent method with signature ${responsibleMethodSignature.metadata.name}" - ) - - // Override the parameter by calling shouldShowAds and setting the parameter to the result - result.method.implementation!!.addInstructions( - 0, - """ - invoke-static { }, Lfi/vanced/libraries/youtube/whitelisting/Whitelist;->shouldShowAds()Z - move-result v1 - """.trimIndent().toInstructions() - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/home/annotation/PromotionsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/home/annotation/PromotionsCompatibility.kt new file mode 100644 index 000000000..367d4bc6b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/home/annotation/PromotionsCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.ad.home.annotation + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.03.38", "17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class PromotionsCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/HomeAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/HomeAdsPatch.kt new file mode 100644 index 000000000..6b22b16e1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/HomeAdsPatch.kt @@ -0,0 +1,1710 @@ +/** +package app.revanced.patches.youtube.ad + +import app.revanced.extensions.injectHideCall +import app.revanced.patcher.annotations.Compatibility +import app.revanced.patcher.annotations.Package +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.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 org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.formats.Instruction11x + + +private val packageMetadata = listOf( +PackageMetadata( +"com.google.android.youtube", +listOf("17.03.38") +), +) + +private val patchMetadata = PatchMetadata( +"home-ads", +"Home Ads Patch", +"Patch to remove ads in YouTube", +packageMetadata, +"0.0.1" +) + +private val signatureDescription = "Required signature for ${patchMetadata.name}. Discovered in version 17.03.38." + +class HomeAdsPatch : BytecodePatch( +patchMetadata, +listOf( +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-1", +MethodMetadata( +"Ljke;", +"k", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"Z", +AccessFlags.PRIVATE or AccessFlags.FINAL, +listOf("L"), +listOf( +Opcode.INVOKE_DIRECT, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.GOTO, +Opcode.IGET_OBJECT, +Opcode.IF_EQ, +Opcode.CONST, +Opcode.GOTO, +Opcode.CONST, +Opcode.INVOKE_DIRECT, +Opcode.MOVE_RESULT_OBJECT, +Opcode.INVOKE_DIRECT, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.INVOKE_STATIC, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.INVOKE_STATIC, +Opcode.IGET_OBJECT, +Opcode.GOTO, +Opcode.IGET_OBJECT, +Opcode.INVOKE_STATIC, +Opcode.MOVE_RESULT, +Opcode.IF_EQZ, +Opcode.IGET_OBJECT, +Opcode.IF_EQ, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-2", +MethodMetadata( +"Ljsi;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"I" +), +listOf( +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +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.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +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, +Opcode.IGET_OBJECT, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CONST, +Opcode.CONST_4, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT, +Opcode.IPUT_BOOLEAN, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-3", +MethodMetadata( +"Ljrh;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_16, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.CONST_4, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.MOVE_OBJECT_FROM16 +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-4", +MethodMetadata( +"Ljrk;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, +listOf("L", "I"), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-5", +MethodMetadata( +"Ljrn;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, +listOf("L", "I"), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-6", +MethodMetadata( +"Ljrq;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-7", +MethodMetadata( +"Ljrr;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"I", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-8", +MethodMetadata( +"Ljrt;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-9", +MethodMetadata( +"Ljru;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-10", +MethodMetadata( +"Ljrv;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_16, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-11", +MethodMetadata( +"Ljpm;", +"lX", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, +listOf("L", "L"), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.INVOKE_STATIC, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-12", +MethodMetadata( +"Ljpr;", +"b", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PRIVATE or AccessFlags.FINAL, +listOf(), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.IGET_OBJECT, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.CONST_4, +Opcode.INVOKE_VIRTUAL, +Opcode.CONST_4, +Opcode.INVOKE_VIRTUAL, +Opcode.RETURN_VOID +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-13", +MethodMetadata( +"Ljqk;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST_4, +Opcode.INVOKE_STATIC, +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-14", +MethodMetadata( +"Ljqa;", +"b", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PRIVATE or AccessFlags.FINAL, +listOf(), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.RETURN_VOID +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-15", +MethodMetadata( +"Ljra;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, +listOf("L", "I"), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.CONST_16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.IGET_OBJECT, +Opcode.IGET_OBJECT, +Opcode.IGET_OBJECT, +Opcode.IGET_OBJECT, +Opcode.IGET_OBJECT, +Opcode.IGET_OBJECT, +Opcode.CONST_4, +Opcode.CONST_4, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.CONST, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.NEW_INSTANCE, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.CONST_4, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.RETURN_VOID +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-16", +MethodMetadata( +"Ljrd;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.CONST_4, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.CONST_16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.CONST_4, +Opcode.CONST_4, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.CONST, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.NEW_INSTANCE, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.RETURN_VOID +) +), +MethodSignature( +MethodSignatureMetadata( +"home-ads-method-17", +MethodMetadata( +"Ljre;", +"", +), +PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. +packageMetadata, +signatureDescription, +"0.0.1" +), +"V", +AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, +listOf( +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"L", +"[B", +"[B", +"[B", +"[B" +), +listOf( +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.CHECK_CAST, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.IF_NEZ, +Opcode.MOVE_OBJECT_FROM16, +Opcode.GOTO, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_4, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.CONST_16, +Opcode.INVOKE_DIRECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.CONST_16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.CONST_4, +Opcode.CONST_4, +Opcode.CONST_4, +Opcode.CONST_16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT_RANGE, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.CONST, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_RESULT_OBJECT, +Opcode.CHECK_CAST, +Opcode.NEW_INSTANCE, +Opcode.CONST_16, +Opcode.INVOKE_DIRECT, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.NEW_INSTANCE, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_DIRECT, +Opcode.IPUT_OBJECT, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.SGET_OBJECT, +Opcode.MOVE_OBJECT_FROM16, +Opcode.INVOKE_VIRTUAL, +Opcode.MOVE_OBJECT_FROM16, +Opcode.IF_EQZ, +Opcode.SGET_OBJECT, +Opcode.INVOKE_VIRTUAL, +Opcode.RETURN_VOID +) +) +) +) { +override fun execute(data: BytecodeData): PatchResult { +for (i in 0 until signatures.count()) { +val signature = signatures.elementAt(i) +val result = signature.result!! +val implementation = result.method.implementation!! +val index = result.scanData.startIndex +val instructions = implementation.instructions + +val register = (instructions[index + (if (i < 2) -1 else 1)] as Instruction11x).registerA +implementation.injectHideCall(index + 2, register) +} + +return PatchResultSuccess() +} +} + **/ \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/PromotionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/PromotionsPatch.kt new file mode 100644 index 000000000..c8d397c50 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/home/patch/PromotionsPatch.kt @@ -0,0 +1,65 @@ +package app.revanced.patches.youtube.ad.home.patch + +import app.revanced.extensions.injectHideCall +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +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.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +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.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod +import app.revanced.patches.youtube.ad.home.annotation.PromotionsCompatibility +import app.revanced.patches.youtube.ad.home.signatures.PromotedDiscoveryActionParentSignature +import app.revanced.patches.youtube.ad.home.signatures.PromotedDiscoveryAppParentSignature +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.formats.Instruction11x + +@Patch +@Name("home-promo-ads") +@Description("Patch to remove promoted ads in YouTube.") +@PromotionsCompatibility +@Version("0.0.1") +class PromotionsPatch : BytecodePatch( + listOf( + PromotedDiscoveryAppParentSignature, PromotedDiscoveryActionParentSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + for (signature in signatures) { + val result = signature.result!! + + val requiredMethod = + result.findParentMethod(@Name("promotion-ads-signature") @MatchingMethod(name = "d") @DirectPatternScanMethod @PromotionsCompatibility @Version( + "0.0.1" + ) object : MethodSignature( + "V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("Z", "Z"), null + ) {}) ?: return PatchResultError("Required parent method could not be found.") + + val toBePatchedInvokeOffset = + requiredMethod.immutableMethod.implementation!!.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_DIRECT } + val toBePatchedMethod = + data.toMethodWalker(requiredMethod.immutableMethod).walk(toBePatchedInvokeOffset, true) + .getMethod() as MutableMethod + + val implementation = toBePatchedMethod.implementation!! + val invokeVirtualOffset = implementation.instructions.indexOfFirst { it.opcode == Opcode.INVOKE_VIRTUAL } + + val moveResultInstruction = implementation.instructions[invokeVirtualOffset + 1] + if (moveResultInstruction.opcode != Opcode.MOVE_RESULT_OBJECT) return PatchResultError("The toBePatchedInvokeOffset offset was wrong in ${(this::class.annotations.find { it is Name } as Name).name}") + + val register = (moveResultInstruction as Instruction11x).registerA + implementation.injectHideCall(invokeVirtualOffset + 2, register) + } + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryActionParentSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryActionParentSignature.kt new file mode 100644 index 000000000..c3c8d73ee --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryActionParentSignature.kt @@ -0,0 +1,58 @@ +package app.revanced.patches.youtube.ad.home.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("promoted-discovery-app-parent-signature") +@MatchingMethod( + "Ljre;", "lP" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@SeekbarTappingCompatibility +@Version("0.0.1") +object PromotedDiscoveryActionParentSignature : MethodSignature( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, + listOf("L", "L"), + listOf( + Opcode.MOVE_OBJECT_FROM16, + Opcode.MOVE_OBJECT_FROM16, + Opcode.MOVE_OBJECT_FROM16, + Opcode.CHECK_CAST, + Opcode.INVOKE_VIRTUAL_RANGE, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.IGET_BOOLEAN, + Opcode.CONST_4, + Opcode.XOR_INT_2ADDR, + Opcode.IGET_BOOLEAN, + Opcode.INVOKE_DIRECT, + Opcode.IGET_BOOLEAN, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.CONST_4, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryAppParentSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryAppParentSignature.kt new file mode 100644 index 000000000..7c3ad070b --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/home/signatures/PromotedDiscoveryAppParentSignature.kt @@ -0,0 +1,61 @@ +package app.revanced.patches.youtube.ad.home.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("promoted-discovery-action-parent-signature") +@MatchingMethod( + "Ljqv;", + "lP" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@SeekbarTappingCompatibility +@Version("0.0.1") + +object PromotedDiscoveryAppParentSignature : MethodSignature( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL or AccessFlags.BRIDGE or AccessFlags.SYNTHETIC, + listOf("L", "L"), + listOf( + Opcode.INVOKE_DIRECT, + Opcode.IGET_BOOLEAN, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.NEW_ARRAY, + Opcode.IPUT_OBJECT, + Opcode.CONST_4, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IF_GE, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.APUT_OBJECT, + Opcode.ADD_INT_LIT8, + Opcode.GOTO + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt new file mode 100644 index 000000000..1e6a92ac1 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.ad.video.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class VideoAdsCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt new file mode 100644 index 000000000..ef1f5272f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt @@ -0,0 +1,51 @@ +package app.revanced.patches.youtube.ad.video.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.or +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +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.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.DirectPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility +import app.revanced.patches.youtube.ad.video.signatures.ShowVideoAdsConstructorSignature +import org.jf.dexlib2.AccessFlags + +@Patch +@Name("video-ads") +@Description("Patch to remove ads in the YouTube video player.") +@VideoAdsCompatibility +@Version("0.0.1") +class VideoAdsPatch : BytecodePatch( + listOf( + ShowVideoAdsConstructorSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val result = + signatures.first().result!!.findParentMethod(@Name("show-video-ads-method-signature") @MatchingMethod( + definingClass = "zai" + ) @DirectPatternScanMethod @VideoAdsCompatibility @Version("0.0.1") object : MethodSignature( + "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), null + ) {}) ?: return PatchResultError("Required parent method could not be found.") + + + // Override the parameter by calling shouldShowAds and setting the parameter to the result + result.method.implementation!!.addInstructions( + 0, """ + invoke-static { }, Lfi/vanced/libraries/youtube/whitelisting/Whitelist;->shouldShowAds()Z + move-result v1 + """.trimIndent().toInstructions() + ) + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/signatures/ShowVideoAdsConstructorSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/signatures/ShowVideoAdsConstructorSignature.kt new file mode 100644 index 000000000..ca0ae3453 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/ad/video/signatures/ShowVideoAdsConstructorSignature.kt @@ -0,0 +1,40 @@ +package app.revanced.patches.youtube.ad.video.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("show-video-ads-constructor-signature") +@MatchingMethod( + "Laadb", + "", +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@SeekbarTappingCompatibility +@Version("0.0.1") +object ShowVideoAdsConstructorSignature : MethodSignature( + "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf( + Opcode.INVOKE_DIRECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.NEW_INSTANCE, + null, // either CONST_4 or CONST_16 + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.CONST_4, + Opcode.IPUT_BOOLEAN, + Opcode.RETURN_VOID + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/EnableSeekbarTappingPatch.kt deleted file mode 100644 index 65ecd1215..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/EnableSeekbarTappingPatch.kt +++ /dev/null @@ -1,186 +0,0 @@ -package app.revanced.patches.youtube.interaction - -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.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.toInstructions -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21t -import org.jf.dexlib2.iface.Method -import org.jf.dexlib2.iface.instruction.formats.Instruction11n -import org.jf.dexlib2.iface.instruction.formats.Instruction35c - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.17.34") - ) -) - -class EnableSeekbarTappingPatch : BytecodePatch( - PatchMetadata( - "seekbar-tapping", - "Enable seekbar tapping patch", - "Enable tapping on the seekbar of the YouTube player.", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "enable-seekbar-tapping-parent-signature", - MethodMetadata("Lzhj;", "J"), // unknown - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - "Signature for a parent method, which is needed to find the actual method required to be patched.", - "0.0.1" - ), - "L", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf(), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.NEW_ARRAY, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.APUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.APUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.RETURN_OBJECT - ) - ), - MethodSignature( - MethodSignatureMetadata( - "enable-seekbar-tapping-signature", - MethodMetadata("Lfao;", "onTouchEvent"), // unknown - 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("L"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.IGET, - Opcode.IGET_OBJECT, - Opcode.IGET, - Opcode.DIV_INT_2ADDR, - Opcode.ADD_INT, - Opcode.SUB_INT_2ADDR, - Opcode.INT_TO_FLOAT, - Opcode.CMPG_FLOAT, - Opcode.IF_GTZ, - Opcode.INT_TO_FLOAT, - Opcode.CMPG_FLOAT, - Opcode.IF_GTZ, - Opcode.CONST_4, - Opcode.INVOKE_INTERFACE, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - var result = signatures.first().result!! - - val tapSeekMethods = mutableMapOf() - - // find the methods which tap the seekbar - for (it in result.definingClassProxy.immutableClass.methods) { - if (it.implementation == null) continue - - val instructions = it.implementation!!.instructions - // here we make sure we actually find the method because it has more then 7 instructions - if (instructions.count() < 7) continue - - // we know that the 7th instruction has the opcode CONST_4 - val instruction = instructions.elementAt(6) - if (instruction.opcode != Opcode.CONST_4) continue - - // the literal for this instruction has to be either 1 or 2 - val literal = (instruction as Instruction11n).narrowLiteral - - // method founds - if (literal == 1) tapSeekMethods["P"] = it - if (literal == 2) tapSeekMethods["O"] = it - } - - // replace map because we dont need the upper one anymore - result = signatures.last().result!! - - val implementation = result.method.implementation!! - - // if tap-seeking is enabled, do not invoke the two methods below - val pMethod = tapSeekMethods["P"]!! - val oMethod = tapSeekMethods["O"]!! - - // get the required register - val instruction = implementation.instructions[result.scanData.endIndex] - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) - return PatchResultError("Could not find the correct register") - val register = (instruction as Instruction35c).registerC - - // the instructions are written in reverse order. - implementation.addInstructions( - result.scanData.endIndex + 1, - """ - invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V - invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V - """.trimIndent().toInstructions() - ) - - // if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label - val elseLabel = implementation.newLabelForIndex(result.scanData.endIndex + 1) - implementation.addInstruction( - result.scanData.endIndex + 1, - BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel) - ) - implementation.addInstructions( - result.scanData.endIndex + 1, - """ - invoke-static { }, Lfi/razerman/youtube/preferences/BooleanPreferences;->isTapSeekingEnabled()Z - move-result v0 - """.trimIndent().toInstructions() - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt new file mode 100644 index 000000000..8287b9070 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt @@ -0,0 +1,14 @@ +package app.revanced.patches.youtube.interaction.seekbar.annotation + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class SeekbarTappingCompatibility + diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt new file mode 100644 index 000000000..3670d72cb --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt @@ -0,0 +1,94 @@ +package app.revanced.patches.youtube.interaction.seekbar.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +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.util.smali.toInstructions +import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility +import app.revanced.patches.youtube.interaction.seekbar.signatures.SeekbarTappingParentSignature +import app.revanced.patches.youtube.interaction.seekbar.signatures.SeekbarTappingSignature +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction21t +import org.jf.dexlib2.iface.Method +import org.jf.dexlib2.iface.instruction.formats.Instruction11n +import org.jf.dexlib2.iface.instruction.formats.Instruction35c + + +@Patch +@Name("seekbar-tapping") +@Description("Enable tapping on the seekbar of the YouTube player.") +@SeekbarTappingCompatibility +@Version("0.0.1") +class EnableSeekbarTappingPatch : BytecodePatch( + listOf( + SeekbarTappingParentSignature, SeekbarTappingSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + var result = signatures.first().result!! + + val tapSeekMethods = mutableMapOf() + + // find the methods which tap the seekbar + for (it in result.definingClassProxy.immutableClass.methods) { + if (it.implementation == null) continue + + val instructions = it.implementation!!.instructions + // here we make sure we actually find the method because it has more then 7 instructions + if (instructions.count() < 7) continue + + // we know that the 7th instruction has the opcode CONST_4 + val instruction = instructions.elementAt(6) + if (instruction.opcode != Opcode.CONST_4) continue + + // the literal for this instruction has to be either 1 or 2 + val literal = (instruction as Instruction11n).narrowLiteral + + // method founds + if (literal == 1) tapSeekMethods["P"] = it + if (literal == 2) tapSeekMethods["O"] = it + } + + // replace map because we dont need the upper one anymore + result = signatures.last().result!! + + val implementation = result.method.implementation!! + + // if tap-seeking is enabled, do not invoke the two methods below + val pMethod = tapSeekMethods["P"]!! + val oMethod = tapSeekMethods["O"]!! + + // get the required register + val instruction = implementation.instructions[result.scanData.endIndex] + if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register") + val register = (instruction as Instruction35c).registerC + + // the instructions are written in reverse order. + implementation.addInstructions( + result.scanData.endIndex + 1, """ + invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V + invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V + """.trimIndent().toInstructions() + ) + + // if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label + val elseLabel = implementation.newLabelForIndex(result.scanData.endIndex + 1) + implementation.addInstruction( + result.scanData.endIndex + 1, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel) + ) + implementation.addInstructions( + result.scanData.endIndex + 1, """ + invoke-static { }, Lfi/razerman/youtube/preferences/BooleanPreferences;->isTapSeekingEnabled()Z + move-result v0 + """.trimIndent().toInstructions() + ) + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingParentSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingParentSignature.kt new file mode 100644 index 000000000..554b41464 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingParentSignature.kt @@ -0,0 +1,51 @@ +package app.revanced.patches.youtube.interaction.seekbar.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("enable-seekbar-tapping-parent") +@MatchingMethod("Lzhj;", "J") +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@SeekbarTappingCompatibility +@Version("0.0.1") +object SeekbarTappingParentSignature : MethodSignature( + "L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_4, + Opcode.NEW_ARRAY, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_WIDE, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_4, + Opcode.APUT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_WIDE, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CONST_4, + Opcode.APUT_OBJECT, + Opcode.CONST, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.RETURN_OBJECT + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingSignature.kt new file mode 100644 index 000000000..7b471c070 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/signatures/SeekbarTappingSignature.kt @@ -0,0 +1,41 @@ +package app.revanced.patches.youtube.interaction.seekbar.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("enable-seekbar-tapping-signature") +@MatchingMethod("Lfao;", "onTouchEvent") +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@SeekbarTappingCompatibility +@Version("0.0.1") +object SeekbarTappingSignature : MethodSignature( + "Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_WIDE, + Opcode.IGET, + Opcode.IGET_OBJECT, + Opcode.IGET, + Opcode.DIV_INT_2ADDR, + Opcode.ADD_INT, + Opcode.SUB_INT_2ADDR, + Opcode.INT_TO_FLOAT, + Opcode.CMPG_FLOAT, + Opcode.IF_GTZ, + Opcode.INT_TO_FLOAT, + Opcode.CMPG_FLOAT, + Opcode.IF_GTZ, + Opcode.CONST_4, + Opcode.INVOKE_INTERFACE, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.INVOKE_VIRTUAL + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/CreateButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/CreateButtonRemoverPatch.kt deleted file mode 100644 index 7293dd65f..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/CreateButtonRemoverPatch.kt +++ /dev/null @@ -1,102 +0,0 @@ -package app.revanced.patches.youtube.layout - -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 -import org.jf.dexlib2.iface.instruction.formats.Instruction35c - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.14.35", "17.17.34") - ) -) - -class CreateButtonRemoverPatch : BytecodePatch( - PatchMetadata( - "create-button", - "Create button patch", - "Disable the create button.", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "create-button-method", - MethodMetadata("Lkne", "z"), // unknown - 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("Z"), - listOf( - Opcode.IGET, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.CONST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - ) - ) - ) -) { - 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 - val implementation = result.method.implementation!! - val instruction = implementation.instructions[result.scanData.endIndex + 1] - if (instruction.opcode != Opcode.INVOKE_STATIC) - return PatchResultError("Could not find the correct register") - val register = (instruction as Instruction35c).registerC - - // Hide the button view via proxy by passing it to the hideCreateButton method - implementation.addInstruction( - result.scanData.endIndex + 1, - "invoke-static { v$register }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".toInstruction() - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/HideReelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/HideReelsPatch.kt deleted file mode 100644 index 47ce377b6..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/HideReelsPatch.kt +++ /dev/null @@ -1,115 +0,0 @@ -package app.revanced.patches.youtube.layout - -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.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.youtube", - listOf("17.17.34") - ) -) - -class HideReelsPatch : BytecodePatch( - PatchMetadata( - "hide-reels", - "Hide reels patch", - "Hide reels on the page.", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "hide-reels-signature", - MethodMetadata("Ljvy", ""), // unknown - PatternScanMethod.Fuzzy(3), // 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.CONSTRUCTOR, - listOf( - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "L", - "[B", - "[B", - "[B", - "[B", - "[B", - "[B" - ), - listOf( - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.INVOKE_DIRECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.MOVE_OBJECT_FROM16, - 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 - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - val result = signatures.first().result!! - val implementation = result.method.implementation!! - - // HideReel will hide the reel view before it is being used, - // so we pass the view to the HideReel method - implementation.addInstruction( - result.scanData.endIndex, - "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".toInstruction() - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/MinimizedPlaybackPatch.kt deleted file mode 100644 index 91551d523..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/MinimizedPlaybackPatch.kt +++ /dev/null @@ -1,89 +0,0 @@ -package app.revanced.patches.youtube.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 - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.14.35", "17.17.34") - ) -) - -class MinimizedPlaybackPatch : BytecodePatch( - PatchMetadata( - "minimized-playback", - "Minimized Playback Patch", - "Enable minimized and background playback.", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "minimized-playback-manager", - MethodMetadata("Lype", "j"), // unknown - 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 - ) - ) - ) -) { - 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( - 0, - """ - const/4 v0, 0x1 - return v0 - """.trimIndent().toInstructions() - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/OldQualityLayoutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/OldQualityLayoutPatch.kt deleted file mode 100644 index 80114a368..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/OldQualityLayoutPatch.kt +++ /dev/null @@ -1,127 +0,0 @@ -package app.revanced.patches.youtube.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.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.toInstructions -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21t - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.17.34") - ) -) - -class OldQualityLayoutPatch : BytecodePatch( - PatchMetadata( - "old-quality-layout", - "Old Quality Layout Patch", - "Enable the original quality flyout menu", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "old-quality-parent-method-signature", - MethodMetadata("Libh", ""), // unknown - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - "Signature to find a parent method required by the Old Quality Layout patch.", - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "L", "L", "L", "L", "L", "L"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_4, - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - var result = signatures.first().result!! - - result = result.findParentMethod( - MethodSignature( - MethodSignatureMetadata( - "old-quality-method-signature", - MethodMetadata("Libh", null), // unknown - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - "Signature to find the method required by the Old Quality Layout patch", - "0.0.1" - ), - "L", - AccessFlags.FINAL or AccessFlags.PRIVATE, - listOf("Z"), - listOf( - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.GOTO, - Opcode.IGET_OBJECT, - ) - ) - ) ?: return PatchResultError("Method old-quality-patch-method has not been found") - - val implementation = result.method.implementation!! - - // if useOldStyleQualitySettings == true, jump over all instructions - val jmpInstruction = - BuilderInstruction21t( - Opcode.IF_NEZ, - 0, - implementation.instructions[result.scanData.endIndex].location.labels.first() - ) - implementation.addInstruction(5, jmpInstruction) - implementation.addInstructions( - 0, - """ - invoke-static { }, Lfi/razerman/youtube/XGlobals;->useOldStyleQualitySettings()Z - move-result v0 - """.trimIndent().toInstructions() - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/ShortsButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/ShortsButtonRemoverPatch.kt deleted file mode 100644 index 7a393ef15..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/ShortsButtonRemoverPatch.kt +++ /dev/null @@ -1,135 +0,0 @@ -package app.revanced.patches.youtube.layout - -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.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 -import org.jf.dexlib2.iface.instruction.formats.Instruction11x - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.14.35", "17.17.34") - ) -) - -class ShortsButtonRemoverPatch : BytecodePatch( - PatchMetadata( - "shorts-button", - "Shorts button patch", - "Hide the shorts button.", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "pivotbar-buttons-method-tabenum", - MethodMetadata("Lkne", "z"), // unknown - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - "Signature for the pivotbar method that creates all button views.", - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("Z"), - listOf( - Opcode.CHECK_CAST, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.INVOKE_STATIC, // SomeEnum.fromValue(tabOrdinal) - Opcode.MOVE_RESULT_OBJECT - ) - ), - MethodSignature( - MethodSignatureMetadata( - "pivotbar-buttons-method-view", - MethodMetadata("Lkne", "z"), // unknown - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - "Signature for the pivotbar method that creates all button views.", - "0.0.1" - ), - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("Z"), - listOf( - Opcode.NEW_INSTANCE, // new StateListDrawable() - Opcode.INVOKE_DIRECT, - Opcode.NEW_ARRAY, - Opcode.CONST, - Opcode.CONST_16, - Opcode.APUT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.MOVE, - Opcode.MOVE_OBJECT, - Opcode.INVOKE_VIRTUAL_RANGE, // pivotBar.getView(drawable, tabName, z, i, map, akebVar, optional) - Opcode.MOVE_RESULT_OBJECT, - ) - ), - ) -) { - override fun execute(data: BytecodeData): PatchResult { - val result1 = signatures.first().result!! - val implementation1 = result1.method.implementation!! - val moveEnumInstruction = implementation1.instructions[result1.scanData.endIndex] - val enumRegister = (moveEnumInstruction as Instruction11x).registerA - - val result2 = signatures.last().result!! - val implementation2 = result2.method.implementation!! - val moveViewInstruction = implementation2.instructions[result2.scanData.endIndex] - val viewRegister = (moveViewInstruction as Instruction11x).registerA - - // Save the tab enum in XGlobals to avoid smali/register workarounds - implementation1.addInstruction( - result1.scanData.endIndex + 1, - "sput-object v$enumRegister, Lfi/razerman/youtube/XGlobals;->lastPivotTab:Ljava/lang/Enum;".toInstruction() - ) - - // Hide the button view via proxy by passing it to the hideShortsButton method - // It only hides it if the last tab name is "TAB_SHORTS" - implementation2.addInstruction( - result2.scanData.endIndex + 2, - "invoke-static { v$viewRegister }, Lfi/razerman/youtube/XAdRemover;->hideShortsButton(Landroid/view/View;)V".toInstruction() - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/annotations/CreateButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/annotations/CreateButtonCompatibility.kt new file mode 100644 index 000000000..c00fa9aec --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/annotations/CreateButtonCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.createbutton.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class CreateButtonCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/patch/CreateButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/patch/CreateButtonRemoverPatch.kt new file mode 100644 index 000000000..288d04810 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/patch/CreateButtonRemoverPatch.kt @@ -0,0 +1,46 @@ +package app.revanced.patches.youtube.layout.createbutton.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +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.util.smali.toInstruction +import app.revanced.patches.youtube.layout.createbutton.signatures.CreateButtonSignature +import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.iface.instruction.formats.Instruction35c + +@Patch +@Name("disable-create-button") +@Description("Disable the create button.") +@MinimizedPlaybackCompatibility +@Version("0.0.1") +class CreateButtonRemoverPatch : BytecodePatch( + listOf( + CreateButtonSignature + ) +) { + 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 + val implementation = result.method.implementation!! + val instruction = implementation.instructions[result.scanData.endIndex + 1] + if (instruction.opcode != Opcode.INVOKE_STATIC) + return PatchResultError("Could not find the correct register") + val register = (instruction as Instruction35c).registerC + + // Hide the button view via proxy by passing it to the hideCreateButton method + implementation.addInstruction( + result.scanData.endIndex + 1, + "invoke-static { v$register }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".toInstruction() + ) + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/signatures/CreateButtonSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/signatures/CreateButtonSignature.kt new file mode 100644 index 000000000..022a9a329 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/createbutton/signatures/CreateButtonSignature.kt @@ -0,0 +1,57 @@ +package app.revanced.patches.youtube.layout.createbutton.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.layout.amoled.annotations.AmoledCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("create-button-signature") +@MatchingMethod( + "Lkne", "z" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@AmoledCompatibility +@Version("0.0.1") +object CreateButtonSignature : MethodSignature( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + listOf("Z"), + listOf( + Opcode.IGET, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.CONST, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.INVOKE_DIRECT_RANGE, + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt new file mode 100644 index 000000000..07fbe86df --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.minimizedplayback.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class MinimizedPlaybackCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt new file mode 100644 index 000000000..8cd9c79b3 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt @@ -0,0 +1,39 @@ +package app.revanced.patches.youtube.layout.minimizedplayback.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility +import app.revanced.patches.youtube.layout.minimizedplayback.signatures.MinimizedPlaybackManagerSignature + + +@Patch +@Name("minimized-playback") +@Description("Enable minimized and background playback.") +@MinimizedPlaybackCompatibility +@Version("0.0.1") + +class MinimizedPlaybackPatch : BytecodePatch( + listOf( + MinimizedPlaybackManagerSignature + ) +) { + 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( + 0, """ + const/4 v0, 0x1 + return v0 + """.trimIndent().toInstructions() + ) + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/signatures/MinimizedPlaybackManagerSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/signatures/MinimizedPlaybackManagerSignature.kt new file mode 100644 index 000000000..934737768 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/minimizedplayback/signatures/MinimizedPlaybackManagerSignature.kt @@ -0,0 +1,51 @@ +package app.revanced.patches.youtube.layout.minimizedplayback.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("minimized-playback-manager-signature") +@MatchingMethod( + "Lype", "j" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@MinimizedPlaybackCompatibility +@Version("0.0.1") +object MinimizedPlaybackManagerSignature : MethodSignature( + "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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt new file mode 100644 index 000000000..8992bf9ec --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.oldqualitylayout.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class OldQualityLayoutCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt new file mode 100644 index 000000000..927dd43cc --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt @@ -0,0 +1,66 @@ +package app.revanced.patches.youtube.layout.oldqualitylayout.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.or +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +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.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility +import app.revanced.patches.youtube.layout.oldqualitylayout.signatures.OldQualityParentSignature +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode +import org.jf.dexlib2.builder.instruction.BuilderInstruction21t + +@Patch +@Name("old-quality-layout") +@Description("Enable the original quality flyout menu.") +@OldQualityLayoutCompatibility +@Version("0.0.1") +class OldQualityLayoutPatch : BytecodePatch( + listOf( + OldQualityParentSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val result = signatures.first().result!!.findParentMethod(@Name("old-quality-signature") @MatchingMethod( + definingClass = "Libh" + ) @FuzzyPatternScanMethod(2) @OldQualityLayoutCompatibility @Version("0.0.1") object : MethodSignature( + "L", AccessFlags.FINAL or AccessFlags.PRIVATE, listOf("Z"), listOf( + Opcode.CONST_4, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.IGET_OBJECT, + Opcode.GOTO, + Opcode.IGET_OBJECT, + ) + ) {}) ?: return PatchResultError("Required parent method could not be found.") + + val implementation = result.method.implementation!! + + // if useOldStyleQualitySettings == true, jump over all instructions + val jmpInstruction = BuilderInstruction21t( + Opcode.IF_NEZ, 0, implementation.instructions[result.scanData.endIndex].location.labels.first() + ) + implementation.addInstruction(5, jmpInstruction) + implementation.addInstructions( + 0, """ + invoke-static { }, Lfi/razerman/youtube/XGlobals;->useOldStyleQualitySettings()Z + move-result v0 + """.trimIndent().toInstructions() + ) + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/signatures/OldQualityParentSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/signatures/OldQualityParentSignature.kt new file mode 100644 index 000000000..c9dd15a28 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/signatures/OldQualityParentSignature.kt @@ -0,0 +1,50 @@ +package app.revanced.patches.youtube.layout.oldqualitylayout.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("old-quality-parent-method-signature") +@MatchingMethod( + "Libh", "" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@OldQualityLayoutCompatibility +@Version("0.0.1") +object OldQualityParentSignature : MethodSignature( + "V", + AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, + listOf("L", "L", "L", "L", "L", "L", "L"), + listOf( + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.SGET_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.SGET_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET_BOOLEAN, + Opcode.CONST_4, + Opcode.CONST_4, + Opcode.CONST_4, + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt new file mode 100644 index 000000000..2144d954f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.reels.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class HideReelsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt new file mode 100644 index 000000000..8b5e14f76 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt @@ -0,0 +1,38 @@ +package app.revanced.patches.youtube.layout.reels.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstruction +import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility +import app.revanced.patches.youtube.layout.reels.signatures.HideReelsSignature + +@Patch +@Name("hide-reels") +@Description("Hide reels on the page.") +@HideReelsCompatibility +@Version("0.0.1") +class HideReelsPatch : BytecodePatch( + listOf( + HideReelsSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val result = signatures.first().result!! + val implementation = result.method.implementation!! + + // HideReel will hide the reel view before it is being used, + // so we pass the view to the HideReel method + implementation.addInstruction( + result.scanData.endIndex, + "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".toInstruction() + ) + + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/signatures/HideReelsSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/signatures/HideReelsSignature.kt new file mode 100644 index 000000000..44baac54e --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/signatures/HideReelsSignature.kt @@ -0,0 +1,58 @@ +package app.revanced.patches.youtube.layout.reels.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("hide-reels-signature") +@MatchingMethod( + "Ljvy", "" +) +@FuzzyPatternScanMethod(3) // FIXME: Test this threshold and find the best value. +@HideReelsCompatibility +@Version("0.0.1") +object HideReelsSignature : MethodSignature( + "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf( + "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "[B", "[B", "[B", "[B", "[B", "[B" + ), listOf( + Opcode.MOVE_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.INVOKE_DIRECT, + Opcode.MOVE_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT_FROM16, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT_FROM16, + Opcode.IPUT_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IPUT_OBJECT, + Opcode.MOVE_OBJECT_FROM16, + 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 + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/annotations/ShortsButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/annotations/ShortsButtonCompatibility.kt new file mode 100644 index 000000000..d55ca4904 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/annotations/ShortsButtonCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.layout.shorts.button.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class ShortsButtonCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/patch/ShortsButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/patch/ShortsButtonRemoverPatch.kt new file mode 100644 index 000000000..63571bef2 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/patch/ShortsButtonRemoverPatch.kt @@ -0,0 +1,53 @@ +package app.revanced.patches.youtube.layout.shorts.button.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.smali.toInstruction +import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility +import app.revanced.patches.youtube.layout.shorts.button.signatures.PivotBarButtonTabenumSignature +import app.revanced.patches.youtube.layout.shorts.button.signatures.PivotBarButtonsViewSignature +import org.jf.dexlib2.iface.instruction.formats.Instruction11x + +@Patch +@Name("shorts-button") +@Description("Hide the shorts button.") +@ShortsButtonCompatibility +@Version("0.0.1") +class ShortsButtonRemoverPatch : BytecodePatch( + listOf( + PivotBarButtonTabenumSignature, PivotBarButtonsViewSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val result1 = signatures.first().result!! + val implementation1 = result1.method.implementation!! + val moveEnumInstruction = implementation1.instructions[result1.scanData.endIndex] + val enumRegister = (moveEnumInstruction as Instruction11x).registerA + + val result2 = signatures.last().result!! + val implementation2 = result2.method.implementation!! + val moveViewInstruction = implementation2.instructions[result2.scanData.endIndex] + val viewRegister = (moveViewInstruction as Instruction11x).registerA + + // Save the tab enum in XGlobals to avoid smali/register workarounds + implementation1.addInstruction( + result1.scanData.endIndex + 1, + "sput-object v$enumRegister, Lfi/razerman/youtube/XGlobals;->lastPivotTab:Ljava/lang/Enum;".toInstruction() + ) + + // Hide the button view via proxy by passing it to the hideShortsButton method + // It only hides it if the last tab name is "TAB_SHORTS" + implementation2.addInstruction( + result2.scanData.endIndex + 2, + "invoke-static { v$viewRegister }, Lfi/razerman/youtube/XAdRemover;->hideShortsButton(Landroid/view/View;)V".toInstruction() + ) + + return PatchResultSuccess() + } +} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonTabenumSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonTabenumSignature.kt new file mode 100644 index 000000000..ea37ba632 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonTabenumSignature.kt @@ -0,0 +1,45 @@ +package app.revanced.patches.youtube.layout.shorts.button.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("pivotbar-buttons-tabenum-signature") +@MatchingMethod( + "Lkne", "z" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@ShortsButtonCompatibility +@Version("0.0.1") +object PivotBarButtonTabenumSignature : MethodSignature( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + listOf("Z"), + listOf( + Opcode.CHECK_CAST, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT, + Opcode.IGET_OBJECT, + Opcode.CHECK_CAST, + Opcode.IGET_OBJECT, + Opcode.IF_NEZ, + Opcode.SGET_OBJECT, + Opcode.IGET, + Opcode.INVOKE_STATIC, // SomeEnum.fromValue(tabOrdinal) + Opcode.MOVE_RESULT_OBJECT + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonsViewSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonsViewSignature.kt new file mode 100644 index 000000000..b3140fe7f --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/shorts/button/signatures/PivotBarButtonsViewSignature.kt @@ -0,0 +1,49 @@ +package app.revanced.patches.youtube.layout.shorts.button.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.extensions.or +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.layout.shorts.button.annotations.ShortsButtonCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("pivotbar-buttons-view-signature") +@MatchingMethod( + "Lkne", "z" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@ShortsButtonCompatibility +@Version("0.0.1") +object PivotBarButtonsViewSignature : MethodSignature( + "V", + AccessFlags.PUBLIC or AccessFlags.FINAL, + listOf("Z"), + listOf( + Opcode.NEW_INSTANCE, // new StateListDrawable() + Opcode.INVOKE_DIRECT, + Opcode.NEW_ARRAY, + Opcode.CONST, + Opcode.CONST_16, + Opcode.APUT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.SGET_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_VIRTUAL, + Opcode.MOVE_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.MOVE, + Opcode.MOVE_OBJECT, + Opcode.INVOKE_VIRTUAL_RANGE, // pivotBar.getView(drawable, tabName, z, i, map, akebVar, optional) + Opcode.MOVE_RESULT_OBJECT, + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/IntegrationsPatch.kt deleted file mode 100644 index 33b7ea253..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/IntegrationsPatch.kt +++ /dev/null @@ -1,125 +0,0 @@ -package app.revanced.patches.youtube.misc - -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.proxy.mutableTypes.MutableMethod.Companion.toMutable -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.immutable.ImmutableMethod -import org.jf.dexlib2.immutable.ImmutableMethodImplementation - -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.03.38", "17.14.35", "17.17.34") - ) -) - -class IntegrationsPatch : BytecodePatch( - PatchMetadata( - "integrations", - "Inject Integrations Patch", - "Applies mandatory patches to implement the ReVanced integrations into the application.", - compatiblePackages, - "0.0.1" - ), - listOf( - MethodSignature( - MethodSignatureMetadata( - "integrations-patch", - MethodMetadata("Lacnx", "onCreate"), - PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value. - compatiblePackages, - "Inject the integrations into the application with the method of this signature", - "0.0.1" - ), - "V", - AccessFlags.PUBLIC.value, - listOf(), - listOf( - Opcode.SGET_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IGET_OBJECT, - Opcode.CONST_STRING, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.MOVE_OBJECT, - Opcode.CHECK_CAST, - Opcode.CONST_4, - Opcode.CONST_STRING, - Opcode.INVOKE_INTERFACE_RANGE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SPUT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_SUPER, - Opcode.INVOKE_VIRTUAL - ) - ) - ) -) { - override fun execute(data: BytecodeData): PatchResult { - val result = signatures.first().result!! - - val implementation = result.method.implementation!! - val count = implementation.registerCount - 1 - - implementation.addInstructions( - result.scanData.endIndex + 1, - """ - invoke-static {v$count}, Lpl/jakubweg/StringRef;->setContext(Landroid/content/Context;)V - sput-object v$count, Lapp/revanced/integrations/Globals;->context:Landroid/content/Context; - """.trimIndent().toInstructions() - ) - - val classDef = result.definingClassProxy.resolve() - classDef.methods.add( - ImmutableMethod( - classDef.type, - "getAppContext", - null, - "Landroid/content/Context;", - AccessFlags.PUBLIC or AccessFlags.STATIC, - null, - null, - ImmutableMethodImplementation( - 1, - """ - invoke-static { }, Lapp/revanced/integrations/Globals;->getAppContext()Landroid/content/Context; - move-result-object v0 - return-object v0 - """.trimIndent().toInstructions(), - null, - null - ) - ).toMutable() - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt new file mode 100644 index 000000000..318ea09da --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.misc.integrations.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.03.38", "17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class IntegrationsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt new file mode 100644 index 000000000..538da04d3 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt @@ -0,0 +1,65 @@ +package app.revanced.patches.youtube.misc.integrations.patch + +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.data.implementation.BytecodeData +import app.revanced.patcher.extensions.addInstructions +import app.revanced.patcher.extensions.or +import app.revanced.patcher.patch.annotations.Patch +import app.revanced.patcher.patch.implementation.BytecodePatch +import app.revanced.patcher.patch.implementation.misc.PatchResult +import app.revanced.patcher.patch.implementation.misc.PatchResultSuccess +import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable +import app.revanced.patcher.util.smali.toInstructions +import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility +import app.revanced.patches.youtube.misc.integrations.signatures.InitSignature +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.immutable.ImmutableMethod +import org.jf.dexlib2.immutable.ImmutableMethodImplementation + +@Patch +@Name("integrations") +@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") +@IntegrationsCompatibility +@Version("0.0.1") +class IntegrationsPatch : BytecodePatch( + listOf( + InitSignature + ) +) { + override fun execute(data: BytecodeData): PatchResult { + val result = signatures.first().result!! + + val implementation = result.method.implementation!! + val count = implementation.registerCount - 1 + + implementation.addInstructions( + result.scanData.endIndex + 1, """ + invoke-static {v$count}, Lpl/jakubweg/StringRef;->setContext(Landroid/content/Context;)V + sput-object v$count, Lapp/revanced/integrations/Globals;->context:Landroid/content/Context; + """.trimIndent().toInstructions() + ) + + val classDef = result.definingClassProxy.resolve() + classDef.methods.add( + ImmutableMethod( + classDef.type, + "getAppContext", + null, + "Landroid/content/Context;", + AccessFlags.PUBLIC or AccessFlags.STATIC, + null, + null, + ImmutableMethodImplementation( + 1, """ + invoke-static { }, Lapp/revanced/integrations/Globals;->getAppContext()Landroid/content/Context; + move-result-object v0 + return-object v0 + """.trimIndent().toInstructions(), null, null + ) + ).toMutable() + ) + return PatchResultSuccess() + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/signatures/InitSignature.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/signatures/InitSignature.kt new file mode 100644 index 000000000..390fd033a --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/signatures/InitSignature.kt @@ -0,0 +1,57 @@ +package app.revanced.patches.youtube.misc.integrations.signatures + +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version +import app.revanced.patcher.signature.implementation.method.MethodSignature +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility +import org.jf.dexlib2.AccessFlags +import org.jf.dexlib2.Opcode + +@Name("init-signature") +@MatchingMethod( + "Lacnx", "onCreate" +) +@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. +@IntegrationsCompatibility +@Version("0.0.1") +object InitSignature : MethodSignature( + "V", + AccessFlags.PUBLIC.value, + listOf(), + listOf( + Opcode.SGET_OBJECT, + Opcode.NEW_INSTANCE, + Opcode.INVOKE_DIRECT, + Opcode.IGET_OBJECT, + Opcode.CONST_STRING, + Opcode.IF_NEZ, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.IGET_OBJECT, + Opcode.MOVE_OBJECT, + Opcode.CHECK_CAST, + Opcode.MOVE_OBJECT, + Opcode.CHECK_CAST, + Opcode.CONST_4, + Opcode.CONST_STRING, + Opcode.INVOKE_INTERFACE_RANGE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.SPUT_OBJECT, + Opcode.SGET_OBJECT, + Opcode.INVOKE_STATIC, + Opcode.INVOKE_STATIC, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.CHECK_CAST, + Opcode.INVOKE_VIRTUAL, + Opcode.INVOKE_SUPER, + Opcode.INVOKE_VIRTUAL + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt new file mode 100644 index 000000000..a04be9849 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.youtube.misc.manifest.annotations + +import app.revanced.patcher.annotation.Compatibility +import app.revanced.patcher.annotation.Package + +@Compatibility( + [Package( + "com.google.android.youtube", arrayOf("17.14.35", "17.17.34") + )] +) +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +internal annotation class FixLocaleConfigErrorCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/FixLocaleConfigErrorPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt similarity index 56% rename from src/main/kotlin/app/revanced/patches/youtube/misc/FixLocaleConfigErrorPatch.kt rename to src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt index aefc1807f..df1233d9c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/FixLocaleConfigErrorPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt @@ -1,28 +1,22 @@ -package app.revanced.patches.youtube.misc +package app.revanced.patches.youtube.misc.manifest.patch +import app.revanced.patcher.annotation.Description +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.annotation.Version import app.revanced.patcher.data.implementation.ResourceData +import app.revanced.patcher.patch.annotations.Patch 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 app.revanced.patches.youtube.misc.manifest.annotations.FixLocaleConfigErrorCompatibility import org.w3c.dom.Element -private val compatiblePackages = listOf( - PackageMetadata( - "com.google.android.youtube", - listOf("17.14.35", "17.17.34") - ) -) -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" - ), -) { +@Patch +@Name("locale-config-fix") +@Description("Fix an error when building the resources by patching the manifest file.") +@FixLocaleConfigErrorCompatibility +@Version("0.0.1") +class FixLocaleConfigErrorPatch : ResourcePatch() { override fun execute(data: ResourceData): PatchResult { // create an xml editor instance val editor = data.getXmlEditor("AndroidManifest.xml") @@ -35,7 +29,7 @@ class FixLocaleConfigErrorPatch : ResourcePatch( // by replacing the attributes name val attribute = "android:localeConfig" - applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute)) + applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute)) applicationNode.removeAttribute("android:localeConfig") // close & save the modified file diff --git a/src/test/kotlin/app/revanced/patches/SignatureChecker.kt b/src/test/kotlin/app/revanced/patches/SignatureChecker.kt index 43bf21de7..ffa80f2c0 100644 --- a/src/test/kotlin/app/revanced/patches/SignatureChecker.kt +++ b/src/test/kotlin/app/revanced/patches/SignatureChecker.kt @@ -1,17 +1,18 @@ package app.revanced.patches import app.revanced.patcher.Patcher -import app.revanced.patcher.signature.MethodMetadata -import app.revanced.patcher.signature.MethodSignature -import app.revanced.patcher.signature.PatternScanMethod +import app.revanced.patcher.annotation.Name +import app.revanced.patcher.signature.implementation.method.annotation.FuzzyPatternScanMethod +import app.revanced.patcher.signature.implementation.method.annotation.MatchingMethod +import app.revanced.patcher.signature.implementation.method.annotation.PatternScanMethod import org.jf.dexlib2.iface.Method import org.junit.Test import java.io.File internal class SignatureChecker { @Test - fun checkSignatures() { - return + fun checkMethodSignatures() { + // FIXME: instead of having this as a test, it should be turned into a task which can be ran manually val file = File("stock.apk") if (!file.exists()) { @@ -19,24 +20,26 @@ internal class SignatureChecker { } val patcher = Patcher(file, "signatureCheckerCache", false) patcher.addPatches(Index.patches.map { it() }) - val unresolved = mutableListOf() + val unresolved = mutableListOf() for (signature in patcher.resolveSignatures()) { + val signatureAnnotations = signature::class.annotations + + val nameAnnotation = signatureAnnotations.find { it is Name } as Name if (!signature.resolved) { - unresolved.add(signature) + unresolved.add(nameAnnotation.name) continue } - val patternScanMethod = signature.metadata.patternScanMethod - if (patternScanMethod is PatternScanMethod.Fuzzy) { - val warnings = patternScanMethod.warnings!! + val patternScanMethod = + signatureAnnotations.find { it::class.annotations.any { method -> method is PatternScanMethod } } + if (patternScanMethod is FuzzyPatternScanMethod) { + val warnings = signature.result!!.scanData.warnings!! val method = signature.result!!.method - val methodFromMetadata = - if (signature.metadata.methodMetadata != null) signature.metadata.methodMetadata!! else MethodMetadata( - null, - null - ) - println("Signature: ${signature.metadata.name}.\nMethod: ${methodFromMetadata.definingClass}->${methodFromMetadata.name} (Signature matches: ${method.definingClass}->${method.toStr()})\nWarnings: ${warnings.count()}") + val methodFromMetadata = + signatureAnnotations.find { it is MatchingMethod } as MatchingMethod? ?: MatchingMethod() + + println("Signature: ${nameAnnotation}.\nMethod: ${methodFromMetadata.definingClass}->${methodFromMetadata.name} (Signature matches: ${method.definingClass}->${method.toStr()})\nWarnings: ${warnings.count()}") for (warning in warnings) { println("${warning.instructionIndex} / ${warning.patternIndex}: ${warning.wrongOpcode} (expected: ${warning.correctOpcode})") } @@ -46,8 +49,8 @@ internal class SignatureChecker { } if (unresolved.isNotEmpty()) { val base = Exception("${unresolved.size} signatures were not resolved.") - for (signature in unresolved) { - base.addSuppressed(Exception("Signature ${signature.metadata.name} was not resolved!")) + for (name in unresolved) { + base.addSuppressed(Exception("Signature $name was not resolved!")) } throw base }