refactor: make patches compatible with breaking changes of the patcher

This commit is contained in:
oSumAtrIX 2022-04-14 10:17:53 +02:00
parent 582ce70ce2
commit 5119905955
No known key found for this signature in database
GPG Key ID: A9B3094ACDB604B4
9 changed files with 488 additions and 91 deletions

View File

@ -1,4 +1,4 @@
package app.revanced.shared package app.revanced
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patches.ad.VideoAdsPatch import app.revanced.patches.ad.VideoAdsPatch
@ -7,7 +7,7 @@ import app.revanced.patches.layout.*
import app.revanced.patches.misc.IntegrationsPatch import app.revanced.patches.misc.IntegrationsPatch
/** /**
* Index contains all the patches and signatures. * Index contains all the patches.
*/ */
@Suppress("Unused") @Suppress("Unused")
object Index { object Index {

View File

@ -18,7 +18,7 @@ class VideoAdsPatch : Patch(
metadata = PatchMetadata( metadata = PatchMetadata(
shortName = "video-ads", shortName = "video-ads",
name = "YouTube Video Ads Patch", name = "YouTube Video Ads Patch",
description = "Patch to remove ads in the YouTube video player", description = "Patch to remove ads in the YouTube video player.",
compatiblePackages = compatiblePackages, compatiblePackages = compatiblePackages,
version = "0.0.1" version = "0.0.1"
), ),
@ -62,11 +62,7 @@ class VideoAdsPatch : Patch(
) )
) { ) {
override fun execute(patcherData: PatcherData): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
val constructorSignature = signatures.first() var result = signatures.first().result!!
var result = signatures.first().result
result ?: return PatchResultError(
"Could not resolve required signature ${constructorSignature.methodSignatureMetadata.name}"
)
val responsibleMethodSignature = MethodSignature( val responsibleMethodSignature = MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata( methodSignatureMetadata = MethodSignatureMetadata(

View File

@ -1,31 +1,135 @@
package app.revanced.patches.interaction package app.revanced.patches.interaction
import app.revanced.patcher.cache.Cache import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchMetadata import app.revanced.patcher.patch.PatchMetadata
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.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.asInstructions import app.revanced.patcher.smali.asInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
import org.jf.dexlib2.iface.Method import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.formats.Instruction11n import org.jf.dexlib2.iface.instruction.formats.Instruction11n
private val compatiblePackages = arrayOf("com.google.android.youtube")
class EnableSeekbarTappingPatch : Patch( class EnableSeekbarTappingPatch : Patch(
PatchMetadata( metadata = PatchMetadata(
"enable-seekbar-tapping", "seekbar-tapping",
"TODO", "Enable seekbar tapping patch",
"TODO" "Enable tapping on the seekbar of the YouTube player.",
compatiblePackages,
"1.0.0"
),
signatures = listOf(
MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata(
name = "enable-seekbar-tapping-parent-signature",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for a parent method, which is needed to find the actual method required to be patched.",
version = "0.0.1"
),
returnType = "L",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
methodParameters = listOf(),
opcodes = 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 = MethodSignatureMetadata(
name = "enable-seekbar-tapping-signature",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for the method required to be patched.",
version = "0.0.1"
),
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
methodParameters = listOf("L"),
opcodes = listOf(
Opcode.CMPG_DOUBLE,
Opcode.IF_GTZ,
Opcode.GOTO,
Opcode.INT_TO_FLOAT,
Opcode.INT_TO_FLOAT,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT,
Opcode.IF_NEZ,
Opcode.RETURN,
Opcode.IGET_OBJECT,
Opcode.IF_EQZ,
Opcode.INVOKE_VIRTUAL,
Opcode.MOVE_RESULT_WIDE,
Opcode.INT_TO_FLOAT,
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(cache: Cache): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
var map = cache.methodMap["tap-seekbar-parent-method"] var result = signatures.first().result!!
val tapSeekMethods = mutableMapOf<String, Method>() val tapSeekMethods = mutableMapOf<String, Method>()
// find the methods which tap the seekbar // find the methods which tap the seekbar
for (it in map.definingClassProxy.immutableClass.methods) { for (it in result.definingClassProxy.immutableClass.methods) {
if (it.implementation == null) continue if (it.implementation == null) continue
val instructions = it.implementation!!.instructions val instructions = it.implementation!!.instructions
@ -45,16 +149,16 @@ class EnableSeekbarTappingPatch : Patch(
} }
// replace map because we dont need the upper one anymore // replace map because we dont need the upper one anymore
map = cache.methodMap["enable-seekbar-tapping"] result = signatures.last().result!!
val implementation = map.method.implementation!! val implementation = result.method.implementation!!
// if tap-seeking is enabled, do not invoke the two methods below // if tap-seeking is enabled, do not invoke the two methods below
val pMethod = tapSeekMethods["P"]!! val pMethod = tapSeekMethods["P"]!!
val oMethod = tapSeekMethods["O"]!! val oMethod = tapSeekMethods["O"]!!
implementation.addInstructions( implementation.addInstructions(
map.scanData.endIndex, result.scanData.endIndex,
""" """
invoke-virtual { v12, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V invoke-virtual { v12, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V
invoke-virtual { v12, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V invoke-virtual { v12, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V
@ -62,13 +166,13 @@ class EnableSeekbarTappingPatch : Patch(
) )
// if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label // if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label
val elseLabel = implementation.newLabelForIndex(map.scanData.endIndex) val elseLabel = implementation.newLabelForIndex(result.scanData.endIndex)
implementation.addInstruction( implementation.addInstruction(
map.scanData.endIndex, result.scanData.endIndex,
BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel) BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel)
) )
implementation.addInstructions( implementation.addInstructions(
map.scanData.endIndex, result.scanData.endIndex,
""" """
invoke-static { }, Lfi/razerman/youtube/preferences/BooleanPreferences;->isTapSeekingEnabled()Z invoke-static { }, Lfi/razerman/youtube/preferences/BooleanPreferences;->isTapSeekingEnabled()Z
move-result v0 move-result v0

View File

@ -1,25 +1,85 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchMetadata import app.revanced.patcher.patch.PatchMetadata
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.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.asInstruction import app.revanced.patcher.smali.asInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = arrayOf("com.google.android.youtube")
class CreateButtonRemoverPatch : Patch( class CreateButtonRemoverPatch : Patch(
PatchMetadata( metadata = PatchMetadata(
"create-button-remover", "create-button",
"TODO", "Create button patch",
"TODO" "Disable the create button.",
compatiblePackages,
"1.0.0"
),
signatures = listOf(
MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata(
name = "create-button-method",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for the method required to be patched.",
version = "0.0.1"
),
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
methodParameters = listOf("Z"),
opcodes = 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,
Opcode.MOVE_OBJECT
)
)
) )
) { ) {
override fun execute(cache: Cache): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
val map = cache.methodMap["create-button-patch"] val result = signatures.first().result!!
// Hide the button view via proxy by passing it to the hideCreateButton method // Hide the button view via proxy by passing it to the hideCreateButton method
map.method.implementation!!.addInstruction( result.method.implementation!!.addInstruction(
map.scanData.endIndex, result.scanData.endIndex,
"invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".asInstruction() "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->hideCreateButton(Landroid/view/View;)V".asInstruction()
) )

View File

@ -1,27 +1,106 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchMetadata import app.revanced.patcher.patch.PatchMetadata
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.patch.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.asInstruction import app.revanced.patcher.smali.asInstruction
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = arrayOf("com.google.android.youtube")
class HideReelsPatch : Patch( class HideReelsPatch : Patch(
PatchMetadata( metadata = PatchMetadata(
"hide-reels", "hide-reels",
"TODO", "Hide reels patch",
"TODO" "Hide reels on the page.",
compatiblePackages,
"1.0.0"
),
signatures = listOf(
MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata(
name = "hide-reels-signature",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for the method required to be patched.",
version = "0.0.1"
),
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
methodParameters = listOf(
"L",
"L",
"L",
"L",
"L",
"L",
"L",
"L",
"L",
"L",
"L",
"[B",
"[B",
"[B",
"[B",
"[B",
"[B"
),
opcodes = 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(cache: Cache): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
val map = cache.methodMap["hide-reel-patch"] val result = signatures.first().result!!
val implementation = map.method.implementation!! val implementation = result.method.implementation!!
// HideReel will hide the reel view before it is being used, // HideReel will hide the reel view before it is being used,
// so we pass the view to the HideReel method // so we pass the view to the HideReel method
implementation.addInstruction( implementation.addInstruction(
map.scanData.endIndex - 1, result.scanData.endIndex - 1,
"invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".asInstruction() "invoke-static { v2 }, Lfi/razerman/youtube/XAdRemover;->HideReel(Landroid/view/View;)V".asInstruction()
) )

View File

@ -1,13 +1,15 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.* import app.revanced.patcher.patch.*
import app.revanced.patcher.proxy.mutableTypes.MutableMethod.Companion.toMutable 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.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.asInstructions import app.revanced.patcher.smali.asInstructions
import app.revanced.patches.SHARED_METADATA
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction22c import org.jf.dexlib2.builder.instruction.BuilderInstruction22c
@ -17,20 +19,72 @@ import org.jf.dexlib2.iface.instruction.formats.Instruction35c
import org.jf.dexlib2.immutable.ImmutableMethod import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodImplementation import org.jf.dexlib2.immutable.ImmutableMethodImplementation
private val compatiblePackages = arrayOf("com.google.android.youtube")
class HideSuggestionsPatch : Patch( class HideSuggestionsPatch : Patch(
PatchMetadata( metadata = PatchMetadata(
"hide-suggestions", "hide-suggestions",
"TODO", "Hide suggestions patch",
"TODO" "Hide suggested videos.",
compatiblePackages,
"1.0.0"
),
signatures = listOf(
MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata(
name = "hide-suggestions-parent-method",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for a parent method, which is needed to find the actual method required to be patched.",
version = "0.0.1"
),
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
methodParameters = listOf("L", "Z"),
opcodes = 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_EQ
)
)
) )
) { ) {
override fun execute(cache: Cache): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
val map = cache.methodMap["hide-suggestions-patch"].findParentMethod( val result = signatures.first().result!!.findParentMethod(
MethodSignature( MethodSignature(
"hide-suggestions-method", methodSignatureMetadata = MethodSignatureMetadata(
SHARED_METADATA, name = "hide-suggestions-method",
"V", methodMetadata = MethodMetadata(null, null), // unknown
AccessFlags.PUBLIC or AccessFlags.FINAL, patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for the method, which is required to be patched.",
version = "0.0.1"
),
returnType = "V",
accessFlags = AccessFlags.FINAL or AccessFlags.PUBLIC,
listOf("Z"), listOf("Z"),
listOf( listOf(
Opcode.IPUT_BOOLEAN, Opcode.IPUT_BOOLEAN,
@ -40,11 +94,11 @@ class HideSuggestionsPatch : Patch(
Opcode.RETURN_VOID Opcode.RETURN_VOID
) )
) )
) ?: return PatchResultError("Parent method hide-suggestions-method has not been found") ) ?: return PatchResultError("Method old-quality-patch-method has not been found")
// deep clone the method in order to add a new register // deep clone the method in order to add a new register
// TODO: replace by a mutable method implementation with settable register count when available // TODO: replace by a mutable method implementation with settable register count when available
val originalMethod = map.immutableMethod val originalMethod = result.immutableMethod
val originalImplementation = originalMethod.implementation!! val originalImplementation = originalMethod.implementation!!
val clonedMethod = ImmutableMethod( val clonedMethod = ImmutableMethod(
originalMethod.returnType, originalMethod.returnType,
@ -96,7 +150,7 @@ class HideSuggestionsPatch : Patch(
} }
// resolve the class proxy // resolve the class proxy
val clazz = map.definingClassProxy.resolve() val clazz = result.definingClassProxy.resolve()
// remove the old method & add the clone with our additional register // remove the old method & add the clone with our additional register
clazz.methods.remove(originalMethod) clazz.methods.remove(originalMethod)

View File

@ -1,33 +1,80 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.*
import app.revanced.patcher.patch.PatchMetadata import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.patch.PatchResult import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.patch.PatchResultSuccess import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.asInstructions import app.revanced.patcher.smali.asInstructions
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
private val compatiblePackages = arrayOf("com.google.android.youtube")
class MinimizedPlaybackPatch : Patch( class MinimizedPlaybackPatch : Patch(
PatchMetadata( metadata = PatchMetadata(
"minimized-playback", "minimized-playback",
"TODO", "Minimized Playback Patch",
"TODO" "Enable minimized and background playback.",
compatiblePackages,
"1.0.0"
),
signatures = listOf(
MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata(
name = "minimized-playback-manager",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature for the method required to be patched.",
version = "0.0.1"
),
returnType = "Z",
accessFlags = AccessFlags.PUBLIC or AccessFlags.STATIC,
methodParameters = listOf("L"),
opcodes = 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_EQ
)
)
) )
) { ) {
override fun execute(cache: Cache): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
// Instead of removing all instructions like Vanced, // Instead of removing all instructions like Vanced,
// we return the method at the beginning instead // we return the method at the beginning instead
cache.methodMap["minimized-playback-manager"] signatures.first().result!!.method.implementation!!.addInstructions(
.method 0,
.implementation!! """
.addInstructions( const/4 v0, 0x1
0, return v0
"""
const/4 v0, 0x1
return v0
""".trimIndent().asInstructions() """.trimIndent().asInstructions()
) )
return PatchResultSuccess() return PatchResultSuccess()
} }
} }

View File

@ -1,30 +1,91 @@
package app.revanced.patches.layout package app.revanced.patches.layout
import app.revanced.patcher.cache.Cache import app.revanced.patcher.PatcherData
import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or import app.revanced.patcher.extensions.AccessFlagExtensions.Companion.or
import app.revanced.patcher.extensions.addInstructions import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.patch.* import app.revanced.patcher.patch.*
import app.revanced.patcher.signature.MethodMetadata
import app.revanced.patcher.signature.MethodSignature import app.revanced.patcher.signature.MethodSignature
import app.revanced.patcher.signature.MethodSignatureMetadata
import app.revanced.patcher.signature.PatternScanMethod
import app.revanced.patcher.smali.asInstructions import app.revanced.patcher.smali.asInstructions
import app.revanced.patches.SHARED_METADATA
import org.jf.dexlib2.AccessFlags import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction21t import org.jf.dexlib2.builder.instruction.BuilderInstruction21t
private val compatiblePackages = arrayOf("com.google.android.youtube")
class OldQualityLayoutPatch : Patch( class OldQualityLayoutPatch : Patch(
PatchMetadata( metadata = PatchMetadata(
"old-quality-layout", "old-quality-layout",
"TODO", "Old Quality Layout Patch",
"TODO" "Enable the original quality flyout menu",
compatiblePackages,
"1.0.0"
),
signatures = listOf(
MethodSignature(
methodSignatureMetadata = MethodSignatureMetadata(
name = "old-quality-parent-method-signature",
methodMetadata = MethodMetadata(null, null), // unknown
patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature to find a parent method required by the Old Quality Layout patch.",
version = "0.0.1"
),
returnType = "V",
accessFlags = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
methodParameters = listOf("L", "L", "L", "L", "L", "L", "L"),
opcodes = listOf(
Opcode.IPUT_OBJECT,
Opcode.CONST,
Opcode.CONST,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
Opcode.IPUT_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_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,
)
)
) )
) { ) {
override fun execute(cache: Cache): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
val map = cache.methodMap["old-quality-patch"].findParentMethod( var result = signatures.first().result!!
result = result.findParentMethod(
MethodSignature( MethodSignature(
"old-quality-patch-method", methodSignatureMetadata = MethodSignatureMetadata(
SHARED_METADATA, name = "old-quality-method-signature",
"L", methodMetadata = MethodMetadata(null, null), // unknown
AccessFlags.FINAL or AccessFlags.PUBLIC, patternScanMethod = PatternScanMethod.Fuzzy(2), // FIXME: Test this threshold and find the best value.
compatiblePackages = compatiblePackages,
description = "Signature to find the method required by the Old Quality Layout patch",
version = "0.0.1"
),
returnType = "L",
accessFlags = AccessFlags.FINAL or AccessFlags.PUBLIC,
emptyList(), emptyList(),
listOf( listOf(
Opcode.IGET, Opcode.IGET,
@ -36,9 +97,9 @@ class OldQualityLayoutPatch : Patch(
Opcode.RETURN_OBJECT Opcode.RETURN_OBJECT
) )
) )
) ?: return PatchResultError("Parent method old-quality-patch-method has not been found") ) ?: return PatchResultError("Method old-quality-patch-method has not been found")
val implementation = map.method.implementation!! val implementation = result.method.implementation!!
// if useOldStyleQualitySettings == true, jump over all instructions and return the field at the end // if useOldStyleQualitySettings == true, jump over all instructions and return the field at the end
val jmpInstruction = val jmpInstruction =

View File

@ -20,8 +20,8 @@ private val compatiblePackages = arrayOf("com.google.android.youtube")
class IntegrationsPatch : Patch( class IntegrationsPatch : Patch(
metadata = PatchMetadata( metadata = PatchMetadata(
"integrations", "integrations",
"Inject integrations", "Inject integrations Patch",
"Applies mandatory patches to implement the ReVanced integrations into the application", "Applies mandatory patches to implement the ReVanced integrations into the application.",
compatiblePackages, compatiblePackages,
"1.0.0" "1.0.0"
), ),
@ -76,11 +76,7 @@ class IntegrationsPatch : Patch(
) )
) { ) {
override fun execute(patcherData: PatcherData): PatchResult { override fun execute(patcherData: PatcherData): PatchResult {
val signature = signatures.first() val result = signatures.first().result!!
val result = signatures.first().result
result ?: return PatchResultError(
"Could not resolve required signature ${signature.methodSignatureMetadata.name}"
)
val implementation = result.method.implementation!! val implementation = result.method.implementation!!
val count = implementation.registerCount - 1 val count = implementation.registerCount - 1