refactor(hide-upgrade-button): optimize the patching process

This commit is contained in:
inotia00 2023-04-28 11:20:03 +09:00
parent f691796f24
commit 9d8bec4dd3
5 changed files with 114 additions and 166 deletions

View File

@ -1,61 +0,0 @@
package app.revanced.patches.music.layout.upgradebutton.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value.
object PivotBarConstructorFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
parameters = listOf("L", "Z"),
opcodes = 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
)
)

View File

@ -1,104 +0,0 @@
package app.revanced.patches.music.layout.upgradebutton.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.util.smali.toInstructions
import app.revanced.patches.music.layout.upgradebutton.fingerprints.*
import app.revanced.patches.music.misc.integrations.patch.MusicIntegrationsPatch
import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility
import app.revanced.util.integrations.Constants.INTEGRATIONS_PATH
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.builder.instruction.BuilderInstruction22t
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.formats.Instruction22c
import org.jf.dexlib2.iface.instruction.formats.Instruction35c
@Patch
@Name("hide-upgrade-button")
@Description("Remove upgrade tab from pivot bar, hide upgrade banner from homepage.")
@DependsOn(
[
MusicIntegrationsPatch::class,
SharedResourceIdPatch::class
]
)
@YouTubeMusicCompatibility
@Version("0.0.1")
class RemoveUpgradeButtonPatch : BytecodePatch(
listOf(
PivotBarConstructorFingerprint,
NotifierShelfFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
val result = PivotBarConstructorFingerprint.result?: return PivotBarConstructorFingerprint.toErrorResult()
val implementation = result.mutableMethod.implementation!!
val pivotBarElementFieldRef =
(implementation.instructions[result.scanResult.patternScanResult!!.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
""".toInstructions().toMutableList()
val endIndex = result.scanResult.patternScanResult!!.endIndex
// replace the instruction to retain the label at given index
implementation.replaceInstruction(
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(
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(endIndex)
)
)
implementation.addInstructions(
endIndex, instructionList
)
NotifierShelfFingerprint.result?.let {
with (it.mutableMethod) {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = (instruction(targetIndex) as OneRegisterInstruction).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $INTEGRATIONS_PATH/adremover/AdRemoverAPI;->HideViewWithLayout1dp(Landroid/view/View;)V"
)
}
} ?: return NotifierShelfFingerprint.toErrorResult()
return PatchResultSuccess()
}
}

View File

@ -1,4 +1,4 @@
package app.revanced.patches.music.layout.upgradebutton.fingerprints package app.revanced.patches.music.misc.upgradebutton.fingerprints
import app.revanced.patcher.extensions.or import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint

View File

@ -0,0 +1,22 @@
package app.revanced.patches.music.misc.upgradebutton.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import org.jf.dexlib2.AccessFlags
import org.jf.dexlib2.Opcode
import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction
object PivotBarConstructorFingerprint : MethodFingerprint(
returnType = "V",
access = AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR,
opcodes = listOf(
Opcode.IPUT_OBJECT,
Opcode.RETURN_VOID
),
customFingerprint = { methodDef ->
methodDef.name == "<init>"
&& methodDef.implementation!!.instructions.any {
((it as? NarrowLiteralInstruction)?.narrowLiteral == 117501096)
}
}
)

View File

@ -0,0 +1,91 @@
package app.revanced.patches.music.misc.upgradebutton.patch
import app.revanced.extensions.toErrorResult
import app.revanced.patcher.annotation.Description
import app.revanced.patcher.annotation.Name
import app.revanced.patcher.annotation.Version
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.instruction
import app.revanced.patcher.extensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patches.music.misc.integrations.patch.MusicIntegrationsPatch
import app.revanced.patches.music.misc.resourceid.patch.SharedResourceIdPatch
import app.revanced.patches.music.misc.upgradebutton.fingerprints.*
import app.revanced.patches.shared.annotation.YouTubeMusicCompatibility
import app.revanced.util.integrations.Constants.INTEGRATIONS_PATH
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction
import org.jf.dexlib2.iface.reference.FieldReference
@Patch
@Name("hide-upgrade-button")
@Description("Remove upgrade tab from pivot bar, hide upgrade banner from homepage.")
@DependsOn(
[
MusicIntegrationsPatch::class,
SharedResourceIdPatch::class
]
)
@YouTubeMusicCompatibility
@Version("0.0.1")
class RemoveUpgradeButtonPatch : BytecodePatch(
listOf(
PivotBarConstructorFingerprint,
NotifierShelfFingerprint
)
) {
override fun execute(context: BytecodeContext): PatchResult {
PivotBarConstructorFingerprint.result?.let {
with (it.mutableMethod) {
val targetIndex = it.scanResult.patternScanResult!!.startIndex
val targetRegisterA = (instruction(targetIndex) as TwoRegisterInstruction).registerA
val targetRegisterB = (instruction(targetIndex) as TwoRegisterInstruction).registerB
val replaceReference =
(instruction(targetIndex) as ReferenceInstruction).reference as FieldReference
val replaceReferenceToCall = replaceReference.definingClass +
"->" +
replaceReference.name +
":" +
replaceReference.type
replaceInstruction(
targetIndex,
"invoke-interface {v$targetRegisterA}, Ljava/util/List;->size()I"
)
addInstructions(
targetIndex + 1,"""
move-result v1
const/4 v2, 0x3
if-le v1, v2, :dismiss
invoke-interface {v$targetRegisterA, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object;
:dismiss
iput-object v$targetRegisterA, v$targetRegisterB, $replaceReferenceToCall
"""
)
}
} ?: return PivotBarConstructorFingerprint.toErrorResult()
NotifierShelfFingerprint.result?.let {
with (it.mutableMethod) {
val targetIndex = it.scanResult.patternScanResult!!.endIndex
val targetRegister = (instruction(targetIndex) as OneRegisterInstruction).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $INTEGRATIONS_PATH/adremover/AdRemoverAPI;->HideViewWithLayout1dp(Landroid/view/View;)V"
)
}
} ?: return NotifierShelfFingerprint.toErrorResult()
return PatchResultSuccess()
}
}