mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-05-04 08:34:27 +02:00
refactor(YouTube/Return YouTube Dislike): make patch more robust by removing opcode patterns from fingerprints
This commit is contained in:
parent
34e5606c22
commit
dd2f636a4a
@ -3,8 +3,6 @@ package app.revanced.patches.youtube.utils.returnyoutubedislike.general
|
|||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
import app.revanced.patcher.patch.annotation.CompatiblePackage
|
||||||
@ -16,11 +14,8 @@ import app.revanced.patches.youtube.utils.playerresponse.PlayerResponsePatch
|
|||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.DislikeFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.DislikeFingerprint
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.LikeFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.LikeFingerprint
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.RemoveLikeFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.RemoveLikeFingerprint
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentAtomicReferenceFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentAtomicReferenceLegacyFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentConstructorFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentConstructorFingerprint
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentContextFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentContextFingerprint
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints.TextComponentTmpFingerprint
|
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.oldlayout.ReturnYouTubeDislikeOldLayoutPatch
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.oldlayout.ReturnYouTubeDislikeOldLayoutPatch
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.ReturnYouTubeDislikeRollingNumberPatch
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.ReturnYouTubeDislikeRollingNumberPatch
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.shorts.ReturnYouTubeDislikeShortsPatch
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.shorts.ReturnYouTubeDislikeShortsPatch
|
||||||
@ -28,10 +23,8 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch
|
|||||||
import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch
|
import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch
|
||||||
import app.revanced.util.exception
|
import app.revanced.util.exception
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
|
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.iface.reference.Reference
|
|
||||||
|
|
||||||
@Patch(
|
@Patch(
|
||||||
name = "Return YouTube Dislike",
|
name = "Return YouTube Dislike",
|
||||||
@ -101,88 +94,34 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
|
|
||||||
TextComponentConstructorFingerprint.result?.let { parentResult ->
|
TextComponentConstructorFingerprint.result?.let { parentResult ->
|
||||||
// Resolves fingerprints
|
// Resolves fingerprints
|
||||||
val parentClassDef = parentResult.classDef
|
TextComponentContextFingerprint.resolve(context, parentResult.classDef)
|
||||||
TextComponentContextFingerprint.resolve(context, parentClassDef)
|
|
||||||
TextComponentTmpFingerprint.resolve(context, parentClassDef)
|
|
||||||
TextComponentAtomicReferenceFingerprint.resolve(context, parentClassDef)
|
|
||||||
TextComponentAtomicReferenceLegacyFingerprint.resolve(context, parentClassDef)
|
|
||||||
|
|
||||||
TextComponentContextFingerprint.result?.let {
|
TextComponentContextFingerprint.result?.let {
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val booleanIndex = it.scanResult.patternScanResult!!.endIndex
|
val conversionContextFieldIndex = implementation!!.instructions.indexOfFirst { instruction ->
|
||||||
|
instruction.opcode == Opcode.IGET_OBJECT
|
||||||
|
&& (instruction as ReferenceInstruction).reference.toString().endsWith("Ljava/util/Map;")
|
||||||
|
} - 1
|
||||||
|
val conversionContextFieldReference =
|
||||||
|
getInstruction<ReferenceInstruction>(conversionContextFieldIndex).reference
|
||||||
|
|
||||||
for (index in booleanIndex downTo 0) {
|
val charSequenceIndex = implementation!!.instructions.indexOfFirst { instruction ->
|
||||||
if (getInstruction(index).opcode != Opcode.IGET_OBJECT) continue
|
instruction.opcode == Opcode.IGET_OBJECT
|
||||||
|
&& (instruction as ReferenceInstruction).reference.toString().endsWith("Ljava/util/BitSet;")
|
||||||
val targetReference =
|
} - 1
|
||||||
getInstruction<ReferenceInstruction>(index).reference.toString()
|
val charSequenceRegister = getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerA
|
||||||
|
val freeRegister = getInstruction<TwoRegisterInstruction>(charSequenceIndex).registerB
|
||||||
if (targetReference.endsWith("Ljava/util/Map;")) {
|
|
||||||
conversionContextFieldReference =
|
|
||||||
getInstruction<ReferenceInstruction>(index - 1).reference
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ?: throw TextComponentContextFingerprint.exception
|
|
||||||
|
|
||||||
TextComponentTmpFingerprint.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
tmpRegister =
|
|
||||||
getInstruction<FiveRegisterInstruction>(startIndex).registerE
|
|
||||||
}
|
|
||||||
} ?: throw TextComponentTmpFingerprint.exception
|
|
||||||
|
|
||||||
|
|
||||||
val textComponentAtomicReferenceResult =
|
|
||||||
TextComponentAtomicReferenceFingerprint.result
|
|
||||||
?: TextComponentAtomicReferenceLegacyFingerprint.result
|
|
||||||
?: throw TextComponentAtomicReferenceLegacyFingerprint.exception
|
|
||||||
|
|
||||||
TextComponentAtomicReferenceFingerprint.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val startIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
val originalRegisterA =
|
|
||||||
getInstruction<TwoRegisterInstruction>(startIndex + 2).registerA
|
|
||||||
|
|
||||||
replaceInstruction(
|
|
||||||
startIndex + 2,
|
|
||||||
"move-object v$originalRegisterA, v$tmpRegister"
|
|
||||||
)
|
|
||||||
replaceInstruction(
|
|
||||||
startIndex + 1,
|
|
||||||
"move-result-object v$tmpRegister"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textComponentAtomicReferenceResult.let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val atomicReferenceStartIndex = it.scanResult.patternScanResult!!.startIndex
|
|
||||||
val insertIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val moveCharSequenceInstruction =
|
|
||||||
getInstruction<TwoRegisterInstruction>(insertIndex)
|
|
||||||
|
|
||||||
val atomicReferenceRegister =
|
|
||||||
getInstruction<FiveRegisterInstruction>(atomicReferenceStartIndex).registerC
|
|
||||||
|
|
||||||
val charSequenceRegister =
|
|
||||||
moveCharSequenceInstruction.registerB
|
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
insertIndex + 1, """
|
charSequenceIndex - 1, """
|
||||||
move-object/from16 v$tmpRegister, p0
|
move-object/from16 v$freeRegister, p0
|
||||||
iget-object v$tmpRegister, v$tmpRegister, $conversionContextFieldReference
|
iget-object v$freeRegister, v$freeRegister, $conversionContextFieldReference
|
||||||
invoke-static {v$tmpRegister, v$atomicReferenceRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
invoke-static {v$freeRegister, v$charSequenceRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onLithoTextLoaded(Ljava/lang/Object;Ljava/lang/CharSequence;)Ljava/lang/CharSequence;
|
||||||
move-result-object v$charSequenceRegister
|
move-result-object v$charSequenceRegister
|
||||||
move-object v${moveCharSequenceInstruction.registerA}, v${charSequenceRegister}
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
removeInstruction(insertIndex)
|
|
||||||
}
|
}
|
||||||
}
|
} ?: throw TextComponentContextFingerprint.exception
|
||||||
} ?: throw TextComponentConstructorFingerprint.exception
|
} ?: throw TextComponentConstructorFingerprint.exception
|
||||||
|
|
||||||
VideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
VideoIdPatch.injectCall("$INTEGRATIONS_RYD_CLASS_DESCRIPTOR->newVideoLoaded(Ljava/lang/String;)V")
|
||||||
@ -208,9 +147,6 @@ object ReturnYouTubeDislikePatch : BytecodePatch(
|
|||||||
private const val FILTER_CLASS_DESCRIPTOR =
|
private const val FILTER_CLASS_DESCRIPTOR =
|
||||||
"$COMPONENTS_PATH/ReturnYouTubeDislikeFilterPatch;"
|
"$COMPONENTS_PATH/ReturnYouTubeDislikeFilterPatch;"
|
||||||
|
|
||||||
private lateinit var conversionContextFieldReference: Reference
|
|
||||||
private var tmpRegister: Int = 12
|
|
||||||
|
|
||||||
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
|
private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind)
|
||||||
|
|
||||||
private data class VotePatch(val fingerprint: MethodFingerprint, val voteKind: Vote)
|
private data class VotePatch(val fingerprint: MethodFingerprint, val voteKind: Vote)
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
object TextComponentAtomicReferenceFingerprint : MethodFingerprint(
|
|
||||||
returnType = "L",
|
|
||||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.MOVE_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.MOVE_OBJECT
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,18 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
object TextComponentAtomicReferenceLegacyFingerprint : MethodFingerprint(
|
|
||||||
returnType = "L",
|
|
||||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_VIRTUAL,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT,
|
|
||||||
Opcode.CHECK_CAST,
|
|
||||||
Opcode.MOVE_OBJECT
|
|
||||||
)
|
|
||||||
)
|
|
@ -1,16 +0,0 @@
|
|||||||
package app.revanced.patches.youtube.utils.returnyoutubedislike.general.fingerprints
|
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
|
||||||
|
|
||||||
object TextComponentTmpFingerprint : MethodFingerprint(
|
|
||||||
returnType = "L",
|
|
||||||
accessFlags = AccessFlags.PROTECTED or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("L"),
|
|
||||||
opcodes = listOf(
|
|
||||||
Opcode.INVOKE_STATIC,
|
|
||||||
Opcode.MOVE_RESULT_OBJECT, // last instruction of the method
|
|
||||||
)
|
|
||||||
)
|
|
@ -2,11 +2,13 @@ package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber
|
|||||||
|
|
||||||
import app.revanced.patcher.data.BytecodeContext
|
import app.revanced.patcher.data.BytecodeContext
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
|
||||||
|
import app.revanced.patcher.extensions.InstructionExtensions.addInstructionsWithLabels
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||||
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
|
import app.revanced.patcher.extensions.InstructionExtensions.removeInstruction
|
||||||
import app.revanced.patcher.patch.BytecodePatch
|
import app.revanced.patcher.patch.BytecodePatch
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.annotation.Patch
|
import app.revanced.patcher.patch.annotation.Patch
|
||||||
|
import app.revanced.patcher.util.smali.ExternalLabel
|
||||||
import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
|
import app.revanced.patches.youtube.utils.fingerprints.RollingNumberTextViewAnimationUpdateFingerprint
|
||||||
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
|
import app.revanced.patches.youtube.utils.integrations.Constants.UTILS_PATH
|
||||||
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberMeasureAnimatedTextFingerprint
|
import app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints.RollingNumberMeasureAnimatedTextFingerprint
|
||||||
@ -31,6 +33,7 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch(
|
|||||||
RollingNumberSetterFingerprint,
|
RollingNumberSetterFingerprint,
|
||||||
RollingNumberMeasureTextParentFingerprint,
|
RollingNumberMeasureTextParentFingerprint,
|
||||||
RollingNumberTextViewFingerprint,
|
RollingNumberTextViewFingerprint,
|
||||||
|
RollingNumberMeasureAnimatedTextFingerprint,
|
||||||
RollingNumberTextViewAnimationUpdateFingerprint
|
RollingNumberTextViewAnimationUpdateFingerprint
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@ -88,41 +91,42 @@ object ReturnYouTubeDislikeRollingNumberPatch : BytecodePatch(
|
|||||||
}
|
}
|
||||||
} ?: throw RollingNumberSetterFingerprint.exception
|
} ?: throw RollingNumberSetterFingerprint.exception
|
||||||
|
|
||||||
RollingNumberMeasureTextParentFingerprint.result?.let { parentResult ->
|
// Rolling Number text views use the measured width of the raw string for layout.
|
||||||
// Rolling Number text views use the measured width of the raw string for layout.
|
// Modify the measure text calculation to include the left drawable separator if needed.
|
||||||
// Modify the measure text calculation to include the left drawable separator if needed.
|
RollingNumberMeasureAnimatedTextFingerprint.result?.let {
|
||||||
RollingNumberMeasureAnimatedTextFingerprint.also {
|
it.mutableMethod.apply {
|
||||||
it.resolve(
|
val endIndex = it.scanResult.patternScanResult!!.endIndex
|
||||||
context,
|
val measuredTextWidthIndex = endIndex - 2
|
||||||
parentResult.classDef
|
val measuredTextWidthRegister =
|
||||||
)
|
getInstruction<TwoRegisterInstruction>(measuredTextWidthIndex).registerA
|
||||||
}.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
|
||||||
val returnInstructionIndex = it.scanResult.patternScanResult!!.endIndex
|
|
||||||
val measuredTextWidthRegister =
|
|
||||||
getInstruction<OneRegisterInstruction>(returnInstructionIndex).registerA
|
|
||||||
|
|
||||||
replaceInstruction( // Replace instruction to preserve control flow label.
|
addInstructions(
|
||||||
returnInstructionIndex,
|
endIndex + 1, """
|
||||||
"invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F"
|
invoke-static {p1, v$measuredTextWidthRegister}, $INTEGRATIONS_RYD_CLASS_DESCRIPTOR->onRollingNumberMeasured(Ljava/lang/String;F)F
|
||||||
)
|
move-result v$measuredTextWidthRegister
|
||||||
addInstructions(
|
"""
|
||||||
returnInstructionIndex + 1, """
|
)
|
||||||
move-result v$measuredTextWidthRegister
|
|
||||||
return v$measuredTextWidthRegister
|
val ifGeIndex = implementation!!.instructions.indexOfFirst { instruction ->
|
||||||
"""
|
instruction.opcode == Opcode.IF_GE
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} ?: throw RollingNumberMeasureAnimatedTextFingerprint.exception
|
val ifGeInstruction = getInstruction<TwoRegisterInstruction>(ifGeIndex)
|
||||||
|
|
||||||
|
removeInstruction(ifGeIndex)
|
||||||
|
addInstructionsWithLabels(
|
||||||
|
ifGeIndex, """
|
||||||
|
if-ge v${ifGeInstruction.registerA}, v${ifGeInstruction.registerB}, :jump
|
||||||
|
""", ExternalLabel("jump", getInstruction(endIndex))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} ?: throw RollingNumberMeasureAnimatedTextFingerprint.exception
|
||||||
|
|
||||||
|
RollingNumberMeasureTextParentFingerprint.result?.classDef?.let { parentClassDef ->
|
||||||
|
RollingNumberMeasureStaticLabelFingerprint.resolve(context, parentClassDef)
|
||||||
|
|
||||||
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
// Additional text measurement method. Used if YouTube decides not to animate the likes count
|
||||||
// and sometimes used for initial video load.
|
// and sometimes used for initial video load.
|
||||||
RollingNumberMeasureStaticLabelFingerprint.also {
|
RollingNumberMeasureStaticLabelFingerprint.result?.let {
|
||||||
it.resolve(
|
|
||||||
context,
|
|
||||||
parentResult.classDef
|
|
||||||
)
|
|
||||||
}.result?.let {
|
|
||||||
it.mutableMethod.apply {
|
it.mutableMethod.apply {
|
||||||
val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
val measureTextIndex = it.scanResult.patternScanResult!!.startIndex + 1
|
||||||
val freeRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
val freeRegister = getInstruction<TwoRegisterInstruction>(0).registerA
|
||||||
|
@ -1,23 +1,34 @@
|
|||||||
package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints
|
package app.revanced.patches.youtube.utils.returnyoutubedislike.rollingnumber.fingerprints
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.or
|
|
||||||
import app.revanced.patcher.fingerprint.MethodFingerprint
|
import app.revanced.patcher.fingerprint.MethodFingerprint
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves to class found in [RollingNumberMeasureTextParentFingerprint].
|
* Compatible with YouTube v18.30.xx to v18.49.xx
|
||||||
*/
|
*/
|
||||||
object RollingNumberMeasureAnimatedTextFingerprint : MethodFingerprint(
|
object RollingNumberMeasureAnimatedTextFingerprint : MethodFingerprint(
|
||||||
returnType = "F",
|
|
||||||
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
|
|
||||||
parameters = listOf("Ljava/lang/String;"),
|
|
||||||
opcodes = listOf(
|
opcodes = listOf(
|
||||||
Opcode.INVOKE_VIRTUAL,
|
Opcode.INVOKE_VIRTUAL,
|
||||||
Opcode.MOVE_RESULT,
|
Opcode.MOVE_RESULT,
|
||||||
Opcode.ADD_FLOAT_2ADDR,
|
Opcode.ADD_FLOAT_2ADDR, // measuredTextWidth
|
||||||
Opcode.ADD_INT_LIT8,
|
Opcode.ADD_INT_LIT8,
|
||||||
Opcode.GOTO,
|
Opcode.GOTO
|
||||||
Opcode.RETURN
|
),
|
||||||
)
|
customFingerprint = custom@{ methodDef, _ ->
|
||||||
|
if (methodDef.implementation == null)
|
||||||
|
return@custom false
|
||||||
|
|
||||||
|
for (instruction in methodDef.implementation!!.instructions) {
|
||||||
|
if (instruction.opcode != Opcode.INVOKE_VIRTUAL)
|
||||||
|
continue
|
||||||
|
|
||||||
|
val invokeInstruction = instruction as ReferenceInstruction
|
||||||
|
if (!invokeInstruction.reference.toString().endsWith("Landroid/text/TextPaint;->measureText([CII)F"))
|
||||||
|
continue
|
||||||
|
|
||||||
|
return@custom true
|
||||||
|
}
|
||||||
|
return@custom false
|
||||||
|
}
|
||||||
)
|
)
|
Loading…
x
Reference in New Issue
Block a user