diff --git a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt index 6def9221f..20bf5465a 100644 --- a/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt +++ b/src/main/kotlin/app/revanced/patches/music/utils/resourceid/SharedResourceIdPatch.kt @@ -69,7 +69,7 @@ object SharedResourceIdPatch : ResourcePatch() { MiniPlayerPlayPauseReplayButton = find(ID, "mini_player_play_pause_replay_button") MusicMenuLikeButtons = find(LAYOUT, "music_menu_like_buttons") MusicNotifierShelf = find(LAYOUT, "music_notifier_shelf") - MusicTastebuilderShelf = find(LAYOUT, "music_tastebuilder_shelf") + MusicTasteBuilderShelf = find(LAYOUT, "music_tastebuilder_shelf") NamesInactiveAccountThumbnailSize = find(DIMEN, "names_inactive_account_thumbnail_size") OfflineSettingsMenuItem = find(ID, "offline_settings_menu_item") PlayerCastMediaRouteButton = find(LAYOUT, "player_cast_media_route_button") diff --git a/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt index 753f2ec58..586f88397 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/NavigationButtonsPatch.kt @@ -9,8 +9,8 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage import app.revanced.patcher.patch.annotation.Patch import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.AutoMotiveFingerprint +import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarButtonViewFingerprint import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarEnumFingerprint -import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarShortsButtonViewFingerprint import app.revanced.patches.youtube.utils.fingerprints.PivotBarCreateButtonViewFingerprint import app.revanced.patches.youtube.utils.integrations.Constants.NAVIGATION import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch @@ -80,7 +80,7 @@ object NavigationButtonsPatch : BytecodePatch( with( arrayOf( PivotBarEnumFingerprint, - PivotBarShortsButtonViewFingerprint + PivotBarButtonViewFingerprint ).onEach { it.resolve( context, diff --git a/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/fingerprints/PivotBarShortsButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/fingerprints/PivotBarButtonViewFingerprint.kt similarity index 78% rename from src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/fingerprints/PivotBarShortsButtonViewFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/fingerprints/PivotBarButtonViewFingerprint.kt index 51acdfc07..87f4e0a18 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/fingerprints/PivotBarShortsButtonViewFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/navigation/navigationbuttons/fingerprints/PivotBarButtonViewFingerprint.kt @@ -3,10 +3,10 @@ package app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints import app.revanced.patcher.fingerprint.MethodFingerprint import com.android.tools.smali.dexlib2.Opcode -object PivotBarShortsButtonViewFingerprint : MethodFingerprint( +object PivotBarButtonViewFingerprint : MethodFingerprint( opcodes = listOf( Opcode.INVOKE_VIRTUAL_RANGE, Opcode.MOVE_RESULT_OBJECT, // target reference - Opcode.GOTO, + null, ) ) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualitySetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/VideoQualitySetterFingerprint.kt similarity index 85% rename from src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualitySetterFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/VideoQualitySetterFingerprint.kt index 6ade62aee..9ee8ccdab 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/VideoQualitySetterFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/fingerprints/VideoQualitySetterFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.video.quality.fingerprints +package app.revanced.patches.youtube.utils.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt index eb2b6dd2b..5133617c7 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/SponsorBlockBytecodePatch.kt @@ -7,31 +7,30 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.annotation.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patches.youtube.utils.fingerprints.SeekbarFingerprint import app.revanced.patches.youtube.utils.fingerprints.SeekbarOnDrawFingerprint import app.revanced.patches.youtube.utils.fingerprints.TotalTimeFingerprint import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint +import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH import app.revanced.patches.youtube.utils.overridespeed.OverrideSpeedHookPatch import app.revanced.patches.youtube.utils.playercontrols.PlayerControlsPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InsetOverlayViewLayout -import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TotalTime import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.SegmentPlaybackControllerFingerprint import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch import app.revanced.patches.youtube.utils.videoid.withoutshorts.VideoIdWithoutShortsPatch import app.revanced.util.exception +import app.revanced.util.getTargetIndex +import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversed +import app.revanced.util.getTargetIndexWithMethodReferenceName +import app.revanced.util.getTargetIndexWithMethodReferenceNameReversed import app.revanced.util.getWideLiteralInstructionIndex import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.builder.BuilderInstruction -import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction3rc import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c import com.android.tools.smali.dexlib2.iface.reference.FieldReference -import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( dependencies = [ @@ -50,179 +49,123 @@ object SponsorBlockBytecodePatch : BytecodePatch( YouTubeControlsOverlayFingerprint ) ) { + private const val INTEGRATIONS_SPONSOR_BLOCK_PATH = + "$INTEGRATIONS_PATH/sponsorblock" + + private const val INTEGRATIONS_SPONSOR_BLOCK_UI_PATH = + "$INTEGRATIONS_SPONSOR_BLOCK_PATH/ui" + + private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR = + "$INTEGRATIONS_SPONSOR_BLOCK_PATH/SegmentPlaybackController;" + override fun execute(context: BytecodeContext) { - /** - * Hook the video time methods - */ VideoIdPatch.apply { + // Hook the video time method videoTimeHook( - INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, + INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, "setVideoTime" ) + // Initialize SponsorBlock onCreateHook( - INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, + INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, "initialize" ) } + val seekBarClass = SeekbarFingerprint.result?.mutableClass + ?: throw SeekbarFingerprint.exception + SeekbarOnDrawFingerprint.resolve(context, seekBarClass) + RectangleFieldInvalidatorFingerprint.resolve(context, seekBarClass) - /** - * Seekbar drawing - */ - SeekbarFingerprint.result?.mutableClass?.let { mutableClass -> - insertMethod = SeekbarOnDrawFingerprint.also { - it.resolve( - context, - mutableClass - ) - }.result?.mutableMethod - ?: throw SeekbarOnDrawFingerprint.exception - insertInstructions = insertMethod.implementation!!.instructions - } ?: throw SeekbarFingerprint.exception + SeekbarOnDrawFingerprint.result?.mutableMethod?.apply { + // Get left and right of seekbar rectangle + val moveObjectIndex = getTargetIndex(Opcode.MOVE_OBJECT_FROM16) - - /** - * Get left and right of seekbar rectangle - */ - val moveRectangleToRegisterIndex = insertInstructions.indexOfFirst { - it.opcode == Opcode.MOVE_OBJECT_FROM16 - } - - insertMethod.addInstruction( - moveRectangleToRegisterIndex + 1, - "invoke-static/range {p0 .. p0}, " + - "$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V" - ) - - for ((index, instruction) in insertInstructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_STATIC) continue - - val invokeInstruction = insertMethod.getInstruction(index) - if ((invokeInstruction.reference as MethodReference).name != "round") continue - - val insertIndex = index + 2 - - insertMethod.addInstruction( - insertIndex, - "invoke-static {v${invokeInstruction.registerC}}, " + - "$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V" + addInstruction( + moveObjectIndex + 1, + "invoke-static/range {p0 .. p0}, " + + "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V" ) - break - } + // Set seekbar thickness + val roundIndex = getTargetIndexWithMethodReferenceName("round") + 1 + val roundRegister = getInstruction(roundIndex).registerA - /** - * Draw segment - */ - for ((index, instruction) in insertInstructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_VIRTUAL_RANGE) continue - - val invokeInstruction = instruction as BuilderInstruction3rc - if ((invokeInstruction.reference as MethodReference).name != "restore") continue - - val drawSegmentInstructionInsertIndex = index - 1 - - val (canvasInstance, centerY) = - insertMethod.getInstruction( - drawSegmentInstructionInsertIndex - ).let { it.registerC to it.registerE } - - insertMethod.addInstruction( - drawSegmentInstructionInsertIndex, - "invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V" + addInstruction( + roundIndex + 1, + "invoke-static {v$roundRegister}, " + + "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V" ) - break + + // Draw segment + val drawCircleIndex = getTargetIndexWithMethodReferenceNameReversed("drawCircle") + val drawCircleInstruction = getInstruction(drawCircleIndex) + addInstruction( + drawCircleIndex, + "invoke-static {v${drawCircleInstruction.registerC}, v${drawCircleInstruction.registerE}}, " + + "$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V" + ) + } ?: throw SeekbarOnDrawFingerprint.exception + + // Voting & Shield button + arrayOf("CreateSegmentButtonController;", "VotingButtonController;").forEach { className -> + PlayerControlsPatch.initializeSB("$INTEGRATIONS_SPONSOR_BLOCK_UI_PATH/$className") + PlayerControlsPatch.injectVisibility("$INTEGRATIONS_SPONSOR_BLOCK_UI_PATH/$className") } - - /** - * Voting & Shield button - */ - arrayOf("CreateSegmentButtonController", "VotingButtonController").forEach { - PlayerControlsPatch.initializeSB("$INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/ui/$it;") - PlayerControlsPatch.injectVisibility("$INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/ui/$it;") - } - - - /** - * Append the new time to the player layout - */ + // Append timestamp TotalTimeFingerprint.result?.let { it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(TotalTime) + 2 + val targetIndex = getTargetIndexWithMethodReferenceName("getString") + 1 val targetRegister = getInstruction(targetIndex).registerA addInstructions( targetIndex + 1, """ - invoke-static {v$targetRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; + invoke-static {v$targetRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; move-result-object v$targetRegister """ ) } } ?: throw TotalTimeFingerprint.exception - - /** - * Initialize the SponsorBlock view - */ + // Initialize the SponsorBlock view YouTubeControlsOverlayFingerprint.result?.let { it.mutableMethod.apply { - val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout) + 3 - val targetRegister = getInstruction(targetIndex).registerA + val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout) + val checkCastIndex = getTargetIndex(targetIndex, Opcode.CHECK_CAST) + val targetRegister = getInstruction(checkCastIndex).registerA addInstruction( - targetIndex + 1, - "invoke-static {v$targetRegister}, $INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/ui/SponsorBlockViewController;->initialize(Landroid/view/ViewGroup;)V" + checkCastIndex + 1, + "invoke-static {v$targetRegister}, $INTEGRATIONS_SPONSOR_BLOCK_UI_PATH/SponsorBlockViewController;->initialize(Landroid/view/ViewGroup;)V" ) } } ?: throw YouTubeControlsOverlayFingerprint.exception + // Replace strings + RectangleFieldInvalidatorFingerprint.result?.let { result -> + result.mutableMethod.apply { + val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate") + val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(invalidateIndex + 1, "Landroid/graphics/Rect;") + val rectangleFieldName = (getInstruction(rectangleIndex).reference as FieldReference).name - /** - * Replace strings - */ - SeekbarFingerprint.result?.mutableClass?.let { mutableClass -> - RectangleFieldInvalidatorFingerprint.also { - it.resolve( - context, - mutableClass - ) - }.result?.let { - it.mutableMethod.apply { - val rectangleReference = - getInstruction(implementation!!.instructions.count() - 3).reference - val rectangleFieldName = (rectangleReference as FieldReference).name + SegmentPlaybackControllerFingerprint.result?.let { + it.mutableMethod.apply { + val replaceIndex = it.scanResult.patternScanResult!!.startIndex + val replaceRegister = + getInstruction(replaceIndex).registerA - SegmentPlaybackControllerFingerprint.result?.let { result -> - result.mutableMethod.apply { - val replaceIndex = result.scanResult.patternScanResult!!.startIndex - val replaceRegister = - getInstruction(replaceIndex).registerA + replaceInstruction( + replaceIndex, + "const-string v$replaceRegister, \"$rectangleFieldName\"" + ) + } + } ?: throw SegmentPlaybackControllerFingerprint.exception + } + } ?: throw YouTubeControlsOverlayFingerprint.exception - replaceInstruction( - replaceIndex, - "const-string v$replaceRegister, \"$rectangleFieldName\"" - ) - } - } ?: throw SegmentPlaybackControllerFingerprint.exception - } - } ?: throw RectangleFieldInvalidatorFingerprint.exception - } ?: throw SeekbarFingerprint.exception - - - /** - * Inject VideoIdPatch - */ - VideoIdWithoutShortsPatch.injectCall("$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") + // Inject VideoIdPatch + VideoIdWithoutShortsPatch.injectCall("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") } - - private const val INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/youtube/sponsorblock" - - private const val INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR = - "$INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/SegmentPlaybackController;" - - private lateinit var insertMethod: MutableMethod - private lateinit var insertInstructions: List } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt index 34e54eeb8..d06bb6b64 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/RectangleFieldInvalidatorFingerprint.kt @@ -1,23 +1,9 @@ package app.revanced.patches.youtube.utils.sponsorblock.fingerprints -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import app.revanced.util.fingerprint.MethodReferenceNameFingerprint -object RectangleFieldInvalidatorFingerprint : MethodFingerprint( +object RectangleFieldInvalidatorFingerprint : MethodReferenceNameFingerprint( returnType = "V", - customFingerprint = custom@{ methodDef, _ -> - val instructions = methodDef.implementation?.instructions!! - val instructionCount = instructions.count() - - // the method has definitely more than 5 instructions - if (instructionCount < 5) return@custom false - - val referenceInstruction = - instructions.elementAt(instructionCount - 2) // the second to last instruction - val reference = - ((referenceInstruction as? ReferenceInstruction)?.reference as? MethodReference) - - reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method - } + parameters = emptyList(), + reference = { "invalidate" } ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/SegmentPlaybackControllerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/SegmentPlaybackControllerFingerprint.kt index 5dee6545c..1e6830259 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/SegmentPlaybackControllerFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/utils/sponsorblock/fingerprints/SegmentPlaybackControllerFingerprint.kt @@ -2,6 +2,7 @@ package app.revanced.patches.youtube.utils.sponsorblock.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode @@ -11,7 +12,7 @@ object SegmentPlaybackControllerFingerprint : MethodFingerprint( parameters = listOf("Ljava/lang/Object;"), opcodes = listOf(Opcode.CONST_STRING), customFingerprint = { methodDef, _ -> - methodDef.definingClass == "Lapp/revanced/integrations/youtube/sponsorblock/SegmentPlaybackController;" + methodDef.definingClass == "$INTEGRATIONS_PATH/sponsorblock/SegmentPlaybackController;" && methodDef.name == "setSponsorBarRect" } ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/hdr/fingerprints/HdrCapabilitiesFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/hdr/fingerprints/HdrCapabilitiesFingerprint.kt index c98291a99..4d2f96e7b 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/hdr/fingerprints/HdrCapabilitiesFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/hdr/fingerprints/HdrCapabilitiesFingerprint.kt @@ -1,27 +1,9 @@ package app.revanced.patches.youtube.video.hdr.fingerprints -import app.revanced.patcher.fingerprint.MethodFingerprint -import com.android.tools.smali.dexlib2.Opcode -import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference +import app.revanced.util.fingerprint.MethodReferenceNameFingerprint -object HdrCapabilitiesFingerprint : MethodFingerprint( +object HdrCapabilitiesFingerprint : MethodReferenceNameFingerprint( returnType = "Z", parameters = listOf("I", "Landroid/view/Display;"), - customFingerprint = custom@{ methodDef, _ -> - if (methodDef.implementation == null) - return@custom false - - for (instruction in methodDef.implementation!!.instructions) { - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) - continue - - val objectInstruction = instruction as ReferenceInstruction - if ((objectInstruction.reference as MethodReference).name != "getSupportedHdrTypes") - continue - - return@custom true - } - return@custom false - } + reference = { "getSupportedHdrTypes" } ) diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt index bf021936a..4cd9e628d 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/VideoQualityPatch.kt @@ -16,7 +16,7 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch import app.revanced.patches.youtube.utils.videoid.withoutshorts.VideoIdWithoutShortsPatch -import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualitySetterFingerprint +import app.revanced.patches.youtube.utils.fingerprints.VideoQualitySetterFingerprint import app.revanced.util.copyXmlNode import app.revanced.util.exception import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction diff --git a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt index c5a0ced78..08ba5045d 100644 --- a/src/main/kotlin/app/revanced/util/BytecodeUtils.kt +++ b/src/main/kotlin/app/revanced/util/BytecodeUtils.kt @@ -143,6 +143,15 @@ fun BytecodeContext.traverseClassHierarchy( inline fun Instruction.getReference() = (this as? ReferenceInstruction)?.reference as? T +/** + * Get the index of the first [Instruction] that matches the predicate. + * + * @param predicate The predicate to match. + * @return The index of the first [Instruction] that matches the predicate. + */ +fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) = + this.implementation!!.instructions.indexOfFirst(predicate) + fun MutableMethod.getTargetIndex(opcode: Opcode) = getTargetIndex(0, opcode) fun MutableMethod.getTargetIndexReversed(opcode: Opcode) = @@ -220,6 +229,12 @@ fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(startIndex: Int, return -1 } +fun MutableMethod.getTargetIndexWithReference(reference: String) += getTargetIndexWithReference(0, reference) + +fun MutableMethod.getTargetIndexWithReferenceReversed(reference: String) + = getTargetIndexWithReferenceReversed(implementation!!.instructions.size - 1, reference) + fun MutableMethod.getTargetIndexWithReference(startIndex: Int, reference: String) = implementation!!.instructions.let { startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction -> diff --git a/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt b/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt new file mode 100644 index 000000000..f2252f881 --- /dev/null +++ b/src/main/kotlin/app/revanced/util/fingerprint/MethodReferenceNameFingerprint.kt @@ -0,0 +1,34 @@ +package app.revanced.util.fingerprint + +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.util.containsMethodReferenceNameInstructionIndex +import com.android.tools.smali.dexlib2.Opcode + +/** + * A fingerprint to resolve methods that contain a specific method reference name value. + * + * @param returnType The method's return type compared using String.startsWith. + * @param accessFlags The method's exact access flags using values of AccessFlags. + * @param parameters The parameters of the method. Partial matches allowed and follow the same rules as returnType. + * @param opcodes An opcode pattern of the method's instructions. Wildcard or unknown opcodes can be specified by null. + * @param strings A list of the method's strings compared each using String.contains. + * @param reference A supplier for the method reference name value to check for. + */ +abstract class MethodReferenceNameFingerprint( + returnType: String? = null, + accessFlags: Int? = null, + parameters: Iterable? = null, + opcodes: Iterable? = null, + strings: Iterable? = null, + // Has to be a supplier because the fingerprint is created before patches can check reference. + reference: () -> String +) : MethodFingerprint( + returnType = returnType, + accessFlags = accessFlags, + parameters = parameters, + opcodes = opcodes, + strings = strings, + customFingerprint = { methodDef, _ -> + methodDef.containsMethodReferenceNameInstructionIndex(reference()) + } +) \ No newline at end of file